@microsoft/m365-spec-parser 0.2.2-alpha.a0aeb8641.0 → 0.2.2-alpha.ab66695dd.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.
- package/dist/index.esm2017.js +16 -21
- package/dist/index.esm2017.js.map +1 -1
- package/dist/index.esm2017.mjs +56 -28
- package/dist/index.esm2017.mjs.map +1 -1
- package/dist/index.esm5.js +16 -21
- package/dist/index.esm5.js.map +1 -1
- package/dist/index.node.cjs.js +56 -28
- package/dist/index.node.cjs.js.map +1 -1
- package/dist/src/constants.d.ts +3 -1
- package/dist/src/interfaces.d.ts +6 -0
- package/dist/src/manifestUpdater.d.ts +3 -3
- package/dist/src/specParser.d.ts +1 -1
- package/dist/src/utils.d.ts +1 -0
- package/package.json +3 -3
package/dist/index.node.cjs.js
CHANGED
|
@@ -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://
|
|
225
|
+
ConstantString.PluginManifestSchema = "https://developer.microsoft.com/json-schemas/copilot/plugin/v2.1/schema.json";
|
|
222
226
|
|
|
223
227
|
// Copyright (c) Microsoft Corporation.
|
|
224
228
|
class SpecParserError extends Error {
|
|
@@ -231,16 +235,19 @@ class SpecParserError extends Error {
|
|
|
231
235
|
// Copyright (c) Microsoft Corporation.
|
|
232
236
|
class Utils {
|
|
233
237
|
static hasNestedObjectInSchema(schema) {
|
|
234
|
-
if (schema
|
|
238
|
+
if (this.isObjectSchema(schema)) {
|
|
235
239
|
for (const property in schema.properties) {
|
|
236
240
|
const nestedSchema = schema.properties[property];
|
|
237
|
-
if (nestedSchema
|
|
241
|
+
if (this.isObjectSchema(nestedSchema)) {
|
|
238
242
|
return true;
|
|
239
243
|
}
|
|
240
244
|
}
|
|
241
245
|
}
|
|
242
246
|
return false;
|
|
243
247
|
}
|
|
248
|
+
static isObjectSchema(schema) {
|
|
249
|
+
return schema.type === "object" || (!schema.type && !!schema.properties);
|
|
250
|
+
}
|
|
244
251
|
static containMultipleMediaTypes(bodyObject) {
|
|
245
252
|
return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
|
|
246
253
|
}
|
|
@@ -469,7 +476,7 @@ class Utils {
|
|
|
469
476
|
optionalParams.push(parameter);
|
|
470
477
|
}
|
|
471
478
|
}
|
|
472
|
-
else if (schema
|
|
479
|
+
else if (Utils.isObjectSchema(schema)) {
|
|
473
480
|
const { properties } = schema;
|
|
474
481
|
for (const property in properties) {
|
|
475
482
|
let isRequired = false;
|
|
@@ -807,7 +814,7 @@ class Validator {
|
|
|
807
814
|
}
|
|
808
815
|
const isRequiredWithoutDefault = isRequired && schema.default === undefined;
|
|
809
816
|
const isCopilot = this.projectType === exports.ProjectType.Copilot;
|
|
810
|
-
if (isCopilot &&
|
|
817
|
+
if (isCopilot && Utils.hasNestedObjectInSchema(schema)) {
|
|
811
818
|
paramResult.isValid = false;
|
|
812
819
|
paramResult.reason = [exports.ErrorType.RequestBodyContainsNestedObject];
|
|
813
820
|
return paramResult;
|
|
@@ -823,7 +830,7 @@ class Validator {
|
|
|
823
830
|
paramResult.optionalNum = paramResult.optionalNum + 1;
|
|
824
831
|
}
|
|
825
832
|
}
|
|
826
|
-
else if (schema
|
|
833
|
+
else if (Utils.isObjectSchema(schema)) {
|
|
827
834
|
const { properties } = schema;
|
|
828
835
|
for (const property in properties) {
|
|
829
836
|
let isRequired = false;
|
|
@@ -859,7 +866,7 @@ class Validator {
|
|
|
859
866
|
for (let i = 0; i < paramObject.length; i++) {
|
|
860
867
|
const param = paramObject[i];
|
|
861
868
|
const schema = param.schema;
|
|
862
|
-
if (isCopilot &&
|
|
869
|
+
if (isCopilot && Utils.hasNestedObjectInSchema(schema)) {
|
|
863
870
|
paramResult.isValid = false;
|
|
864
871
|
paramResult.reason.push(exports.ErrorType.ParamsContainsNestedObject);
|
|
865
872
|
continue;
|
|
@@ -902,17 +909,6 @@ class Validator {
|
|
|
902
909
|
}
|
|
903
910
|
return paramResult;
|
|
904
911
|
}
|
|
905
|
-
hasNestedObjectInSchema(schema) {
|
|
906
|
-
if (schema.type === "object") {
|
|
907
|
-
for (const property in schema.properties) {
|
|
908
|
-
const nestedSchema = schema.properties[property];
|
|
909
|
-
if (nestedSchema.type === "object") {
|
|
910
|
-
return true;
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
}
|
|
914
|
-
return false;
|
|
915
|
-
}
|
|
916
912
|
}
|
|
917
913
|
|
|
918
914
|
// Copyright (c) Microsoft Corporation.
|
|
@@ -971,7 +967,7 @@ class CopilotValidator extends Validator {
|
|
|
971
967
|
const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
|
|
972
968
|
if (requestJsonBody) {
|
|
973
969
|
const requestBodySchema = requestJsonBody.schema;
|
|
974
|
-
if (requestBodySchema
|
|
970
|
+
if (!Utils.isObjectSchema(requestBodySchema)) {
|
|
975
971
|
result.reason.push(exports.ErrorType.PostBodySchemaIsNotJson);
|
|
976
972
|
}
|
|
977
973
|
const requestBodyParamResult = this.checkPostBodySchema(requestBodySchema, requestBody.required);
|
|
@@ -1418,7 +1414,7 @@ class AdaptiveCardGenerator {
|
|
|
1418
1414
|
return [template];
|
|
1419
1415
|
}
|
|
1420
1416
|
// some schema may not contain type but contain properties
|
|
1421
|
-
if (
|
|
1417
|
+
if (Utils.isObjectSchema(schema)) {
|
|
1422
1418
|
const { properties } = schema;
|
|
1423
1419
|
const result = [];
|
|
1424
1420
|
for (const property in properties) {
|
|
@@ -1486,7 +1482,7 @@ class AdaptiveCardGenerator {
|
|
|
1486
1482
|
}
|
|
1487
1483
|
// Find the first array property in the response schema object with the well-known name
|
|
1488
1484
|
static getResponseJsonPathFromSchema(schema) {
|
|
1489
|
-
if (
|
|
1485
|
+
if (Utils.isObjectSchema(schema)) {
|
|
1490
1486
|
const { properties } = schema;
|
|
1491
1487
|
for (const property in properties) {
|
|
1492
1488
|
const schema = properties[property];
|
|
@@ -1638,7 +1634,7 @@ function inferProperties(card) {
|
|
|
1638
1634
|
|
|
1639
1635
|
// Copyright (c) Microsoft Corporation.
|
|
1640
1636
|
class ManifestUpdater {
|
|
1641
|
-
static updateManifestWithAiPlugin(manifestPath, outputSpecPath, apiPluginFilePath, spec, options, authInfo) {
|
|
1637
|
+
static updateManifestWithAiPlugin(manifestPath, outputSpecPath, apiPluginFilePath, spec, options, authInfo, existingPluginManifestInfo) {
|
|
1642
1638
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1643
1639
|
const manifest = yield fs__default['default'].readJSON(manifestPath);
|
|
1644
1640
|
const apiPluginRelativePath = ManifestUpdater.getRelativePath(manifestPath, apiPluginFilePath);
|
|
@@ -1655,7 +1651,7 @@ class ManifestUpdater {
|
|
|
1655
1651
|
}
|
|
1656
1652
|
const appName = this.removeEnvs(manifest.name.short);
|
|
1657
1653
|
const specRelativePath = ManifestUpdater.getRelativePath(manifestPath, outputSpecPath);
|
|
1658
|
-
const [apiPlugin, warnings] = yield ManifestUpdater.generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authInfo, options);
|
|
1654
|
+
const [apiPlugin, warnings] = yield ManifestUpdater.generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authInfo, options, existingPluginManifestInfo);
|
|
1659
1655
|
return [manifest, apiPlugin, warnings];
|
|
1660
1656
|
});
|
|
1661
1657
|
}
|
|
@@ -1678,7 +1674,7 @@ class ManifestUpdater {
|
|
|
1678
1674
|
throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(schema)), exports.ErrorType.UpdateManifestFailed);
|
|
1679
1675
|
}
|
|
1680
1676
|
}
|
|
1681
|
-
static generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authInfo, options) {
|
|
1677
|
+
static generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authInfo, options, existingPluginManifestInfo) {
|
|
1682
1678
|
var _a, _b, _c, _d;
|
|
1683
1679
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1684
1680
|
const warnings = [];
|
|
@@ -1727,7 +1723,7 @@ class ManifestUpdater {
|
|
|
1727
1723
|
if (requestBody) {
|
|
1728
1724
|
const requestJsonBody = requestBody.content["application/json"];
|
|
1729
1725
|
const requestBodySchema = requestJsonBody.schema;
|
|
1730
|
-
if (requestBodySchema
|
|
1726
|
+
if (Utils.isObjectSchema(requestBodySchema)) {
|
|
1731
1727
|
for (const property in requestBodySchema.properties) {
|
|
1732
1728
|
const schema = requestBodySchema.properties[property];
|
|
1733
1729
|
ManifestUpdater.checkSchema(schema, method, pathUrl);
|
|
@@ -1738,9 +1734,18 @@ class ManifestUpdater {
|
|
|
1738
1734
|
throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(requestBodySchema)), exports.ErrorType.UpdateManifestFailed);
|
|
1739
1735
|
}
|
|
1740
1736
|
}
|
|
1737
|
+
let funcDescription = operationItem.description || operationItem.summary || "";
|
|
1738
|
+
if (funcDescription.length > ConstantString.FunctionDescriptionMaxLens) {
|
|
1739
|
+
warnings.push({
|
|
1740
|
+
type: exports.WarningType.FuncDescriptionTooLong,
|
|
1741
|
+
content: Utils.format(ConstantString.FuncDescriptionTooLong, safeFunctionName, funcDescription.length.toString(), ConstantString.FunctionDescriptionMaxLens.toString()),
|
|
1742
|
+
data: safeFunctionName,
|
|
1743
|
+
});
|
|
1744
|
+
funcDescription = funcDescription.slice(0, ConstantString.FunctionDescriptionMaxLens);
|
|
1745
|
+
}
|
|
1741
1746
|
const funcObj = {
|
|
1742
1747
|
name: safeFunctionName,
|
|
1743
|
-
description:
|
|
1748
|
+
description: funcDescription,
|
|
1744
1749
|
};
|
|
1745
1750
|
if (options.allowResponseSemantics) {
|
|
1746
1751
|
try {
|
|
@@ -1789,6 +1794,10 @@ class ManifestUpdater {
|
|
|
1789
1794
|
if (yield fs__default['default'].pathExists(apiPluginFilePath)) {
|
|
1790
1795
|
apiPlugin = yield fs__default['default'].readJSON(apiPluginFilePath);
|
|
1791
1796
|
}
|
|
1797
|
+
else if (existingPluginManifestInfo &&
|
|
1798
|
+
(yield fs__default['default'].pathExists(existingPluginManifestInfo.manifestPath))) {
|
|
1799
|
+
apiPlugin = yield fs__default['default'].readJSON(existingPluginManifestInfo.manifestPath);
|
|
1800
|
+
}
|
|
1792
1801
|
else {
|
|
1793
1802
|
apiPlugin = {
|
|
1794
1803
|
$schema: ConstantString.PluginManifestSchema,
|
|
@@ -1811,6 +1820,11 @@ class ManifestUpdater {
|
|
|
1811
1820
|
}
|
|
1812
1821
|
}
|
|
1813
1822
|
apiPlugin.runtimes = apiPlugin.runtimes || [];
|
|
1823
|
+
// Need to delete previous runtime since spec path has changed
|
|
1824
|
+
if (existingPluginManifestInfo) {
|
|
1825
|
+
const relativePath = ManifestUpdater.getRelativePath(existingPluginManifestInfo.manifestPath, existingPluginManifestInfo.specPath);
|
|
1826
|
+
apiPlugin.runtimes = apiPlugin.runtimes.filter((runtime) => runtime.spec.url !== relativePath);
|
|
1827
|
+
}
|
|
1814
1828
|
const index = apiPlugin.runtimes.findIndex((runtime) => {
|
|
1815
1829
|
var _a, _b;
|
|
1816
1830
|
return runtime.spec.url === specRelativePath &&
|
|
@@ -2013,6 +2027,7 @@ class SpecParser {
|
|
|
2013
2027
|
validate() {
|
|
2014
2028
|
return __awaiter(this, void 0, void 0, function* () {
|
|
2015
2029
|
try {
|
|
2030
|
+
let hash = "";
|
|
2016
2031
|
try {
|
|
2017
2032
|
yield this.loadSpec();
|
|
2018
2033
|
if (!this.parser.$refs.circular) {
|
|
@@ -2028,8 +2043,13 @@ class SpecParser {
|
|
|
2028
2043
|
status: exports.ValidationStatus.Error,
|
|
2029
2044
|
warnings: [],
|
|
2030
2045
|
errors: [{ type: exports.ErrorType.SpecNotValid, content: e.toString() }],
|
|
2046
|
+
specHash: hash,
|
|
2031
2047
|
};
|
|
2032
2048
|
}
|
|
2049
|
+
if (this.unResolveSpec.servers) {
|
|
2050
|
+
const serverString = JSON.stringify(this.unResolveSpec.servers);
|
|
2051
|
+
hash = crypto.createHash("sha256").update(serverString).digest("hex");
|
|
2052
|
+
}
|
|
2033
2053
|
const errors = [];
|
|
2034
2054
|
const warnings = [];
|
|
2035
2055
|
if (!this.options.allowSwagger && this.isSwaggerFile) {
|
|
@@ -2039,6 +2059,7 @@ class SpecParser {
|
|
|
2039
2059
|
errors: [
|
|
2040
2060
|
{ type: exports.ErrorType.SwaggerNotSupported, content: ConstantString.SwaggerNotSupported },
|
|
2041
2061
|
],
|
|
2062
|
+
specHash: hash,
|
|
2042
2063
|
};
|
|
2043
2064
|
}
|
|
2044
2065
|
// Remote reference not supported
|
|
@@ -2072,6 +2093,7 @@ class SpecParser {
|
|
|
2072
2093
|
status: status,
|
|
2073
2094
|
warnings: warnings,
|
|
2074
2095
|
errors: errors,
|
|
2096
|
+
specHash: hash,
|
|
2075
2097
|
};
|
|
2076
2098
|
}
|
|
2077
2099
|
catch (err) {
|
|
@@ -2194,7 +2216,7 @@ class SpecParser {
|
|
|
2194
2216
|
* @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
|
|
2195
2217
|
* @param pluginFilePath File path of the api plugin file to generate.
|
|
2196
2218
|
*/
|
|
2197
|
-
generateForCopilot(manifestPath, filter, outputSpecPath, pluginFilePath, signal) {
|
|
2219
|
+
generateForCopilot(manifestPath, filter, outputSpecPath, pluginFilePath, existingPluginFilePath, signal) {
|
|
2198
2220
|
return __awaiter(this, void 0, void 0, function* () {
|
|
2199
2221
|
const result = {
|
|
2200
2222
|
allSuccess: true,
|
|
@@ -2209,7 +2231,13 @@ class SpecParser {
|
|
|
2209
2231
|
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
2210
2232
|
throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
|
|
2211
2233
|
}
|
|
2212
|
-
const
|
|
2234
|
+
const existingPluginManifestInfo = existingPluginFilePath
|
|
2235
|
+
? {
|
|
2236
|
+
manifestPath: existingPluginFilePath,
|
|
2237
|
+
specPath: this.pathOrSpec,
|
|
2238
|
+
}
|
|
2239
|
+
: undefined;
|
|
2240
|
+
const [updatedManifest, apiPlugin, warnings] = yield ManifestUpdater.updateManifestWithAiPlugin(manifestPath, outputSpecPath, pluginFilePath, newSpec, this.options, authInfo, existingPluginManifestInfo);
|
|
2213
2241
|
result.warnings.push(...warnings);
|
|
2214
2242
|
yield fs__default['default'].outputJSON(manifestPath, updatedManifest, { spaces: 4 });
|
|
2215
2243
|
yield fs__default['default'].outputJSON(pluginFilePath, apiPlugin, { spaces: 4 });
|