@microsoft/m365-spec-parser 0.2.3-alpha.786f6c493.0 → 0.2.3-alpha.8abc127ff.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.
@@ -83,8 +83,6 @@ exports.ErrorType = void 0;
83
83
  ErrorType["PostBodySchemaIsNotJson"] = "post-body-schema-is-not-json";
84
84
  ErrorType["PostBodyContainsRequiredUnsupportedSchema"] = "post-body-contains-required-unsupported-schema";
85
85
  ErrorType["ParamsContainRequiredUnsupportedSchema"] = "params-contain-required-unsupported-schema";
86
- ErrorType["ParamsContainsNestedObject"] = "params-contains-nested-object";
87
- ErrorType["RequestBodyContainsNestedObject"] = "request-body-contains-nested-object";
88
86
  ErrorType["ExceededRequiredParamsLimit"] = "exceeded-required-params-limit";
89
87
  ErrorType["NoParameter"] = "no-parameter";
90
88
  ErrorType["NoAPIInfo"] = "no-api-info";
@@ -152,7 +150,7 @@ ConstantString.WrappedCardResponseLayout = "list";
152
150
  ConstantString.GetMethod = "get";
153
151
  ConstantString.PostMethod = "post";
154
152
  ConstantString.AdaptiveCardVersion = "1.5";
155
- ConstantString.AdaptiveCardSchema = "http://adaptivecards.io/schemas/adaptive-card.json";
153
+ ConstantString.AdaptiveCardSchema = "https://adaptivecards.io/schemas/adaptive-card.json";
156
154
  ConstantString.AdaptiveCardType = "AdaptiveCard";
157
155
  ConstantString.TextBlockType = "TextBlock";
158
156
  ConstantString.ImageType = "Image";
