42 |
43 | To register the device with your Amazon account, open Amazon account linking in your browser.
44 | After you link your account, come back to this page to complete device registration.
45 |
46 |
47 | If an error occurs during the account linking process, return to Create device to verify your product information.
49 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/media/deviceRegistry/deviceRegistryInProgress.js:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 |
7 | const vscode = acquireVsCodeApi();
8 | const DEVICE_MESSAGE_TYPE = {
9 | USER_CODE: "userCode",
10 | RETRY: "retry",
11 | RETRY_USER_CODE: "retryForUserCode",
12 | TO_FIRST_PAGE: "toFirstPage",
13 | };
14 |
15 | window.onload = function () {
16 | //Read user_code
17 | const label = document.getElementById("userCode");
18 | const previousState = vscode.getState();
19 | label.innerHTML = previousState.userCode;
20 | validTime.innerText = "Valid until " + previousState.expiredTime;
21 | document.getElementById("externalLink").href = previousState.externalLink;
22 |
23 | refresh.onclick = retryForUserCode;
24 | firstPage.onclick = backToFirstPage;
25 | firstPageLink.onclick = backToFirstPage;
26 | // eslint-disable-next-line @typescript-eslint/no-misused-promises
27 | window.addEventListener("message", async (event) => {
28 | const message = event.data;
29 | if (message.type === DEVICE_MESSAGE_TYPE.USER_CODE) {
30 | const expiredTime = getExpiredTime(message.response.expires_in);
31 | const state = vscode.getState() || {};
32 | state["userCode"] = message.response.user_code;
33 | state["expiredTime"] = expiredTime;
34 | state["externalLink"] = message.response.verification_uri;
35 | await new Promise(() => {
36 | vscode.setState(state);
37 | const label = document.getElementById("userCode");
38 | label.innerHTML = message.response.user_code;
39 | validTime.innerText = "Valid until " + expiredTime;
40 | document.getElementById("externalLink").href = message.response.verification_uri;
41 | });
42 | } else if (message.type === DEVICE_MESSAGE_TYPE.RETRY) {
43 | validTime.innerText = message.information.toString();
44 | }
45 | });
46 | };
47 |
48 | function retryForUserCode() {
49 | validTime.innerText = "";
50 | vscode.postMessage({
51 | type: DEVICE_MESSAGE_TYPE.RETRY_USER_CODE,
52 | });
53 | }
54 |
55 | function backToFirstPage() {
56 | vscode.postMessage({
57 | type: DEVICE_MESSAGE_TYPE.TO_FIRST_PAGE,
58 | });
59 | }
60 |
61 | function getExpiredTime(expiresTime) {
62 | const datetime = new Date();
63 | datetime.setSeconds(datetime.getSeconds() + expiresTime);
64 | const hour = datetime.getHours();
65 | const minute = datetime.getMinutes();
66 | const expiredTime = (hour > 9 ? hour.toString() : `0${hour}`) + ":" + (minute > 9 ? minute.toString() : `0${minute}`);
67 | return expiredTime;
68 | }
69 |
--------------------------------------------------------------------------------
/media/docs/create_apl_doc.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexa/ask-toolkit-for-vscode/2fd1033f594a3281e1612d51d0c216a14e5e344d/media/docs/create_apl_doc.gif
--------------------------------------------------------------------------------
/media/docs/create_self_hosted_skill.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexa/ask-toolkit-for-vscode/2fd1033f594a3281e1612d51d0c216a14e5e344d/media/docs/create_self_hosted_skill.gif
--------------------------------------------------------------------------------
/media/docs/create_skill.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexa/ask-toolkit-for-vscode/2fd1033f594a3281e1612d51d0c216a14e5e344d/media/docs/create_skill.gif
--------------------------------------------------------------------------------
/media/docs/deploy_hosted_skill.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexa/ask-toolkit-for-vscode/2fd1033f594a3281e1612d51d0c216a14e5e344d/media/docs/deploy_hosted_skill.gif
--------------------------------------------------------------------------------
/media/docs/deploy_self_hosted_skill.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexa/ask-toolkit-for-vscode/2fd1033f594a3281e1612d51d0c216a14e5e344d/media/docs/deploy_self_hosted_skill.gif
--------------------------------------------------------------------------------
/media/docs/deploy_skill.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexa/ask-toolkit-for-vscode/2fd1033f594a3281e1612d51d0c216a14e5e344d/media/docs/deploy_skill.gif
--------------------------------------------------------------------------------
/media/docs/download_self_hosted_skill.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexa/ask-toolkit-for-vscode/2fd1033f594a3281e1612d51d0c216a14e5e344d/media/docs/download_self_hosted_skill.gif
--------------------------------------------------------------------------------
/media/docs/local_debugging.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexa/ask-toolkit-for-vscode/2fd1033f594a3281e1612d51d0c216a14e5e344d/media/docs/local_debugging.gif
--------------------------------------------------------------------------------
/media/docs/sign_in_flow.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexa/ask-toolkit-for-vscode/2fd1033f594a3281e1612d51d0c216a14e5e344d/media/docs/sign_in_flow.gif
--------------------------------------------------------------------------------
/media/images/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Amazon, Alexa, and all related logos (the “Marks”) are trademarks of Amazon.com, or its affiliates.
2 | Subject to your compliance with the terms of the Amazon Developer Services Agreement,
3 | available at https://developer.amazon.com/support/legal/da, and the Trademark Guidelines,
4 | available at https://developer.amazon.com/support/legal/tuabg#trademark, you may use the Marks solely
5 | for the purpose expressly authorized in the Alexa Skills Toolkit for VS Code.
--------------------------------------------------------------------------------
/media/images/ask_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexa/ask-toolkit-for-vscode/2fd1033f594a3281e1612d51d0c216a14e5e344d/media/images/ask_icon.png
--------------------------------------------------------------------------------
/media/initialLogin/initialLogin.html:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
12 | Sign in
13 |
52 |
61 |
62 |
63 |
64 |
65 |
Sign in
66 |
67 |
68 |
69 |
70 | To start using the Alexa Skills Kit (ASK) Toolkit you first need to sign in with your Amazon Developer Account
71 | and grant permission to access your skills.
72 |
19 | Use the page opened in your browser to log in with your Amazon Developer Account and grant the toolkit
20 | permission to access your skill resources.
21 |
22 |
23 |
--------------------------------------------------------------------------------
/media/profileManager/profileManager.html:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
12 | Profile Manager
13 |
14 |
15 |
16 |
17 |
18 |
19 |
Profile manager
20 |
21 |
22 |
23 |
24 | The profile manager guides you through logging in with your Amazon Developer Account and granting permission for
25 | the toolkit to access your Alexa Skills resources. The toolkit supports storing credentials under multiple profiles,
26 | useful if you are working across multiple developer accounts. The currently in-use profile is displayed on the toolkit
27 | status bar and can be changed at any time.
28 |
29 | Once you select a new or existing profile, your web browser will be opened to a Login with Amazon prompt and
30 | you will be guided through the process of signing in and granting permission to the toolkit.
31 |
24 | The Skill Information page provides some basic information about your skill. You can check and confirm
25 | the skill metadata before going ahead with cloning the skill for local development.
26 |
27 |
28 |
29 |
30 |
${skillName}
31 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/media/skillInfo/skillInformation.js:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | /* eslint-disable @typescript-eslint/explicit-function-return-type */
7 | /* eslint-disable no-undef */
8 | const vscode = acquireVsCodeApi();
9 |
10 | window.onload = function () {
11 | document.getElementById("cloneSkill").onsubmit = function cloneSkill() {
12 | vscode.postMessage();
13 | return false;
14 | };
15 |
16 | const skillLocaleNameTable = document.getElementById("skillLocaleNames");
17 | const tableBody = skillLocaleNameTable.tBodies[0];
18 |
19 | let localesInfoArray = document.getElementById("localeNameMap").value;
20 | localesInfoArray = JSON.parse(localesInfoArray.replace(/'/g, '"'));
21 |
22 | localesInfoArray.forEach((localeInfo) => {
23 | const row = document.createElement("tr");
24 |
25 | const column1 = document.createElement("td");
26 | column1.appendChild(document.createTextNode(localeInfo[0]));
27 | row.appendChild(column1);
28 |
29 | const column2 = document.createElement("td");
30 | column2.appendChild(document.createTextNode(localeInfo[1]));
31 | row.appendChild(column2);
32 |
33 | tableBody.appendChild(row);
34 | });
35 | };
36 |
--------------------------------------------------------------------------------
/src/acdlServer/keywordsProvider.ts:
--------------------------------------------------------------------------------
1 | import {ACDLLexer} from "@alexa/acdl/dist/cjs/syntax/ACDLLexer";
2 |
3 | // valid keywords tart with a-zA-Z, end with a-zA-Z, no space
4 | const validKeywordCharacters = /^[a-zA-Z]+$/;
5 |
6 | // keywords that are excluded from the list
7 | const excludedKeywords = ["multimodal"];
8 |
9 | // extra keywords that are not part of the ACDLLexer
10 | const extraKeywords = ["confirmAction", "confirmArgs", "ensure", "expect", "response", "skill", "utterances"];
11 |
12 | // TODO: How to get the builtin expressions?
13 | // eslint-disable-next-line @typescript-eslint/dot-notation
14 | export const KEYWORDS = ACDLLexer["_LITERAL_NAMES"].reduce((acc, literalName) => {
15 | // ACDLLexer['_LITERAL_NAMES'] contains items that are undefined, filter them out.
16 | if (typeof literalName === "string") {
17 | // string items are wrapped with single quote, change "'namespace'" to "namespace"
18 | const sanitizedLiteralName = literalName.replace(/[']/g, "");
19 | // filter out the literaNames that are symbols like ">"
20 | if (validKeywordCharacters.test(sanitizedLiteralName) && !excludedKeywords.includes(sanitizedLiteralName)) {
21 | acc.push(sanitizedLiteralName);
22 | }
23 | }
24 | return acc;
25 | }, extraKeywords);
26 |
--------------------------------------------------------------------------------
/src/aplContainer/commands/syncAplResource.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import {AbstractCommand, CommandContext} from "../../runtime";
7 | import {AplResourceSyncWebview} from "../webViews/aplResourceSyncWebview";
8 | import * as vscode from "vscode";
9 | import {EXTENSION_COMMAND_CONFIG} from "../config/configuration";
10 | import {Logger} from "../../logger";
11 |
12 | export class SyncAplResourceCommand extends AbstractCommand {
13 | constructor() {
14 | super(EXTENSION_COMMAND_CONFIG.DOWNLOAD_APL_DOCUMENT.NAME);
15 | }
16 |
17 | // eslint-disable-next-line @typescript-eslint/require-await
18 | async execute(context: CommandContext, skillFolderWs: vscode.Uri): Promise {
19 | Logger.debug(`Calling method: ${this.commandName}`);
20 | const aplResourceSyncWebview = new AplResourceSyncWebview(
21 | "Sync APL resource",
22 | "syncAplResource",
23 | context.extensionContext,
24 | skillFolderWs,
25 | );
26 | aplResourceSyncWebview.showView();
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/aplContainer/constants/messages.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | export const PROMPT_MESSAGES = Object.freeze({
7 | CREATE_SAMPLE_TEMPLATE: "Choose a template",
8 | ENTER_NAME_FOR_TEMPLATE: "Enter a name for the APL document",
9 | PREVIEW_APL_NO_APL_FOUND_IN_DIRECTORY: "No APL documents found. Create an APL document before selecting Preview",
10 | TEMPLATE_NAMING_HINTS: "Hint: Template name only accepts alphanumeric characters, periods, underscores and dashes",
11 | SYNC_APL_RESOURCE_RETRIEVING_INFORMATION: "Retrieving list of APL documents...",
12 | SYNC_APL_RESOURCE_NO_RESOURCE_FOUND_IN_CONSOLE:
13 | "No APL documents found in the Alexa Developer Console. Create an APL document locally by clicking on Alexa Presentation Language > Create.",
14 | });
15 |
16 | export const ERROR_MESSAGES = Object.freeze({
17 | CHANGE_VIEWPORT_PROFILE_NO_APL_PREVIEW:
18 | "There is no APL document selected. Choose an APL document and then choose Change viewport profile",
19 | CHANGE_VIEWPORT_PROFILE_NO_MATCHED_VIEWPORT: "The selected viewport profile cannot be loaded.",
20 | CREATE_APL_FROM_SAMPLE_TEMPLATE_NAME_EXISTS: "The APL document must have a unique name.",
21 | CREATE_APL_FROM_SAMPLE_NO_SAMPLE_TEMPLATE_FOUND: "This APL document sample is not available.",
22 | PREVIEW_APL_NO_APL_DOCUMENT_FOUND: "There is no document.json file in the APL document folder, so the APL cannot be previewed.",
23 | NO_SKILL_PACKAGE_FOUND: "There was a failure loading APL from the zip file",
24 | });
25 |
26 | export const SUCCESS_MESSAGES = Object.freeze({
27 | CREATE_APL_FROM_SAMPLE_SUCCESS: "Success: APL document created.",
28 | SYNC_APL_RESOURCE_SUCCESS: "Success: APL document downloaded.",
29 | });
30 |
--------------------------------------------------------------------------------
/src/aplContainer/models/index.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as vscode from "vscode";
7 |
8 | /**
9 | * Interface of APL resource
10 | *
11 | * @export
12 | * @interface AplResource
13 | */
14 | export interface AplResource {
15 | sources?: string;
16 | document: string;
17 | datasources?: string;
18 | }
19 |
20 | /**
21 | * Interface of APL Sample Template QuickPickItem
22 | *
23 | * @export
24 | * @interface SampleTemplateQuickPickItem
25 | */
26 | export interface SampleTemplateQuickPickItem extends vscode.QuickPickItem {
27 | id: string;
28 | }
29 |
--------------------------------------------------------------------------------
/src/aplContainer/utils/viewportProfileHelper.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 |
7 | import {getDefaultViewport, IViewport, ViewportMode, ViewportShape} from "apl-suggester";
8 |
9 | /**
10 | * DP -> Pixel convert
11 | * https://aplspec.aka.corp.amazon.com/release-1.3/html/viewport.html?highlight=viewport#dpi
12 | * @param {number} dpValue - dp value
13 | * @param {number} dpi - dpi
14 | */
15 | export const getPixelValueFromDpValue = (dpValue: number, dpi: number): number => {
16 | return Math.round((dpi / 160) * dpValue);
17 | };
18 |
19 | /**
20 | * IViewport -> IViewportCharacteristics (defined in APL webviewhost) convert
21 | * https://code.amazon.com/packages/APLViewhostWeb/blobs/6c9fe801a56e6b66213f930ba19a107e1c9462b7/--/js/apl-html/src/APLRenderer.ts#L36
22 | * @param {IViewport} activeViewport
23 | * @returns {any} - viewport characteristic used in APL webviewhost renderer config
24 | */
25 | export function getViewportCharacteristicsFromViewPort(activeViewport: IViewport): any {
26 | if (activeViewport) {
27 | return {
28 | isRound: activeViewport.shape === ViewportShape.ROUND,
29 | height: getPixelValueFromDpValue(activeViewport.height, activeViewport.dpi),
30 | width: getPixelValueFromDpValue(activeViewport.width, activeViewport.dpi),
31 | dpi: activeViewport.dpi,
32 | };
33 | }
34 | return {
35 | isRound: false,
36 | height: 600,
37 | width: 1024,
38 | dpi: 160,
39 | };
40 | }
41 |
42 | export const DEFAULT_VIEWPORT_CHARACTERISTICS = getViewportCharacteristicsFromViewPort(getDefaultViewport());
43 | export const DEFAULT_VIEWPORT_NAME = "Echo Show 1";
44 | export const DEFAULT_VIEWPORT_MODE = ViewportMode.HUB;
--------------------------------------------------------------------------------
/src/askContainer/commands/accessToken.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import {AbstractCommand, CommandContext, Utils, Resource} from "../../runtime";
7 |
8 | export class AccessTokenCommand extends AbstractCommand {
9 | async execute(context: CommandContext): Promise {
10 | const profile = Utils.getCachedProfile(context.extensionContext);
11 | if (profile === undefined) {
12 | throw new Error("Profile not defined.");
13 | }
14 | const access_token = await Utils.refreshToken(profile);
15 | if (access_token === undefined) {
16 | throw new Error("Access token unavailable.");
17 | }
18 | return access_token;
19 | }
20 | constructor() {
21 | super("ask.accessToken");
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/askContainer/commands/cloneSkill.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import {SmapiResource, AbstractCommand, CommandContext} from "../../runtime";
7 |
8 | import {SkillInfo} from "../../models/types";
9 | import {executeClone} from "../../utils/cloneSkillHelper";
10 | import {Logger} from "../../logger";
11 |
12 | export class CloneSkillCommand extends AbstractCommand {
13 | constructor() {
14 | super("askContainer.skillsConsole.cloneSkill");
15 | }
16 |
17 | async execute(context: CommandContext, skillInfo: SmapiResource): Promise {
18 | Logger.debug(`Calling method: ${this.commandName}, args: `, skillInfo);
19 | await executeClone(context, skillInfo);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/askContainer/commands/cloneSkill/cloneNonHostedSkillManager.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as fs from "fs";
7 | import * as path from "path";
8 | import * as vscode from "vscode";
9 |
10 | import {AbstractCloneSkillManager} from "./abstractCloneSkillManager";
11 | import {createSkillPackageFolder, syncSkillPackage} from "../../../utils/skillPackageHelper";
12 | import {SKILL, SKILL_FOLDER} from "../../../constants";
13 | import {Logger} from "../../../logger";
14 |
15 | export class CloneNonHostedSkillManager extends AbstractCloneSkillManager {
16 | async cloneSkill(progressBar: vscode.Progress<{message: string; increment: number}>): Promise {
17 | Logger.verbose(`Calling method: cloneSkill, args: `, progressBar);
18 |
19 | const incrAmount = 25;
20 | fs.mkdirSync(path.join(this.fsPath, SKILL_FOLDER.HIDDEN_ASK_FOLDER));
21 | this.createAskResourcesConfig(false);
22 | this.createAskStateConfig();
23 | progressBar.report({
24 | increment: incrAmount,
25 | message: "Skill metadata files created. Checking skill package...",
26 | });
27 |
28 | createSkillPackageFolder(this.fsPath);
29 | progressBar.report({
30 | increment: incrAmount,
31 | message: "Skill package created. Syncing from service...",
32 | });
33 |
34 | const skillPkgPath = path.join(this.fsPath, SKILL_FOLDER.SKILL_PACKAGE.NAME);
35 | const skillPackageStatus = await syncSkillPackage(
36 | skillPkgPath,
37 | this.skillInfo.data.skillSummary.skillId!,
38 | this.context,
39 | SKILL.STAGE.DEVELOPMENT,
40 | );
41 | void this.postCloneSkill(false, skillPackageStatus.skill?.eTag);
42 | progressBar.report({
43 | increment: incrAmount,
44 | message: "Skill package synced.",
45 | });
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/askContainer/commands/cloneSkillFromConsole.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import {CloneSkillCommand} from "./cloneSkill/cloneSkill";
7 |
8 | export class CloneSkillFromConsoleCommand extends CloneSkillCommand {
9 | constructor() {
10 | super("askContainer.skillsConsole.cloneSkillFromConsole");
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/askContainer/commands/createSkill.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import {AbstractCommand, CommandContext} from "../../runtime";
7 | import {CreateSkillWebview} from "../webViews/createSkillWebview/createSkillWebview";
8 | import {Logger} from "../../logger";
9 |
10 | export class CreateSkillCommand extends AbstractCommand {
11 | private createSkillWebview: CreateSkillWebview;
12 |
13 | constructor(createSkillWebview: CreateSkillWebview) {
14 | super("ask.new");
15 | this.createSkillWebview = createSkillWebview;
16 | }
17 |
18 | // eslint-disable-next-line @typescript-eslint/require-await
19 | async execute(context: CommandContext): Promise {
20 | Logger.debug(`Calling method: ${this.commandName}`);
21 | this.createSkillWebview.showView();
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/askContainer/commands/deployHostedSkill.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as vscode from "vscode";
7 | import {logAskError} from "../../exceptions";
8 | import {Logger} from "../../logger";
9 | import {AbstractCommand, CommandContext} from "../../runtime";
10 | import {checkProfileSkillAccess} from "../../utils/skillHelper";
11 | import {DeployHostedSkillWebview} from "../webViews/deploySkillWebview/deployHostedSkillWebview";
12 |
13 | export class DeployHostedSkillCommand extends AbstractCommand {
14 | private deploySkillWebview: DeployHostedSkillWebview;
15 |
16 | constructor(webview: DeployHostedSkillWebview) {
17 | super("askContainer.skillsConsole.deployHostedSkill");
18 | this.deploySkillWebview = webview;
19 | }
20 |
21 | // eslint-disable-next-line @typescript-eslint/require-await
22 | async execute(context: CommandContext, skillFolderWs: vscode.WorkspaceFolder): Promise {
23 | Logger.debug(`Calling method: ${this.commandName}`);
24 | try {
25 | checkProfileSkillAccess(context.extensionContext);
26 |
27 | this.deploySkillWebview.showView();
28 | } catch (err) {
29 | throw logAskError(`Cannot open deploy skill view`, err, true);
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/askContainer/commands/deployNonHostedSkill.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as vscode from "vscode";
7 | import {logAskError} from "../../exceptions";
8 | import {Logger} from "../../logger";
9 | import {AbstractCommand, CommandContext} from "../../runtime";
10 | import {checkProfileSkillAccess} from "../../utils/skillHelper";
11 | import {DeployNonHostedSkillWebview} from "../webViews/deploySkillWebview/deployNonHostedSkillWebview";
12 |
13 | export class DeployNonHostedSkillCommand extends AbstractCommand {
14 | private deployNonHostedSkillWebview: DeployNonHostedSkillWebview;
15 |
16 | constructor(webview: DeployNonHostedSkillWebview) {
17 | super("askContainer.skillsConsole.deploySelfHostedSkill");
18 | this.deployNonHostedSkillWebview = webview;
19 | }
20 |
21 | // eslint-disable-next-line @typescript-eslint/require-await
22 | async execute(context: CommandContext, skillFolderWs: vscode.WorkspaceFolder): Promise {
23 | Logger.debug(`Calling method: ${this.commandName}`);
24 | try {
25 | checkProfileSkillAccess(context.extensionContext);
26 |
27 | this.deployNonHostedSkillWebview.showView();
28 | } catch (err) {
29 | throw logAskError(`Cannot open deploy skill view`, err, true);
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/askContainer/commands/deploySkill.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as vscode from "vscode";
7 | import {logAskError} from "../../exceptions";
8 | import {Logger} from "../../logger";
9 | import {AbstractCommand, CommandContext} from "../../runtime";
10 | import {checkProfileSkillAccess} from "../../utils/skillHelper";
11 | import {DeploySkillWebview} from "../webViews/deploySkillWebview";
12 |
13 | export class DeploySkillCommand extends AbstractCommand {
14 | private deploySkillWebview: DeploySkillWebview;
15 |
16 | constructor(webview: DeploySkillWebview) {
17 | super("askContainer.skillsConsole.deploySkill");
18 | this.deploySkillWebview = webview;
19 | }
20 |
21 | async execute(context: CommandContext, skillFolderWs: vscode.WorkspaceFolder): Promise {
22 | Logger.debug(`Calling method: ${this.commandName}`);
23 | try {
24 | checkProfileSkillAccess(context.extensionContext);
25 |
26 | // eslint-disable-next-line @typescript-eslint/await-thenable
27 | await this.deploySkillWebview.showView();
28 | } catch (err) {
29 | throw logAskError(`Cannot open deploy skill view`, err, true);
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/askContainer/commands/deviceDeletionCommand.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 |
7 | import * as vscode from "vscode";
8 | import {Logger} from "../../logger";
9 | import {AbstractCommand, CommandContext} from "../../runtime";
10 | import {onDeviceDeletionEventEmitter} from "../events";
11 | import {getRegisteredDeviceId, deleteRegisteredDevice} from "../../utils/avs/deviceTokenUtil";
12 | import {ERRORS} from "../../constants";
13 |
14 | export class DeviceDeletionCommand extends AbstractCommand {
15 | constructor() {
16 | super("askContainer.skillsConsole.deviceDeletion");
17 | }
18 |
19 | async execute(context: CommandContext): Promise {
20 | Logger.debug(`Calling method: ${this.commandName}`);
21 | const registeredDeviceId = await getRegisteredDeviceId(context.extensionContext);
22 | if (registeredDeviceId && registeredDeviceId !== null) {
23 | const deleteConfirm = "Yes";
24 | const deleteReject = "No";
25 | const option = await vscode.window.showWarningMessage(
26 | ERRORS.DEVICE_DELETION_WARNING(registeredDeviceId),
27 | deleteConfirm,
28 | deleteReject,
29 | );
30 | if (option === deleteConfirm) {
31 | Logger.verbose("Confirmed device deletion");
32 | await deleteRegisteredDevice(registeredDeviceId, context.extensionContext);
33 | onDeviceDeletionEventEmitter.fire(registeredDeviceId);
34 | } else {
35 | Logger.verbose("Device deletion cancelled");
36 | }
37 | } else {
38 | void vscode.window.showInformationMessage(ERRORS.NO_DEVICES_REGISTERED);
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/askContainer/commands/deviceRegistryCommand.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 |
7 | import {logAskError} from "../../exceptions";
8 | import {Logger} from "../../logger";
9 | import {AbstractCommand, CommandContext} from "../../runtime";
10 | import {DeviceRegistryWebview} from "../webViews/deviceRegistryWebview";
11 |
12 | export class DeviceRegistryCommand extends AbstractCommand {
13 | private deviceRegistryWebview: DeviceRegistryWebview;
14 |
15 | constructor(webview: DeviceRegistryWebview, commandOverride?: string) {
16 | super(commandOverride ?? "askContainer.skillsConsole.deviceRegistry");
17 | this.deviceRegistryWebview = webview;
18 | }
19 |
20 | async execute(context: CommandContext): Promise {
21 | Logger.debug(`Calling method: ${this.commandName}`);
22 | try {
23 | this.deviceRegistryWebview.showView();
24 | } catch (err) {
25 | throw logAskError(`Cannot open device registry webview`, err, true);
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/askContainer/commands/init.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import {AbstractCommand, CommandContext} from "../../runtime";
7 | import {ProfileManagerWebview} from "../webViews/profileManagerWebview";
8 | import {Logger} from "../../logger";
9 |
10 | export class InitCommand extends AbstractCommand {
11 | private profileManager: ProfileManagerWebview;
12 |
13 | constructor(profileManager: ProfileManagerWebview) {
14 | super("ask.init");
15 | this.profileManager = profileManager;
16 | }
17 |
18 | async execute(context: CommandContext): Promise {
19 | Logger.debug(`Calling method: ${this.commandName}`);
20 | this.profileManager.showView();
21 | this.profileManager.populateProfilesList();
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/askContainer/commands/listSkills.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as model from "ask-smapi-model";
7 | import {DEFAULT_PROFILE, EN_US_LOCALE} from "../../constants";
8 | import {logAskError} from "../../exceptions";
9 | import {Logger} from "../../logger";
10 | import {AbstractCommand, CommandContext, SmapiClientFactory, SmapiResource, Utils} from "../../runtime";
11 |
12 | import skillSummary = model.v1.skill.SkillSummary;
13 | import skillManagementServiceClient = model.services.skillManagement.SkillManagementServiceClient;
14 |
15 | export class ListSkillsCommand extends AbstractCommand>> {
16 | constructor() {
17 | super("ask.container.listSkills");
18 | }
19 |
20 | private async getSkillsList(
21 | smapiClientInstance: skillManagementServiceClient,
22 | vendorId: string,
23 | nextToken: undefined | string,
24 | skillsList: Array>,
25 | ): Promise>> {
26 | const listSkills: model.v1.skill.ListSkillResponse = await smapiClientInstance.listSkillsForVendorV1(vendorId, nextToken);
27 | listSkills.skills?.forEach((listSkill) => {
28 | let skillName = "someSkill";
29 | if (listSkill.nameByLocale !== undefined && Object.values(listSkill.nameByLocale).length > 0) {
30 | if (listSkill.nameByLocale[EN_US_LOCALE]) {
31 | skillName = listSkill.nameByLocale[EN_US_LOCALE];
32 | } else {
33 | skillName = Object.values(listSkill.nameByLocale)[0];
34 | }
35 | }
36 | skillsList.push(new SmapiResource(listSkill, skillName));
37 | });
38 |
39 | if (listSkills.isTruncated ?? true) {
40 | await this.getSkillsList(smapiClientInstance, vendorId, listSkills.nextToken, skillsList);
41 | }
42 |
43 | return skillsList;
44 | }
45 |
46 | async execute(context: CommandContext): Promise>> {
47 | Logger.debug(`Calling method: ${this.commandName}`);
48 | const skills: Array> = [];
49 | let profile = Utils.getCachedProfile(context.extensionContext);
50 | profile = profile ?? DEFAULT_PROFILE;
51 | let vendorId: string;
52 | try {
53 | vendorId = Utils.resolveVendorId(profile);
54 | } catch (err) {
55 | throw logAskError(`Failed to retrieve vendorID for profile ${profile}`, err, true);
56 | }
57 |
58 | await this.getSkillsList(SmapiClientFactory.getInstance(profile, context.extensionContext), vendorId, undefined, skills);
59 | return skills;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/askContainer/commands/local-debug/debugAdapterPath.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as child_process from "child_process";
7 | import * as fs from "fs";
8 | import * as path from "path";
9 | import * as vscode from "vscode";
10 | import {DEFAULT_ENCODING, LOCAL_DEBUG} from "../../../constants";
11 | import {logAskError} from "../../../exceptions";
12 | import {Logger} from "../../../logger";
13 | import {AbstractCommand, CommandContext} from "../../../runtime";
14 |
15 | export class DebugAdapterPathCommand extends AbstractCommand {
16 | async execute(context: CommandContext, debugArgs: any): Promise {
17 | Logger.debug(`Calling method: ${this.commandName}, args:`, debugArgs);
18 | const languageType: string = debugArgs.type;
19 | if (languageType === LOCAL_DEBUG.NODE_DEPENDENCIES.LANG_TYPE) {
20 | const URIs = await vscode.workspace.findFiles(LOCAL_DEBUG.NODE_DEPENDENCIES.DEP_REGEX);
21 | if (URIs.length === 0) {
22 | throw logAskError(LOCAL_DEBUG.NODE_DEPENDENCIES.DEP_INSTALL_MSG);
23 | }
24 | return URIs[0].fsPath;
25 | } else if (languageType === LOCAL_DEBUG.PYTHON_DEPENDENCIES.LANG_TYPE) {
26 | const pythonInterpreterPath: string = debugArgs.pythonPath;
27 | const sitePkgUint8Array: Uint8Array = child_process.execSync(LOCAL_DEBUG.PYTHON_DEPENDENCIES.SITE_PKGS_CHECK(pythonInterpreterPath));
28 | let sitePkgLocationsStr = new TextDecoder(DEFAULT_ENCODING).decode(sitePkgUint8Array);
29 |
30 | // Preprocessing the string to get site locations for searching
31 | // https://docs.python.org/3/library/site.html#site.getsitepackages gives an array of strings
32 | // eg: "['sitePkg-A', 'sitePkg-B']", and we need to preprocess to get each location
33 | sitePkgLocationsStr = sitePkgLocationsStr.replace("[", "").replace("]", "").trim();
34 | const sitePkgLocations = sitePkgLocationsStr.split(",");
35 |
36 | for (let sitePkgLocation of sitePkgLocations) {
37 | // Remove extra quotes and white spaces
38 | sitePkgLocation = sitePkgLocation.replace(/['"]+/g, "").trim();
39 | const localDebuggerPath = path.join(sitePkgLocation, LOCAL_DEBUG.PYTHON_DEPENDENCIES.DEP_PATH);
40 | if (fs.existsSync(localDebuggerPath)) {
41 | return localDebuggerPath;
42 | }
43 | }
44 | throw logAskError(LOCAL_DEBUG.PYTHON_DEPENDENCIES.DEP_INSTALL_MSG);
45 | }
46 | throw logAskError(LOCAL_DEBUG.DEBUG_PATH_ERROR(languageType));
47 | }
48 |
49 | constructor() {
50 | super("ask.debugAdapterPath");
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/askContainer/commands/login.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import {AbstractCommand, CommandContext} from "../../runtime";
7 | import {InitialLoginWebview} from "../webViews/initialLogin";
8 | import * as vscode from "vscode";
9 | import {registerWebviews} from "../../utils/webViews/viewManager";
10 | import {Logger} from "../../logger";
11 |
12 | export class LoginCommand extends AbstractCommand {
13 | private loginView: InitialLoginWebview;
14 |
15 | constructor(context: vscode.ExtensionContext) {
16 | super("ask.login");
17 | this.loginView = new InitialLoginWebview("Sign in", "initialLogin", context);
18 | registerWebviews(this.loginView);
19 | }
20 |
21 | async execute(context: CommandContext, dispose?: boolean): Promise {
22 | Logger.debug(`Calling method: ${this.commandName}`);
23 | if (dispose) {
24 | this.loginView.dispose();
25 | } else {
26 | this.loginView.showView();
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/askContainer/commands/refreshSkillActions.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import {AbstractCommand, CommandContext} from "../../runtime";
7 | import {Logger} from "../../logger";
8 | import {onWorkspaceOpenEventEmitter} from "../events";
9 |
10 | export class RefreshSkillActionsCommand extends AbstractCommand {
11 | constructor() {
12 | super("askContainer.skill-actions.refresh");
13 | }
14 |
15 | async execute(context: CommandContext): Promise {
16 | Logger.debug(`Calling method: ${this.commandName}`);
17 | onWorkspaceOpenEventEmitter.fire(undefined);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/askContainer/commands/showToolkitUpdates.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import {AbstractCommand, CommandContext} from "../../runtime";
7 | import {ToolkitUpdateWebview} from "../webViews/toolkitUpdateWebview";
8 | import {Logger} from "../../logger";
9 |
10 | export class ShowToolkitUpdatesCommand extends AbstractCommand {
11 | private toolkitUpdate: ToolkitUpdateWebview;
12 |
13 | constructor(toolkitUpdate: ToolkitUpdateWebview) {
14 | super("ask.showToolkitUpdates");
15 | this.toolkitUpdate = toolkitUpdate;
16 | }
17 |
18 | async execute(context: CommandContext): Promise {
19 | Logger.debug(`Calling method: ${this.commandName}`);
20 | this.toolkitUpdate.showView();
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/askContainer/commands/simulateReplay.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import {logAskError} from "../../exceptions";
7 | import {Logger} from "../../logger";
8 | import {AbstractCommand, CommandContext} from "../../runtime";
9 | import {SimulateSkillWebview} from "../webViews/simulateSkillWebview";
10 |
11 | export class SimulateReplayCommand extends AbstractCommand {
12 | private simulateSkillWebview: SimulateSkillWebview;
13 |
14 | constructor(webview: SimulateSkillWebview) {
15 | super("askContainer.skillsConsole.simulateReplay");
16 | this.simulateSkillWebview = webview;
17 | }
18 |
19 | async execute(context: CommandContext): Promise {
20 | Logger.debug(`Calling method: ${this.commandName}`);
21 | try {
22 | this.simulateSkillWebview.showView();
23 | void this.simulateSkillWebview.replaySessionInSimulator();
24 | } catch (err) {
25 | throw logAskError(`Cannot open test skill view`, err, true);
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/askContainer/commands/simulateSkill.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import {logAskError} from "../../exceptions";
7 | import {Logger} from "../../logger";
8 | import {AbstractCommand, CommandContext} from "../../runtime";
9 | import {SimulateSkillWebview} from "../webViews/simulateSkillWebview";
10 |
11 | export class SimulateSkillCommand extends AbstractCommand {
12 | private simulateSkillWebview: SimulateSkillWebview;
13 |
14 | constructor(webview: SimulateSkillWebview) {
15 | super("askContainer.skillsConsole.simulateSkill");
16 | this.simulateSkillWebview = webview;
17 | }
18 |
19 | async execute(context: CommandContext): Promise {
20 | Logger.debug(`Calling method: ${this.commandName}`);
21 | try {
22 | this.simulateSkillWebview.showView();
23 | } catch (err) {
24 | throw logAskError(`Cannot open test skill view`, err, true);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/askContainer/commands/skillIdFromWorkspaceCommand.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import {ERRORS} from "../../constants";
7 | import {logAskError} from "../../exceptions";
8 | import {AbstractCommand, CommandContext, Utils} from "../../runtime";
9 | import {checkProfileSkillAccess, getSkillDetailsFromWorkspace} from "../../utils/skillHelper";
10 |
11 | export class GetSkillIdFromWorkspaceCommand extends AbstractCommand {
12 | // eslint-disable-next-line @typescript-eslint/require-await
13 | async execute(context: CommandContext): Promise {
14 | checkProfileSkillAccess(context.extensionContext);
15 | const skillId = getSkillDetailsFromWorkspace(context.extensionContext).skillId;
16 | if (!Utils.isNonBlankString(skillId)) {
17 | throw logAskError(`${ERRORS.MISSING_INFO_LOCAL_DEBUG("SkillId")}`);
18 | }
19 | return skillId;
20 | }
21 | constructor() {
22 | super("ask.skillIdFromWorkspace");
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/askContainer/commands/syncInteractionModel.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as vscode from "vscode";
7 | import {logAskError} from "../../exceptions";
8 | import {Logger} from "../../logger";
9 | import {AbstractCommand, CommandContext} from "../../runtime";
10 | import {checkProfileSkillAccess} from "../../utils/skillHelper";
11 | import {InteractionModelSyncWebview} from "../webViews/interactionModelSync";
12 |
13 | export class SyncInteractionModelCommand extends AbstractCommand {
14 | private syncInteractionModelView: InteractionModelSyncWebview;
15 |
16 | constructor(syncInteractionModelView: InteractionModelSyncWebview) {
17 | super("ask.container.syncInteractionModel");
18 | this.syncInteractionModelView = syncInteractionModelView;
19 | }
20 |
21 | // eslint-disable-next-line @typescript-eslint/require-await
22 | async execute(context: CommandContext, skillFolderWs: vscode.Uri): Promise {
23 | Logger.debug(`Calling method: ${this.commandName}`);
24 | try {
25 | checkProfileSkillAccess(context.extensionContext);
26 | this.syncInteractionModelView.showView(skillFolderWs);
27 | } catch (err) {
28 | throw logAskError(`View failed to load; try again.`, err, true);
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/askContainer/commands/syncManifest.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as vscode from "vscode";
7 | import {logAskError} from "../../exceptions";
8 | import {Logger} from "../../logger";
9 | import {AbstractCommand, CommandContext} from "../../runtime";
10 | import {checkProfileSkillAccess} from "../../utils/skillHelper";
11 | import {ManifestSyncWebview} from "../webViews/manifestSync";
12 |
13 | export class SyncManifestCommand extends AbstractCommand {
14 | private syncManifestView: ManifestSyncWebview;
15 |
16 | constructor(syncManifestView: ManifestSyncWebview) {
17 | super("ask.container.syncManifest");
18 | this.syncManifestView = syncManifestView;
19 | }
20 |
21 | // eslint-disable-next-line @typescript-eslint/require-await
22 | async execute(context: CommandContext, skillFolderWs: vscode.Uri): Promise {
23 | Logger.debug(`Calling method: ${this.commandName}`);
24 | try {
25 | checkProfileSkillAccess(context.extensionContext);
26 | this.syncManifestView.showView(skillFolderWs);
27 | } catch (err) {
28 | throw logAskError(`Cannot open sync manifest view`, err, true);
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/askContainer/commands/welcome.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import {AbstractCommand, CommandContext} from "../../runtime";
7 | import {WelcomeScreenWebview} from "../webViews/welcomeScreenWebview";
8 | import {Logger} from "../../logger";
9 | import {registerWebviews} from "../../utils/webViews/viewManager";
10 | import * as vscode from "vscode";
11 |
12 | export class WelcomeCommand extends AbstractCommand {
13 | private welcomeScreen: WelcomeScreenWebview;
14 |
15 | constructor(context: vscode.ExtensionContext) {
16 | super("ask.welcome");
17 | this.welcomeScreen = new WelcomeScreenWebview("Alexa Skills Kit", "welcomeScreen", context);
18 | registerWebviews(this.welcomeScreen);
19 | }
20 |
21 | async execute(context: CommandContext): Promise {
22 | Logger.debug(`Calling method: ${this.commandName}`);
23 | this.welcomeScreen.showView();
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/askContainer/events.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 |
7 | import {EventEmitter} from "vscode";
8 | import {PluginTreeItem, Resource} from "../runtime";
9 |
10 | export const onSkillConsoleViewChangeEventEmitter: EventEmitter | undefined> = new EventEmitter<
11 | PluginTreeItem | undefined
12 | >();
13 |
14 | export const onWorkspaceOpenEventEmitter: EventEmitter | undefined> = new EventEmitter<
15 | PluginTreeItem | undefined
16 | >();
17 |
18 | export const onDeviceRegistrationEventEmitter: EventEmitter = new EventEmitter();
19 |
20 | export const onDeviceDeletionEventEmitter: EventEmitter = new EventEmitter();
21 |
--------------------------------------------------------------------------------
/src/askContainer/treeViews/helpView.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as vscode from "vscode";
7 | import {PluginTreeItem, Resource, AbstractTreeView} from "../../runtime";
8 |
9 | import {HelpViewProvider} from "./treeViewProviders/helpViewProvider";
10 | import {TREE_VIEW_IDS} from "../../constants";
11 |
12 | export class HelpView extends AbstractTreeView {
13 | protected view: vscode.TreeView>;
14 |
15 | constructor(context: vscode.ExtensionContext) {
16 | super(context);
17 | this.view = vscode.window.createTreeView(TREE_VIEW_IDS.HELP, {
18 | treeDataProvider: new HelpViewProvider(this),
19 | showCollapseAll: true,
20 | });
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/askContainer/treeViews/skillActionsView.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as vscode from "vscode";
7 | import {PluginTreeItem, Resource, AbstractTreeView} from "../../runtime";
8 |
9 | import {SkillActionsViewProvider} from "./treeViewProviders/skillActionsViewProvider";
10 | import {TREE_VIEW_IDS} from "../../constants";
11 |
12 | export class SkillActionsView extends AbstractTreeView {
13 | protected view: vscode.TreeView>;
14 |
15 | constructor(context: vscode.ExtensionContext) {
16 | super(context);
17 | this.view = vscode.window.createTreeView(TREE_VIEW_IDS.SKILL_ACTIONS, {
18 | treeDataProvider: new SkillActionsViewProvider(this),
19 | showCollapseAll: true,
20 | });
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/askContainer/treeViews/skillConsoleView.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as vscode from "vscode";
7 | import {PluginTreeItem, Resource, AbstractTreeView} from "../../runtime";
8 |
9 | import {SkillsConsoleViewProvider} from "./treeViewProviders/skillConsoleViewProvider";
10 | import {TREE_VIEW_IDS} from "../../constants";
11 |
12 | export class SkillsConsoleView extends AbstractTreeView {
13 | protected view: vscode.TreeView>;
14 |
15 | constructor(context: vscode.ExtensionContext) {
16 | super(context);
17 | this.view = vscode.window.createTreeView>(TREE_VIEW_IDS.SKILLS_CONSOLE, {
18 | treeDataProvider: new SkillsConsoleViewProvider(this),
19 | showCollapseAll: true,
20 | });
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/askContainer/webViews/createSkillWebview/abstractCreateSkillManager.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import {ExtensionContext, Progress} from "vscode";
7 |
8 | import {createSkillWebViewType} from "./createSkillWebview";
9 | import {DEFAULT_PROFILE} from "../../../constants";
10 | import {Utils} from "../../../runtime";
11 |
12 | export abstract class AbstractCreateSkillManager {
13 | protected context: ExtensionContext;
14 | protected skillFolder: string;
15 | protected profile: string;
16 |
17 | constructor(context: ExtensionContext, skillFolder: string) {
18 | this.context = context;
19 | this.skillFolder = skillFolder;
20 | this.profile = Utils.getCachedProfile(this.context) ?? DEFAULT_PROFILE;
21 | }
22 |
23 | abstract createSkill(userInput: createSkillWebViewType, progress?: Progress): Promise;
24 | }
25 |
--------------------------------------------------------------------------------
/src/askContainer/webViews/deploySkillWebview/deployNonHostedSkillManager.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as vscode from "vscode";
7 |
8 | import {Logger} from "../../../logger";
9 | import {AbstractWebView} from "../../../runtime";
10 |
11 | import {AbstractDeploySkillManager} from "./abstractDeploySkillManager";
12 |
13 | export class DeployNonHostedSkillManager extends AbstractDeploySkillManager {
14 | private currentHash: string;
15 |
16 | constructor(context: vscode.ExtensionContext, skillFolderWs: vscode.Uri, currentHash: string) {
17 | super(context, skillFolderWs);
18 | this.currentHash = currentHash;
19 | }
20 |
21 | async deploySkill(view: AbstractWebView, isForce?: boolean, eTag?: string): Promise {
22 | Logger.verbose("Calling method: deploySkill");
23 |
24 | await this.deploySkillPackage(view, isForce, eTag, this.currentHash);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/askContainer/webViews/initialLogin.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as vscode from "vscode";
7 | import {DEFAULT_PROFILE, WEB_VIEW_NAME} from "../../constants";
8 | import {AskParameterAbsenceError, logAskError} from "../../exceptions";
9 | import {Logger} from "../../logger";
10 | import {AbstractWebView} from "../../runtime";
11 | import {authenticate} from "../../utils/webViews/authHelper";
12 | import {ViewLoader} from "../../utils/webViews/viewLoader";
13 | import {AUTH_FLOW_RESULT} from "./profileManagerWebview";
14 |
15 | type SignInType = {
16 | profileName: string;
17 | };
18 |
19 | export class InitialLoginWebview extends AbstractWebView {
20 | private loader: ViewLoader;
21 |
22 | constructor(viewTitle: string, viewId: string, context: vscode.ExtensionContext) {
23 | super(viewTitle, viewId, context);
24 | this.loader = new ViewLoader(this.extensionContext, WEB_VIEW_NAME.INITIAL_LOGIN, this);
25 | }
26 |
27 | onViewChangeListener(event: vscode.WebviewPanelOnDidChangeViewStateEvent): void {
28 | Logger.debug(`Calling method: ${this.viewId}.getHtmlForView`);
29 |
30 | return;
31 | }
32 |
33 | onReceiveMessageListener(message: SignInType): void {
34 | Logger.debug(`Calling method: ${this.viewId}.onReceiveMessageListener, args:`, message);
35 | this.doAuthenticate();
36 | }
37 |
38 | getHtmlForView(...args: unknown[]): string {
39 | Logger.debug(`Calling method: ${this.viewId}.getHtmlForView`);
40 | return this.loader.renderView({
41 | name: WEB_VIEW_NAME.INITIAL_LOGIN,
42 | js: true,
43 | });
44 | }
45 |
46 | async doAuthenticate(): Promise {
47 | Logger.debug(`Calling method: ${this.viewId}.doAuthenticate`);
48 | try {
49 | await authenticate(this.extensionContext, this, DEFAULT_PROFILE);
50 | void vscode.commands.executeCommand("workbench.action.reloadWindow");
51 | } catch (error) {
52 | Logger.error(error);
53 | let viewArgs;
54 | if (error instanceof AskParameterAbsenceError) {
55 | viewArgs = AUTH_FLOW_RESULT.VENDOR_ID_ABSENCE;
56 | } else {
57 | viewArgs = AUTH_FLOW_RESULT.FAILED;
58 | viewArgs.message = error instanceof Error ? error.message : error;
59 | }
60 | this.loader = new ViewLoader(this.extensionContext, "profileManager", this);
61 | if (!this.isDisposed()) {
62 | this.getPanel().webview.html = this.loader.renderView({
63 | name: "authFlowResult",
64 | args: viewArgs,
65 | });
66 | }
67 | }
68 | }
69 |
70 | reviveView(): void {
71 | Logger.debug(`Calling method: ${this.viewId}.reviveView`);
72 | throw logAskError("Method not implemented.");
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/askContainer/webViews/toolkitUpdateWebview.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import {AbstractWebView} from "../../runtime";
7 | import {ExtensionContext, WebviewPanelOnDidChangeViewStateEvent} from "vscode";
8 | import {ViewLoader} from "../../utils/webViews/viewLoader";
9 | import {Logger} from "../../logger";
10 | import {WEB_VIEW_NAME} from "../../constants";
11 |
12 | export class ToolkitUpdateWebview extends AbstractWebView {
13 | private loader: ViewLoader;
14 |
15 | constructor(viewTitle: string, viewId: string, context: ExtensionContext) {
16 | super(viewTitle, viewId, context);
17 | this.isGlobal = true;
18 | this.loader = new ViewLoader(this.extensionContext, WEB_VIEW_NAME.TOOLKIT_UPDATE, this);
19 | }
20 |
21 | onViewChangeListener(event: WebviewPanelOnDidChangeViewStateEvent): void {
22 | Logger.debug(`Calling method: ${this.viewId}.onViewChangeListener`);
23 | return;
24 | }
25 |
26 | onReceiveMessageListener(message: any): void {
27 | Logger.debug(`Calling method: ${this.viewId}.onReceiveMessageListener, args: `, message);
28 | return;
29 | }
30 |
31 | getHtmlForView(...args: unknown[]): string {
32 | Logger.debug(`Calling method: ${this.viewId}.getHtmlForView`);
33 | return this.loader.renderView({
34 | name: WEB_VIEW_NAME.TOOLKIT_UPDATE,
35 | js: false,
36 | });
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/exceptions.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as vscode from "vscode";
7 | import {Logger} from "./logger";
8 |
9 | export class AskError extends Error {
10 | constructor(message: string) {
11 | super(message);
12 | this.name = "AskError";
13 | }
14 | }
15 |
16 | export class AskParameterAbsenceError extends AskError {
17 | constructor(message: string) {
18 | super(message);
19 | this.name = "AskParameterAbsenceError";
20 | }
21 | }
22 |
23 | export function logAskError(message: string, error: any | undefined = undefined, exposeToUser = false): Error {
24 | let errMsg: string;
25 | if (error !== undefined) {
26 | let msg: string;
27 | if (error instanceof Error) {
28 | msg = error.message;
29 | } else {
30 | msg = error;
31 | }
32 | errMsg = `${message}. Reason: ${msg}`;
33 | } else {
34 | errMsg = `${message}.`;
35 | }
36 |
37 | Logger.error(errMsg);
38 |
39 | if (exposeToUser) {
40 | void vscode.window.showErrorMessage(errMsg);
41 | }
42 |
43 | return new AskError(errMsg);
44 | }
45 |
--------------------------------------------------------------------------------
/src/extensionGlobals.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import {ExtensionContext} from "vscode";
7 |
8 | import {GenericCommand, AbstractWebView, AbstractTreeView} from "../src/runtime/lib/API";
9 | import {SkillPackageWatcher} from "./askContainer/fileSystem/skillPackageWatcher";
10 | /**
11 | * Namespace for common variables used globally in the extension.
12 | * All variables here must be initialized in the activate() method of extension.ts
13 | */
14 | export namespace ext {
15 | export let context: ExtensionContext;
16 | /**
17 | * Commands which will be available when extension is activated
18 | */
19 | export let askGeneralCommands: GenericCommand[];
20 |
21 | /**
22 | * Commands which will be available when extension is activated
23 | * And when a skill is detected
24 | */
25 | export let askSkillCommands: GenericCommand[];
26 |
27 | /**
28 | * Webviews which are registered in this extension
29 | */
30 | export const webViews: AbstractWebView[] = [];
31 |
32 | /**
33 | * TreeViews which are registered in this extension
34 | */
35 | export const treeViews: AbstractTreeView[] = [];
36 |
37 | export let skillPackageWatcher: SkillPackageWatcher;
38 | }
39 |
--------------------------------------------------------------------------------
/src/models/resourcesConfig/abstractResourcesConfig.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as R from "ramda";
7 | import {write, read} from "../../runtime/lib/utils/jsonUtility";
8 |
9 | /**
10 | * A utility class to define common methods for getting and setting data in a config JSON file
11 | */
12 | export class AbstractResourcesConfig {
13 | protected filePath: string;
14 | content: any;
15 |
16 | /**
17 | * Constructor for an ask resources config class
18 | * @param filePath The path of the config file
19 | * @param content The JSON object of the config file, the given content will replace an existing one
20 | */
21 | constructor(filePath: string, content?: any) {
22 | this.filePath = filePath;
23 | if (content !== undefined) {
24 | write(filePath, content);
25 | }
26 | this.read();
27 | }
28 |
29 | /**
30 | * To get the value with the given lens path from the JSON object
31 | * @param pathArray
32 | */
33 | getProperty(pathArray: string[]): string {
34 | return R.view(R.lensPath(pathArray), this.content);
35 | }
36 |
37 | /**
38 | * To assign a value to the given lens path in the JSON object
39 | * @param pathArray
40 | * @param value
41 | */
42 | setProperty(pathArray: string[], value: string | undefined): void {
43 | this.content = R.set(R.lensPath(pathArray), value, this.content);
44 | }
45 |
46 | /**
47 | * To write a JSON file
48 | */
49 | write(): void {
50 | write(this.filePath, this.content);
51 | }
52 |
53 | /**
54 | * To read the JSON file
55 | */
56 | read(): any {
57 | this.content = read(this.filePath);
58 | // eslint-disable-next-line @typescript-eslint/no-unsafe-return
59 | return this.content;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/models/resourcesConfig/askResource.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as fs from "fs-extra";
7 | import * as path from "path";
8 |
9 | import {ASK_RESOURCES_JSON, BASE_RESOURCES_CONFIG, SKILL_FOLDER} from "../../constants";
10 | import {AbstractResourcesConfig} from "./abstractResourcesConfig";
11 |
12 | /**
13 | * A utility class to create, get and set data in ask-resources.json file
14 | */
15 | export class AskResources extends AbstractResourcesConfig {
16 | /**
17 | * The constructor for AskResources class
18 | * @param skillFolderPath
19 | * @param content the given content to initialize or overwrite the file
20 | */
21 | constructor(skillFolderPath: string, content?: any) {
22 | const filePath = path.join(skillFolderPath, SKILL_FOLDER.ASK_RESOURCES_JSON_CONFIG);
23 | if (!fs.existsSync(filePath)) {
24 | if (content === undefined) {
25 | content = BASE_RESOURCES_CONFIG;
26 | }
27 | fs.ensureDirSync(path.dirname(filePath));
28 | }
29 | super(filePath, content);
30 | }
31 |
32 | // getter and setter
33 |
34 | getSkillId(profile: string): string {
35 | return this.getProperty([ASK_RESOURCES_JSON.PROFILES, profile, ASK_RESOURCES_JSON.SKILL_ID]);
36 | }
37 |
38 | setSkillId(profile: string, skillId: string): void {
39 | this.setProperty([ASK_RESOURCES_JSON.PROFILES, profile, ASK_RESOURCES_JSON.SKILL_ID], skillId);
40 | }
41 |
42 | getProfile(profile: string): string {
43 | return this.getProperty([ASK_RESOURCES_JSON.PROFILES, profile]);
44 | }
45 |
46 | setProfile(profile: string, profileVale: string | undefined): void {
47 | this.setProperty([ASK_RESOURCES_JSON.PROFILES, profile], profileVale);
48 | }
49 |
50 | getSkillMetaSrc(profile: string): string {
51 | return this.getProperty([
52 | ASK_RESOURCES_JSON.PROFILES,
53 | profile,
54 | ASK_RESOURCES_JSON.SKILL_METADATA.NAME,
55 | ASK_RESOURCES_JSON.SKILL_METADATA.SRC,
56 | ]);
57 | }
58 |
59 | setSkillMetaSrc(profile: string, skillMetaSrc: string): void {
60 | this.setProperty(
61 | [ASK_RESOURCES_JSON.PROFILES, profile, ASK_RESOURCES_JSON.SKILL_METADATA.NAME, ASK_RESOURCES_JSON.SKILL_METADATA.SRC],
62 | skillMetaSrc,
63 | );
64 | }
65 |
66 | getSkillInfraType(profile: string): string {
67 | return this.getProperty([
68 | ASK_RESOURCES_JSON.PROFILES,
69 | profile,
70 | ASK_RESOURCES_JSON.SKILL_INFRASTRUCTURE.NAME,
71 | ASK_RESOURCES_JSON.SKILL_INFRASTRUCTURE.TYPE,
72 | ]);
73 | }
74 |
75 | setSkillInfraType(profile: string, type: string): void {
76 | this.setProperty(
77 | [ASK_RESOURCES_JSON.PROFILES, profile, ASK_RESOURCES_JSON.SKILL_INFRASTRUCTURE.NAME, ASK_RESOURCES_JSON.SKILL_INFRASTRUCTURE.TYPE],
78 | type,
79 | );
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/models/resourcesConfig/askStates.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as fs from "fs-extra";
7 | import * as path from "path";
8 |
9 | import {ASK_STATES_JSON, BASE_STATES_CONFIG, SKILL_FOLDER} from "../../constants";
10 | import {AbstractResourcesConfig} from "./abstractResourcesConfig";
11 |
12 | /**
13 | * A utility class to create, get and set data in ask-states.json file
14 | */
15 | export class AskStates extends AbstractResourcesConfig {
16 | /**
17 | * The constructor for AskStates class
18 | * @param skillFolderPath
19 | * @param content the given content to initialize or overwrite the file
20 | */
21 | constructor(skillFolderPath: string, content?: any) {
22 | const filePath = path.join(skillFolderPath, SKILL_FOLDER.HIDDEN_ASK_FOLDER, SKILL_FOLDER.ASK_STATES_JSON_CONFIG);
23 | if (!fs.existsSync(filePath)) {
24 | if (content === undefined) {
25 | content = BASE_STATES_CONFIG;
26 | }
27 | }
28 | fs.ensureDirSync(path.dirname(filePath));
29 | super(filePath, content);
30 | }
31 |
32 | // getter and setter
33 |
34 | getSkillId(profile: string): string {
35 | return this.getProperty([ASK_STATES_JSON.PROFILES, profile, ASK_STATES_JSON.SKILL_ID]);
36 | }
37 |
38 | setSkillId(profile: string, skillId: string): void {
39 | this.setProperty([ASK_STATES_JSON.PROFILES, profile, ASK_STATES_JSON.SKILL_ID], skillId);
40 | }
41 |
42 | getSkillMetaLastDeployHash(profile: string): string {
43 | return this.getProperty([
44 | ASK_STATES_JSON.PROFILES,
45 | profile,
46 | ASK_STATES_JSON.SKILL_METADATA.NAME,
47 | ASK_STATES_JSON.SKILL_METADATA.LAST_DEPLOY_HASH,
48 | ]);
49 | }
50 |
51 | setSkillMetaLastDeployHash(profile: string, lastDeployHash: string): void {
52 | this.setProperty(
53 | [ASK_STATES_JSON.PROFILES, profile, ASK_STATES_JSON.SKILL_METADATA.NAME, ASK_STATES_JSON.SKILL_METADATA.LAST_DEPLOY_HASH],
54 | lastDeployHash,
55 | );
56 | }
57 |
58 | getSkillMetaETag(profile: string): string {
59 | return this.getProperty([ASK_STATES_JSON.PROFILES, profile, ASK_STATES_JSON.SKILL_METADATA.NAME, ASK_STATES_JSON.SKILL_METADATA.ETAG]);
60 | }
61 |
62 | setSkillMetaETag(profile: string, eTag: string): void {
63 | this.setProperty([ASK_STATES_JSON.PROFILES, profile, ASK_STATES_JSON.SKILL_METADATA.NAME, ASK_STATES_JSON.SKILL_METADATA.ETAG], eTag);
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/models/types.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import {SmapiClientFactory} from "../runtime";
7 | import * as model from "ask-smapi-model";
8 | import skillSummary = model.v1.skill.SkillSummary;
9 | import hostedSkillMetadata = model.v1.skill.AlexaHosted.HostedSkillMetadata;
10 |
11 | export class SkillInfo {
12 | skillSummary: skillSummary;
13 | isHosted: boolean | undefined;
14 | hostedSkillMetadata: hostedSkillMetadata | undefined;
15 |
16 | constructor(
17 | skillSummary: skillSummary,
18 | isHosted: boolean | undefined = undefined,
19 | hostedSkillMetadata: hostedSkillMetadata | undefined = undefined,
20 | ) {
21 | this.skillSummary = skillSummary;
22 | this.hostedSkillMetadata = hostedSkillMetadata;
23 | this.isHosted = isHosted;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/runtime/index.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as Utils from "./lib/utils/index";
7 |
8 | export * from "./lib/API";
9 | export * from "./lib/credentialsManager";
10 | export * from "./lib/types";
11 | export * from "./lib/smapiClientFactory";
12 | export {Utils};
13 |
--------------------------------------------------------------------------------
/src/runtime/lib/credentialsManager.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import {logAskError} from "../../exceptions";
7 | import {resolver} from "./utils/configuration";
8 | import {AUTH} from "./utils/constants";
9 | import {readToken, StoredToken} from "./utils/oauthWrapper";
10 | import {resolveVendorId} from "./utils/profileHelper";
11 |
12 | export class Credentials {
13 | readonly clientId: string;
14 | readonly clientSecret: string;
15 | readonly refreshToken: string;
16 | readonly vendorId: string;
17 |
18 | constructor(clientId: string, clientSecret: string, refreshToken: string, vendorId: string) {
19 | this.clientId = clientId;
20 | this.clientSecret = clientSecret;
21 | this.refreshToken = refreshToken;
22 | this.vendorId = vendorId;
23 | }
24 | }
25 |
26 | export class CredentialsManager {
27 | public static getCredentials(profile: string, clientId?: string, clientSecret?: string): Credentials {
28 | const token: StoredToken | undefined = readToken(profile);
29 | let vendorId: string;
30 | try {
31 | vendorId = resolveVendorId(profile);
32 | } catch (err) {
33 | throw logAskError(`Failed to retrieve vendorID for profile ${profile}`, err, true);
34 | }
35 | return new Credentials(
36 | resolver([clientId, process.env.ASK_LWA_CLIENT_ID, AUTH.DEFAULT_CLIENT_ID]),
37 | resolver([clientSecret, process.env.ASK_LWA_CLIENT_CONFIRMATION, AUTH.DEFAULT_CLIENT_CONFIRMATION]),
38 | token!.refresh_token,
39 | vendorId,
40 | );
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/runtime/lib/index.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import "./API";
7 | import "./types";
8 | import "./smapiClientFactory";
9 | import "./credentialsManager";
10 |
--------------------------------------------------------------------------------
/src/runtime/lib/smapiClientFactory.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as vscode from "vscode";
7 | import {RefreshTokenConfig, CustomSmapiClientBuilder} from "ask-smapi-sdk";
8 | import * as smapiModel from "ask-smapi-model";
9 | import {CredentialsManager, Credentials} from "./credentialsManager";
10 | import {resolver} from "./utils/configuration";
11 | import {AUTH} from "./utils/constants";
12 | import {EXTENSION_ID} from "../../constants";
13 |
14 | export class SmapiClientFactory {
15 | private static readonly profileInstanceMap: Map = new Map();
16 |
17 | private constructor() {}
18 |
19 | public static getInstance(
20 | profile: string,
21 | context: vscode.ExtensionContext,
22 | ): smapiModel.services.skillManagement.SkillManagementServiceClient {
23 | let smapiClient = this.profileInstanceMap.get(profile);
24 | if (!smapiClient) {
25 | const authConfig: Credentials = CredentialsManager.getCredentials(profile);
26 | const refreshTokenConfig: RefreshTokenConfig = {
27 | clientId: authConfig.clientId,
28 | clientSecret: authConfig.clientSecret,
29 | refreshToken: authConfig.refreshToken,
30 | };
31 | const pluginVersion: string = vscode.extensions.getExtension(EXTENSION_ID)?.packageJSON.version;
32 | smapiClient = new CustomSmapiClientBuilder()
33 | .withApiEndpoint(resolver([process.env.ASK_SMAPI_SERVER_BASE_URL, undefined]))
34 | .withAuthEndpoint(resolver([process.env.ASK_LWA_TOKEN_HOST, AUTH.DEFAULT_ASK_LWA_TOKEN_HOST]))
35 | .withRefreshTokenConfig(refreshTokenConfig)
36 | .withCustomUserAgent(`alexa-skills-kit-toolkit/${pluginVersion}`)
37 | .client();
38 | this.profileInstanceMap.set(profile, smapiClient);
39 | }
40 | return smapiClient;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/runtime/lib/telemetry/constants.ts:
--------------------------------------------------------------------------------
1 | export enum MetricActionResult {
2 | SUCCESS = "Success",
3 | FAILURE = "Failure",
4 | }
5 |
6 | export enum TelemetryEnabled {
7 | ENABLED = "Enabled",
8 | DISABLED = "Disabled",
9 | USE_IDE_SETTINGS = "Use IDE settings",
10 | }
11 |
12 | export enum ActionType {
13 | COMMAND = "command",
14 | EVENT = "event",
15 | TOOLS_DOCS_VSCODE = "TOOLS_DOCS_VSCODE",
16 | TOOLS_DOCS_CLI = "TOOLS_DOCS_CLI",
17 | TOOLS_DOCS_ASK_SDK = "TOOLS_DOCS_ASK_SDK",
18 | TOOLS_DOCS_SMAPI_SDK = "TOOLS_DOCS_SMAPI_SDK",
19 | IM_EDITOR = "IM_EDITOR",
20 | ACDL_SERVER = "ACDL_SERVER",
21 | }
22 |
--------------------------------------------------------------------------------
/src/runtime/lib/telemetry/metricAction.ts:
--------------------------------------------------------------------------------
1 | import uuid from "uuid";
2 | import { ActionType, MetricActionResult } from "./constants";
3 |
4 | export class MetricAction {
5 | private result?: MetricActionResult;
6 |
7 | private name: string;
8 |
9 | private startTime: Date;
10 |
11 | private type: ActionType;
12 |
13 | public id: string;
14 |
15 | private endTime?: Date;
16 |
17 | private failureMessage: string;
18 |
19 | private ended: boolean;
20 |
21 | /**
22 | * @constructor
23 | * @param {string} name - The action name.
24 | * @param {string} type - The action type.
25 | */
26 | constructor(name: string, type: ActionType) {
27 | this.failureMessage = "";
28 | this.name = name;
29 | this.startTime = new Date();
30 | this.type = type;
31 | this.id = uuid();
32 | this.ended = false;
33 | }
34 |
35 | /**
36 | * Closes action
37 | * @param {Error} [error] - Error object indicating an error.
38 | */
39 | public end(error?: Error) {
40 | if (this.ended) {
41 | return;
42 | }
43 |
44 | const hasError = error instanceof Error;
45 | this.result = hasError ? MetricActionResult.FAILURE : MetricActionResult.SUCCESS;
46 | this.failureMessage = hasError ? (error?.message as string) : "";
47 | this.endTime = new Date();
48 | this.ended = true;
49 | }
50 |
51 | /**
52 | * Implementation of custom toJSON method to modify serialization with JSON.stringify
53 | */
54 | protected toJSON() {
55 | return {
56 | end_time: this.endTime,
57 | failure_message: this.failureMessage,
58 | name: this.name,
59 | result: this.result,
60 | start_time: this.startTime,
61 | type: this.type,
62 | id: this.id,
63 | };
64 | }
65 | }
--------------------------------------------------------------------------------
/src/runtime/lib/types.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | export interface Resource {
7 | label?: string;
8 | }
9 |
10 | export class SmapiResource {
11 | label?: string;
12 | data: T;
13 |
14 | constructor(data: T, label?: string) {
15 | this.data = data;
16 | this.label = label;
17 | }
18 | }
19 | export interface CustomResource extends Resource {
20 | description: string;
21 | hasChildren?: boolean;
22 | }
23 |
--------------------------------------------------------------------------------
/src/runtime/lib/utils/configuration.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import {isNonBlankString} from "./stringUtils";
7 |
8 | //TODO: Extend support for Promises.
9 | export function resolver(chain: Array): string {
10 | for (const item of chain) {
11 | if (item !== undefined && isNonBlankString(item)) {
12 | return item;
13 | }
14 | }
15 | return "";
16 | }
17 |
--------------------------------------------------------------------------------
/src/runtime/lib/utils/constants.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | export const AUTH = {
7 | PLACEHOLDER_ENVIRONMENT_VAR_PROFILE_NAME: "__ENVIRONMENT_ASK_PROFILE__",
8 | DEFAULT_CLIENT_ID: "amzn1.application-oa2-client.aad322b5faab44b980c8f87f94fbac56",
9 | DEFAULT_CLIENT_CONFIRMATION: "1642d8869b829dda3311d6c6539f3ead55192e3fc767b9071c888e60ef151cf9",
10 | SIGNIN_URL: "https://www.amazon.com/ap/signin",
11 | SIGNIN_PATH: "/ap/signin",
12 | DEFAULT_LWA_AUTHORIZE_HOST: "https://www.amazon.com",
13 | DEFAULT_ASK_LWA_TOKEN_HOST: "https://api.amazon.com",
14 | };
15 |
16 | export const EXTENSION_STATE_KEY = {
17 | CACHED_SKILLS: "AskContainer.HostedSkillsCache",
18 | LWA_PROFILE: "LwaProfile",
19 | CLIENT_ID: "CLIENT_ID",
20 | CLIENT_SECRET: "CLIENT_SECRET",
21 | ASK_LWA_AUTHORIZE_HOST: "ASK_LWA_AUTHORIZE_HOST",
22 | ASK_LWA_TOKEN_HOST: "ASK_LWA_TOKEN_HOST",
23 | ASK_SMAPI_SERVER_BASE_URL: "ASK_SMAPI_SERVER_BASE_URL",
24 | };
25 |
26 | export const FILE_PATH = {
27 | ASK: {
28 | HIDDEN_FOLDER: ".ask",
29 | PROFILE_FILE: "cli_config",
30 | },
31 | };
32 |
33 | export const CONFIGURATION = {
34 | FILE_PERMISSION: {
35 | USER_READ_WRITE: "0600",
36 | },
37 | JSON_DISPLAY_INTENT: 2,
38 | };
39 |
--------------------------------------------------------------------------------
/src/runtime/lib/utils/index.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | export * from "./jsonUtility";
7 | export * from "./lwa";
8 | export * from "./oauthWrapper";
9 | export * from "./profileHelper";
10 | export * from "./stringUtils";
11 | export * from "./configuration";
12 |
--------------------------------------------------------------------------------
/src/runtime/lib/utils/jsonRead.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import {readFileSync} from "jsonfile";
7 |
8 | export function readFile(filePath: string): any {
9 | let file: any;
10 | try {
11 | file = readFileSync(filePath);
12 | } catch (e) {
13 | console.error("Invalid json: " + filePath);
14 | return null;
15 | }
16 | return file;
17 | }
18 |
19 | export function readString(str: string): any {
20 | let jsonObj: any;
21 | try {
22 | jsonObj = JSON.parse(str);
23 | } catch (e) {
24 | console.error("Invalid json string: " + str);
25 | return null;
26 | }
27 | return jsonObj;
28 | }
29 |
30 | export function getProperty(jsonObject: any, track: string): any {
31 | const trackArray: string[] = track.split(".").slice(1);
32 | let property: any = jsonObject;
33 | for (let i = 0; i < trackArray.length; i++) {
34 | if (property.hasOwnProperty(trackArray[i])) {
35 | property = property[trackArray[i]];
36 | } else {
37 | console.log('The property "' + trackArray[i] + '" does not exist.');
38 | return null;
39 | }
40 | }
41 | return property;
42 | }
43 |
--------------------------------------------------------------------------------
/src/runtime/lib/utils/serverFactory.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import {createServer, Server} from "http";
7 | import {checkPortStatus} from "portscanner";
8 |
9 | /**
10 | * Factory for localhost server instances used for LWA and CAPTCHA validation
11 | * responses.
12 | */
13 | export class ServerFactory {
14 | private static server: Server;
15 |
16 | /**
17 | * Gets an instance of an HTTP server.
18 | * Currently locked to port 9090.
19 | */
20 | public static async getInstance(): Promise {
21 | if (this.server) {
22 | this.server.close();
23 | }
24 | const SERVER_PORT = 9090;
25 | const portStatus = await checkPortStatus(SERVER_PORT);
26 | if (portStatus === "open") {
27 | throw new Error("LWA listening port already in use.");
28 | }
29 | this.server = createServer();
30 | return this.server;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/runtime/lib/utils/stringUtils.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import {is, isEmpty} from "ramda";
7 |
8 | export function isNonEmptyString(str: string | undefined): boolean {
9 | return str !== undefined && is(String, str) && !isEmpty(str);
10 | }
11 |
12 | export function isNonBlankString(str: string | undefined): boolean {
13 | return isNonEmptyString(str) && str !== undefined && !!str.trim();
14 | }
15 |
16 | /**
17 | * Check if input string is a valid lambda function name
18 | * @param {string} str
19 | */
20 | export function isLambdaFunctionName(str: string): boolean {
21 | if (!isNonBlankString(str)) {
22 | return false;
23 | }
24 |
25 | // This regex can be used to check if the str
26 | // could be a valid lambda function name
27 | const lambdaFunctionNameRegex = /^([a-zA-Z0-9-_]+)$/;
28 | return lambdaFunctionNameRegex.test(str);
29 | }
30 |
31 | /**
32 | * Check if the input string is a meaningful diff result or only contains header message
33 | */
34 | export function hasDiffContent(str: string): boolean {
35 | if (!isNonBlankString(str)) {
36 | return false;
37 | }
38 |
39 | const lines = str.split(/\r\n|\n/);
40 |
41 | // Exclude the case when string only contains three lines of headers (diff example shown as below):
42 | // ===================================================================
43 | // --- local {filename}
44 | // +++ remote {filename}
45 | // (new line)
46 | if (lines.length <= 4) {
47 | return false;
48 | }
49 |
50 | // Exclude when there is no line starting with "-" or "+"
51 | for (const line of lines) {
52 | if ((line.startsWith("-") && !line.startsWith("---")) || (line.startsWith("+") && !line.startsWith("+++"))) {
53 | return true;
54 | }
55 | }
56 | return false;
57 | }
58 |
59 | /**
60 | * Filter non-alphanumeric in a string and remove the character
61 | * @param {string} str
62 | */
63 | export function filterNonAlphanumeric(str: string): string {
64 | if (!str) {
65 | return str;
66 | }
67 | return str.replace(/[^a-zA-Z0-9-]+/g, "");
68 | }
69 |
--------------------------------------------------------------------------------
/src/utils/avs/avsInterface.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 |
7 | export interface IDirective {
8 | header: IHeader;
9 | payload: any;
10 | }
11 |
12 | export interface IHeader {
13 | namespace: string;
14 | name: string;
15 | messageId?: string;
16 | dialogRequestId?: string;
17 | }
18 |
19 | export interface IPayload {}
20 |
21 | /**
22 | * This payload is for the directive of SkillDebugger.CaptureDebuggingInfo.
23 | */
24 | export interface ISkillDebuggerPayload extends IPayload {
25 | skillId: string | null;
26 | type: string; // "ConsideredIntents" or "SkillExecutionInfo".
27 | content: any;
28 | }
29 |
30 | export interface ISkillDebuggerContent {
31 | invocationRequest: any;
32 | invocationResponse: any;
33 | }
34 |
35 | /**
36 | * This payload is for the directive of SpeechSynthesizer.speak.
37 | */
38 | export interface ISpeakPayload extends IPayload {
39 | caption: any;
40 | format: string;
41 | token: string;
42 | }
43 |
44 | /**
45 | * This payload is for the directive of Alexa.Presentation.APL.RenderDocument.
46 | */
47 | export interface IAplDocumentPayload extends IPayload {
48 | presentationToken: string;
49 | document: any;
50 | datasources?: any;
51 | }
52 |
53 | /**
54 | * This payload is for the directive of Alexa.Presentation.APL.ExecuteCommands.
55 | */
56 | export interface IExecuteCommandsPayload extends IPayload {
57 | presentationToken: string;
58 | commands: any;
59 | }
60 |
61 | export interface IDeviceCodeResponse {
62 | user_code: string;
63 | device_code: string;
64 | verification_uri: string;
65 | expires_in: number;
66 | interval: number;
67 | }
68 |
69 | export interface IEvent {
70 | header: IHeader;
71 | payload: any;
72 | }
73 |
74 | export interface IEventPack {
75 | event: IEvent;
76 | context: IEvent[];
77 | }
78 |
--------------------------------------------------------------------------------
/src/utils/avs/simulateAVSHelper.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 |
7 | import * as vscode from "vscode";
8 | import * as simulateReplayHelper from "../../utils/simulateReplayHelper";
9 | import {EXTENSION_STATE_KEY, SIMULATOR_MESSAGE_TYPE} from "../../constants";
10 | import {Logger} from "../../logger";
11 | import {readDeviceToken} from "./deviceTokenUtil";
12 | import {AVSClient} from "./avsClient";
13 |
14 | /**
15 | * Generate apeechCall AVS for the text utterances.
16 | */
17 | export async function callAvsForRecognizeEvent(
18 | userInput: string,
19 | isNewSession: boolean,
20 | context: vscode.ExtensionContext,
21 | ): Promise> {
22 | Logger.verbose(`Calling method: simulateAVSHelper.callAvsForRecognizeEvent`);
23 | const token = await readDeviceToken(context);
24 | const region = await context.secrets.get(EXTENSION_STATE_KEY.REGISTERED_DEVICE.REGION);
25 | if (isNewSession) {
26 | await AVSClient.getInstance(token, context, region).sendNewSessionEvent();
27 | }
28 | const response = await AVSClient.getInstance(token, context).sendAudioEvent(userInput, isNewSession, context);
29 | return {
30 | invocationRequests: response.debugging.request,
31 | invocationResponses: response.debugging.response,
32 | alexaExecutionInfo: response.debugging.intent,
33 | alexaResponse: response.alexaResponse,
34 | documents: response.documents,
35 | dataSources: response.dataSources,
36 | viewport: JSON.stringify(simulateReplayHelper.aplViewport),
37 | viewportName: JSON.stringify(simulateReplayHelper.viewportName),
38 | type: SIMULATOR_MESSAGE_TYPE.UTTERANCE,
39 | aplCommands: response.aplCommands,
40 | };
41 | }
42 |
43 | /**
44 | * Call AVS with the user event callback when user click on the APL preview.
45 | * @param userEvent
46 | */
47 | export async function callAvsForAplUserEvent(
48 | userEvent: Record,
49 | context: vscode.ExtensionContext,
50 | ): Promise> {
51 | Logger.verbose(`Calling method: simulateAVSHelper.callAvsForAplUserEvent`);
52 | const token = await readDeviceToken(context);
53 | const region = await context.secrets.get(EXTENSION_STATE_KEY.REGISTERED_DEVICE.REGION);
54 | const response = await AVSClient.getInstance(token, context, region).sendUserEvent(userEvent);
55 | return {
56 | invocationRequests: "",
57 | invocationResponses: "",
58 | alexaExecutionInfo: "",
59 | alexaResponse: response.alexaResponse,
60 | documents: response.documents,
61 | dataSources: response.dataSources,
62 | viewport: JSON.stringify(simulateReplayHelper.aplViewport),
63 | viewportName: JSON.stringify(simulateReplayHelper.viewportName),
64 | type: SIMULATOR_MESSAGE_TYPE.UTTERANCE,
65 | aplCommands: response.aplCommands,
66 | };
67 | }
68 |
--------------------------------------------------------------------------------
/src/utils/commands/contactToolkitTeam.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | "use strict";
7 | import * as vscode from "vscode";
8 |
9 | import {EXTERNAL_LINKS} from "../../constants";
10 | import {AbstractCommand, CommandContext} from "../../runtime";
11 | import {Logger} from "../../logger";
12 |
13 | export class ContactToolkitTeamCommand extends AbstractCommand {
14 | protected feedbackOptions = new Map();
15 |
16 | constructor() {
17 | super("ask.contactToolkitTeam");
18 |
19 | for (const option of Object.values(EXTERNAL_LINKS.CONTACT_ALEXA_TEAM)) {
20 | this.feedbackOptions.set(option.TITLE, option.URL);
21 | }
22 | }
23 |
24 | async execute(context: CommandContext): Promise {
25 | Logger.debug(`Calling method: ${this.commandName}`);
26 |
27 | const pickedContactMethod = await vscode.window.showQuickPick(Array.from(this.feedbackOptions.keys()));
28 | if (pickedContactMethod) {
29 | await vscode.env.openExternal(vscode.Uri.parse(this.feedbackOptions.get(pickedContactMethod) as string));
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/utils/commands/getToolkitInfo.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as vscode from "vscode";
7 | import * as os from "os";
8 | import * as child_process from "child_process";
9 |
10 | import {AbstractCommand} from "../../runtime";
11 | import {Logger} from "../../logger";
12 | import {DEFAULT_ENCODING, EXTENSION_ID} from "../../constants";
13 |
14 | export class GetToolkitInfoCommand extends AbstractCommand {
15 | constructor() {
16 | super("ask.aboutToolkit");
17 | }
18 |
19 | private getToolkitDetails(): string {
20 | const osType = os.type();
21 | const osArch = os.arch();
22 | const osRelease = os.release();
23 | const vsCodeVersion = vscode.version;
24 | const gitVersionUint8Array: Uint8Array = child_process.execSync("git --version");
25 | const gitVersion = new TextDecoder(DEFAULT_ENCODING).decode(gitVersionUint8Array);
26 | const pluginVersion: string = vscode.extensions.getExtension(EXTENSION_ID)?.packageJSON.version;
27 |
28 | const toolkitDetails = `OS: ${osType} ${osArch} ${osRelease}\nVisual Studio Code Version: ${vsCodeVersion}\nAlexa Skills Toolkit Version: ${pluginVersion}\nGit Version: ${gitVersion}`;
29 |
30 | return toolkitDetails;
31 | }
32 |
33 | async execute(): Promise {
34 | Logger.debug(`Calling method: ${this.commandName}`);
35 |
36 | const toolkitEnvDetails = this.getToolkitDetails();
37 | const result = await vscode.window.showInformationMessage(toolkitEnvDetails, {modal: true}, "Copy");
38 | if (result === "Copy") {
39 | void vscode.env.clipboard.writeText(toolkitEnvDetails);
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/utils/commands/openUrl.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as vscode from "vscode";
7 | import {logAskError} from "../../exceptions";
8 | import {Logger} from "../../logger";
9 | import {AbstractCommand, CommandContext} from "../../runtime";
10 | import {checkProfileSkillAccess} from "../skillHelper";
11 |
12 | export class OpenUrlCommand extends AbstractCommand {
13 | constructor() {
14 | super("ask.container.openUrl");
15 | }
16 |
17 | async execute(context: CommandContext, url: string, skipSkillAccessCheck = false): Promise {
18 | Logger.debug(`Calling method: ${this.commandName}, args: `, url, skipSkillAccessCheck);
19 |
20 | try {
21 | if (!skipSkillAccessCheck) {
22 | checkProfileSkillAccess(context.extensionContext);
23 | }
24 | await vscode.env.openExternal(vscode.Uri.parse(url));
25 | } catch (err) {
26 | throw logAskError(`Open URL failed`, err, true);
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/utils/commands/openWorkspace.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as vscode from "vscode";
7 | import {logAskError} from "../../exceptions";
8 | import {Logger} from "../../logger";
9 | import {AbstractCommand, CommandContext} from "../../runtime";
10 | import {openWorkspaceFolder} from "../../utils/workspaceHelper";
11 |
12 | export class OpenWorkspaceCommand extends AbstractCommand {
13 | constructor() {
14 | super("ask.container.openWorkspace");
15 | }
16 |
17 | async execute(context: CommandContext): Promise {
18 | Logger.debug(`Calling method: ${this.commandName}`);
19 | const userChoseWorkSpace = await vscode.window.showOpenDialog({
20 | canSelectFiles: false,
21 | canSelectFolders: true,
22 | canSelectMany: false,
23 | });
24 | if (!userChoseWorkSpace) {
25 | throw logAskError("Cannot find a workspace to create the skill project");
26 | }
27 |
28 | await openWorkspaceFolder(userChoseWorkSpace[0]);
29 | // await vscode.commands.executeCommand('vscode.openFolder', userChoseWorkSpace[0]);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/utils/dateHelper.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import {Logger} from "../logger";
7 |
8 | export function getCurrentDate(): string {
9 | Logger.verbose(`Calling method: getCurrentDate`);
10 | const date = new Date();
11 | let month: string | number = date.getMonth() + 1;
12 | let strDate: string | number = date.getDate();
13 |
14 | if (month <= 9) {
15 | month = "0" + month;
16 | }
17 | if (strDate <= 9) {
18 | strDate = "0" + strDate;
19 | }
20 | const currentDate: string = date.getFullYear().toString() + month + strDate + date.getHours() + date.getMinutes() + date.getSeconds();
21 | return currentDate;
22 | }
23 |
--------------------------------------------------------------------------------
/src/utils/hashHelper.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as folderHash from "folder-hash";
7 |
8 | export async function getHash(sourcePath: string): Promise {
9 | const option = {algo: "sha1"};
10 | return new Promise((resolve, reject) => {
11 | // eslint-disable-next-line @typescript-eslint/no-unsafe-call
12 | folderHash.hashElement(sourcePath, "", option, (error, result) => {
13 | if (error !== null && error !== undefined) {
14 | reject(error);
15 | }
16 | // @ts-ignore
17 | resolve(result);
18 | });
19 | });
20 | }
21 |
--------------------------------------------------------------------------------
/src/utils/httpHelper.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as vscode from "vscode";
7 | import * as child_process from "child_process";
8 | import * as os from "os";
9 | import {EXTENSION_ID} from "../constants";
10 | import {Logger} from "../logger";
11 |
12 | export function resolveUserAgent(): string {
13 | Logger.verbose(`Calling method: resolveUserAgent`);
14 | const pluginVersion: string = vscode.extensions.getExtension(EXTENSION_ID)?.packageJSON.version;
15 | const vsCodeVersion = vscode.version;
16 | const osType = os.type();
17 | const osArch = os.arch();
18 | const gitVersionUint8Array: Buffer = child_process.execSync("git --version");
19 | const gitVersion = gitVersionUint8Array.toString().replace("\n", "");
20 | return `askToolkit/${pluginVersion} VSCode/${vsCodeVersion} ${osType}/${osArch} Git/${gitVersion}`;
21 | }
22 |
--------------------------------------------------------------------------------
/src/utils/mediaHelper.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as vscode from "vscode";
7 | import * as path from "path";
8 |
9 | export function getImagesFolder(context: vscode.ExtensionContext): string {
10 | return context.asAbsolutePath(path.join("third-party", "resources", "from-vscode-icons"));
11 | }
12 |
--------------------------------------------------------------------------------
/src/utils/retry.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | export async function promiseRetry(retries: number, fn: () => Promise): Promise {
7 | return fn().catch((err: Error) => {
8 | if (retries > 1) {
9 | return promiseRetry(retries - 1, fn);
10 | } else {
11 | return Promise.reject(err);
12 | }
13 | });
14 | }
15 |
--------------------------------------------------------------------------------
/src/utils/statusBarHelper.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 |
7 | "use strict";
8 | import * as vscode from "vscode";
9 |
10 | /**
11 | * Create a status bar item.
12 | * @param {number} priority The higher the priority, the more left the icon will be.
13 | * @param {string} commandName The function that will be triggered when the user click the button.
14 | * @param {string} iconText The shape and text of the button.
15 | * @param {string} tooltip The description when hovering the button.
16 | * @return {vscode.StatusBarItem}
17 | */
18 | export function createStatusBarItem(
19 | priority: number,
20 | commandName: string | undefined,
21 | iconText: string,
22 | tooltip: string,
23 | aligment: vscode.StatusBarAlignment = vscode.StatusBarAlignment.Left,
24 | ): vscode.StatusBarItem {
25 | const item = vscode.window.createStatusBarItem(aligment, priority);
26 | item.command = commandName;
27 | item.text = iconText;
28 | item.tooltip = tooltip;
29 | item.show();
30 | return item;
31 | }
32 |
--------------------------------------------------------------------------------
/src/utils/webViews/authHelper.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import {Token} from "simple-oauth2";
7 | import {EventEmitter, ExtensionContext} from "vscode";
8 | import {AbstractWebView, PluginTreeItem, Resource, Utils} from "../../runtime";
9 | import {onSkillConsoleViewChangeEventEmitter} from "../../askContainer/events";
10 | import {Logger} from "../../logger";
11 | import {DEFAULT_PROFILE, EXTENSION_STATE_KEY} from "../../constants";
12 | import {AskParameterAbsenceError} from "../../exceptions";
13 | import {ViewLoader} from "./viewLoader";
14 | import {clearCachedSkills} from "../skillHelper";
15 |
16 | export async function authenticate(
17 | context: ExtensionContext,
18 | webview?: AbstractWebView,
19 | profileName?: string,
20 | eventEmitter?: EventEmitter>,
21 | ): Promise {
22 | Logger.debug(`Calling method: authenticate, args: `, profileName);
23 | const profile = profileName ?? DEFAULT_PROFILE;
24 |
25 | if (webview && !webview.isDisposed()) {
26 | const loader = new ViewLoader(context, "profileManager", webview);
27 | webview.getPanel().webview.html = loader.renderView({
28 | name: "initiateAuthFlow",
29 | js: false,
30 | });
31 | }
32 | const token: Token = await Utils.accessTokenGenerator({});
33 | Utils.deleteProfile(profile);
34 | Utils.writeToken(token, profile);
35 | const hasVendorId = await Utils.setVendorId(profile, context);
36 | if (!hasVendorId) {
37 | Utils.deleteProfile(profile);
38 | throw new AskParameterAbsenceError("No Vendor Id.");
39 | }
40 | context.globalState.update("LwaProfile", profile);
41 | context.globalState.update("didFirstTimeLogin", true);
42 | clearCachedSkills(context);
43 | onSkillConsoleViewChangeEventEmitter.fire(undefined);
44 | }
45 |
--------------------------------------------------------------------------------
/src/utils/webViews/viewManager.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import {AbstractWebView} from "../../runtime";
7 | import {ext} from "../../extensionGlobals";
8 |
9 | export function registerWebviews(...views: AbstractWebView[]): void {
10 | views.forEach((view) => {
11 | ext.webViews.push(view);
12 | });
13 | }
14 |
15 | export function disposeWebviews(shouldRemoveWebViews?: boolean, shouldCloseGlobalViews?: boolean): void {
16 | ext.webViews.forEach((view) => {
17 | if (view !== undefined && view.getPanel() !== undefined) {
18 | // If global dispose is true, dispose all else dispose only the non global views.
19 | if (shouldCloseGlobalViews !== undefined && shouldCloseGlobalViews) {
20 | view.dispose();
21 | } else if (!view.getIsGlobal()) {
22 | view.dispose();
23 | }
24 | }
25 | });
26 | // Remove existing web views when resetting the workspace.
27 | if (shouldRemoveWebViews !== undefined && shouldRemoveWebViews) {
28 | removeWebViews();
29 | }
30 | }
31 |
32 | function removeWebViews(): void {
33 | ext.webViews.splice(0, ext.webViews.length);
34 | }
35 |
--------------------------------------------------------------------------------
/src/utils/zipHelper.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import AdmZip from "adm-zip";
7 | import * as fs from "fs";
8 | import * as path from "path";
9 | import {AskError, logAskError} from "../exceptions";
10 | import {Logger} from "../logger";
11 |
12 | export function unzipFile(zipLocation: string, destPath: string, overWriteFiles = true, deleteZipAfter = true): void {
13 | Logger.verbose(`Calling method: unzipFile, args: `, zipLocation, destPath, overWriteFiles, deleteZipAfter);
14 | const zip = new AdmZip(zipLocation);
15 | try {
16 | zip.extractAllTo(destPath, overWriteFiles);
17 |
18 | if (deleteZipAfter) {
19 | fs.unlinkSync(zipLocation);
20 | }
21 | } catch (unzipErr) {
22 | throw logAskError(`Unzip failed: ${unzipErr}`);
23 | }
24 | }
25 |
26 | export function createZipFile(sourceDir: string, zipFileDir: string): string {
27 | Logger.verbose(`Calling method: createZipFile, args: `, sourceDir, zipFileDir);
28 | try {
29 | fs.accessSync(sourceDir, fs.constants.W_OK);
30 | if (path.extname(zipFileDir) === ".zip") {
31 | throw new AskError(`The source file ${zipFileDir} has already been compressed. Skip the zipping`);
32 | }
33 | const zip = new AdmZip();
34 | zip.addLocalFolder(sourceDir);
35 | const zipFilePath = path.join(zipFileDir, "ask_tmp.zip");
36 | zip.writeZip(zipFilePath);
37 | return zipFilePath;
38 | } catch (error) {
39 | throw logAskError(`Create temp zip failed: ${error}`);
40 | }
41 | }
42 |
43 | export function zipDirectory(sourceDir: string, outDir: string): void {
44 | Logger.verbose(`Calling method: zipDirectory, args: `, sourceDir, outDir);
45 | try {
46 | const zip = new AdmZip();
47 | zip.addLocalFolder(sourceDir);
48 | const zipFilePath = path.join(outDir);
49 | zip.writeZip(zipFilePath);
50 | } catch (error) {
51 | throw logAskError(`Zip Directory failed: ${error}`);
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/test/acdlServer/completionUtils.ts:
--------------------------------------------------------------------------------
1 | import * as acdl from "@alexa/acdl";
2 | import {Apply} from "@alexa/acdl/dist/cjs/apply";
3 |
4 | export function getMockedTypeChecker(): acdl.TypeChecker {
5 | return {
6 | getVisibleNames: () => {},
7 | isNameReference: () => {},
8 | resolveNameReferenceToDecl: () => {},
9 | getType: () => {},
10 | getApply: () => {},
11 | } as unknown as acdl.TypeChecker;
12 | }
13 |
14 | export function getMockedApplyWithArgs() {
15 | const mockedArgumentDecl1 = {name: {name: "decl1"}} as acdl.ArgumentDeclaration;
16 | const mockedArgumentDecl2 = {name: {name: "decl2"}} as acdl.ArgumentDeclaration;
17 | const mockedArgumentDecl3 = {name: {name: "decl3"}} as acdl.ArgumentDeclaration;
18 | const argArray = [mockedArgumentDecl1, mockedArgumentDecl2, mockedArgumentDecl3];
19 | return {
20 | decl: {
21 | kind: "ActionDeclaration",
22 | arguments: argArray,
23 | },
24 | argumentDeclarations: argArray,
25 | };
26 | }
27 |
28 | export function getMockedApplyWithoutArgs(): Apply {
29 | return {
30 | decl: {
31 | kind: "ActionDeclaration",
32 | arguments: undefined,
33 | },
34 | } as Apply;
35 | }
36 |
--------------------------------------------------------------------------------
/test/acdlServer/mockACDL/ask-resources.json:
--------------------------------------------------------------------------------
1 | {
2 | "askcliResourcesVersion": "2020-03-31",
3 | "profiles": {
4 | "default": {
5 | "skillMetadata": {
6 | "src": "./skill-package"
7 | }
8 | }
9 | }
10 | }
--------------------------------------------------------------------------------
/test/acdlServer/mockACDL/skill-package/conversations/Weather.acdl:
--------------------------------------------------------------------------------
1 | namespace com.weatherbot
2 |
3 | import com.amazon.alexa.ask.conversations.*
4 | import com.amazon.ask.types.builtins.AMAZON.*
5 | import com.amazon.alexa.schema.Nothing
6 | import prompts.weather_apla
7 | import prompts.request_city_apla
8 | import prompts.request_date_apla
9 | import prompts.request_city_date_apla
10 |
11 | type CityAndDate {
12 | optional City cityName
13 | optional DATE date
14 | }
15 |
16 | getWeatherEvent = utterances(
17 | [
18 | "What's the weather {date} in {cityName}",
19 | "what is the weather {date}",
20 | "How is the weather {date}",
21 | "How is weather in {cityName} {date}",
22 | "how is weather",
23 | "can you please give me weather report for {date}"
24 | ]
25 | )
26 |
27 | type WeatherResult {
28 | City cityName
29 | NUMBER highTemp
30 | NUMBER lowTemp
31 | }
32 |
33 | type ResponsePayload {
34 | WeatherResult weatherResult
35 | }
36 |
37 | action WeatherResult getWeather(City cityName, DATE date)
38 |
39 | dialog Nothing Weather {
40 | sample {
41 | weatherRequest = expect(Invoke, getWeatherEvent)
42 |
43 | ensure(
44 | RequestArguments {arguments = [getWeather.arguments.cityName], response = request_city_apla},
45 | RequestArguments {arguments = [getWeather.arguments.date], response = request_date_apla},
46 | RequestArguments {arguments = [getWeather.arguments.cityName, getWeather.arguments.date], response = request_city_date_apla}
47 | )
48 |
49 | weatherResult = getWeather(weatherRequest.cityName, weatherRequest.date)
50 |
51 | response(weather_apla, Notify {actionName = getWeather}, payload = ResponsePayload {weatherResult = weatherResult})
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/test/acdlServer/mockACDL/skill-package/interactionModels/custom/en-US.json:
--------------------------------------------------------------------------------
1 | {
2 | "interactionModel": {
3 | "languageModel": {
4 | "invocationName": "my weather bot",
5 | "intents": [
6 | {
7 | "name": "AMAZON.CancelIntent",
8 | "samples": []
9 | },
10 | {
11 | "name": "AMAZON.HelpIntent",
12 | "samples": []
13 | },
14 | {
15 | "name": "AMAZON.StopIntent",
16 | "samples": []
17 | },
18 | {
19 | "name": "GetWeatherIntent",
20 | "samples": [
21 | "what is the weather",
22 | "how is the weather",
23 | "tell me the weather"
24 | ]
25 | },
26 | {
27 | "name": "AMAZON.NavigateHomeIntent",
28 | "samples": []
29 | },
30 | {
31 | "name": "AMAZON.FallbackIntent",
32 | "samples": []
33 | }
34 | ],
35 | "types": []
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/test/acdlServer/mockACDL/skill-package/response/prompts/AlexaConversationsBye/document.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "APL-A",
3 | "version": "0.1",
4 | "mainTemplate": {
5 | "parameters": [
6 | "payload"
7 | ],
8 | "item": {
9 | "type": "RandomSelector",
10 | "description": "Change 'type' above to try different Selector Component Types like Sequential",
11 | "items": [
12 | {
13 | "type": "Speech",
14 | "contentType": "text",
15 | "content": "Bye.",
16 | "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that"
17 | }
18 | ]
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/test/acdlServer/mockACDL/skill-package/response/prompts/AlexaConversationsNotifyFailure/document.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "APL-A",
3 | "version": "0.1",
4 | "mainTemplate": {
5 | "parameters": [
6 | "payload"
7 | ],
8 | "item": {
9 | "type": "RandomSelector",
10 | "description": "Change 'type' above to try different Selector Component Types like Sequential",
11 | "items": [
12 | {
13 | "type": "Speech",
14 | "contentType": "text",
15 | "content": "Sorry, there was an error in the request.",
16 | "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that"
17 | }
18 | ]
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/test/acdlServer/mockACDL/skill-package/response/prompts/AlexaConversationsOutOfDomain/document.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "APL-A",
3 | "version": "0.1",
4 | "mainTemplate": {
5 | "parameters": [
6 | "payload"
7 | ],
8 | "item": {
9 | "type": "RandomSelector",
10 | "description": "Change 'type' above to try different Selector Component Types like Sequential",
11 | "items": [
12 | {
13 | "type": "Speech",
14 | "contentType": "text",
15 | "content": "Sorry, I don't understand.",
16 | "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that"
17 | }
18 | ]
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/test/acdlServer/mockACDL/skill-package/response/prompts/AlexaConversationsProvideHelp/document.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "APL-A",
3 | "version": "0.1",
4 | "mainTemplate": {
5 | "parameters": [
6 | "payload"
7 | ],
8 | "item": {
9 | "type": "RandomSelector",
10 | "description": "Change 'type' above to try different Selector Component Types like Sequential",
11 | "items": [
12 | {
13 | "type": "Speech",
14 | "contentType": "text",
15 | "content": "I can give you the weather report. Just say \"what's the weather\" to start.",
16 | "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that"
17 | }
18 | ]
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/test/acdlServer/mockACDL/skill-package/response/prompts/AlexaConversationsRequestMore/document.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "APL-A",
3 | "version": "0.1",
4 | "mainTemplate": {
5 | "parameters": [
6 | "payload"
7 | ],
8 | "item": {
9 | "type": "RandomSelector",
10 | "description": "Change 'type' above to try different Selector Component Types like Sequential",
11 | "items": [
12 | {
13 | "type": "Speech",
14 | "contentType": "text",
15 | "content": "What do you want to do.",
16 | "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that"
17 | }
18 | ]
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/test/acdlServer/mockACDL/skill-package/response/prompts/AlexaConversationsThankYou/document.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "APL-A",
3 | "version": "0.1",
4 | "mainTemplate": {
5 | "parameters": [
6 | "payload"
7 | ],
8 | "item": {
9 | "type": "RandomSelector",
10 | "description": "Change 'type' above to try different Selector Component Types like Sequential",
11 | "items": [
12 | {
13 | "type": "Speech",
14 | "contentType": "text",
15 | "content": "Thank you.",
16 | "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that"
17 | }
18 | ]
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/test/acdlServer/mockACDL/skill-package/response/prompts/AlexaConversationsWelcome/document.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "APL-A",
3 | "version": "0.1",
4 | "mainTemplate": {
5 | "parameters": [
6 | "payload"
7 | ],
8 | "item": {
9 | "type": "RandomSelector",
10 | "description": "Change 'type' above to try different Selector Component Types like Sequential",
11 | "items": [
12 | {
13 | "type": "Speech",
14 | "contentType": "text",
15 | "content": "Welcome to the weather bot, I can give you the weather report. Just say \"what's the weather\" to start.",
16 | "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that"
17 | }
18 | ]
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/test/acdlServer/mockACDL/skill-package/response/prompts/AlexaConversationsYouAreWelcome/document.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "APL-A",
3 | "version": "0.1",
4 | "mainTemplate": {
5 | "parameters": [
6 | "payload"
7 | ],
8 | "item": {
9 | "type": "RandomSelector",
10 | "description": "Change 'type' above to try different Selector Component Types like Sequential",
11 | "items": [
12 | {
13 | "type": "Speech",
14 | "contentType": "text",
15 | "content": "You are welcome.",
16 | "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that"
17 | }
18 | ]
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/test/acdlServer/mockACDL/skill-package/response/prompts/request_city_apla/document.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "APL-A",
3 | "version": "0.1",
4 | "mainTemplate": {
5 | "parameters": [
6 | "payload"
7 | ],
8 | "item": {
9 | "type": "RandomSelector",
10 | "description": "Change 'type' above to try different Selector Component Types like Sequential",
11 | "items": [
12 | {
13 | "type": "Speech",
14 | "contentType": "text",
15 | "content": "Which city?",
16 | "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that"
17 | }
18 | ]
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/test/acdlServer/mockACDL/skill-package/response/prompts/request_city_date_apla/document.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "APL-A",
3 | "version": "0.1",
4 | "mainTemplate": {
5 | "parameters": [
6 | "payload"
7 | ],
8 | "item": {
9 | "type": "RandomSelector",
10 | "description": "Change 'type' above to try different Selector Component Types like Sequential",
11 | "items": [
12 | {
13 | "type": "Speech",
14 | "contentType": "text",
15 | "content": "Which city and for which date?",
16 | "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that"
17 | }
18 | ]
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/test/acdlServer/mockACDL/skill-package/response/prompts/request_date_apla/document.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "APL-A",
3 | "version": "0.1",
4 | "mainTemplate": {
5 | "parameters": [
6 | "payload"
7 | ],
8 | "item": {
9 | "type": "RandomSelector",
10 | "description": "Change 'type' above to try different Selector Component Types like Sequential",
11 | "items": [
12 | {
13 | "type": "Speech",
14 | "contentType": "text",
15 | "content": "Which date?",
16 | "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that"
17 | }
18 | ]
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/test/acdlServer/mockACDL/skill-package/response/prompts/weather_apla/document.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "APL-A",
3 | "version": "0.1",
4 | "mainTemplate": {
5 | "parameters": [
6 | "payload"
7 | ],
8 | "item": {
9 | "type": "RandomSelector",
10 | "description": "Change 'type' above to try different Selector Component Types like Sequential",
11 | "items": [
12 | {
13 | "when": "${payload.weatherResult != null && payload.weatherResult.cityName != null && payload.weatherResult.highTemp != null && payload.weatherResult.lowTemp != null}",
14 | "type": "Speech",
15 | "contentType": "text",
16 | "content": "In ${payload.weatherResult.cityName}, it's a high of ${payload.weatherResult.highTemp} degrees and a low of ${payload.weatherResult.lowTemp} degrees.",
17 | "description": "Expand on 'items' array to add multiple prompts, use response template arguments by adding it to 'content' like this ${payload.input_argument_name} and add SSML by changing 'contentType' to 'SSML' and adding SSML to 'content' like that"
18 | }
19 | ]
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/test/acdlServer/mockACDL/skill-package/skill.json:
--------------------------------------------------------------------------------
1 | {
2 | "manifest": {
3 | "publishingInformation": {
4 | "locales": {
5 | "en-US": {
6 | "summary": "Sample Short Description",
7 | "examplePhrases": [
8 | "Alexa open my weather bot",
9 | "hello",
10 | "help"
11 | ],
12 | "name": "template-weather-bot-blank",
13 | "description": "Sample Full Description"
14 | }
15 | },
16 | "isAvailableWorldwide": true,
17 | "testingInstructions": "Sample Testing Instructions.",
18 | "category": "KNOWLEDGE_AND_TRIVIA",
19 | "distributionCountries": []
20 | },
21 | "apis": {
22 | "custom": {
23 | "dialogManagement": {
24 | "sessionStartDelegationStrategy": {
25 | "target": "AMAZON.Conversations"
26 | },
27 | "dialogManagers": [
28 | {
29 | "type": "AMAZON.Conversations"
30 | }
31 | ]
32 | }
33 | }
34 | },
35 | "manifestVersion": "1.0"
36 | }
37 | }
--------------------------------------------------------------------------------
/test/askContainer/commands/deviceRegistry.test.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as vscode from "vscode";
7 | import * as assert from "assert";
8 | import * as sinon from "sinon";
9 |
10 | import {DeviceRegistryCommand} from "../../../src/askContainer/commands/deviceRegistryCommand";
11 | import {stubTelemetryClient} from "../../../test/testUtilities";
12 |
13 | describe("Command askContainer.skillsConsole.deviceRegistry", () => {
14 | let command: DeviceRegistryCommand;
15 | let sandbox: sinon.SinonSandbox;
16 |
17 | after(() => {
18 | command.dispose();
19 | });
20 | beforeEach(() => {
21 | sandbox = sinon.createSandbox();
22 | stubTelemetryClient(sandbox);
23 | });
24 |
25 | afterEach(() => {
26 | sandbox.restore();
27 | });
28 |
29 | it("Should show the view when executed", async () => {
30 | const showViewSpy = sinon.spy();
31 |
32 | command = new DeviceRegistryCommand({showView: showViewSpy} as any, "askContainer.skillsConsole.deviceRegistryTest");
33 | /*
34 | undefined argument due to
35 |
36 | https://code.visualstudio.com/api/references/contribution-points#contributes.menus
37 | Note: When a command is invoked from a (context) menu, VS Code tries to infer the currently selected resource
38 | and passes that as a parameter when invoking the command.
39 |
40 | */
41 | await vscode.commands.executeCommand("askContainer.skillsConsole.deviceRegistryTest", undefined);
42 |
43 | assert.ok(showViewSpy.called);
44 | });
45 | });
46 |
--------------------------------------------------------------------------------
/test/askContainer/webview/profileManagerWebview.test.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as assert from "assert";
7 | import * as sinon from "sinon";
8 | import * as vscode from "vscode";
9 | import {ProfileManagerWebview} from "../../../src/askContainer/webViews/profileManagerWebview";
10 | import {FakeExtensionContext, FakeWebviewPanelOnDidChangeViewStateEvent} from "../../testUtilities";
11 | import {EXTENSION_STATE_KEY} from "../../../src/constants";
12 |
13 | describe("Webview_deploySkill tests", () => {
14 | let webView: ProfileManagerWebview;
15 | let sandbox: sinon.SinonSandbox;
16 |
17 | beforeEach(() => {
18 | sandbox = sinon.createSandbox();
19 | });
20 |
21 | afterEach(() => {
22 | sandbox.restore();
23 | });
24 |
25 | it("When message is deleteProfile, should display error message if profileName equals current profile", async () => {
26 | const fakeContext = FakeExtensionContext.getFakeExtContext();
27 | fakeContext.globalState.update(EXTENSION_STATE_KEY.LWA_PROFILE, "fakeProfileName");
28 | webView = new ProfileManagerWebview("fakeTitle", "fakeID", fakeContext);
29 |
30 | const message = {deleteProfile: "fakeProfileName"};
31 | const spy = sinon.spy(vscode.window, "showErrorMessage");
32 |
33 | await webView.onReceiveMessageListener(message);
34 | assert.deepStrictEqual(true, spy.called);
35 | });
36 | });
37 |
--------------------------------------------------------------------------------
/test/definitionUtils.ts:
--------------------------------------------------------------------------------
1 | import * as acdl from "@alexa/acdl";
2 | import {uinteger} from "vscode-languageclient";
3 | import {SourceLocation} from "@alexa/acdl";
4 | import {Position} from "vscode-languageserver/node";
5 |
6 | export function createMockNode(typeStr: string, name: string, uri: string, loc: acdl.SourceLocation | undefined): T {
7 | return {
8 | loc,
9 | kind: typeStr,
10 | name: {name, uri, loc} as acdl.Name,
11 | } as unknown as T;
12 | }
13 |
14 | export function createSrcLocation(
15 | startLine: uinteger,
16 | startCharacter: uinteger,
17 | endLine: uinteger,
18 | endCharacter: uinteger,
19 | ): SourceLocation {
20 | return {
21 | begin: {line: startLine, character: startCharacter},
22 | end: {line: endLine, character: endCharacter},
23 | };
24 | }
25 |
26 | export function createMockTypeChecker(): acdl.TypeChecker {
27 | return {
28 | lookupName: () => {},
29 | } as unknown as acdl.TypeChecker;
30 | }
31 |
32 | export function convertACDLToVSCodeSrcPosition(line: number, char: number): Position {
33 | return {line: line - 1, character: char};
34 | }
35 |
36 | export function convertVSCodeToACDLSrcPosition(line: number, char: number): Position {
37 | return {line: line + 1, character: char};
38 | }
39 |
--------------------------------------------------------------------------------
/test/extension.test.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | "use stirct";
7 |
8 | import * as assert from "assert";
9 | import * as vscode from "vscode";
10 | import {EXTENSION_PUBLISHER, EXTENSION_FULL_NAME} from "../src/constants";
11 | import {ext} from "../src/extensionGlobals";
12 | import * as sinon from "sinon";
13 | import * as s3ScriptChecker from "../src/utils/s3ScriptChecker";
14 |
15 | const extensionId = `${EXTENSION_PUBLISHER}.${EXTENSION_FULL_NAME}`;
16 |
17 | describe("Alexa Skill Kit Extension", () => {
18 | let extension: vscode.Extension | undefined;
19 |
20 | it("Extension should be present", () => {
21 | extension = vscode.extensions.getExtension(extensionId);
22 | assert.ok(extension !== undefined);
23 | });
24 |
25 | it("should activate", async () => {
26 | extension = vscode.extensions.getExtension(extensionId);
27 | if (extension !== undefined) {
28 | sinon.stub(s3ScriptChecker, "checkAllSkillS3Scripts");
29 | await extension.activate();
30 | assert.ok(extension.isActive);
31 | } else {
32 | assert.fail("Extension is not available");
33 | }
34 | });
35 |
36 | after(() => {
37 | ext.askGeneralCommands.forEach((command) => {
38 | command.dispose();
39 | });
40 | });
41 | });
42 |
--------------------------------------------------------------------------------
/test/index.ts:
--------------------------------------------------------------------------------
1 | // PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING
2 | //
3 | // This file is providing the test runner to use when running extension tests.
4 | // By default the test runner in use is Mocha based.
5 | //
6 | // You can provide your own test runner if you want to override it by exporting
7 | // a function run(testRoot: string, clb: (error:Error) => void) that the extension
8 | // host can call to run the tests. The test runner is expected to use console.log
9 | // to report the results back to the caller. When the tests are finished, return
10 | // a possible error to the callback or null if none.
11 |
12 | /* eslint-disable eslint-comments/disable-enable-pair */
13 | /* eslint-disable @typescript-eslint/no-this-alias */
14 | /* eslint-disable prefer-const */
15 | /* eslint-disable @typescript-eslint/no-unsafe-call */
16 | /* eslint-disable @typescript-eslint/no-var-requires */
17 |
18 | "use strict";
19 |
20 | import * as glob from "glob";
21 | import Mocha from "mocha";
22 | import * as paths from "path";
23 |
24 | // The test coverage approach is inspired by https://github.com/microsoft/vscode-js-debug/blob/master/src/test/testRunner.ts
25 | function setupCoverage() {
26 | const NYC = require("nyc");
27 | const nyc = new NYC({
28 | // set the project root
29 | cwd: paths.join(__dirname, "..", ".."),
30 | exclude: ["**/test/**", ".vscode-test/**"],
31 | reporter: ["html"],
32 | tempDir: paths.join(__dirname, "..", "..", "coverage", ".nyc_output"),
33 | all: true,
34 | instrument: true,
35 | hookRequire: true,
36 | hookRunInContext: true,
37 | hookRunInThisContext: true,
38 | });
39 |
40 | nyc.reset();
41 | nyc.wrap();
42 |
43 | // eslint-disable-next-line @typescript-eslint/no-unsafe-return
44 | return nyc;
45 | }
46 |
47 | const mocha = new Mocha({
48 | ui: "bdd",
49 | color: true,
50 | timeout: 30 * 1000, // for windows extension activation test
51 | });
52 |
53 | export async function run(): Promise {
54 | let nyc;
55 | if (shouldGenerateCoverage()) {
56 | nyc = setupCoverage();
57 | }
58 | // only search test files under out/test
59 | const testsRoot = paths.resolve(__dirname, "..");
60 | const options = {cwd: testsRoot};
61 | const files = glob.sync("**/**.test.js", options);
62 | for (const file of files) {
63 | mocha.addFile(paths.resolve(testsRoot, file));
64 | }
65 | try {
66 | await new Promise((resolve, reject) =>
67 | mocha.run((failures) => (failures ? reject(new Error(`${failures} tests failed`)) : resolve())),
68 | );
69 | } finally {
70 | if (nyc !== undefined) {
71 | nyc.writeCoverageFile();
72 | nyc.report();
73 | }
74 | }
75 | }
76 |
77 | function shouldGenerateCoverage(): boolean {
78 | // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
79 | return (process.env.ASK_TOOLKIT_NO_COVERAGE || "false").toLowerCase() !== "true";
80 | }
81 |
--------------------------------------------------------------------------------
/test/mockSkill/skill-package-NHS/skill.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexa/ask-toolkit-for-vscode/2fd1033f594a3281e1612d51d0c216a14e5e344d/test/mockSkill/skill-package-NHS/skill.txt
--------------------------------------------------------------------------------
/test/mockSkill/skill-package/alexaSkill.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexa/ask-toolkit-for-vscode/2fd1033f594a3281e1612d51d0c216a14e5e344d/test/mockSkill/skill-package/alexaSkill.json
--------------------------------------------------------------------------------
/test/mockSkill/skill-package/interaction/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexa/ask-toolkit-for-vscode/2fd1033f594a3281e1612d51d0c216a14e5e344d/test/mockSkill/skill-package/interaction/.gitkeep
--------------------------------------------------------------------------------
/test/mockSkill/skill-package/interactionModels/custom/en-US.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexa/ask-toolkit-for-vscode/2fd1033f594a3281e1612d51d0c216a14e5e344d/test/mockSkill/skill-package/interactionModels/custom/en-US.json
--------------------------------------------------------------------------------
/test/mockSkill/skill-package/skill.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexa/ask-toolkit-for-vscode/2fd1033f594a3281e1612d51d0c216a14e5e344d/test/mockSkill/skill-package/skill.json
--------------------------------------------------------------------------------
/test/runTest.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as path from "path";
7 |
8 | import {runTests} from "vscode-test";
9 | import {env} from "process";
10 |
11 | async function main() {
12 | try {
13 | // The folder containing the Extension Manifest package.json
14 | // Passed to `--extensionDevelopmentPath`
15 | const extensionDevelopmentPath = path.resolve(__dirname, "../../");
16 |
17 | // The path to the extension test runner script
18 | // Passed to --extensionTestsPath
19 | const extensionTestsPath = path.resolve(__dirname, "./");
20 |
21 | env.ASK_TOOLKIT_IGNORE_WEBPACK_BUNDLE = "true";
22 |
23 | // Download VS Code, unzip it and run the integration test
24 | await runTests({
25 | extensionDevelopmentPath,
26 | extensionTestsPath,
27 | launchArgs: ["--disable-extensions"],
28 | });
29 | } catch (err) {
30 | console.error(err);
31 | console.error("Failed to run tests");
32 | process.exit(1);
33 | }
34 | }
35 |
36 | // eslint-disable-next-line no-void
37 | void main();
38 |
--------------------------------------------------------------------------------
/test/utils/commands/debugAdapterPath.test.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as assert from "assert";
7 | import child_process from "child_process";
8 | import fs from "fs";
9 | import * as path from "path";
10 | import * as sinon from "sinon";
11 | import * as vscode from "vscode";
12 | import {DebugAdapterPathCommand} from "../../../src/askContainer/commands/local-debug/debugAdapterPath";
13 | import {LOCAL_DEBUG} from "../../../src/constants";
14 | import {stubTelemetryClient} from "../../../test/testUtilities";
15 |
16 | describe("Command ask.debugAdapterPath", () => {
17 | let command: DebugAdapterPathCommand;
18 | let sandbox: sinon.SinonSandbox;
19 | let commandId: string;
20 | before(() => {
21 | command = new DebugAdapterPathCommand();
22 | commandId = command.commandName;
23 | });
24 | after(() => {
25 | command.dispose();
26 | });
27 | beforeEach(() => {
28 | sandbox = sinon.createSandbox();
29 | stubTelemetryClient(sandbox);
30 | });
31 |
32 | afterEach(() => {
33 | sandbox.restore();
34 | });
35 |
36 | it("Constructor should work as expected", () => {
37 | assert.strictEqual(command.title, commandId);
38 | assert.strictEqual(command.command, commandId);
39 | });
40 |
41 | it("Should be able to return node local debugger path from the installed node_modules", async () => {
42 | const mockedDebugArgs = {
43 | type: "pwa-node",
44 | };
45 | const fakePath = [{fsPath: "test"}];
46 |
47 | sandbox.stub(vscode.workspace, "findFiles").resolves(fakePath);
48 |
49 | const debuggerPath = await vscode.commands.executeCommand(commandId, mockedDebugArgs);
50 | assert.ok(debuggerPath === fakePath[0].fsPath);
51 | });
52 |
53 | it("Should be able to return python local debugger path from the installed node_modules", async () => {
54 | const mockPythonPath = "test/site-packages";
55 | const localDebuggerPath = path.join(mockPythonPath, LOCAL_DEBUG.PYTHON_DEPENDENCIES.DEP_PATH);
56 | const mockedDebugArgs = {
57 | type: "python",
58 | pythonPath: mockPythonPath,
59 | };
60 | const testSitePkgLocation = "['test/site-packages']";
61 |
62 | sandbox.stub(child_process, "execSync");
63 | sandbox.stub(TextDecoder.prototype, "decode").returns(testSitePkgLocation);
64 | sandbox.stub(fs, "existsSync").withArgs(localDebuggerPath).returns(true);
65 |
66 | const debuggerPath = await vscode.commands.executeCommand(commandId, mockedDebugArgs);
67 | assert.ok(debuggerPath === localDebuggerPath);
68 | });
69 | });
70 |
--------------------------------------------------------------------------------
/test/utils/commands/openUrl.test.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as vscode from "vscode";
7 | import * as assert from "assert";
8 | import * as sinon from "sinon";
9 |
10 | import {OpenUrlCommand} from "../../../src/utils/commands/openUrl";
11 | import * as skillHelper from "../../../src/utils/skillHelper";
12 | import {stubTelemetryClient} from "../../../test/testUtilities";
13 | describe("Command ask.container.openUrl", () => {
14 | let command: OpenUrlCommand;
15 | let sandbox: sinon.SinonSandbox;
16 | let commandId: string;
17 | before(() => {
18 | command = new OpenUrlCommand();
19 | commandId = command.commandName;
20 | });
21 | after(() => {
22 | command.dispose();
23 | });
24 | beforeEach(() => {
25 | sandbox = sinon.createSandbox();
26 | stubTelemetryClient(sandbox);
27 | });
28 |
29 | afterEach(() => {
30 | sandbox.restore();
31 | });
32 | it("Constructor should work as expected", () => {
33 | assert.strictEqual(command.title, commandId);
34 | assert.strictEqual(command.command, commandId);
35 | });
36 |
37 | it("Should check skillProfileAccess by default", async () => {
38 | const testUrl = "https://test.com";
39 | const skillAccessStub = sandbox.stub(skillHelper, "checkProfileSkillAccess");
40 | const openExternalStub = sandbox.stub(vscode.env, "openExternal");
41 | await vscode.commands.executeCommand(commandId, testUrl);
42 | assert.ok(skillAccessStub.calledOnce);
43 | assert.ok(openExternalStub.calledOnceWith(vscode.Uri.parse(testUrl)));
44 | });
45 |
46 | it("Should be able to skip skillProfileAccess", async () => {
47 | const testUrl = "https://test.com";
48 | const skillAccessStub = sandbox.stub(skillHelper, "checkProfileSkillAccess");
49 | const openExternalStub = sandbox.stub(vscode.env, "openExternal");
50 | await vscode.commands.executeCommand(commandId, testUrl, true);
51 | assert.ok(skillAccessStub.notCalled);
52 | assert.ok(openExternalStub.calledOnceWith(vscode.Uri.parse(testUrl)));
53 | });
54 |
55 | it.skip("Should throw error when open url failed", async () => {
56 | const testUrl = "https://test.com";
57 | sandbox.stub(skillHelper, "checkProfileSkillAccess");
58 | sandbox.stub(vscode.env, "openExternal").throws(new Error("foo"));
59 | try {
60 | await vscode.commands.executeCommand(commandId, testUrl, true);
61 | } catch (e) {
62 | assert.strictEqual(e.message, `Running the contributed command: '${commandId}' failed.`);
63 | return;
64 | }
65 | assert.fail("Should throw an error");
66 | });
67 | });
68 |
--------------------------------------------------------------------------------
/test/utils/commands/openWorkspace.test.ts:
--------------------------------------------------------------------------------
1 | /*---------------------------------------------------------------------------------------------
2 | * Alexa Skills Toolkit for Visual Studio Code
3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | * SPDX-License-Identifier: Apache-2.0
5 | *--------------------------------------------------------------------------------------------*/
6 | import * as vscode from "vscode";
7 | import * as assert from "assert";
8 | import * as sinon from "sinon";
9 |
10 | import {OpenWorkspaceCommand} from "../../../src/utils/commands/openWorkspace";
11 | import * as workSpaceHelper from "../../../src/utils/workspaceHelper";
12 | import {stubTelemetryClient} from "../../../test/testUtilities";
13 |
14 | describe("Command ask.container.openWorkspace", () => {
15 | let command: OpenWorkspaceCommand;
16 | let sandbox: sinon.SinonSandbox;
17 | let commandId: string;
18 | before(() => {
19 | command = new OpenWorkspaceCommand();
20 | commandId = command.commandName;
21 | });
22 | after(() => {
23 | command.dispose();
24 | });
25 | beforeEach(() => {
26 | sandbox = sinon.createSandbox();
27 | stubTelemetryClient(sandbox);
28 | });
29 |
30 | afterEach(() => {
31 | sandbox.restore();
32 | });
33 | it("Constructor should work as expected", () => {
34 | assert.strictEqual(command.title, commandId);
35 | assert.strictEqual(command.command, commandId);
36 | });
37 |
38 | it("Should be able to call showOpenDialog with fixed config, and openWorkSpace folder with user provided path", async () => {
39 | const fakePath = ["fakePath"];
40 | const showOpenDialogStub = sandbox.stub(vscode.window, "showOpenDialog").resolves(fakePath);
41 | const openWorkspaceStub = sandbox.stub(workSpaceHelper, "openWorkspaceFolder");
42 | const expectedConfig = {
43 | canSelectFiles: false,
44 | canSelectFolders: true,
45 | canSelectMany: false,
46 | };
47 | await vscode.commands.executeCommand(commandId);
48 | assert.ok(showOpenDialogStub.calledOnceWith(expectedConfig));
49 | assert.ok(openWorkspaceStub.calledOnceWith(fakePath[0]));
50 | });
51 |
52 | it.skip("Should throw error when no workspace provided by user", async () => {
53 | sandbox.stub(vscode.window, "showOpenDialog").resolves(undefined);
54 |
55 | try {
56 | await vscode.commands.executeCommand(commandId);
57 | } catch (e) {
58 | assert.strictEqual(e.message, `Running the contributed command: '${commandId}' failed.`);
59 |
60 | return;
61 | }
62 | assert.fail("Should throw an error");
63 | });
64 | });
65 |
--------------------------------------------------------------------------------
/test/utils/gitHelper.test.ts:
--------------------------------------------------------------------------------
1 | import {existsSync, mkdirSync} from "fs";
2 | import {removeSync} from "fs-extra";
3 | import * as assert from "assert";
4 | import os from "os";
5 | import * as fs from "fs";
6 | import sinon from "sinon";
7 | import * as path from "path";
8 | import {LogLevel} from "../../src/logger";
9 | import {GitInTerminalHelper} from "../../src/utils/gitHelper";
10 | import {SYSTEM_ASK_FOLDER} from "../../src/constants";
11 |
12 | describe("GitInTerminalHelper tests", () => {
13 | let sandbox: sinon.SinonSandbox;
14 |
15 | beforeEach(() => {
16 | sandbox = sinon.createSandbox();
17 | });
18 |
19 | afterEach(() => {
20 | sandbox.restore();
21 | });
22 |
23 | describe("init", () => {
24 | const tmpDir = os.tmpdir();
25 | const emptyDir = `${tmpDir}/gitHelperTest`;
26 | beforeEach(() => {
27 | if (!existsSync(emptyDir)) {
28 | mkdirSync(emptyDir);
29 | }
30 | });
31 |
32 | afterEach(() => {
33 | if (existsSync(emptyDir)) {
34 | removeSync(emptyDir);
35 | }
36 | });
37 |
38 | it("creates a .git subfolder when initializing a new repository", () => {
39 | const helper = new GitInTerminalHelper(emptyDir, LogLevel.off);
40 | helper.init();
41 | assert.strictEqual(existsSync(`${emptyDir}/.git`), true);
42 | });
43 | });
44 |
45 | describe("getCurrentBranch", () => {
46 | it("returns the branch 'master'", () => {
47 | const helper = new GitInTerminalHelper("mockRepo", LogLevel.off);
48 | sandbox.stub(helper, "_execChildProcessSync").returns("master");
49 | const currentBranch = helper.getCurrentBranch();
50 | assert.strictEqual(
51 | currentBranch,
52 | "master",
53 | `Current branch not equal to master. Current branch: ${currentBranch}\nRepository location: ${helper.folderPath}`,
54 | );
55 | });
56 | });
57 | });
58 |
--------------------------------------------------------------------------------
/third-party/README.md:
--------------------------------------------------------------------------------
1 | # Third Party components
2 |
3 | ## VS Code Icons
4 |
5 | Some UI icons are sourced from [Visual Studio Code Icons](https://github.com/microsoft/vscode-icons). These files are located within [third-party/resources/from-vscode-icons](resources/from-vscode-icons).
6 |
--------------------------------------------------------------------------------
/third-party/resources/from-vscode-icons/dark/open-preview.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/third-party/resources/from-vscode-icons/dark/refresh.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/third-party/resources/from-vscode-icons/light/open-preview.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/third-party/resources/from-vscode-icons/light/refresh.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tsconfig.eslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "include": [".eslintrc.js"]
4 | }
5 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "alwaysStrict": true,
4 | "declaration": true,
5 | "declarationMap": true,
6 | "downlevelIteration": true,
7 | "esModuleInterop": true,
8 | "forceConsistentCasingInFileNames": true,
9 | "inlineSourceMap": false,
10 | "lib": ["DOM", "ES2019", "ES5", "ES6", "ES2020.Promise", "ESNext.AsyncIterable", "ES2019.Array"],
11 | "module": "CommonJS",
12 | "moduleResolution": "Node",
13 | "noEmitOnError": false,
14 | "noFallthroughCasesInSwitch": true,
15 | "noImplicitAny": false,
16 | "noImplicitReturns": true,
17 | "noImplicitThis": true,
18 | "noUnusedLocals": false,
19 | "noUnusedParameters": false,
20 | "resolveJsonModule": true,
21 | "skipLibCheck": true,
22 | "strict": false, // FIXME: turn off temporarily after bumping up the TS version
23 | "strictBindCallApply": true,
24 | "strictFunctionTypes": false,
25 | "strictNullChecks": true,
26 | "strictPropertyInitialization": false,
27 | "target": "ES2018",
28 | "useDefineForClassFields": true,
29 | "outDir": "out",
30 | "rootDir": ".",
31 | "sourceMap": true
32 | },
33 | "exclude": ["node_modules", ".vscode-test", "out"]
34 | }
35 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 |
3 | "use strict";
4 |
5 | const path = require("path");
6 | const CopyPlugin = require("copy-webpack-plugin");
7 |
8 | /**@type {import('webpack').Configuration}*/
9 | const config = {
10 | target: "node", // vscode extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/
11 |
12 | entry: {
13 | extension: "./src/extension.ts",
14 | "server/acdlServer": "./src/acdlServer/index.ts",
15 | }, // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/
16 | output: {
17 | filename: "[name].js",
18 | libraryTarget: "commonjs2",
19 | devtoolModuleFilenameTemplate: "../[resource-path]",
20 | },
21 | devtool: "source-map",
22 | externals: {
23 | vscode: "commonjs vscode", // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/
24 | },
25 | resolve: {
26 | // support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader
27 | extensions: [".ts", ".js"],
28 | },
29 | module: {
30 | rules: [
31 | {
32 | test: /\.ts$/,
33 | exclude: /node_modules/,
34 | use: [
35 | {
36 | loader: "ts-loader",
37 | },
38 | ],
39 | },
40 | ],
41 | },
42 | plugins: [
43 | new CopyPlugin({
44 | patterns: [
45 | {from: "./node_modules/@alexa/acdl/dist/lib", to: "lib"},
46 | {from: "./node_modules/@alexa/ask-expressions-spec/", to: "node_modules/@alexa/ask-expressions-spec"},
47 | ],
48 | }),
49 | ],
50 | };
51 | module.exports = config;
52 |
--------------------------------------------------------------------------------