@microsoft/m365-spec-parser 0.2.2-alpha.9389d4dc7.0 → 0.2.2-alpha.99de858a6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,6 +3,7 @@ import converter from 'swagger2openapi';
3
3
  import jsyaml from 'js-yaml';
4
4
  import fs from 'fs-extra';
5
5
  import path from 'path';
6
+ import { createHash } from 'crypto';
6
7
 
7
8
  // Copyright (c) Microsoft Corporation.
8
9
  /**
@@ -58,6 +59,7 @@ var WarningType;
58
59
  WarningType["GenerateCardFailed"] = "generate-card-failed";
59
60
  WarningType["OperationOnlyContainsOptionalParam"] = "operation-only-contains-optional-param";
60
61
  WarningType["ConvertSwaggerToOpenAPI"] = "convert-swagger-to-openapi";
62
+ WarningType["FuncDescriptionTooLong"] = "function-description-too-long";
61
63
  WarningType["Unknown"] = "unknown";
62
64
  })(WarningType || (WarningType = {}));
63
65
  /**
@@ -96,6 +98,7 @@ ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please conve
96
98
  ConstantString.SpecVersionNotSupported = "Unsupported OpenAPI version %s. Please use version 3.0.x.";
97
99
  ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
98
100
  ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
101
+ ConstantString.FuncDescriptionTooLong = "The description of the function '%s' is too long. The current length is %s characters, while the maximum allowed length is %s characters.";
99
102
  ConstantString.WrappedCardVersion = "devPreview";
100
103
  ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
101
104
  ConstantString.WrappedCardResponseLayout = "list";
@@ -175,8 +178,9 @@ ConstantString.ConversationStarterMaxLens = 50;
175
178
  ConstantString.CommandTitleMaxLens = 32;
176
179
  ConstantString.ParameterTitleMaxLens = 32;
177
180
  ConstantString.SMERequiredParamsMaxNum = 5;
181
+ ConstantString.FunctionDescriptionMaxLens = 100;
178
182
  ConstantString.DefaultPluginId = "plugin_1";
179
- ConstantString.PluginManifestSchema = "https://aka.ms/json-schemas/copilot-extensions/v2.1/plugin.schema.json";
183
+ ConstantString.PluginManifestSchema = "https://aka.ms/json-schemas/copilot/plugin/v2.1/schema.json";
180
184
 
181
185
  // Copyright (c) Microsoft Corporation.
182
186
  class SpecParserError extends Error {
@@ -1596,7 +1600,7 @@ function inferProperties(card) {
1596
1600
 
1597
1601
  // Copyright (c) Microsoft Corporation.
1598
1602
  class ManifestUpdater {
1599
- static async updateManifestWithAiPlugin(manifestPath, outputSpecPath, apiPluginFilePath, spec, options, authInfo) {
1603
+ static async updateManifestWithAiPlugin(manifestPath, outputSpecPath, apiPluginFilePath, spec, options, authInfo, existingPluginManifestInfo) {
1600
1604
  const manifest = await fs.readJSON(manifestPath);
1601
1605
  const apiPluginRelativePath = ManifestUpdater.getRelativePath(manifestPath, apiPluginFilePath);
1602
1606
  manifest.copilotExtensions = manifest.copilotExtensions || {};
@@ -1612,7 +1616,7 @@ class ManifestUpdater {
1612
1616
  }
1613
1617
  const appName = this.removeEnvs(manifest.name.short);
1614
1618
  const specRelativePath = ManifestUpdater.getRelativePath(manifestPath, outputSpecPath);
1615
- const [apiPlugin, warnings] = await ManifestUpdater.generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authInfo, options);
1619
+ const [apiPlugin, warnings] = await ManifestUpdater.generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authInfo, options, existingPluginManifestInfo);
1616
1620
  return [manifest, apiPlugin, warnings];
1617
1621
  }
1618
1622
  static updateManifestDescription(manifest, spec) {
@@ -1634,7 +1638,7 @@ class ManifestUpdater {
1634
1638
  throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(schema)), ErrorType.UpdateManifestFailed);
1635
1639
  }
1636
1640
  }
1637
- static async generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authInfo, options) {
1641
+ static async generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authInfo, options, existingPluginManifestInfo) {
1638
1642
  var _a, _b, _c, _d;
1639
1643
  const warnings = [];
1640
1644
  const functions = [];
@@ -1693,9 +1697,18 @@ class ManifestUpdater {
1693
1697
  throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(requestBodySchema)), ErrorType.UpdateManifestFailed);
1694
1698
  }
1695
1699
  }
1700
+ let funcDescription = operationItem.description || operationItem.summary || "";
1701
+ if (funcDescription.length > ConstantString.FunctionDescriptionMaxLens) {
1702
+ warnings.push({
1703
+ type: WarningType.FuncDescriptionTooLong,
1704
+ content: Utils.format(ConstantString.FuncDescriptionTooLong, safeFunctionName, funcDescription.length.toString(), ConstantString.FunctionDescriptionMaxLens.toString()),
1705
+ data: safeFunctionName,
1706
+ });
1707
+ funcDescription = funcDescription.slice(0, ConstantString.FunctionDescriptionMaxLens);
1708
+ }
1696
1709
  const funcObj = {
1697
1710
  name: safeFunctionName,
1698
- description: description,
1711
+ description: funcDescription,
1699
1712
  };
1700
1713
  if (options.allowResponseSemantics) {
1701
1714
  try {
@@ -1744,6 +1757,10 @@ class ManifestUpdater {
1744
1757
  if (await fs.pathExists(apiPluginFilePath)) {
1745
1758
  apiPlugin = await fs.readJSON(apiPluginFilePath);
1746
1759
  }
1760
+ else if (existingPluginManifestInfo &&
1761
+ (await fs.pathExists(existingPluginManifestInfo.manifestPath))) {
1762
+ apiPlugin = await fs.readJSON(existingPluginManifestInfo.manifestPath);
1763
+ }
1747
1764
  else {
1748
1765
  apiPlugin = {
1749
1766
  $schema: ConstantString.PluginManifestSchema,
@@ -1766,6 +1783,11 @@ class ManifestUpdater {
1766
1783
  }
1767
1784
  }
1768
1785
  apiPlugin.runtimes = apiPlugin.runtimes || [];
1786
+ // Need to delete previous runtime since spec path has changed
1787
+ if (existingPluginManifestInfo) {
1788
+ const relativePath = ManifestUpdater.getRelativePath(existingPluginManifestInfo.manifestPath, existingPluginManifestInfo.specPath);
1789
+ apiPlugin.runtimes = apiPlugin.runtimes.filter((runtime) => runtime.spec.url !== relativePath);
1790
+ }
1769
1791
  const index = apiPlugin.runtimes.findIndex((runtime) => {
1770
1792
  var _a, _b;
1771
1793
  return runtime.spec.url === specRelativePath &&
@@ -1962,6 +1984,7 @@ class SpecParser {
1962
1984
  */
