"use strict"; // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ManifestUtil = exports.devPreview = void 0; const fs_extra_1 = __importDefault(require("fs-extra")); const ajv_draft_04_1 = __importDefault(require("ajv-draft-04")); const ajv_formats_1 = __importDefault(require("ajv-formats")); const _2020_1 = __importDefault(require("ajv/dist/2020")); const constants_1 = require("./constants"); const node_fetch_1 = __importDefault(require("node-fetch")); __exportStar(require("./manifest"), exports); exports.devPreview = __importStar(require("./devPreviewManifest")); __exportStar(require("./pluginManifest"), exports); __exportStar(require("./declarativeCopilotManifest"), exports); class ManifestUtil { /** * Loads the manifest from the given path without validating its schema. * * @param path - The path to the manifest file. * @throws Will propagate any error thrown by the fs-extra#readJson. * * @returns The Manifest Object. */ static async loadFromPath(path) { return fs_extra_1.default.readJson(path); } /** * Writes the manifest object to the given path. * * @param path - Where to write * @param manifest - Manifest object to be saved * @throws Will propagate any error thrown by the fs-extra#writeJson. * */ static async writeToPath(path, manifest) { return fs_extra_1.default.writeJson(path, manifest, { spaces: 4 }); } /** * Validate manifest against json schema. * * @param manifest - Manifest object to be validated * @param schema - teams-app-manifest schema * @returns An empty array if it passes validation, or an array of error string otherwise. */ static validateManifestAgainstSchema(manifest, schema) { var _a, _b; let validate; if ((_a = schema.$schema) === null || _a === void 0 ? void 0 : _a.includes("2020-12")) { const ajv = new _2020_1.default({ //formats: { uri: true, email: true }, allErrors: true, strictTypes: false, }); (0, ajv_formats_1.default)(ajv, ["uri", "email", "regex"]); validate = ajv.compile(schema); } else { const ajv = new ajv_draft_04_1.default({ formats: { uri: true }, allErrors: true, strictTypes: false }); validate = ajv.compile(schema); } const valid = validate(manifest); if (!valid && validate.errors) { return Promise.resolve((_b = validate.errors) === null || _b === void 0 ? void 0 : _b.map((error) => `${error.instancePath} ${error.message || ""}`)); } else { return Promise.resolve([]); } } static async fetchSchema(manifest) { const schemaUrl = manifest.$schema; if (!schemaUrl) { throw new Error("Manifest does not have a $schema property or schema url is not provided."); } let result; try { const res = await (0, node_fetch_1.default)(schemaUrl); result = (await res.json()); } catch (e) { if (e instanceof Error) { throw new Error(`Failed to get manifest at url ${schemaUrl} due to: ${e.message}`); } else { throw new Error(`Failed to get manifest at url ${schemaUrl} due to: unknown error`); } } return result; } /** * Validate manifest against {@link TeamsAppManifest#$schema}. * * @param manifest - Manifest object to be validated * @throws Will throw if {@link TeamsAppManifest#$schema} is undefined, not valid * or there is any network failure when getting the schema. * * @returns An empty array if schema validation passes, or an array of error string otherwise. */ static async validateManifest(manifest) { const schema = await this.fetchSchema(manifest); return ManifestUtil.validateManifestAgainstSchema(manifest, schema); } /** * Parse the manifest and get properties * @param manifest */ static parseCommonProperties(manifest) { var _a, _b, _c, _d, _e; const capabilities = []; if (manifest.staticTabs && manifest.staticTabs.length > 0) { capabilities.push("staticTab"); } if (manifest.configurableTabs && manifest.configurableTabs.length > 0) { capabilities.push("configurableTab"); } if (manifest.bots && manifest.bots.length > 0) { capabilities.push("Bot"); } if (manifest.composeExtensions && manifest.composeExtensions.length > 0) { capabilities.push("MessageExtension"); } if (manifest.composeExtensions && manifest.composeExtensions.length > 0 && manifest.composeExtensions[0].composeExtensionType == "apiBased" && ((_a = manifest.composeExtensions[0].authorization) === null || _a === void 0 ? void 0 : _a.authType) == "microsoftEntra") { capabilities.push("apiMeAAD"); } const properties = { id: manifest.id, version: manifest.version, capabilities: capabilities, manifestVersion: manifest.manifestVersion, isApiME: false, isSPFx: false, }; // If it's copilot plugin app if (manifest.composeExtensions && manifest.composeExtensions.length > 0 && manifest.composeExtensions[0].composeExtensionType == "apiBased") { properties.isApiME = true; } // If it's SPFx app if (manifest.webApplicationInfo && manifest.webApplicationInfo.id && manifest.webApplicationInfo.id == constants_1.SharePointAppId) { properties.isSPFx = true; } if ((_b = manifest.copilotExtensions) === null || _b === void 0 ? void 0 : _b.plugins) { const apiPlugins = (_c = manifest.copilotExtensions) === null || _c === void 0 ? void 0 : _c.plugins; if (apiPlugins && apiPlugins.length > 0 && apiPlugins[0].file) capabilities.push("plugin"); } if ((_d = manifest.copilotExtensions) === null || _d === void 0 ? void 0 : _d.declarativeCopilots) { const copilotGpts = (_e = manifest.copilotExtensions) === null || _e === void 0 ? void 0 : _e.declarativeCopilots; if (copilotGpts && copilotGpts.length > 0) capabilities.push("copilotGpt"); } return properties; } /** * Parse the manifest and get telemetry propreties e.g. appId, capabilities etc. * @param manifest * @returns Telemetry properties */ static parseCommonTelemetryProperties(manifest) { const properties = ManifestUtil.parseCommonProperties(manifest); const telemetryProperties = {}; const propertiesMap = new Map(Object.entries(properties)); propertiesMap.forEach((value, key) => { if (Array.isArray(value)) { telemetryProperties[key] = value.join(";"); } else { telemetryProperties[key] = value; } }); return telemetryProperties; } } exports.ManifestUtil = ManifestUtil; //# sourceMappingURL=index.js.map