Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 4 additions & 10 deletions Composer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,27 +27,21 @@
"packages/extension-client",
"packages/form-dialogs",
"packages/intellisense",
"packages/lib",
"packages/lib/*",
"packages/server",
"packages/test-utils",
"packages/tools",
"packages/tools/built-in-functions",
"packages/tools/language-servers",
"packages/tools/language-servers/*",
"packages/types",
"packages/ui-plugins/*"
],
"scripts": {
"build": "node scripts/begin.js && yarn build:prod",
"build:prod": "yarn build:dev && yarn build:server && yarn build:client && yarn build:electron",
"build:dev": "yarn build:test && yarn build:lib && yarn build:tools && yarn build:extensions && yarn build:plugins && yarn l10n",
"build:test": "yarn workspace @bfc/test-utils build",
"build:lib": "yarn workspace @bfc/libs build:all",
"build": "node scripts/begin.js && yarn build:prod && yarn l10n",
"build:prod": "yarn build:dev && yarn build:client && yarn build:server && yarn build:electron",
"build:dev": "wsrun -ltm -x @bfc/electron-server -x @bfc/client -x @bfc/server -p @bfc/* -c build && yarn build:plugins",
"build:electron": "yarn workspace @bfc/electron-server build && yarn workspace @bfc/electron-server l10n",
"build:extensions": "wsrun -lt -p @bfc/extension @bfc/intellisense @bfc/extension-client @bfc/adaptive-form @bfc/adaptive-flow @bfc/ui-plugin-* @bfc/form-dialogs -c build",
"build:server": "yarn workspace @bfc/server build",
"build:client": "yarn workspace @bfc/client build",
"build:tools": "yarn workspace @bfc/tools build:all",
"build:plugins": "yarn build:plugins:localpublish && yarn build:plugins:samples && yarn build:plugins:azurePublish && yarn build:plugins:runtimes",
"build:plugins:localpublish": "cd plugins/localPublish && yarn install && yarn build",
"build:plugins:samples": "cd plugins/samples && yarn install && yarn build",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { OBISchema } from '@bfc/shared';
import { JSONSchema7 } from '@bfc/shared';

import { getCustomSchema } from '../../../src/adaptive-flow-editor/utils/getCustomSchema';

Expand All @@ -23,7 +23,7 @@ describe('getCustomSchema', () => {
description: 'Send an activity.',
},
},
} as OBISchema;
} as JSONSchema7;
expect(getCustomSchema({ oneOf: [], definitions: {} }, ejected)).toEqual({
actions: {
oneOf: [
Expand Down Expand Up @@ -59,7 +59,7 @@ describe('getCustomSchema', () => {
description: 'My Trigger.',
},
},
} as OBISchema;
} as JSONSchema7;
expect(getCustomSchema({ oneOf: [], definitions: {} }, ejected)).toEqual({
actions: {
oneOf: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ const VisualDesigner: React.FC<VisualDesignerProps> = ({ onFocus, onBlur, schema
};

const customFlowSchema: FlowUISchema = nodeContext.customSchemas.reduce((result, s) => {
const definitionKeys: string[] = Object.keys(s.definitions);
const definitionKeys = Object.keys(s.definitions ?? {});
definitionKeys.forEach(($kind) => {
result[$kind] = {
widget: 'ActionHeader',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
// Licensed under the MIT License.

import React from 'react';
import { DialogFactory, OBISchema } from '@bfc/shared';
import { DialogFactory, JSONSchema7 } from '@bfc/shared';

export interface NodeRendererContextValue {
focusedId?: string;
focusedEvent?: string;
focusedTab?: string;
clipboardActions: any[];
dialogFactory: DialogFactory;
customSchemas: OBISchema[];
customSchemas: JSONSchema7[];
}

export const defaultRendererContextValue = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { OBISchema, SDKKinds } from '@bfc/shared';
import { JSONSchema7, SDKKinds } from '@bfc/shared';
import pickBy from 'lodash/pickBy';

interface CustomSchemaSet {
actions?: OBISchema;
triggers?: OBISchema;
recognizers?: OBISchema;
actions?: JSONSchema7;
triggers?: JSONSchema7;
recognizers?: JSONSchema7;
}

const pickSchema = (
picked$kinds: SDKKinds[],
sourceSchema: { [key in SDKKinds]: OBISchema }
): OBISchema | undefined => {
type SourceSchema = { [key in SDKKinds]: JSONSchema7 };

const pickSchema = (picked$kinds: SDKKinds[], sourceSchema: SourceSchema): JSONSchema7 | undefined => {
if (!Array.isArray(picked$kinds) || picked$kinds.length === 0) return undefined;

const pickedSchema = picked$kinds.reduce(
(schema, $kind) => {
const definition = sourceSchema[$kind];
schema.definitions = schema.definitions ?? {};
schema.definitions[$kind] = definition;
schema.oneOf?.push({
title: definition.title || $kind,
Expand All @@ -30,11 +30,13 @@ const pickSchema = (
{
oneOf: [],
definitions: {},
} as OBISchema
} as JSONSchema7
);

// Sort `oneOf` list alphabetically
pickedSchema.oneOf?.sort((a, b) => (a.$ref < b.$ref ? -1 : 1));
pickedSchema.oneOf?.sort((a, b) => {
return (a.$ref ?? '') < (b.$ref ?? '') ? -1 : 1;
});

return pickedSchema;
};
Expand All @@ -47,18 +49,18 @@ const roleImplementsInterface = (interfaceName: SDKKinds, $role?: SchemaRole): b
return false;
};

const isActionSchema = (schema: OBISchema) => roleImplementsInterface(SDKKinds.IDialog, schema.$role);
const isTriggerSchema = (schema: OBISchema) => roleImplementsInterface(SDKKinds.ITrigger, schema.$role);
const isRecognizerSchema = (schema: OBISchema) =>
const isActionSchema = (schema: JSONSchema7) => roleImplementsInterface(SDKKinds.IDialog, schema.$role);
const isTriggerSchema = (schema: JSONSchema7) => roleImplementsInterface(SDKKinds.ITrigger, schema.$role);
const isRecognizerSchema = (schema: JSONSchema7) =>
roleImplementsInterface(SDKKinds.IRecognizer, schema.$role) ||
roleImplementsInterface(SDKKinds.IEntityRecognizer, schema.$role);

export const getCustomSchema = (baseSchema?: OBISchema, ejectedSchema?: OBISchema): CustomSchemaSet => {
export const getCustomSchema = (baseSchema?: JSONSchema7, ejectedSchema?: JSONSchema7): CustomSchemaSet => {
if (!baseSchema || !ejectedSchema) return {};
if (typeof baseSchema.definitions !== 'object' || typeof ejectedSchema.definitions !== 'object') return {};

const baseDefinitions = baseSchema.definitions;
const ejectedDefinitions = ejectedSchema.definitions;
const ejectedDefinitions = ejectedSchema.definitions ?? {};

const baseKindHash = Object.keys(baseDefinitions).reduce((hash, $kind) => {
hash[$kind] = true;
Expand All @@ -75,9 +77,9 @@ export const getCustomSchema = (baseSchema?: OBISchema, ejectedSchema?: OBISchem

return pickBy(
{
actions: pickSchema(actionKinds, ejectedDefinitions),
triggers: pickSchema(triggerKinds, ejectedDefinitions),
recognizers: pickSchema(recognizerKinds, ejectedDefinitions),
actions: pickSchema(actionKinds, ejectedDefinitions as SourceSchema),
triggers: pickSchema(triggerKinds, ejectedDefinitions as SourceSchema),
recognizers: pickSchema(recognizerKinds, ejectedDefinitions as SourceSchema),
},
(v) => v !== undefined
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { JSONSchema7, JSONSchema7Definition, SchemaDefinitions } from '@bfc/extension-client';
import { JSONSchema7, SchemaDefinitions } from '@bfc/extension-client';
import { IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown';

import { resolveRef, getValueType } from '../../../utils';
Expand Down Expand Up @@ -43,7 +43,7 @@ function getOptionLabel(schema: JSONSchema7, parent: JSONSchema7): string {
}

export function getOneOfOptions(
oneOf: JSONSchema7Definition[],
oneOf: JSONSchema7[],
parentSchema: JSONSchema7,
definitions?: SchemaDefinitions
): SchemaOption[] {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { jsx } from '@emotion/core';
import React, { useState, useMemo, useRef } from 'react';
import { FieldProps, useShellApi } from '@bfc/extension-client';
import { DefaultButton } from 'office-ui-fabric-react/lib/Button';
import { JSONSchema7 } from 'json-schema';
import { IconButton } from 'office-ui-fabric-react/lib/Button';
import { TextField, ITextField } from 'office-ui-fabric-react/lib/TextField';
import { TooltipHost } from 'office-ui-fabric-react/lib/Tooltip';
Expand Down Expand Up @@ -91,7 +90,7 @@ const ObjectArrayField: React.FC<FieldProps<any[]>> = (props) => {
allOrderProps.length > 2 ||
orderedProperties.some((property) => Array.isArray(property)) ||
Object.entries(properties).some(([key, propSchema]) => {
const resolved = resolveRef(propSchema as JSONSchema7, props.definitions);
const resolved = resolveRef(propSchema, props.definitions);
return allOrderProps.includes(key) && resolved.$role === 'expression';
})
);
Expand Down Expand Up @@ -134,7 +133,7 @@ const ObjectArrayField: React.FC<FieldProps<any[]>> = (props) => {
{...props}
transparentBorder
id={`${id}.${idx}`}
schema={itemSchema as JSONSchema7}
schema={itemSchema}
stackArrayItems={stackArrayItems}
value={item.value}
{...getArrayItemProps(arrayItems, idx, handleChange)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { FieldProps, JSONSchema7, JSONSchema7Definition } from '@bfc/extension-client';
import { FieldProps, JSONSchema7, SchemaDefinitions } from '@bfc/extension-client';
import merge from 'lodash/merge';
import omit from 'lodash/omit';
import { IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown';
Expand All @@ -23,10 +23,7 @@ function getOptionLabel(schema: JSONSchema7): string {
return type || 'unknown';
}

export function getOptions(
schema: JSONSchema7,
definitions?: { [key: string]: JSONSchema7Definition }
): IDropdownOption[] {
export function getOptions(schema: JSONSchema7, definitions?: SchemaDefinitions): IDropdownOption[] {
const { type, oneOf } = schema;

if (type && Array.isArray(type)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import { JSONSchema7, JSONSchema7Definition } from '@bfc/extension-client';
import { JSONSchema7, SchemaDefinitions } from '@bfc/extension-client';

import { resolveRef } from './resolveRef';

export function resolvePropSchema(
schema: JSONSchema7,
path: string,
definitions: {
[k: string]: JSONSchema7Definition;
} = {}
definitions: SchemaDefinitions = {}
): JSONSchema7 | undefined {
const propSchema = schema.properties?.[path];

Expand Down
7 changes: 2 additions & 5 deletions Composer/packages/adaptive-form/src/utils/resolveRef.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import { JSONSchema7, JSONSchema7Definition } from '@bfc/extension-client';
import { JSONSchema7, SchemaDefinitions } from '@bfc/extension-client';
import formatMessage from 'format-message';

export function resolveRef(
schema: JSONSchema7 = {},
definitions: { [key: string]: JSONSchema7Definition } = {}
): JSONSchema7 {
export function resolveRef(schema: JSONSchema7 = {}, definitions: SchemaDefinitions = {}): JSONSchema7 {
if (typeof schema?.$ref === 'string') {
if (!schema?.$ref?.startsWith('#/definitions/')) {
return schema;
Expand Down
1 change: 1 addition & 0 deletions Composer/packages/client/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
build/
public/*-bundle.js
public/plugin-host-preload.js
103 changes: 103 additions & 0 deletions Composer/packages/client/config/extensions.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
const path = require('path');

const PnpWebpackPlugin = require('pnp-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');

const paths = require('./paths');

module.exports = (webpackEnv) => {
const isEnvDevelopment = webpackEnv === 'development';
const isEnvProduction = webpackEnv === 'production';

return [
{
entry: {
'react-bundle': 'react',
},
mode: isEnvProduction ? 'production' : 'development',
// export react globally under a variable named React
output: {
path: path.resolve(__dirname, '../public'),
library: 'React',
libraryTarget: 'var',
},
resolve: {
extensions: ['.js'],
},
optimization: {
minimize: isEnvProduction,
minimizer: [
new TerserPlugin({
extractComments: false,
}),
],
},
},
{
entry: {
'react-dom-bundle': 'react-dom',
},
mode: isEnvProduction ? 'production' : 'development',
// export react-dom globally under a variable named ReactDOM
output: {
path: path.resolve(__dirname, '../public'),
library: 'ReactDOM',
libraryTarget: 'var',
},
externals: {
// ReactDOM depends on React, but we need this to resolve to the globally-exposed React variable in react-bundle.js (created by extensions.config.js).
// If we don't do this, ReactDom will bundle its own copy of React and we will have 2 copies which breaks hooks.
react: 'React',
},
resolve: {
extensions: ['.js'],
},
optimization: {
minimize: isEnvProduction,
minimizer: [
new TerserPlugin({
extractComments: false,
}),
],
},
},
{
mode: isEnvProduction ? 'production' : 'development',
entry: {
'plugin-host-preload': path.resolve(__dirname, '../extension-container/plugin-host-preload.tsx'),
},
output: {
path: path.resolve(__dirname, '../public'),
},
externals: {
// expect react & react-dom to be available in the extension host iframe globally under "React" and "ReactDOM" variables
react: 'React',
'react-dom': 'ReactDOM',
},
resolve: {
extensions: ['.js'],
plugins: [PnpWebpackPlugin],
},
resolveLoader: {
plugins: [
// Also related to Plug'n'Play, but this time it tells Webpack to load its loaders
// from the current package.
PnpWebpackPlugin.moduleLoader(module),
],
},
module: {
rules: [
{
test: /\.tsx?$/,
loader: require.resolve('ts-loader'),
include: [path.resolve(__dirname, '../extension-container')],
options: PnpWebpackPlugin.tsLoaderOptions({
transpileOnly: true,
configFile: path.resolve(__dirname, '../tsconfig.build.json'),
}),
},
],
},
},
];
};
Loading