@microsoft/m365-spec-parser 0.2.2-alpha.8020c3125.0 → 0.2.2-alpha.82b9276fd.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,6 +220,7 @@ 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
225
  ConstantString.PluginManifestSchema = "https://aka.ms/json-schemas/copilot-extensions/v2.1/plugin.schema.json";
222
226
 
@@ -302,23 +306,28 @@ class Utils {
302
306
  return str.charAt(0).toUpperCase() + str.slice(1);
303
307
  }
304
308
  static getResponseJson(operationObject, allowMultipleMediaType = false) {
305
- var _a, _b;
309
+ var _a;
306
310
  let json = {};
307
311
  let multipleMediaType = false;
308
312
  for (const code of ConstantString.ResponseCodeFor20X) {
309
313
  const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
310
- if ((_b = responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) === null || _b === void 0 ? void 0 : _b["application/json"]) {
311
- multipleMediaType = false;
312
- json = responseObject.content["application/json"];
313
- if (Utils.containMultipleMediaTypes(responseObject)) {
314
- multipleMediaType = true;
315
- if (!allowMultipleMediaType) {
316
- json = {};
314
+ if (responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) {
315
+ for (const contentType of Object.keys(responseObject.content)) {
316
+ // json media type can also be "application/json; charset=utf-8"
317
+ if (contentType.indexOf("application/json") >= 0) {
318
+ multipleMediaType = false;
319
+ json = responseObject.content[contentType];
320
+ if (Utils.containMultipleMediaTypes(responseObject)) {
321
+ multipleMediaType = true;
322
+ if (!allowMultipleMediaType) {
323
+ json = {};
324
+ }
325
+ }
326
+ else {
327
+ return { json, multipleMediaType };
328
+ }
317
329
  }
318
330
  }
319
- else {
320
- break;
321
- }
322
331
  }
323
332
  }
324
333
  return { json, multipleMediaType };
@@ -592,10 +601,11 @@ class Utils {
592
601
  currentCount += items.length;
593
602
  }
594
603
  else {
595
- if (currentCount < maxCount) {
596
- result.push(element);
597
- currentCount++;
598
- }
604
+ result.push(element);
605
+ currentCount++;
606
+ }
607
+ if (currentCount >= maxCount) {
608
+ break;
599
609
  }
600
610
  }
601
611
  return result;
@@ -1632,7 +1642,7 @@ function inferProperties(card) {
1632
1642
 
1633
1643
  // Copyright (c) Microsoft Corporation.
1634
1644
  class ManifestUpdater {
1635
- static updateManifestWithAiPlugin(manifestPath, outputSpecPath, apiPluginFilePath, spec, options, authInfo) {
1645
+ static updateManifestWithAiPlugin(manifestPath, outputSpecPath, apiPluginFilePath, spec, options, authInfo, existingPluginManifestInfo) {
1636
1646
  return __awaiter(this, void 0, void 0, function* () {
1637
1647
  const manifest = yield fs__default['default'].readJSON(manifestPath);
1638
1648
  const apiPluginRelativePath = ManifestUpdater.getRelativePath(manifestPath, apiPluginFilePath);
@@ -1649,7 +1659,7 @@ class ManifestUpdater {
1649
1659
  }
1650
1660
  const appName = this.removeEnvs(manifest.name.short);
1651
1661
  const specRelativePath = ManifestUpdater.getRelativePath(manifestPath, outputSpecPath);
1652
- 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);
1653
1663
  return [manifest, apiPlugin, warnings];
1654
1664
  });
1655
1665
  }
@@ -1672,7 +1682,7 @@ class ManifestUpdater {
1672
1682
  throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(schema)), exports.ErrorType.UpdateManifestFailed);
1673
1683
  }
1674
1684
  }
1675
- static generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authInfo, options) {
1685
+ static generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authInfo, options, existingPluginManifestInfo) {
1676
1686
  var _a, _b, _c, _d;
1677
1687
  return __awaiter(this, void 0, void 0, function* () {
1678
1688
  const warnings = [];
@@ -1732,9 +1742,18 @@ class ManifestUpdater {
1732
1742
  throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(requestBodySchema)), exports.ErrorType.UpdateManifestFailed);
1733
1743
  }
1734
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
+ }
1735
1754
  const funcObj = {
1736
1755
  name: safeFunctionName,
1737
- description: description,
1756
+ description: funcDescription,
1738
1757
  };
1739
1758
  if (options.allowResponseSemantics) {
1740
1759
  try {
@@ -1783,6 +1802,10 @@ class ManifestUpdater {
1783
1802
  if (yield fs__default['default'].pathExists(apiPluginFilePath)) {
1784
1803
  apiPlugin = yield fs__default['default'].readJSON(apiPluginFilePath);
1785
1804
  }
1805
+ else if (existingPluginManifestInfo &&
1806
+ (yield fs__default['default'].pathExists(existingPluginManifestInfo.manifestPath))) {
1807
+ apiPlugin = yield fs__default['default'].readJSON(existingPluginManifestInfo.manifestPath);
1808
+ }
1786
1809
  else {
1787
1810
  apiPlugin = {
1788
1811
  $schema: ConstantString.PluginManifestSchema,
@@ -1805,6 +1828,11 @@ class ManifestUpdater {
1805
1828
  }
1806
1829
  }
1807
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
+ }
1808
1836
  const index = apiPlugin.runtimes.findIndex((runtime) => {
1809
1837
  var _a, _b;
1810
1838
  return runtime.spec.url === specRelativePath &&
@@ -2007,6 +2035,7 @@ class SpecParser {
2007
2035
  validate() {
2008
2036
  return __awaiter(this, void 0, void 0, function* () {
2009
2037
  try {
2038
+ let hash = "";
2010
2039
  try {
2011
2040
  yield this.loadSpec();
2012
2041
  if (!this.parser.$refs.circular) {
@@ -2022,8 +2051,13 @@ class SpecParser {
2022
2051
  status: exports.ValidationStatus.Error,
2023
2052
  warnings: [],
2024
2053
  errors: [{ type: exports.ErrorType.SpecNotValid, content: e.toString() }],
2054
+ specHash: hash,
2025
2055
  };
2026
2056
  }
2057
+ if (this.unResolveSpec.servers) {
2058
+ const serverString = JSON.stringify(this.unResolveSpec.servers);
2059
+ hash = crypto.createHash("sha256").update(serverString).digest("hex");
2060
+ }
2027
2061
  const errors = [];
2028
2062
  const warnings = [];
2029
2063
  if (!this.options.allowSwagger && this.isSwaggerFile) {
@@ -2033,6 +2067,7 @@ class SpecParser {
2033
2067
  errors: [
2034
2068
  { type: exports.ErrorType.SwaggerNotSupported, content: ConstantString.SwaggerNotSupported },
2035
2069
  ],
2070
+ specHash: hash,
2036
2071
  };
2037
2072
  }
2038
2073
  // Remote reference not supported
@@ -2066,6 +2101,7 @@ class SpecParser {
2066
2101
  status: status,
2067
2102
  warnings: warnings,
2068
2103
  errors: errors,
2104
+ specHash: hash,
2069
2105
  };
2070
2106
  }
2071
2107
  catch (err) {
@@ -2188,7 +2224,7 @@ class SpecParser {
2188
2224
  * @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
2189
2225
  * @param pluginFilePath File path of the api plugin file to generate.
2190
2226
  */
2191
- generateForCopilot(manifestPath, filter, outputSpecPath, pluginFilePath, signal) {
2227
+ generateForCopilot(manifestPath, filter, outputSpecPath, pluginFilePath, existingPluginFilePath, signal) {
2192
2228
  return __awaiter(this, void 0, void 0, function* () {
2193
2229
  const result = {
2194
2230
  allSuccess: true,
@@ -2203,7 +2239,13 @@ class SpecParser {
2203
2239
  if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
2204
2240
  throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
2205
2241
  }
2206
- 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);
2207
2249
  result.warnings.push(...warnings);
2208
2250
  yield fs__default['default'].outputJSON(manifestPath, updatedManifest, { spaces: 4 });
2209
2251
  yield fs__default['default'].outputJSON(pluginFilePath, apiPlugin, { spaces: 4 });