@microsoft/m365-spec-parser 0.2.1-rc-hotfix.0 → 0.2.2-alpha.4a7c0c761.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.
@@ -17,10 +17,12 @@ var ErrorType;
17
17
  ErrorType["RelativeServerUrlNotSupported"] = "relative-server-url-not-supported";
18
18
  ErrorType["NoSupportedApi"] = "no-supported-api";
19
19
  ErrorType["NoExtraAPICanBeAdded"] = "no-extra-api-can-be-added";
20
+ ErrorType["AddedAPINotInOriginalSpec"] = "added-api-not-in-original-spec";
20
21
  ErrorType["ResolveServerUrlFailed"] = "resolve-server-url-failed";
21
22
  ErrorType["SwaggerNotSupported"] = "swagger-not-supported";
22
23
  ErrorType["MultipleAuthNotSupported"] = "multiple-auth-not-supported";
23
24
  ErrorType["SpecVersionNotSupported"] = "spec-version-not-supported";
25
+ ErrorType["CircularReferenceNotSupported"] = "circular-reference-not-supported";
24
26
  ErrorType["ListFailed"] = "list-failed";
25
27
  ErrorType["listSupportedAPIInfoFailed"] = "list-supported-api-info-failed";
26
28
  ErrorType["FilterSpecFailed"] = "filter-spec-failed";