@@ -239,17 +237,6 @@ class SpecParserError extends Error {
239
237
 
240
238
  // Copyright (c) Microsoft Corporation.
241
239
  class Utils {
242
- static hasNestedObjectInSchema(schema) {
243
- if (this.isObjectSchema(schema)) {
244
- for (const property in schema.properties) {
245
- const nestedSchema = schema.properties[property];
246
- if (this.isObjectSchema(nestedSchema)) {
247
- return true;
248
- }
249
- }
250
- }
251
- return false;
252
- }
253
240
  static isObjectSchema(schema) {
254
241
  return schema.type === "object" || (!schema.type && !!schema.properties);
255
242
  }
@@ -319,27 +306,33 @@ class Utils {
319
306
  let multipleMediaType = false;
320
307
  for (const code of ConstantString.ResponseCodeFor20X) {
321
308
  const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
322
- if (responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) {
323
- for (const contentType of Object.keys(responseObject.content)) {
324
- // json media type can also be "application/json; charset=utf-8"
325
- if (contentType.indexOf("application/json") >= 0) {
326
- multipleMediaType = false;
327
- json = responseObject.content[contentType];
328
- if (Utils.containMultipleMediaTypes(responseObject)) {
329
- multipleMediaType = true;
330
- if (!allowMultipleMediaType) {
331
- json = {};
332
- }
333
- }
334
- else {
335
- return { json, multipleMediaType };
336
- }
337
- }
338
- }
309
+ if (!responseObject) {
310
+ continue;
311
+ }
312
+ multipleMediaType = Utils.containMultipleMediaTypes(responseObject);
313
+ if (!allowMultipleMediaType && multipleMediaType) {
314
+ json = {};
315
+ continue;
316
+ }
317
+ const mediaObj = Utils.getJsonContentType(responseObject);
318
+ if (Object.keys(mediaObj).length > 0) {
319
+ json = mediaObj;
320
+ return { json, multipleMediaType };
339
321
  }
340
322
  }
341
323
  return { json, multipleMediaType };
342
324
  }
325
+ static getJsonContentType(responseObject) {
326
+ if (responseObject.content) {
327
+ for (const contentType of Object.keys(responseObject.content)) {
328
+ // json media type can also be "application/json; charset=utf-8"
329
+ if (contentType.indexOf("application/json") >= 0) {
330
+ return responseObject.content[contentType];
331
+ }
332
+ }
333
+ }
334
+ return {};
335
+ }
343
336
  static convertPathToCamelCase(path) {
344
337
  const pathSegments = path.split(/[./{]/);
345
338
  const camelCaseSegments = pathSegments.map((segment) => {
@@ -375,7 +368,7 @@ class Utils {
375
368
  }
376
369
  return newStr;
377
370
  }
378
- static checkServerUrl(servers) {
371
+ static checkServerUrl(servers, allowHttp = false) {
379
372
  const errors = [];
380
373
  let serverUrl;
381
374
  try {
@@ -398,8 +391,7 @@ class Utils {
398
391
  data: servers,
399
392
  });
400
393
  }
401
- else if (protocol !== "https:") {
402
- // Http server url is not supported
394
+ else if (protocol !== "https:" && !(protocol === "http:" && allowHttp)) {
403
395
  const protocolString = protocol.slice(0, -1);
404
396
  errors.push({
405
397
  type: exports.ErrorType.UrlProtocolNotSupported,
@@ -415,10 +407,11 @@ class Utils {
415
407
  let hasTopLevelServers = false;
416
408
  let hasPathLevelServers = false;
417
409
  let hasOperationLevelServers = false;
410
+ const allowHttp = options.projectType === exports.ProjectType.Copilot;
418
411
  if (spec.servers && spec.servers.length >= 1) {
419
412
  hasTopLevelServers = true;
420
413
  // for multiple server, we only use the first url
421
- const serverErrors = Utils.checkServerUrl(spec.servers);
414
+ const serverErrors = Utils.checkServerUrl(spec.servers, allowHttp);
422
415
  errors.push(...serverErrors);
423
416
  }
424
417
  const paths = spec.paths;
@@ -426,7 +419,7 @@ class Utils {
426
419
  const methods = paths[path];
427
420
  if ((methods === null || methods === void 0 ? void 0 : methods.servers) && methods.servers.length >= 1) {
428
421
  hasPathLevelServers = true;
429
- const serverErrors = Utils.checkServerUrl(methods.servers);
422
+ const serverErrors = Utils.checkServerUrl(methods.servers, allowHttp);
430
423
  errors.push(...serverErrors);
431
424
  }
432
425
  for (const method in methods) {
@@ -434,7 +427,7 @@ class Utils {
434
427
  if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
435
428
  if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
436
429
  hasOperationLevelServers = true;
437
- const serverErrors = Utils.checkServerUrl(operationObject.servers);
430
+ const serverErrors = Utils.checkServerUrl(operationObject.servers, allowHttp);
438
431
  errors.push(...serverErrors);
439
432
  }
440
433
  }
@@ -747,8 +740,8 @@ class Validator {
747
740
  result.reason.push(exports.ErrorType.NoServerInformation);
748
741
  }
749
742
  else {
750
- // server url should be absolute url with https protocol
751
- const serverValidateResult = Utils.checkServerUrl([serverObj]);
743
+ const allowHttp = this.projectType === exports.ProjectType.Copilot;
744
+ const serverValidateResult = Utils.checkServerUrl([serverObj], allowHttp);
752
745
  result.reason.push(...serverValidateResult.map((item) => item.type));
753
746
  }
754
747
  return result;
@@ -796,11 +789,6 @@ class Validator {
796
789
  }
797
790
  const isRequiredWithoutDefault = isRequired && schema.default === undefined;
798
791
  const isCopilot = this.projectType === exports.ProjectType.Copilot;
799
- if (isCopilot && Utils.hasNestedObjectInSchema(schema)) {
800
- paramResult.isValid = false;
801
- paramResult.reason = [exports.ErrorType.RequestBodyContainsNestedObject];
802
- return paramResult;
803
- }
804
792
  if (schema.type === "string" ||
805
793
  schema.type === "integer" ||
806
794
  schema.type === "boolean" ||
@@ -848,11 +836,6 @@ class Validator {
848
836
  for (let i = 0; i < paramObject.length; i++) {
849
837
  const param = paramObject[i];
850
838
  const schema = param.schema;
851
- if (isCopilot && Utils.hasNestedObjectInSchema(schema)) {
852
- paramResult.isValid = false;
853
- paramResult.reason.push(exports.ErrorType.ParamsContainsNestedObject);
854
- continue;
855
- }
856
839
  const isRequiredWithoutDefault = param.required && schema.default === undefined;
857
840
  if (isCopilot) {
858
841
  if (isRequiredWithoutDefault) {
@@ -1327,15 +1310,152 @@ class SpecFilter {
1327
1310
  }
1328
1311
  }
1329
1312
 
1313
+ // Copyright (c) Microsoft Corporation.
1314
+ class JsonDataGenerator {
1315
+ static generate(schema) {
1316
+ return this.generateMockData(schema);
1317
+ }
1318
+ static generateMockData(schema) {
1319
+ if (this.visitedSchemas.has(schema)) {
1320
+ return null; // Prevent circular reference
1321
+ }
1322
+ this.visitedSchemas.add(schema);
1323
+ let result;
1324
+ if (schema.anyOf) {
1325
+ // Select the first schema in anyOf
1326
+ const selectedSchema = schema.anyOf[0];
1327
+ result = this.generateMockData(selectedSchema);
1328
+ }
1329
+ else if (schema.oneOf) {
1330
+ // Select the first schema in oneOf
1331
+ const selectedSchema = schema.oneOf[0];
1332
+ result = this.generateMockData(selectedSchema);
1333
+ }
1334
+ else if (schema.allOf) {
1335
+ // merge all schemas in allOf
1336
+ result = {};
1337
+ for (const subschema of schema.allOf) {
1338
+ const data = this.generateMockData(subschema);
1339
+ result = Object.assign(Object.assign({}, result), data);
1340
+ }
1341
+ }
1342
+ else {
1343
+ switch (schema.type) {
1344
+ case "string":
1345
+ if (schema.example !== undefined) {
1346
+ result = schema.example;
1347
+ }
1348
+ else if (schema.format) {
1349
+ switch (schema.format) {
1350
+ case "date-time":
1351
+ result = "2024-11-01T05:25:43.593Z";
1352
+ break;
1353
+ case "email":
1354
+ result = "example@example.com";
1355
+ break;
1356
+ case "uuid":
1357
+ result = "123e4567-e89b-12d3-a456-426614174000";
1358
+ break;
1359
+ case "ipv4":
1360
+ result = "192.168.0.1";
1361
+ break;
1362
+ case "ipv6":
1363
+ result = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
1364
+ break;
1365
+ default:
1366
+ result = "example string";
1367
+ }
1368
+ }
1369
+ else {
1370
+ result = "example string";
1371
+ }
1372
+ break;
1373
+ case "number":
1374
+ if (schema.example !== undefined) {
1375
+ result = schema.example;
1376
+ }
1377
+ else if (schema.format) {
1378
+ switch (schema.format) {
1379
+ case "float":
1380
+ result = 3.14;
1381
+ break;
1382
+ case "double":
1383
+ result = 3.14159;
1384
+ break;
1385
+ default:
1386
+ result = 123;
1387
+ }
1388
+ }
1389
+ else {
1390
+ result = 123;
1391
+ }
1392
+ break;
1393
+ case "integer":
1394
+ if (schema.example !== undefined) {
1395
+ result = schema.example;
1396
+ }
1397
+ else if (schema.format) {
1398
+ switch (schema.format) {
1399
+ case "int32":
1400
+ result = 123456;
1401
+ break;
1402
+ case "int64":
1403
+ result = 123456789;
1404
+ break;
1405
+ default:
1406
+ result = 123;
1407
+ }
1408
+ }
1409
+ else {
1410
+ result = 123;
1411
+ }
1412
+ break;
1413
+ case "boolean":
1414
+ result = schema.example !== undefined ? schema.example : true;
1415
+ break;
1416
+ case "array":
1417
+ result = [this.generateMockData(schema.items)];
1418
+ break;
1419
+ case "object":
1420
+ result = {};
1421
+ if (schema.properties) {
1422
+ for (const key in schema.properties) {
1423
+ result[key] = this.generateMockData(schema.properties[key]);
1424
+ }
1425
+ }
1426
+ break;
1427
+ default:
1428
+ result = schema.example || null;
1429
+ }
1430
+ }
1431
+ this.visitedSchemas.delete(schema);
1432
+ return result;
1433
+ }
1434
+ }
1435
+ JsonDataGenerator.visitedSchemas = new Set();
1436
+
1330
1437
  // Copyright (c) Microsoft Corporation.
1331
1438
  class AdaptiveCardGenerator {
1332
1439
  static generateAdaptiveCard(operationItem, allowMultipleMediaType = false, maxElementCount = Number.MAX_SAFE_INTEGER) {
1333
1440
  try {
1334
1441
  const { json } = Utils.getResponseJson(operationItem, allowMultipleMediaType);
1335
1442
  let cardBody = [];
1443
+ let jsonData = {};
1444
+ const warnings = [];
1445
+ const operationId = operationItem.operationId;
1336
1446
  let schema = json.schema;
1337
1447
  let jsonPath = "$";
1338
1448
  if (schema && Object.keys(schema).length > 0) {
1449
+ try {
1450
+ jsonData = JsonDataGenerator.generate(schema);
1451
+ }
1452
+ catch (err) {
1453
+ warnings.push({
1454
+ type: exports.WarningType.GenerateJsonDataFailed,
1455
+ content: Utils.format(ConstantString.GenerateJsonDataFailed, operationId, err.toString()),
1456
+ data: operationId,
1457
+ });
1458
+ }
1339
1459
  jsonPath = AdaptiveCardGenerator.getResponseJsonPathFromSchema(schema);
1340
1460
  if (jsonPath !== "$") {
1341
1461
  schema = schema.properties[jsonPath];
@@ -1368,7 +1488,7 @@ class AdaptiveCardGenerator {
1368
1488
  version: ConstantString.AdaptiveCardVersion,
1369
1489
  body: cardBody,
1370
1490
  };
1371
- return [fullCard, jsonPath];
1491
+ return [fullCard, jsonPath, jsonData, warnings];
1372
1492
  }
1373
1493
  catch (err) {
1374
1494
  throw new SpecParserError(err.toString(), exports.ErrorType.GenerateAdaptiveCardFailed);
@@ -1698,36 +1818,11 @@ class ManifestUpdater {
1698
1818
  for (const method in operations) {
1699
1819
  if (options.allowMethods.includes(method)) {
1700
1820
  const operationItem = operations[method];
1701
- const confirmationBodies = [];
1702
1821
  if (operationItem) {
1703
1822
  const operationId = operationItem.operationId;
1704
1823
  const safeFunctionName = operationId.replace(/[^a-zA-Z0-9]/g, "_");
1705
1824
  const description = (_a = operationItem.description) !== null && _a !== void 0 ? _a : "";
1706
1825
  const summary = operationItem.summary;
1707
- const paramObject = operationItem.parameters;
1708
- const requestBody = operationItem.requestBody;
1709
- if (paramObject) {
1710
- for (let i = 0; i < paramObject.length; i++) {
1711
- const param = paramObject[i];
1712
- const schema = param.schema;
1713
- ManifestUpdater.checkSchema(schema, method, pathUrl);
1714
- confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(param.name));
1715
- }
1716
- }
1717
- if (requestBody) {
1718
- const requestJsonBody = requestBody.content["application/json"];
1719
- const requestBodySchema = requestJsonBody.schema;
1720
- if (Utils.isObjectSchema(requestBodySchema)) {
1721
- for (const property in requestBodySchema.properties) {
1722
- const schema = requestBodySchema.properties[property];
1723
- ManifestUpdater.checkSchema(schema, method, pathUrl);
1724
- confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(property));
1725
- }
1726
- }
1727
- else {
1728
- throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(requestBodySchema)), exports.ErrorType.UpdateManifestFailed);
1729
- }
1730
- }
1731
1826
  let funcDescription = operationItem.description || operationItem.summary || "";
1732
1827
  if (funcDescription.length > ConstantString.FunctionDescriptionMaxLens) {
1733
1828
  warnings.push({
@@ -1761,14 +1856,39 @@ class ManifestUpdater {
1761
1856
  }
1762
1857
  }
1763
1858
  if (options.allowConfirmation && method !== ConstantString.GetMethod) {
1764
- if (!funcObj.capabilities) {
1765
- funcObj.capabilities = {};
1859
+ const paramObject = operationItem.parameters;
1860
+ const requestBody = operationItem.requestBody;
1861
+ const confirmationBodies = [];
1862
+ if (paramObject) {
1863
+ for (let i = 0; i < paramObject.length; i++) {
1864
+ const param = paramObject[i];
1865
+ const schema = param.schema;
1866
+ ManifestUpdater.checkSchema(schema, method, pathUrl);
1867
+ confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(param.name));
1868
+ }
1869
+ }
1870
+ if (requestBody) {
1871
+ const requestJsonBody = Utils.getJsonContentType(requestBody);
1872
+ const requestBodySchema = requestJsonBody.schema;
1873
+ if (Utils.isObjectSchema(requestBodySchema)) {
1874
+ for (const property in requestBodySchema.properties) {
1875
+ const schema = requestBodySchema.properties[property];
1876
+ ManifestUpdater.checkSchema(schema, method, pathUrl);
1877
+ confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(property));
1878
+ }
1879
+ }
1880
+ else {
1881
+ throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(requestBodySchema)), exports.ErrorType.UpdateManifestFailed);
1882
+ }
1766
1883
  }
1767
- funcObj.capabilities.confirmation = {
1768
- type: "AdaptiveCard",
1769
- title: (_b = operationItem.summary) !== null && _b !== void 0 ? _b : description,
1770
- };
1771
1884
  if (confirmationBodies.length > 0) {
1885
+ if (!funcObj.capabilities) {
1886
+ funcObj.capabilities = {};
1887
+ }
1888
+ funcObj.capabilities.confirmation = {
1889
+ type: "AdaptiveCard",
1890
+ title: (_b = operationItem.summary) !== null && _b !== void 0 ? _b : description,
1891
+ };
1772
1892
  funcObj.capabilities.confirmation.body = confirmationBodies.join("\n");
1773
1893
  }
1774
1894
  }
@@ -1983,130 +2103,6 @@ class ManifestUpdater {
1983
2103
  }
1984
2104
  }
1985
2105
 
1986
- // Copyright (c) Microsoft Corporation.
1987
- class JsonDataGenerator {
1988
- static generate(schema) {
1989
- return this.generateMockData(schema);
1990
- }
1991
- static generateMockData(schema) {
1992
- if (this.visitedSchemas.has(schema)) {
1993
- return null; // Prevent circular reference
1994
- }
1995
- this.visitedSchemas.add(schema);
1996
- let result;
1997
- if (schema.anyOf) {
1998
- // Select the first schema in anyOf
1999
- const selectedSchema = schema.anyOf[0];
2000
- result = this.generateMockData(selectedSchema);
2001
- }
2002
- else if (schema.oneOf) {
2003
- // Select the first schema in oneOf
2004
- const selectedSchema = schema.oneOf[0];
2005
- result = this.generateMockData(selectedSchema);
2006
- }
2007
- else if (schema.allOf) {
2008
- // merge all schemas in allOf
2009
- result = {};
2010
- for (const subschema of schema.allOf) {
2011
- const data = this.generateMockData(subschema);
2012
- result = Object.assign(Object.assign({}, result), data);
2013
- }
2014
- }
2015
- else {
2016
- switch (schema.type) {
2017
- case "string":
2018
- if (schema.example !== undefined) {
2019
- result = schema.example;
2020
- }
2021
- else if (schema.format) {
2022
- switch (schema.format) {
2023
- case "date-time":
2024
- result = "2024-11-01T05:25:43.593Z";
2025
- break;
2026
- case "email":
2027
- result = "example@example.com";
2028
- break;
2029
- case "uuid":
2030
- result = "123e4567-e89b-12d3-a456-426614174000";
2031
- break;
2032
- case "ipv4":
2033
- result = "192.168.0.1";
2034
- break;
2035
- case "ipv6":
2036
- result = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
2037
- break;
2038
- default:
2039
- result = "example string";
2040
- }
2041
- }
2042
- else {
2043
- result = "example string";
2044
- }
2045
- break;
2046
- case "number":
2047
- if (schema.example !== undefined) {
2048
- result = schema.example;
2049
- }
2050
- else if (schema.format) {
2051
- switch (schema.format) {
2052
- case "float":
2053
- result = 3.14;
2054
- break;
2055
- case "double":
2056
- result = 3.14159;
2057
- break;
2058
- default:
2059
- result = 123;
2060
- }
2061
- }
2062
- else {
2063
- result = 123;
2064
- }
2065
- break;
2066
- case "integer":
2067
- if (schema.example !== undefined) {
2068
- result = schema.example;
2069
- }
2070
- else if (schema.format) {
2071
- switch (schema.format) {
2072
- case "int32":
2073
- result = 123456;
2074
- break;
2075
- case "int64":
2076
- result = 123456789;
2077
- break;
2078
- default:
2079
- result = 123;
2080
- }
2081
- }
2082
- else {
2083
- result = 123;
2084
- }
2085
- break;
2086
- case "boolean":
2087
- result = schema.example !== undefined ? schema.example : true;
2088
- break;
2089
- case "array":
2090
- result = [this.generateMockData(schema.items)];
2091
- break;
2092
- case "object":
2093
- result = {};
2094
- if (schema.properties) {
2095
- for (const key in schema.properties) {
2096
- result[key] = this.generateMockData(schema.properties[key]);
2097
- }
2098
- }
2099
- break;
2100
- default:
2101
- result = schema.example || null;
2102
- }
2103
- }
2104
- this.visitedSchemas.delete(schema);
2105
- return result;
2106
- }
2107
- }
2108
- JsonDataGenerator.visitedSchemas = new Set();
2109
-
2110
2106
  // Copyright (c) Microsoft Corporation.
2111
2107
  /**
2112
2108
  * A class that parses an OpenAPI specification file and provides methods to validate, list, and generate artifacts.
@@ -2415,25 +2411,11 @@ class SpecParser {
2415
2411
  if (this.options.allowMethods.includes(method)) {
2416
2412
  const operation = newSpec.paths[url][method];
2417
2413
  try {
2418
- const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operation);
2414
+ const [card, jsonPath, jsonData, warnings] = AdaptiveCardGenerator.generateAdaptiveCard(operation);
2415
+ result.warnings.push(...warnings);
2419
2416
  const safeAdaptiveCardName = operation.operationId.replace(/[^a-zA-Z0-9]/g, "_");
2420
2417
  const fileName = path__default['default'].join(adaptiveCardFolder, `${safeAdaptiveCardName}.json`);
2421
2418
  const wrappedCard = wrapAdaptiveCard(card, jsonPath);
2422
- const { json } = Utils.getResponseJson(operation, false);
2423
- const schema = json.schema;
2424
- let jsonData = {};
2425
- if (schema && Object.keys(schema).length > 0) {
2426
- try {
2427
- jsonData = JsonDataGenerator.generate(schema);
2428
- }
2429
- catch (err) {
2430
- result.warnings.push({
2431
- type: exports.WarningType.GenerateJsonDataFailed,
2432
- content: Utils.format(ConstantString.GenerateJsonDataFailed, operation.operationId, err.toString()),
2433
- data: operation.operationId,
2434
- });
2435
- }
2436
- }
2437
2419
  yield fs__default['default'].outputJSON(fileName, wrappedCard, { spaces: 2 });
2438
2420
  const dataFileName = path__default['default'].join(adaptiveCardFolder, `${safeAdaptiveCardName}.data.json`);
2439
2421
  yield fs__default['default'].outputJSON(dataFileName, jsonData, { spaces: 2 });