1963
1985
  async validate() {
1964
1986
  try {
1987
+ let hash = "";
1965
1988
  try {
1966
1989
  await this.loadSpec();
1967
1990
  if (!this.parser.$refs.circular) {
@@ -1977,8 +2000,13 @@ class SpecParser {
1977
2000
  status: ValidationStatus.Error,
1978
2001
  warnings: [],
1979
2002
  errors: [{ type: ErrorType.SpecNotValid, content: e.toString() }],
2003
+ specHash: hash,
1980
2004
  };
1981
2005
  }
2006
+ if (this.unResolveSpec.servers) {
2007
+ const serverString = JSON.stringify(this.unResolveSpec.servers);
2008
+ hash = createHash("sha256").update(serverString).digest("hex");
2009
+ }
1982
2010
  const errors = [];
1983
2011
  const warnings = [];
1984
2012
  if (!this.options.allowSwagger && this.isSwaggerFile) {
@@ -1988,6 +2016,7 @@ class SpecParser {
1988
2016
  errors: [
1989
2017
  { type: ErrorType.SwaggerNotSupported, content: ConstantString.SwaggerNotSupported },
1990
2018
  ],
2019
+ specHash: hash,
1991
2020
  };
1992
2021
  }
1993
2022
  // Remote reference not supported
@@ -2021,6 +2050,7 @@ class SpecParser {
2021
2050
  status: status,
2022
2051
  warnings: warnings,
2023
2052
  errors: errors,
2053
+ specHash: hash,
2024
2054
  };
2025
2055
  }
2026
2056
  catch (err) {
@@ -2136,7 +2166,7 @@ class SpecParser {
2136
2166
  * @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
2137
2167
  * @param pluginFilePath File path of the api plugin file to generate.
2138
2168
  */
2139
- async generateForCopilot(manifestPath, filter, outputSpecPath, pluginFilePath, signal) {
2169
+ async generateForCopilot(manifestPath, filter, outputSpecPath, pluginFilePath, existingPluginFilePath, signal) {
2140
2170
  const result = {
2141
2171
  allSuccess: true,
2142
2172
  warnings: [],
@@ -2150,7 +2180,13 @@ class SpecParser {
2150
2180
  if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
2151
2181
  throw new SpecParserError(ConstantString.CancelledMessage, ErrorType.Cancelled);
2152
2182
  }
2153
- const [updatedManifest, apiPlugin, warnings] = await ManifestUpdater.updateManifestWithAiPlugin(manifestPath, outputSpecPath, pluginFilePath, newSpec, this.options, authInfo);
2183
+ const existingPluginManifestInfo = existingPluginFilePath
2184
+ ? {
2185
+ manifestPath: existingPluginFilePath,
2186
+ specPath: this.pathOrSpec,
2187
+ }
2188
+ : undefined;
2189
+ const [updatedManifest, apiPlugin, warnings] = await ManifestUpdater.updateManifestWithAiPlugin(manifestPath, outputSpecPath, pluginFilePath, newSpec, this.options, authInfo, existingPluginManifestInfo);
2154
2190
  result.warnings.push(...warnings);
2155
2191
  await fs.outputJSON(manifestPath, updatedManifest, { spaces: 4 });
2156
2192
  await fs.outputJSON(pluginFilePath, apiPlugin, { spaces: 4 });