@@ -257,7 +259,7 @@ class Utils {
257
259
  static updateFirstLetter(str) {
258
260
  return str.charAt(0).toUpperCase() + str.slice(1);
259
261
  }
260
- static getResponseJson(operationObject) {
262
+ static getResponseJson(operationObject, allowMultipleMediaType = false) {
261
263
  var _a, _b;
262
264
  let json = {};
263
265
  let multipleMediaType = false;
@@ -268,7 +270,9 @@ class Utils {
268
270
  json = responseObject.content["application/json"];
269
271
  if (Utils.containMultipleMediaTypes(responseObject)) {
270
272
  multipleMediaType = true;
271
- json = {};
273
+ if (!allowMultipleMediaType) {
274
+ json = {};
275
+ }
272
276
  }
273
277
  else {
274
278
  break;
@@ -536,6 +540,19 @@ class Utils {
536
540
 
537
541
  // Copyright (c) Microsoft Corporation.
538
542
  class Validator {
543
+ constructor() {
544
+ this.hasCircularReference = false;
545
+ }
546
+ checkCircularReference() {
547
+ try {
548
+ JSON.stringify(this.spec);
549
+ }
550
+ catch (e) {
551
+ if (e.message.includes("Converting circular structure to JSON")) {
552
+ this.hasCircularReference = true;
553
+ }
554
+ }
555
+ }
539
556
  listAPIs() {
540
557
  var _a;
541
558
  if (this.apiMap) {
@@ -631,6 +648,22 @@ class Validator {
631
648
  }
632
649
  return result;
633
650
  }
651
+ validateCircularReference(method, path) {
652
+ const result = { isValid: true, reason: [] };
653
+ if (this.hasCircularReference) {
654
+ const operationObject = this.spec.paths[path][method];
655
+ try {
656
+ JSON.stringify(operationObject);
657
+ }
658
+ catch (e) {
659
+ if (e.message.includes("Converting circular structure to JSON")) {
660
+ result.isValid = false;
661
+ result.reason.push(ErrorType.CircularReferenceNotSupported);
662
+ }
663
+ }
664
+ }
665
+ return result;
666
+ }
634
667
  validateResponse(method, path) {
635
668
  const result = { isValid: true, reason: [] };
636
669
  const operationObject = this.spec.paths[path][method];
@@ -819,6 +852,7 @@ class CopilotValidator extends Validator {
819
852
  this.projectType = ProjectType.Copilot;
820
853
  this.options = options;
821
854
  this.spec = spec;
855
+ this.checkCircularReference();
822
856
  }
823
857
  validateSpec() {
824
858
  const result = { errors: [], warnings: [] };
@@ -844,6 +878,10 @@ class CopilotValidator extends Validator {
844
878
  if (!methodAndPathResult.isValid) {
845
879
  return methodAndPathResult;
846
880
  }
881
+ const circularReferenceResult = this.validateCircularReference(method, path);
882
+ if (!circularReferenceResult.isValid) {
883
+ return circularReferenceResult;
884
+ }
847
885
  const operationObject = this.spec.paths[path][method];
848
886
  // validate auth
849
887
  const authCheckResult = this.validateAuth(method, path);
@@ -887,6 +925,7 @@ class SMEValidator extends Validator {
887
925
  this.projectType = ProjectType.SME;
888
926
  this.options = options;
889
927
  this.spec = spec;
928
+ this.checkCircularReference();
890
929
  }
891
930
  validateSpec() {
892
931
  const result = { errors: [], warnings: [] };
@@ -914,6 +953,10 @@ class SMEValidator extends Validator {
914
953
  if (!methodAndPathResult.isValid) {
915
954
  return methodAndPathResult;
916
955
  }
956
+ const circularReferenceResult = this.validateCircularReference(method, path);
957
+ if (!circularReferenceResult.isValid) {
958
+ return circularReferenceResult;
959
+ }
917
960
  const operationObject = this.spec.paths[path][method];
918
961
  // validate auth
919
962
  const authCheckResult = this.validateAuth(method, path);
@@ -984,6 +1027,7 @@ class TeamsAIValidator extends Validator {
984
1027
  this.projectType = ProjectType.TeamsAi;
985
1028
  this.options = options;
986
1029
  this.spec = spec;
1030
+ this.checkCircularReference();
987
1031
  }
988
1032
  validateSpec() {
989
1033
  const result = { errors: [], warnings: [] };
@@ -1003,6 +1047,10 @@ class TeamsAIValidator extends Validator {
1003
1047
  if (!methodAndPathResult.isValid) {
1004
1048
  return methodAndPathResult;
1005
1049
  }
1050
+ const circularReferenceResult = this.validateCircularReference(method, path);
1051
+ if (!circularReferenceResult.isValid) {
1052
+ return circularReferenceResult;
1053
+ }
1006
1054
  const operationObject = this.spec.paths[path][method];
1007
1055
  // validate operationId
1008
1056
  if (!this.options.allowMissingId && !operationObject.operationId) {
@@ -1078,9 +1126,9 @@ class SpecFilter {
1078
1126
 
1079
1127
  // Copyright (c) Microsoft Corporation.
1080
1128
  class AdaptiveCardGenerator {
1081
- static generateAdaptiveCard(operationItem) {
1129
+ static generateAdaptiveCard(operationItem, allowMultipleMediaType = false) {
1082
1130
  try {
1083
- const { json } = Utils.getResponseJson(operationItem);
1131
+ const { json } = Utils.getResponseJson(operationItem, allowMultipleMediaType);
1084
1132
  let cardBody = [];
1085
1133
  let schema = json.schema;
1086
1134
  let jsonPath = "$";
@@ -1596,7 +1644,6 @@ class ManifestUpdater {
1596
1644
  const auth = authInfo.authScheme;
1597
1645
  const safeRegistrationIdName = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix[authInfo.authScheme.type]}`);
1598
1646
  if (Utils.isAPIKeyAuth(auth) || Utils.isBearerTokenAuth(auth)) {
1599
- const safeApiSecretRegistrationId = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix[authInfo.authScheme.type]}`);
1600
1647
  composeExtension.authorization = {
1601
1648
  authType: "apiSecretServiceAuth",
1602
1649
  apiSecretServiceAuthConfiguration: {
@@ -1605,16 +1652,13 @@ class ManifestUpdater {
1605
1652
  };
1606
1653
  }
1607
1654
  else if (Utils.isOAuthWithAuthCodeFlow(auth)) {
1655
+ // TODO: below schema is coming from design doc, may need to update when shcema is finalized
1608
1656
  composeExtension.authorization = {
1609
1657
  authType: "oAuth2.0",
1610
1658
  oAuthConfiguration: {
1611
1659
  oauthConfigurationId: `\${{${safeRegistrationIdName}}}`,
1612
1660
  },
1613
1661
  };
1614
- updatedPart.webApplicationInfo = {
1615
- id: "${{AAD_APP_CLIENT_ID}}",
1616
- resource: "api://${{DOMAIN}}/${{AAD_APP_CLIENT_ID}}",
1617
- };
1618
1662
  }
1619
1663
  }
1620
1664
  updatedPart.composeExtensions = [composeExtension];
@@ -1650,12 +1694,17 @@ class ManifestUpdater {
1650
1694
  command.parameters = command.parameters.filter((param) => param.isRequired);
1651
1695
  }
1652
1696
  else if (command.parameters && command.parameters.length > 0) {
1653
- command.parameters = [command.parameters[0]];
1654
- warnings.push({
1655
- type: WarningType.OperationOnlyContainsOptionalParam,
1656
- content: Utils.format(ConstantString.OperationOnlyContainsOptionalParam, command.id),
1657
- data: command.id,
1658
- });
1697
+ if (command.parameters.length > 1) {
1698
+ command.parameters = [command.parameters[0]];
1699
+ warnings.push({
1700
+ type: WarningType.OperationOnlyContainsOptionalParam,
1701
+ content: Utils.format(ConstantString.OperationOnlyContainsOptionalParam, command.id),
1702
+ data: {
1703
+ commandId: command.id,
1704
+ parameterName: command.parameters[0].name,
1705
+ },
1706
+ });
1707
+ }
1659
1708
  }
1660
1709
  if (adaptiveCardFolder) {
1661
1710
  const adaptiveCardPath = path.join(adaptiveCardFolder, command.id + ".json");
@@ -1731,7 +1780,13 @@ class SpecParser {
1731
1780
  try {
1732
1781
  try {
1733
1782
  await this.loadSpec();
1734
- await this.parser.validate(this.spec);
1783
+ if (!this.parser.$refs.circular) {
1784
+ await this.parser.validate(this.spec);
1785
+ }
1786
+ else {
1787
+ const clonedUnResolveSpec = JSON.parse(JSON.stringify(this.unResolveSpec));
1788
+ await this.parser.validate(clonedUnResolveSpec);
1789
+ }
1735
1790
  }
1736
1791
  catch (e) {
1737
1792
  return {
@@ -1822,7 +1877,7 @@ class SpecParser {
1822
1877
  if (isValid) {
1823
1878
  const serverObj = Utils.getServerObject(spec, method.toLocaleLowerCase(), path);
1824
1879
  if (serverObj) {
1825
- apiResult.server = Utils.resolveEnv(serverObj.url);
1880
+ apiResult.server = serverObj.url;
1826
1881
  }
1827
1882
  const authArray = Utils.getAuthArray(operation.security, spec);
1828
1883
  for (const auths of authArray) {
@@ -1862,7 +1917,8 @@ class SpecParser {
1862
1917
  if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
1863
1918
  throw new SpecParserError(ConstantString.CancelledMessage, ErrorType.Cancelled);
1864
1919
  }
1865
- const newSpec = (await this.parser.dereference(newUnResolvedSpec));
1920
+ const clonedUnResolveSpec = JSON.parse(JSON.stringify(newUnResolvedSpec));
1921
+ const newSpec = (await this.parser.dereference(clonedUnResolveSpec));
1866
1922
  return [newUnResolvedSpec, newSpec];
1867
1923
  }
1868
1924
  catch (err) {
@@ -1970,7 +2026,8 @@ class SpecParser {
1970
2026
  }
1971
2027
  async loadSpec() {
1972
2028
  if (!this.spec) {
1973
- this.unResolveSpec = (await this.parser.parse(this.pathOrSpec));
2029
+ const spec = (await this.parser.parse(this.pathOrSpec));
2030
+ this.unResolveSpec = this.resolveEnvForSpec(spec);
1974
2031
  // Convert swagger 2.0 to openapi 3.0
1975
2032
  if (!this.unResolveSpec.openapi && this.unResolveSpec.swagger === "2.0") {
1976
2033
  const specObj = await converter.convert(this.unResolveSpec, {});
@@ -2004,6 +2061,11 @@ class SpecParser {
2004
2061
  }
2005
2062
  await fs.outputFile(outputSpecPath, resultStr);
2006
2063
  }
2064
+ resolveEnvForSpec(spec) {
2065
+ const specString = JSON.stringify(spec);
2066
+ const specResolved = Utils.resolveEnv(specString);
2067
+ return JSON.parse(specResolved);
2068
+ }
2007
2069
  }
2008
2070
 
2009
2071
  export { AdaptiveCardGenerator, ConstantString, ErrorType, ProjectType, SpecParser, SpecParserError, Utils, ValidationStatus, WarningType };