diff --git a/Composer/packages/client/__tests__/components/CreationFlow/index.test.tsx b/Composer/packages/client/__tests__/components/CreationFlow/index.test.tsx
index 2a1206494e..8117a34751 100644
--- a/Composer/packages/client/__tests__/components/CreationFlow/index.test.tsx
+++ b/Composer/packages/client/__tests__/components/CreationFlow/index.test.tsx
@@ -5,9 +5,15 @@ import * as React from 'react';
import { render, fireEvent, act } from '@botframework-composer/test-utils';
import { createHistory, createMemorySource, LocationProvider } from '@reach/router';
import { RecoilRoot } from 'recoil';
+import { getDefaultFeatureFlags } from '@bfc/shared';
import CreationFlow from '../../../src/components/CreationFlow/CreationFlow';
-import { focusedStorageFolderState, creationFlowStatusState, dispatcherState } from '../../../src/recoilModel';
+import {
+ focusedStorageFolderState,
+ creationFlowStatusState,
+ dispatcherState,
+ featureFlagsState,
+} from '../../../src/recoilModel';
import { CreationFlowStatus } from '../../../src/constants';
describe('', () => {
@@ -26,7 +32,7 @@ describe('', () => {
saveTemplateId: jest.fn(),
});
set(creationFlowStatusState, CreationFlowStatus.NEW_FROM_TEMPLATE);
-
+ set(featureFlagsState, getDefaultFeatureFlags());
set(focusedStorageFolderState, {
name: 'Desktop',
parent: '/test-folder',
diff --git a/Composer/packages/client/__tests__/components/home.test.tsx b/Composer/packages/client/__tests__/components/home.test.tsx
index e379b8959d..3f4d035646 100644
--- a/Composer/packages/client/__tests__/components/home.test.tsx
+++ b/Composer/packages/client/__tests__/components/home.test.tsx
@@ -3,7 +3,7 @@
import * as React from 'react';
import { fireEvent, render } from '@botframework-composer/test-utils';
-import { ProjectTemplate } from '@bfc/shared';
+import { BotTemplate } from '@bfc/shared';
import { RecentBotList } from '../../src/pages/home/RecentBotList';
import { ExampleList } from '../../src/pages/home/ExampleList';
@@ -32,7 +32,7 @@ describe('', () => {
const templates = [
{ description: 'echo bot', id: 'EchoBot', name: 'Echo Bot' },
{ description: 'empty bot', id: 'EmptyBot', name: 'Empty Bot' },
- ] as ProjectTemplate[];
+ ] as BotTemplate[];
const onClickTemplate = jest.fn((item) => item);
const { container, getByText } = render();
expect(container).toHaveTextContent('Echo Bot');
diff --git a/Composer/packages/client/src/components/CreationFlow/CreateOptions.tsx b/Composer/packages/client/src/components/CreationFlow/CreateOptions.tsx
index e4c6a586b2..184bc6a9b4 100644
--- a/Composer/packages/client/src/components/CreationFlow/CreateOptions.tsx
+++ b/Composer/packages/client/src/components/CreationFlow/CreateOptions.tsx
@@ -20,7 +20,7 @@ import {
DetailsRow,
} from 'office-ui-fabric-react/lib/DetailsList';
import { Sticky, StickyPositionType } from 'office-ui-fabric-react/lib/Sticky';
-import { ProjectTemplate } from '@bfc/shared';
+import { BotTemplate } from '@bfc/shared';
import { DialogWrapper, DialogTypes } from '@bfc/ui-shared';
import { NeutralColors } from '@uifabric/fluent-theme';
import { RouteComponentProps } from '@reach/router';
@@ -105,7 +105,7 @@ const optionKeys = {
// -------------------- CreateOptions -------------------- //
type CreateOptionsProps = {
- templates: ProjectTemplate[];
+ templates: BotTemplate[];
onDismiss: () => void;
onNext: (data: string) => void;
} & RouteComponentProps<{}>;
@@ -119,7 +119,7 @@ export function CreateOptions(props: CreateOptionsProps) {
const selection = useMemo(() => {
return new Selection({
onSelectionChanged: () => {
- const t = selection.getSelection()[0] as ProjectTemplate;
+ const t = selection.getSelection()[0] as BotTemplate;
if (t) {
setCurrentTemplate(t.id);
}
diff --git a/Composer/packages/client/src/pages/home/ExampleList.tsx b/Composer/packages/client/src/pages/home/ExampleList.tsx
index 6054e32c05..5409d82002 100644
--- a/Composer/packages/client/src/pages/home/ExampleList.tsx
+++ b/Composer/packages/client/src/pages/home/ExampleList.tsx
@@ -6,7 +6,7 @@ import { jsx } from '@emotion/core';
import React from 'react';
import { ScrollablePane, ScrollbarVisibility } from 'office-ui-fabric-react/lib/ScrollablePane';
import { List } from 'office-ui-fabric-react/lib/List';
-import { ProjectTemplate } from '@bfc/shared';
+import { BotTemplate } from '@bfc/shared';
import * as exampleIcons from '../../images/samples';
@@ -20,7 +20,7 @@ import {
} from './styles';
interface ExampleListProps {
- examples: ProjectTemplate[];
+ examples: BotTemplate[];
onClick: (templateId: string) => void;
}
@@ -35,7 +35,7 @@ const resolveIcon = (exampleId: string): string => {
export const ExampleList: React.FC = (props) => {
const { onClick, examples } = props;
- function onRenderCell(item?: ProjectTemplate): React.ReactNode {
+ function onRenderCell(item?: BotTemplate): React.ReactNode {
if (!item) {
return;
}
diff --git a/Composer/packages/client/src/recoilModel/atoms/appState.ts b/Composer/packages/client/src/recoilModel/atoms/appState.ts
index a409ccbd7b..c9d812051a 100644
--- a/Composer/packages/client/src/recoilModel/atoms/appState.ts
+++ b/Composer/packages/client/src/recoilModel/atoms/appState.ts
@@ -2,7 +2,7 @@
// Licensed under the MIT License.
import { atom, atomFamily } from 'recoil';
-import { FormDialogSchemaTemplate, FeatureFlagMap, ProjectTemplate, UserSettings } from '@bfc/shared';
+import { FormDialogSchemaTemplate, FeatureFlagMap, BotTemplate, UserSettings } from '@bfc/shared';
import { ExtensionMetadata } from '@bfc/extension-client';
import {
@@ -52,7 +52,7 @@ export const recentProjectsState = atom({
default: [],
});
-export const templateProjectsState = atom({
+export const templateProjectsState = atom({
key: getFullyQualifiedKey('templateProjects'),
default: [],
});
diff --git a/Composer/packages/client/src/recoilModel/selectors/projectTemplates.ts b/Composer/packages/client/src/recoilModel/selectors/projectTemplates.ts
index d3b8a8124d..5567474c85 100644
--- a/Composer/packages/client/src/recoilModel/selectors/projectTemplates.ts
+++ b/Composer/packages/client/src/recoilModel/selectors/projectTemplates.ts
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
+import { BotTemplate } from '@bfc/shared';
import { selector } from 'recoil';
import { featureFlagsState, templateProjectsState } from '../atoms/appState';
@@ -11,13 +12,20 @@ export const filteredTemplatesSelector = selector({
const templates = get(templateProjectsState);
const featureFlags = get(featureFlagsState);
- const filteredTemplates = [...templates];
+ let filteredTemplates = [...templates];
if (!featureFlags?.VA_CREATION?.enabled) {
const vaTemplateIndex = filteredTemplates.findIndex((template) => template.id === 'va-core');
if (vaTemplateIndex !== -1) {
filteredTemplates.splice(vaTemplateIndex, 1);
}
}
+ if (!featureFlags.REMOTE_TEMPLATE_CREATION_EXPERIENCE.enabled) {
+ filteredTemplates = filteredTemplates.filter((template: BotTemplate) => {
+ if (template.path) {
+ return template;
+ }
+ });
+ }
return filteredTemplates;
},
});
diff --git a/Composer/packages/lib/shared/src/featureFlagUtils/index.ts b/Composer/packages/lib/shared/src/featureFlagUtils/index.ts
index 62507fa2f8..a624678f6a 100644
--- a/Composer/packages/lib/shared/src/featureFlagUtils/index.ts
+++ b/Composer/packages/lib/shared/src/featureFlagUtils/index.ts
@@ -14,7 +14,7 @@ export type FeatureFlag = {
enabled: boolean;
};
-export type FeatureFlagKey = 'VA_CREATION' | 'FORM_DIALOG';
+export type FeatureFlagKey = 'VA_CREATION' | 'FORM_DIALOG' | 'REMOTE_TEMPLATE_CREATION_EXPERIENCE';
export type FeatureFlagMap = Record;
@@ -22,7 +22,7 @@ export const getDefaultFeatureFlags = (): FeatureFlagMap => ({
VA_CREATION: {
displayName: formatMessage('VA Creation'),
description: formatMessage('VA template made available in new bot flow.'),
- isHidden: false,
+ isHidden: true,
enabled: false,
},
FORM_DIALOG: {
@@ -31,4 +31,12 @@ export const getDefaultFeatureFlags = (): FeatureFlagMap => ({
isHidden: true,
enabled: false,
},
+ REMOTE_TEMPLATE_CREATION_EXPERIENCE: {
+ displayName: formatMessage('Remote templates'),
+ description: formatMessage(
+ 'If turned on then externally stored templates will be selectable in the new bot flow template list'
+ ),
+ isHidden: true,
+ enabled: false,
+ },
});
diff --git a/Composer/packages/server/package.json b/Composer/packages/server/package.json
index d421c48b75..d7441653a5 100644
--- a/Composer/packages/server/package.json
+++ b/Composer/packages/server/package.json
@@ -62,6 +62,7 @@
"@bfc/lg-languageserver": "*",
"@bfc/lu-languageserver": "*",
"@bfc/shared": "*",
+ "@microsoft/bf-dialog": "4.11.0-dev.20201025.69cf2b9",
"@microsoft/bf-dispatcher": "^4.11.0-beta.20201016.393c6b2",
"@microsoft/bf-generate-library": "^4.10.0-daily.20201026.178799",
"@microsoft/bf-lu": "^4.11.0-rc.20201030.a9f9b96",
diff --git a/Composer/packages/server/src/controllers/__tests__/eject.test.ts b/Composer/packages/server/src/controllers/__tests__/eject.test.ts
index eb621a17d9..d7ffe661d8 100644
--- a/Composer/packages/server/src/controllers/__tests__/eject.test.ts
+++ b/Composer/packages/server/src/controllers/__tests__/eject.test.ts
@@ -51,6 +51,7 @@ beforeAll(async () => {
name: 'C#',
startCommand: 'dotnet run --project azurewebapp',
path: './',
+ identifyManifest: jest.fn(),
eject: jest.fn(),
build: jest.fn(),
run: jest.fn(),
diff --git a/Composer/packages/server/src/controllers/project.ts b/Composer/packages/server/src/controllers/project.ts
index 33c1410db3..6fdae39dd1 100644
--- a/Composer/packages/server/src/controllers/project.ts
+++ b/Composer/packages/server/src/controllers/project.ts
@@ -6,6 +6,7 @@ import * as fs from 'fs';
import { Request, Response } from 'express';
import { Archiver } from 'archiver';
import { ExtensionContext } from '@bfc/extension';
+import { SchemaMerger } from '@microsoft/bf-dialog/lib/library/schemaMerger';
import log from '../logger';
import { BotProjectService } from '../services/project';
@@ -54,6 +55,33 @@ async function createProject(req: Request, res: Response) {
await AssetService.manager.copyBoilerplate(currentProject.dataDir, currentProject.fileStorage);
if (currentProject !== undefined) {
+ if (currentProject.settings?.runtime?.customRuntime === true) {
+ const runtime = ExtensionContext.getRuntimeByProject(currentProject);
+ const runtimePath = currentProject.settings.runtime.path;
+
+ if (!fs.existsSync(runtimePath)) {
+ await runtime.eject(currentProject, currentProject.fileStorage);
+ }
+
+ // install all dependencies and build the app
+ await runtime.build(runtimePath, currentProject);
+
+ const manifestFile = runtime.identifyManifest(runtimePath);
+
+ // run the merge command to merge all package dependencies from the template to the bot project
+ const realMerge = new SchemaMerger(
+ [manifestFile],
+ Path.join(currentProject.dataDir, 'schemas/sdk'),
+ Path.join(currentProject.dataDir, 'dialogs/imported'),
+ false,
+ false,
+ console.log,
+ console.warn,
+ console.error
+ );
+
+ await realMerge.merge();
+ }
await currentProject.updateBotInfo(name, description, preserveRoot);
if (schemaUrl) {
await currentProject.saveSchemaToProject(schemaUrl, locationRef.path);
@@ -367,7 +395,7 @@ async function checkBoilerplateVersion(req: Request, res: Response) {
const currentProject = await BotProjectService.getProjectById(projectId, user);
if (currentProject !== undefined) {
- const latestVersion = AssetService.manager.getBoilerplateCurrentVersion();
+ const latestVersion = await AssetService.manager.getBoilerplateCurrentVersion();
const currentVersion = await AssetService.manager.getBoilerplateVersionFromProject(currentProject);
const updateRequired =
(latestVersion && currentVersion && latestVersion > currentVersion) || // versions are present in both locations, latest is newer
diff --git a/Composer/packages/server/src/locales/en-US.json b/Composer/packages/server/src/locales/en-US.json
index b02415fd27..29c2613422 100644
--- a/Composer/packages/server/src/locales/en-US.json
+++ b/Composer/packages/server/src/locales/en-US.json
@@ -41,6 +41,9 @@
"a_valid_url_should_start_with_http_or_https_327b1a30": {
"message": "A valid URL should start with http:// or https://"
},
+ "a_valid_url_should_start_with_http_or_https_d24b3591": {
+ "message": "A valid url should start with http:// or https://"
+ },
"about_70c18bba": {
"message": "About"
},
@@ -128,6 +131,9 @@
"add_a_welcome_message_9e1480b2": {
"message": "Add a welcome message"
},
+ "add_additional_url_bdfac25d": {
+ "message": "Add additional URL"
+ },
"add_alternative_phrasing_17e0304c": {
"message": "+ Add alternative phrasing"
},
@@ -227,6 +233,9 @@
"any_string_f22dc2e1": {
"message": "any string"
},
+ "append_choices_35c45a2d": {
+ "message": "Append choices"
+ },
"application_language_87691b6": {
"message": "Application Language"
},
@@ -611,6 +620,9 @@
"could_not_connect_to_storage_50411de0": {
"message": "Could not connect to storage."
},
+ "could_not_init_plugin_1f1c29cd": {
+ "message": "Could not init plugin"
+ },
"couldn_t_complete_the_update_a337a359": {
"message": "Couldn''t complete the update:"
},
@@ -683,6 +695,9 @@
"create_kb_from_url_or_file_49ad6671": {
"message": "Create KB from URL or file"
},
+ "create_knowledge_base_db6d66c4": {
+ "message": "Create knowledge base"
+ },
"create_knowledge_base_from_scratch_afe4d2a2": {
"message": "Create knowledge base from scratch"
},
@@ -1268,6 +1283,9 @@
"if_this_problem_persists_please_file_an_issue_on_6fbc8e2b": {
"message": "If this problem persists, please file an issue on"
},
+ "if_turned_on_then_externally_stored_templates_will_3f487651": {
+ "message": "If turned on then externally stored templates will be selectable in the new bot flow template list"
+ },
"if_you_already_have_a_luis_account_provide_the_inf_bede07a4": {
"message": "If you already have a LUIS account, provide the information below. If you do not have an account yet, create a (free) account first."
},
@@ -1403,6 +1421,9 @@
"learn_more_about_knowledge_base_sources_24369b09": {
"message": "Learn more about knowledge base sources. "
},
+ "learn_more_about_qna_maker_skus_998c567": {
+ "message": "Learn more about QnA Maker SKUs."
+ },
"learn_more_about_title_d1d3edbe": {
"message": "Learn more about { title }"
},
@@ -1799,6 +1820,9 @@
"open_notification_panel_5796edb3": {
"message": "Open notification panel"
},
+ "open_skills_page_for_configuration_details_a2a484ea": {
+ "message": "Open Skills page for configuration details"
+ },
"optional_221bcc9d": {
"message": "Optional"
},
@@ -1889,6 +1913,9 @@
"please_select_an_activity_type_92f4a8a1": {
"message": "Please select an activity type"
},
+ "populate_your_knowledge_base_bb2d3605": {
+ "message": "Populate your Knowledge Base"
+ },
"press_enter_to_add_this_item_or_tab_to_move_to_the_6beb8a14": {
"message": "press Enter to add this item or Tab to move to the next interactive element"
},
@@ -2069,6 +2096,9 @@
"regex_intent_is_already_defined_df095c1f": {
"message": "RegEx { intent } is already defined"
},
+ "regular_expression_855557bf": {
+ "message": "Regular Expression"
+ },
"regular_expression_recognizer_44664557": {
"message": "Regular expression recognizer"
},
@@ -2078,6 +2108,9 @@
"reloading_49d2f661": {
"message": "Reloading"
},
+ "remote_templates_a23c242d": {
+ "message": "Remote templates"
+ },
"remove_f47dc62a": {
"message": "Remove"
},
@@ -2315,6 +2348,9 @@
"skills_49cccd6a": {
"message": "Skills"
},
+ "skip_this_step_to_add_questions_and_answers_manual_ed1b9f80": {
+ "message": "Skip this step to add questions and answers manually after creation. The number of sources and file size you can add depends on the QnA service SKU you choose. "
+ },
"sorry_something_went_wrong_with_connecting_bot_run_7d6785e3": {
"message": "Sorry, something went wrong with connecting bot runtime"
},
@@ -2510,6 +2546,9 @@
"this_trigger_type_is_not_supported_by_the_regex_re_dc3eefa2": {
"message": "This trigger type is not supported by the RegEx recognizer. To ensure this trigger is fired, change the recognizer type."
},
+ "this_url_is_duplicated_a0768f44": {
+ "message": "This url is duplicated"
+ },
"this_version_of_the_content_is_out_of_date_and_you_5e878f29": {
"message": "This version of the content is out of date, and your last change was rejected. The content will be automatically refreshed."
},
@@ -2621,6 +2660,9 @@
"typing_activity_6b634ae": {
"message": "Typing activity"
},
+ "unable_to_determine_recognizer_type_from_data_valu_2960f526": {
+ "message": "Unable to determine recognizer type from data: { value }"
+ },
"undo_a7be8fef": {
"message": "Undo"
},
@@ -2672,6 +2714,9 @@
"updating_scripts_e17a5722": {
"message": "Updating scripts... "
},
+ "url_22a5f3b8": {
+ "message": "URL"
+ },
"url_8c4ff7d2": {
"message": "Url"
},
diff --git a/Composer/packages/server/src/models/asset/assetManager.ts b/Composer/packages/server/src/models/asset/assetManager.ts
index 76a614fb20..a5fa019605 100644
--- a/Composer/packages/server/src/models/asset/assetManager.ts
+++ b/Composer/packages/server/src/models/asset/assetManager.ts
@@ -3,9 +3,13 @@
import fs from 'fs';
import path from 'path';
+import { exec } from 'child_process';
+import { promisify } from 'util';
import find from 'lodash/find';
-import { UserIdentity, ExtensionContext } from '@bfc/extension';
+import { UserIdentity, ExtensionContext, BotTemplate, FileExtensions } from '@bfc/extension';
+import { mkdirs, readFile } from 'fs-extra';
+import rimraf from 'rimraf';
import log from '../../logger';
import { LocalDiskStorage } from '../storage/localDiskStorage';
@@ -16,6 +20,9 @@ import StorageService from '../../services/storage';
import { IFileStorage } from '../storage/interface';
import { BotProject } from '../bot/botProject';
+const execAsync = promisify(exec);
+const removeDirAndFiles = promisify(rimraf);
+
export class AssetManager {
public templateStorage: LocalDiskStorage;
private _botProjectFileTemplate;
@@ -52,13 +59,61 @@ export class AssetManager {
return ref;
}
+ private async getRemoteTemplate(template: BotTemplate, destinationPath: string) {
+ // install package
+ if (template.package) {
+ const { stderr: initErr } = await execAsync(
+ `dotnet new -i ${template.package.packageName}::${template.package.packageVersion}`
+ );
+ if (initErr) {
+ throw new Error(initErr);
+ }
+ const { stderr: initErr2 } = await execAsync(`dotnet new ${template.id}`, {
+ cwd: destinationPath,
+ });
+ if (initErr2) {
+ throw new Error(initErr2);
+ }
+ } else {
+ throw new Error('selected template has no local or external address');
+ }
+ }
+
private async copyDataFilesTo(templateId: string, dstDir: string, dstStorage: IFileStorage, locale?: string) {
const template = find(ExtensionContext.extensions.botTemplates, { id: templateId });
- if (template === undefined || template.path === undefined) {
+ if (template === undefined || (template.path === undefined && template.package === undefined)) {
throw new Error(`no such template with id ${templateId}`);
}
- // copy Composer data files
- await copyDir(template.path, this.templateStorage, dstDir, dstStorage);
+
+ let templateSrcPath = template.path;
+ const isHostedTemplate = !templateSrcPath;
+ if (isHostedTemplate) {
+ // create empty temp directory on server for holding externally hosted template src
+ templateSrcPath = path.resolve(__dirname, '../../../temp');
+ if (fs.existsSync(templateSrcPath)) {
+ await removeDirAndFiles(templateSrcPath);
+ }
+ await mkdirs(templateSrcPath, (err) => {
+ if (err) {
+ throw new Error('Error creating temp directory for external template storage');
+ }
+ });
+ await this.getRemoteTemplate(template, templateSrcPath);
+ }
+
+ if (templateSrcPath) {
+ // copy Composer data files
+ await copyDir(templateSrcPath, this.templateStorage, dstDir, dstStorage);
+
+ if (isHostedTemplate) {
+ try {
+ await removeDirAndFiles(templateSrcPath);
+ } catch (err) {
+ throw new Error('Issue deleting temp generated file for external template assets');
+ }
+ }
+ }
+
// if we have a locale override, copy those files over too
if (locale != null) {
const localePath = path.join(__dirname, '..', '..', '..', 'schemas', `sdk.${locale}.schema`);
@@ -76,7 +131,7 @@ export class AssetManager {
public async copyBoilerplate(dstDir: string, dstStorage: IFileStorage) {
for (const boilerplate of ExtensionContext.extensions.baseTemplates) {
const boilerplatePath = boilerplate.path;
- if (await this.templateStorage.exists(boilerplatePath)) {
+ if (boilerplatePath && (await this.templateStorage.exists(boilerplatePath))) {
await copyDir(boilerplatePath, this.templateStorage, dstDir, dstStorage);
}
}
@@ -104,24 +159,27 @@ export class AssetManager {
// return the current version of the boilerplate content, if one exists so specified
// this is based off of the first boilerplate template added to the app.
- public getBoilerplateCurrentVersion(): string | undefined {
+ public async getBoilerplateCurrentVersion(): Promise {
if (!ExtensionContext.extensions.baseTemplates.length) {
return undefined;
}
const boilerplate = ExtensionContext.extensions.baseTemplates[0];
- const location = Path.join(boilerplate.path, 'scripts', 'package.json');
- try {
- if (fs.existsSync(location)) {
- const raw = fs.readFileSync(location, 'utf8');
- const json = JSON.parse(raw);
- if (json && json.version) {
- return json.version;
- } else {
- return undefined;
+ if (boilerplate.path) {
+ const location = Path.join(boilerplate.path, 'scripts', 'package.json');
+ try {
+ if (fs.existsSync(location)) {
+ const raw = await readFile(location, 'utf8');
+
+ const json = JSON.parse(raw);
+ if (json && json.version) {
+ return json.version;
+ } else {
+ return undefined;
+ }
}
+ } catch (err) {
+ return undefined;
}
- } catch (err) {
- return undefined;
}
}
@@ -131,15 +189,17 @@ export class AssetManager {
}
const boilerplate = ExtensionContext.extensions.botTemplates[0];
- const location = Path.join(boilerplate.path, `${boilerplate.id}.botproj`);
- try {
- if (fs.existsSync(location)) {
- const raw = fs.readFileSync(location, 'utf8');
- const json = JSON.parse(raw);
- return json;
+ if (boilerplate.path) {
+ const location = Path.join(boilerplate.path, `${boilerplate.id + FileExtensions.BotProject}`);
+ try {
+ if (fs.existsSync(location)) {
+ const raw = fs.readFileSync(location, 'utf8');
+ const json = JSON.parse(raw);
+ return json;
+ }
+ } catch (err) {
+ return '';
}
- } catch (err) {
- return '';
}
}
}
diff --git a/Composer/packages/server/src/models/bot/botProject.ts b/Composer/packages/server/src/models/bot/botProject.ts
index 27ae3fbf26..b73383275d 100644
--- a/Composer/packages/server/src/models/bot/botProject.ts
+++ b/Composer/packages/server/src/models/bot/botProject.ts
@@ -205,6 +205,15 @@ export class BotProject implements IBotProject {
public getEnvSettings = async (obfuscate: boolean) => {
const settings = await this.settingManager.get(obfuscate);
+ // Resolve relative path for custom runtime if the path is relative
+ if (settings?.runtime?.customRuntime && settings.runtime.path && !Path.isAbsolute(settings.runtime.path)) {
+ const absolutePath = Path.resolve(this.dir, 'settings', settings.runtime.path);
+ if (fs.existsSync(absolutePath)) {
+ settings.runtime.path = absolutePath;
+ await this.updateEnvSettings(settings);
+ }
+ }
+
// fix old bot have no language settings
if (!settings?.defaultLanguage) {
settings.defaultLanguage = defaultLanguage;
diff --git a/Composer/packages/types/src/runtime.ts b/Composer/packages/types/src/runtime.ts
index 3ba1d7dee3..1da0fe28aa 100644
--- a/Composer/packages/types/src/runtime.ts
+++ b/Composer/packages/types/src/runtime.ts
@@ -37,11 +37,17 @@ export type BotTemplate = {
name: string;
description: string;
/* absolute path */
- path: string;
+ path?: string;
/* tags for further grouping and search secenario */
tags?: string[];
/* list of supported runtime versions */
support?: string[];
+ package?: {
+ packageName: string;
+ packageSource: string;
+ packageVersion: string;
+ };
+ index?: number;
};
export type RuntimeTemplate = {
@@ -53,6 +59,8 @@ export type RuntimeTemplate = {
run: (project: IBotProject, localDisk?: any) => Promise;
+ identifyManifest: (runtimePath: string) => string;
+
/** build for deploy method */
buildDeploy: (
runtimePath: string,
diff --git a/Composer/packages/types/src/server.ts b/Composer/packages/types/src/server.ts
index 3dd18f023b..08a3bed1b7 100644
--- a/Composer/packages/types/src/server.ts
+++ b/Composer/packages/types/src/server.ts
@@ -4,18 +4,6 @@ import { Skill, FileInfo } from './indexers';
import { IDiagnostic } from './diagnostic';
import { DialogSetting } from './settings';
-export type ProjectTemplate = {
- id: string;
- name: string;
- description: string;
- /* absolute path */
- path: string;
- /* tags for further grouping and search secenario */
- tags?: string[];
- /* list of supported runtime versions */
- support?: string[];
-};
-
export type IBotProject = {
fileStorage: any;
dir: string;
diff --git a/Composer/yarn.lock b/Composer/yarn.lock
index dce1056d3f..29479ab637 100644
--- a/Composer/yarn.lock
+++ b/Composer/yarn.lock
@@ -7,6 +7,15 @@
resolved "https://botbuilder.myget.org/F/botframework-cli/npm/7zip-bin/-/7zip-bin-5.0.3.tgz#bc5b5532ecafd923a61f2fb097e3b108c0106a3f"
integrity sha1-vFtVMuyv2SOmHy+wl+OxCMAQaj8=
+"@apidevtools/json-schema-ref-parser@^9.0.1":
+ version "9.0.6"
+ resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.6.tgz#5d9000a3ac1fd25404da886da6b266adcd99cf1c"
+ integrity sha512-M3YgsLjI0lZxvrpeGVk9Ap032W6TPQkH6pRAZz81Ac3WUNF79VQooAFnp8umjvVzUmD93NkogxEwbSce7qMsUg==
+ dependencies:
+ "@jsdevtools/ono" "^7.1.3"
+ call-me-maybe "^1.0.1"
+ js-yaml "^3.13.1"
+
"@azure/cognitiveservices-luis-authoring@4.0.0-preview.1":
version "4.0.0-preview.1"
resolved "https://botbuilder.myget.org/F/botframework-cli/npm/@azure/cognitiveservices-luis-authoring/-/@azure/cognitiveservices-luis-authoring-4.0.0-preview.1.tgz#79de764893dc997d95713bb6a0487d887dc78f40"
@@ -2965,6 +2974,26 @@
"@types/yargs" "^15.0.0"
chalk "^4.0.0"
+"@jsdevtools/ono@^7.1.3":
+ version "7.1.3"
+ resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796"
+ integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==
+
+"@microsoft/bf-cli-command@4.11.0-dev.20201025.69cf2b9":
+ version "4.11.0-dev.20201025.69cf2b9"
+ resolved "https://registry.yarnpkg.com/@microsoft/bf-cli-command/-/bf-cli-command-4.11.0-dev.20201025.69cf2b9.tgz#286b9dfef6483a55562baf4ebf7a0d99a43075e4"
+ integrity sha512-jhcpVBrFrFepevPZlP9iGJrUPh30E/L8yHr5wvX6jcSt/7RSVD+A7DIShDO+b8n45ii+8ZxVGqEGv7aN5ggp6g==
+ dependencies:
+ "@oclif/command" "~1.5.19"
+ "@oclif/config" "~1.13.3"
+ "@oclif/errors" "~1.2.2"
+ applicationinsights "^1.0.8"
+ chalk "2.4.1"
+ cli-ux "~4.9.3"
+ debug "^4.1.1"
+ fs-extra "^7.0.1"
+ tslib "^2.0.3"
+
"@microsoft/bf-cli-command@^4.10.0-preview.141651":
version "4.10.0-preview.141651"
resolved "https://botbuilder.myget.org/F/botframework-cli/npm/@microsoft/bf-cli-command/-/@microsoft/bf-cli-command-4.10.0-preview.141651.tgz#680875f716285fb8658da8098a0ee524b07c5765"
@@ -2980,6 +3009,33 @@
fs-extra "^7.0.1"
tslib "~1.10.0"
+"@microsoft/bf-dialog@4.11.0-dev.20201025.69cf2b9":
+ version "4.11.0-dev.20201025.69cf2b9"
+ resolved "https://registry.yarnpkg.com/@microsoft/bf-dialog/-/bf-dialog-4.11.0-dev.20201025.69cf2b9.tgz#7f33e2b4d52e355d1f5888b9d1f341ae32fe90c3"
+ integrity sha512-gzBRwKSEkHXgPN9bB5ttuEORRbK7o6Py+7P9JKYQjDrytt2C7ZSqKn7UtVm8/OBO8BDwu9EMONpfq2Ep3FPUtw==
+ dependencies:
+ "@apidevtools/json-schema-ref-parser" "^9.0.1"
+ "@microsoft/bf-cli-command" "4.11.0-dev.20201025.69cf2b9"
+ "@oclif/command" "~1.5.19"
+ "@oclif/config" "~1.13.3"
+ "@oclif/errors" "~1.2.2"
+ "@snyk/nuget-semver" "~1.3.0"
+ "@types/lru-cache" "^5.1.0"
+ "@types/xml2js" "^0.4.4"
+ ajv "^6.12.2"
+ chalk "^2.4.2"
+ clone "^2.1.2"
+ fs-extra "^8.1.0"
+ get-uri "~3.0.2"
+ globby "^11.0.0"
+ json-ptr "~1.3.0"
+ json-schema-merge-allof "~0.7.0"
+ os "~0.1.1"
+ path "^0.12.7"
+ seedrandom "~3.0.5"
+ tslib "^2.0.3"
+ xml2js "^0.4.19"
+
"@microsoft/bf-dispatcher@^4.11.0-beta.20201016.393c6b2":
version "4.11.0-beta.20201016.393c6b2"
resolved "https://registry.yarnpkg.com/@microsoft/bf-dispatcher/-/bf-dispatcher-4.11.0-beta.20201016.393c6b2.tgz#7dab414752f8711fed37ae5625c38fdd0192eddb"
@@ -3243,6 +3299,11 @@
dependencies:
"@sinonjs/commons" "^1.7.0"
+"@snyk/nuget-semver@~1.3.0":
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/@snyk/nuget-semver/-/nuget-semver-1.3.0.tgz#a74ef5340dcada3bc4b3a019b7950738df51199c"
+ integrity sha512-1CL4BzQKFPwml+BBefKuM0v9UfsFOgSKzrTfYpUkiSNkUVsMxXK37LlT3HtG7zGpMxXiG+XXfPopo/96Z0wfNg==
+
"@svgr/babel-plugin-add-jsx-attribute@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-4.0.0.tgz#5acf239cd2747b1a36ec7e708de05d914cb9b948"
@@ -3416,6 +3477,11 @@
"@testing-library/dom" "^7.2.2"
"@types/testing-library__react" "^10.0.1"
+"@tootallnate/once@1":
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
+ integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
+
"@types/anymatch@*":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a"
@@ -4068,6 +4134,13 @@
dependencies:
"@types/node" "*"
+"@types/xml2js@^0.4.4":
+ version "0.4.5"
+ resolved "https://registry.yarnpkg.com/@types/xml2js/-/xml2js-0.4.5.tgz#d21759b056f282d9c7066f15bbf5c19b908f22fa"
+ integrity sha512-yohU3zMn0fkhlape1nxXG2bLEGZRc1FeqF80RoHaYXJN7uibaauXfhzhOJr1Xh36sn+/tx21QAOf07b/xYVk1w==
+ dependencies:
+ "@types/node" "*"
+
"@types/xmldom@^0.1.29":
version "0.1.29"
resolved "https://botbuilder.myget.org/F/botbuilder-v4-js-daily/npm/@types/xmldom/-/@types/xmldom-0.1.29.tgz#c4428b0ca86d3b881475726fd94980b38a27c381"
@@ -8107,6 +8180,11 @@ dashdash@^1.12.0:
dependencies:
assert-plus "^1.0.0"
+data-uri-to-buffer@3:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz#594b8973938c5bc2c33046535785341abc4f3636"
+ integrity sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==
+
data-urls@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b"
@@ -8140,6 +8218,13 @@ debug@3.1.0, debug@=3.1.0:
dependencies:
ms "2.0.0"
+debug@4:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1"
+ integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==
+ dependencies:
+ ms "2.1.2"
+
debug@4.1.1, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
@@ -9839,6 +9924,11 @@ file-loader@4.2.0:
loader-utils "^1.2.3"
schema-utils "^2.0.0"
+file-uri-to-path@2:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-2.0.0.tgz#7b415aeba227d575851e0a5b0c640d7656403fba"
+ integrity sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg==
+
filelist@^1.0.1:
version "1.0.1"
resolved "https://botbuilder.myget.org/F/botframework-cli/npm/filelist/-/filelist-1.0.1.tgz#f10d1a3ae86c1694808e8f20906f43d4c9132dbb"
@@ -10275,6 +10365,14 @@ fsevents@~2.1.2:
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e"
integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==
+ftp@^0.3.10:
+ version "0.3.10"
+ resolved "https://registry.yarnpkg.com/ftp/-/ftp-0.3.10.tgz#9197d861ad8142f3e63d5a83bfe4c59f7330885d"
+ integrity sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=
+ dependencies:
+ readable-stream "1.1.x"
+ xregexp "2.0.0"
+
function-bind@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
@@ -10389,6 +10487,18 @@ get-stream@^5.0.0, get-stream@^5.1.0:
dependencies:
pump "^3.0.0"
+get-uri@~3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-3.0.2.tgz#f0ef1356faabc70e1f9404fa3b66b2ba9bfc725c"
+ integrity sha512-+5s0SJbGoyiJTZZ2JTpFPLMPSch72KEqGOTvQsBqg0RBWvwhWUSYZFAtz3TPW0GXJuLBJPts1E241iHg+VRfhg==
+ dependencies:
+ "@tootallnate/once" "1"
+ data-uri-to-buffer "3"
+ debug "4"
+ file-uri-to-path "2"
+ fs-extra "^8.1.0"
+ ftp "^0.3.10"
+
get-value@^2.0.3, get-value@^2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
@@ -12561,6 +12671,13 @@ json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2:
resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==
+json-ptr@~1.3.0:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/json-ptr/-/json-ptr-1.3.2.tgz#17f45b322a843b1f2fbcc9b45132bd9b3ba8cd38"
+ integrity sha512-tFH40YQ+lG7mgYYM1kGZOhQngO4SbOEHZJlA4W+NtetWZ20EUU3BPU+30uWRKumuAJoSo5eqrsXD2h72ioS8ew==
+ dependencies:
+ tslib "^2.0.0"
+
json-schema-compare@^0.2.2:
version "0.2.2"
resolved "https://botbuilder.myget.org/F/botbuilder-v4-js-daily/npm/json-schema-compare/-/json-schema-compare-0.2.2.tgz#dd601508335a90c7f4cfadb6b2e397225c908e56"
@@ -12584,6 +12701,15 @@ json-schema-merge-allof@^0.6.0:
json-schema-compare "^0.2.2"
lodash "^4.17.4"
+json-schema-merge-allof@~0.7.0:
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/json-schema-merge-allof/-/json-schema-merge-allof-0.7.0.tgz#84d3e8c3e03d3060014286958eb8834fa9d76304"
+ integrity sha512-kvsuSVnl1n5xnNEu5ed4o8r8ujSA4/IgRtHmpgfMfa7FOMIRAzN4F9qbuklouTn5J8bi83y6MQ11n+ERMMTXZg==
+ dependencies:
+ compute-lcm "^1.1.0"
+ json-schema-compare "^0.2.2"
+ lodash "^4.17.4"
+
json-schema-ref-parser@^7.1.0, json-schema-ref-parser@^7.1.3:
version "7.1.4"
resolved "https://botbuilder.myget.org/F/botbuilder-v4-js-daily/npm/json-schema-ref-parser/-/json-schema-ref-parser-7.1.4.tgz#abb3f2613911e9060dc2268477b40591753facf0"
@@ -13827,6 +13953,11 @@ ms@2.1.1, ms@^2.1.1:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
+ms@2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
+ integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
+
multicast-dns-service-types@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901"
@@ -14560,6 +14691,11 @@ os-tmpdir@^1.0.0, os-tmpdir@~1.0.2:
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
+os@~0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/os/-/os-0.1.1.tgz#208845e89e193ad4d971474b93947736a56d13f3"
+ integrity sha1-IIhF6J4ZOtTZcUdLk5R3NqVtE/M=
+
osenv@^0.1.4:
version "0.1.5"
resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410"
@@ -16421,6 +16557,16 @@ read-text-file@^1.1.0:
string_decoder "~1.1.1"
util-deprecate "~1.0.1"
+readable-stream@1.1.x:
+ version "1.1.14"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
+ integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk=
+ dependencies:
+ core-util-is "~1.0.0"
+ inherits "~2.0.1"
+ isarray "0.0.1"
+ string_decoder "~0.10.x"
+
readable-stream@^3.0.6, readable-stream@^3.1.1:
version "3.2.0"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.2.0.tgz#de17f229864c120a9f56945756e4f32c4045245d"
@@ -20148,6 +20294,11 @@ xmlhttprequest@1:
resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc"
integrity sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=
+xregexp@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943"
+ integrity sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=
+
xregexp@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.3.0.tgz#7e92e73d9174a99a59743f67a4ce879a04b5ae50"
diff --git a/extensions/runtimes/src/index.ts b/extensions/runtimes/src/index.ts
index 43e3ced362..a67fa2a38e 100644
--- a/extensions/runtimes/src/index.ts
+++ b/extensions/runtimes/src/index.ts
@@ -39,6 +39,9 @@ export default async (composer: any): Promise => {
}
composer.log('FINISHED BUILDING!');
},
+ identifyManifest: (runtimePath: string): string => {
+ return path.join(runtimePath, 'azurewebapp', 'Microsoft.BotFramework.Composer.WebApp.csproj');
+ },
run: async (project: any, localDisk: IFileStorage) => {
composer.log('RUN THIS C# PROJECT!');
},
@@ -182,6 +185,9 @@ export default async (composer: any): Promise => {
}
composer.log('BUILD COMPLETE');
},
+ identifyManifest: (runtimePath: string): string => {
+ return path.join(runtimePath, 'Microsoft.BotFramework.Composer.WebApp.csproj');
+ },
run: async (project: any, localDisk: IFileStorage) => {
// do stuff
},
diff --git a/extensions/samples/package.json b/extensions/samples/package.json
index 9305660613..ea180714dc 100644
--- a/extensions/samples/package.json
+++ b/extensions/samples/package.json
@@ -11,6 +11,7 @@
"author": "",
"license": "ISC",
"dependencies": {
+ "@botframework-composer/types": "file:../../Composer/packages/types",
"path": "^0.12.7",
"portfinder": "^1.0.26",
"rimraf": "^3.0.2",
diff --git a/extensions/samples/src/index.ts b/extensions/samples/src/index.ts
index 75e1175527..bdab71868e 100644
--- a/extensions/samples/src/index.ts
+++ b/extensions/samples/src/index.ts
@@ -3,6 +3,7 @@
import path from 'path';
import fs from 'fs';
+import { BotTemplate } from '@botframework-composer/types';
const samplesDir = path.resolve(__dirname, '../assets/projects');
const boilerplateDir = path.resolve(__dirname, '../assets/shared');
@@ -68,9 +69,22 @@ const samplesRegitry = {
},
};
-function getSamples(): any[] {
+function getRemoteSamples(): BotTemplate[] {
+ return [{
+ id: 'conversationalcore',
+ name: 'Conversational Core',
+ description: 'A hosted template that provides a root bot extended by common .lg packages',
+ package: {
+ packageName: 'Microsoft.ConversationalCore.Template',
+ packageSource: 'nuget',
+ packageVersion: '0.0.1-preview5'
+ }
+ }]
+}
+
+function getSamples(): BotTemplate[] {
const subPaths = fs.readdirSync(samplesDir);
- const samples = [];
+ let samples: BotTemplate[] = [];
for (const subPath of subPaths) {
const fullPath = samplesDir + '/' + subPath;
if (!fs.statSync(fullPath).isDirectory()) {
@@ -79,12 +93,15 @@ function getSamples(): any[] {
// only looking for directories
const dirname = subPath;
- let sample = { id: dirname, name: dirname, description: dirname, path: fullPath, ...samplesRegitry['*'] };
+ let sample: BotTemplate = { id: dirname, name: dirname, description: dirname, path: fullPath, ...samplesRegitry['*'] };
if (samplesRegitry[sample.id]) {
sample = { ...sample, ...samplesRegitry[sample.id] };
}
samples.push(sample);
}
+
+ samples = samples.concat(getRemoteSamples());
+
samples.sort((a, b) => {
if (a.index && b.index) {
return a.index - b.index;
diff --git a/extensions/samples/yarn.lock b/extensions/samples/yarn.lock
index 5e8e3282ee..17ee65b0d8 100644
--- a/extensions/samples/yarn.lock
+++ b/extensions/samples/yarn.lock
@@ -2,11 +2,79 @@
# yarn lockfile v1
+"@botframework-composer/types@file:../../Composer/packages/types":
+ version "0.0.2"
+ dependencies:
+ "@types/express" "^4.16.1"
+ json-schema "^0.2.5"
+
+"@types/body-parser@*":
+ version "1.19.0"
+ resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.0.tgz#0685b3c47eb3006ffed117cdd55164b61f80538f"
+ integrity sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==
+ dependencies:
+ "@types/connect" "*"
+ "@types/node" "*"
+
+"@types/connect@*":
+ version "3.4.33"
+ resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.33.tgz#31610c901eca573b8713c3330abc6e6b9f588546"
+ integrity sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==
+ dependencies:
+ "@types/node" "*"
+
+"@types/express-serve-static-core@*":
+ version "4.17.13"
+ resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.13.tgz#d9af025e925fc8b089be37423b8d1eac781be084"
+ integrity sha512-RgDi5a4nuzam073lRGKTUIaL3eF2+H7LJvJ8eUnCI0wA6SNjXc44DCmWNiTLs/AZ7QlsFWZiw/gTG3nSQGL0fA==
+ dependencies:
+ "@types/node" "*"
+ "@types/qs" "*"
+ "@types/range-parser" "*"
+
+"@types/express@^4.16.1":
+ version "4.17.8"
+ resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.8.tgz#3df4293293317e61c60137d273a2e96cd8d5f27a"
+ integrity sha512-wLhcKh3PMlyA2cNAB9sjM1BntnhPMiM0JOBwPBqttjHev2428MLEB4AYVN+d8s2iyCVZac+o41Pflm/ZH5vLXQ==
+ dependencies:
+ "@types/body-parser" "*"
+ "@types/express-serve-static-core" "*"
+ "@types/qs" "*"
+ "@types/serve-static" "*"
+
+"@types/mime@*":
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.3.tgz#c893b73721db73699943bfc3653b1deb7faa4a3a"
+ integrity sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==
+
+"@types/node@*":
+ version "14.14.3"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.3.tgz#e1c09064121f894baaad2bd9f12ce4a41bffb274"
+ integrity sha512-33/L34xS7HVUx23e0wOT2V1qPF1IrHgQccdJVm9uXGTB9vFBrrzBtkQymT8VskeKOxjz55MSqMv0xuLq+u98WQ==
+
"@types/node@^14.11.8":
version "14.11.8"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.11.8.tgz#fe2012f2355e4ce08bca44aeb3abbb21cf88d33f"
integrity sha512-KPcKqKm5UKDkaYPTuXSx8wEP7vE9GnuaXIZKijwRYcePpZFDVuy2a57LarFKiORbHOuTOOwYzxVxcUzsh2P2Pw==
+"@types/qs@*":
+ version "6.9.5"
+ resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.5.tgz#434711bdd49eb5ee69d90c1d67c354a9a8ecb18b"
+ integrity sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ==
+
+"@types/range-parser@*":
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c"
+ integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==
+
+"@types/serve-static@*":
+ version "1.13.6"
+ resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.6.tgz#866b1b8dec41c36e28c7be40ac725b88be43c5c1"
+ integrity sha512-nuRJmv7jW7VmCVTn+IgYDkkbbDGyIINOeu/G0d74X3lm6E5KfMeQPJhxIt1ayQeQB3cSxvYs1RA/wipYoFB4EA==
+ dependencies:
+ "@types/mime" "*"
+ "@types/node" "*"
+
async@^2.6.2:
version "2.6.3"
resolved "https://registry.npmjs.org/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
@@ -74,6 +142,11 @@ inherits@2.0.3:
resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
+json-schema@^0.2.5:
+ version "0.2.5"
+ resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.5.tgz#97997f50972dd0500214e208c407efa4b5d7063b"
+ integrity sha512-gWJOWYFrhQ8j7pVm0EM8Slr+EPVq1Phf6lvzvD/WCeqkrx/f2xBI0xOsRRS9xCn3I4vKtP519dvs3TP09r24wQ==
+
lodash@^4.17.14:
version "4.17.17"
resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.17.tgz#d9018b3acc57a95c9dcf4a45c6b63b877b6c2d45"