@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.
@@ -7,6 +7,7 @@ var converter = require('swagger2openapi');
7
7
  var jsyaml = require('js-yaml');
8
8
  var fs = require('fs-extra');
9
9
  var path = require('path');
10
+ var crypto = require('crypto');
10
11
 
11
12
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
12
13
 
@@ -100,6 +101,7 @@ exports.WarningType = void 0;
100
101
  WarningType["GenerateCardFailed"] = "generate-card-failed";
101
102
  WarningType["OperationOnlyContainsOptionalParam"] = "operation-only-contains-optional-param";
102
103
  WarningType["ConvertSwaggerToOpenAPI"] = "convert-swagger-to-openapi";
104
+ WarningType["FuncDescriptionTooLong"] = "function-description-too-long";
103
105
  WarningType["Unknown"] = "unknown";
104
106
  })(exports.WarningType || (exports.WarningType = {}));
105
107
  /**
@@ -138,6 +140,7 @@ ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please conve
138
140
  ConstantString.SpecVersionNotSupported = "Unsupported OpenAPI version %s. Please use version 3.0.x.";
139
141
  ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
140
142
  ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
143
+ 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.";
141
144
  ConstantString.WrappedCardVersion = "devPreview";
142
145
  ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
143
146
  ConstantString.WrappedCardResponseLayout = "list";
@@ -217,8 +220,9 @@ ConstantString.ConversationStarterMaxLens = 50;
217
220
  ConstantString.CommandTitleMaxLens = 32;
218
221
  ConstantString.ParameterTitleMaxLens = 32;
219
222
  ConstantString.SMERequiredParamsMaxNum = 5;
223
+ ConstantString.FunctionDescriptionMaxLens = 100;
220
224
  ConstantString.DefaultPluginId = "plugin_1";
221
- ConstantString.PluginManifestSchema = "https://aka.ms/json-schemas/copilot-extensions/v2.1/plugin.schema.json";
225
+ ConstantString.PluginManifestSchema = "https://aka.ms/json-schemas/copilot/plugin/v2.1/schema.json";
222
226
 
223
227
  // Copyright (c) Microsoft Corporation.
224
228
  class SpecParserError extends Error {
@@ -1638,7 +1642,7 @@ function inferProperties(card) {
1638
1642
 
1639
1643
  // Copyright (c) Microsoft Corporation.
1640
1644
  class ManifestUpdater {
1641
- static updateManifestWithAiPlugin(manifestPath, outputSpecPath, apiPluginFilePath, spec, options, authInfo) {
1645
+ static updateManifestWithAiPlugin(manifestPath, outputSpecPath, apiPluginFilePath, spec, options, authInfo, existingPluginManifestInfo) {
1642
1646
  return __awaiter(this, void 0, void 0, function* () {
1643
1647
  const manifest = yield fs__default['default'].readJSON(manifestPath);
1644
1648
  const apiPluginRelativePath = ManifestUpdater.getRelativePath(manifestPath, apiPluginFilePath);
@@ -1655,7 +1659,7 @@ class ManifestUpdater {
1655
1659
  }
1656
1660
  const appName = this.removeEnvs(manifest.name.short);
1657
1661
  const specRelativePath = ManifestUpdater.getRelativePath(manifestPath, outputSpecPath);
1658
- const [apiPlugin, warnings] = yield ManifestUpdater.generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authInfo, options);
1662
+ const [apiPlugin, warnings] = yield ManifestUpdater.generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authInfo, options, existingPluginManifestInfo);
1659
1663
  return [manifest, apiPlugin, warnings];
1660
1664
  });
1661
1665
  }
@@ -1678,7 +1682,7 @@ class ManifestUpdater {
1678
1682
  throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(schema)), exports.ErrorType.UpdateManifestFailed);
1679
1683
  }
1680
1684
  }
1681
- static generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authInfo, options) {
1685
+ static generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authInfo, options, existingPluginManifestInfo) {
1682
1686
  var _a, _b, _c, _d;
1683
1687
  return __awaiter(this, void 0, void 0, function* () {
1684
1688
  const warnings = [];
@@ -1738,9 +1742,18 @@ class ManifestUpdater {
1738
1742
  throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(requestBodySchema)), exports.ErrorType.UpdateManifestFailed);
1739
1743
  }
1740
1744
  }
1745
+ let funcDescription = operationItem.description || operationItem.summary || "";
1746
+ if (funcDescription.length > ConstantString.FunctionDescriptionMaxLens) {
1747
+ warnings.push({
1748
+ type: exports.WarningType.FuncDescriptionTooLong,
1749
+ content: Utils.format(ConstantString.FuncDescriptionTooLong, safeFunctionName, funcDescription.length.toString(), ConstantString.FunctionDescriptionMaxLens.toString()),
1750
+ data: safeFunctionName,
1751
+ });
1752
+ funcDescription = funcDescription.slice(0, ConstantString.FunctionDescriptionMaxLens);
1753
+ }
1741
1754
  const funcObj = {
1742
1755
  name: safeFunctionName,
1743
- description: description,
1756
+ description: funcDescription,
1744
1757
  };
1745
1758
  if (options.allowResponseSemantics) {
1746
1759
  try {
@@ -1789,6 +1802,10 @@ class ManifestUpdater {
1789
1802
  if (yield fs__default['default'].pathExists(apiPluginFilePath)) {
1790
1803
  apiPlugin = yield fs__default['default'].readJSON(apiPluginFilePath);
1791
1804
  }
1805
+ else if (existingPluginManifestInfo &&
1806
+ (yield fs__default['default'].pathExists(existingPluginManifestInfo.manifestPath))) {
1807
+ apiPlugin = yield fs__default['default'].readJSON(existingPluginManifestInfo.manifestPath);
1808
+ }
1792
1809
  else {
1793
1810
  apiPlugin = {
1794
1811
  $schema: ConstantString.PluginManifestSchema,
@@ -1811,6 +1828,11 @@ class ManifestUpdater {
1811
1828
  }
1812
1829
  }
1813
1830
  apiPlugin.runtimes = apiPlugin.runtimes || [];
1831
+ // Need to delete previous runtime since spec path has changed
1832
+ if (existingPluginManifestInfo) {
1833
+ const relativePath = ManifestUpdater.getRelativePath(existingPluginManifestInfo.manifestPath, existingPluginManifestInfo.specPath);
1834
+ apiPlugin.runtimes = apiPlugin.runtimes.filter((runtime) => runtime.spec.url !== relativePath);
1835
+ }
1814
1836
  const index = apiPlugin.runtimes.findIndex((runtime) => {
1815
1837
  var _a, _b;
1816
1838
  return runtime.spec.url === specRelativePath &&
@@ -2013,6 +2035,7 @@ class SpecParser {
2013
2035
  validate() {
2014
2036
  return __awaiter(this, void 0, void 0, function* () {
2015
2037
  try {
2038
+ let hash = "";
2016
2039
  try {
2017
2040
  yield this.loadSpec();
2018
2041
  if (!this.parser.$refs.circular) {
@@ -2028,8 +2051,13 @@ class SpecParser {
2028
2051
  status: exports.ValidationStatus.Error,
2029
2052
  warnings: [],
2030
2053
  errors: [{ type: exports.ErrorType.SpecNotValid, content: e.toString() }],
2054
+ specHash: hash,
2031
2055
  };
2032
2056
  }
2057
+ if (this.unResolveSpec.servers) {
2058
+ const serverString = JSON.stringify(this.unResolveSpec.servers);
2059
+ hash = crypto.createHash("sha256").update(serverString).digest("hex");
2060
+ }
2033
2061
  const errors = [];
2034
2062
  const warnings = [];
2035
2063
  if (!this.options.allowSwagger && this.isSwaggerFile) {
@@ -2039,6 +2067,7 @@ class SpecParser {
2039
2067
  errors: [
2040
2068
  { type: exports.ErrorType.SwaggerNotSupported, content: ConstantString.SwaggerNotSupported },
2041
2069
  ],
2070
+ specHash: hash,
2042
2071
  };
2043
2072
  }
2044
2073
  // Remote reference not supported
@@ -2072,6 +2101,7 @@ class SpecParser {
2072
2101
  status: status,
2073
2102
  warnings: warnings,
2074
2103
  errors: errors,
2104
+ specHash: hash,
2075
2105
  };
2076
2106
  }
2077
2107
  catch (err) {
@@ -2194,7 +2224,7 @@ class SpecParser {
2194
2224
  * @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
2195
2225
  * @param pluginFilePath File path of the api plugin file to generate.
2196
2226
  */
2197
- generateForCopilot(manifestPath, filter, outputSpecPath, pluginFilePath, signal) {
2227
+ generateForCopilot(manifestPath, filter, outputSpecPath, pluginFilePath, existingPluginFilePath, signal) {
2198
2228
  return __awaiter(this, void 0, void 0, function* () {
2199
2229
  const result = {
2200
2230
  allSuccess: true,
@@ -2209,7 +2239,13 @@ class SpecParser {
2209
2239
  if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
2210
2240
  throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
2211
2241
  }
2212
- const [updatedManifest, apiPlugin, warnings] = yield ManifestUpdater.updateManifestWithAiPlugin(manifestPath, outputSpecPath, pluginFilePath, newSpec, this.options, authInfo);
2242
+ const existingPluginManifestInfo = existingPluginFilePath
2243
+ ? {
2244
+ manifestPath: existingPluginFilePath,
2245
+ specPath: this.pathOrSpec,
2246
+ }
2247
+ : undefined;
2248
+ const [updatedManifest, apiPlugin, warnings] = yield ManifestUpdater.updateManifestWithAiPlugin(manifestPath, outputSpecPath, pluginFilePath, newSpec, this.options, authInfo, existingPluginManifestInfo);
2213
2249
  result.warnings.push(...warnings);
2214
2250
  yield fs__default['default'].outputJSON(manifestPath, updatedManifest, { spaces: 4 });
2215
2251
  yield fs__default['default'].outputJSON(pluginFilePath, apiPlugin, { spaces: 4 });