@microsoft/m365-spec-parser 0.2.4-alpha.ad0d7aa1a.0 → 0.2.4-alpha.af47bc3a8.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 +21 -7
- package/dist/index.esm2017.js.map +1 -1
- package/dist/index.esm2017.mjs +107 -61
- package/dist/index.esm2017.mjs.map +1 -1
- package/dist/index.esm5.js +21 -7
- package/dist/index.esm5.js.map +1 -1
- package/dist/index.node.cjs.js +110 -62
- package/dist/index.node.cjs.js.map +1 -1
- package/dist/src/constants.d.ts +1 -3
- package/dist/src/interfaces.d.ts +9 -0
- package/dist/src/manifestUpdater.d.ts +3 -3
- package/dist/src/specParser.d.ts +2 -0
- package/dist/src/utils.d.ts +3 -1
- package/package.json +4 -4
package/dist/index.node.cjs.js
CHANGED
|
@@ -9,6 +9,7 @@ var fs = require('fs-extra');
|
|
|
9
9
|
var path = require('path');
|
|
10
10
|
var teamsManifest = require('@microsoft/teams-manifest');
|
|
11
11
|
var crypto = require('crypto');
|
|
12
|
+
var jsonSchemaRefParser = require('@apidevtools/json-schema-ref-parser');
|
|
12
13
|
|
|
13
14
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
14
15
|
|
|
@@ -156,12 +157,7 @@ ConstantString.AdaptiveCardType = "AdaptiveCard";
|
|
|
156
157
|
ConstantString.TextBlockType = "TextBlock";
|
|
157
158
|
ConstantString.ImageType = "Image";
|
|
158
159
|
ConstantString.ContainerType = "Container";
|
|
159
|
-
ConstantString.RegistrationIdPostfix =
|
|
160
|
-
apiKey: "REGISTRATION_ID",
|
|
161
|
-
oauth2: "CONFIGURATION_ID",
|
|
162
|
-
http: "REGISTRATION_ID",
|
|
163
|
-
openIdConnect: "REGISTRATION_ID",
|
|
164
|
-
};
|
|
160
|
+
ConstantString.RegistrationIdPostfix = "REGISTRATION_ID";
|
|
165
161
|
ConstantString.ResponseCodeFor20X = [
|
|
166
162
|
"200",
|
|
167
163
|
"201",
|
|
@@ -173,6 +169,7 @@ ConstantString.ResponseCodeFor20X = [
|
|
|
173
169
|
"207",
|
|
174
170
|
"208",
|
|
175
171
|
"226",
|
|
172
|
+
"2XX",
|
|
176
173
|
"default",
|
|
177
174
|
];
|
|
178
175
|
ConstantString.AllOperationMethods = [
|
|
@@ -250,6 +247,9 @@ class Utils {
|
|
|
250
247
|
static isAPIKeyAuth(authScheme) {
|
|
251
248
|
return authScheme.type === "apiKey";
|
|
252
249
|
}
|
|
250
|
+
static isAPIKeyAuthButNotInCookie(authScheme) {
|
|
251
|
+
return authScheme.type === "apiKey" && authScheme.in !== "cookie";
|
|
252
|
+
}
|
|
253
253
|
static isOAuthWithAuthCodeFlow(authScheme) {
|
|
254
254
|
return !!(authScheme.type === "oauth2" &&
|
|
255
255
|
authScheme.flows &&
|
|
@@ -265,7 +265,8 @@ class Utils {
|
|
|
265
265
|
for (const auths of authSchemeArray) {
|
|
266
266
|
if (auths.length === 1) {
|
|
267
267
|
if (Utils.isOAuthWithAuthCodeFlow(auths[0].authScheme) ||
|
|
268
|
-
Utils.isBearerTokenAuth(auths[0].authScheme)
|
|
268
|
+
Utils.isBearerTokenAuth(auths[0].authScheme) ||
|
|
269
|
+
Utils.isAPIKeyAuthButNotInCookie(auths[0].authScheme)) {
|
|
269
270
|
return false;
|
|
270
271
|
}
|
|
271
272
|
}
|
|
@@ -296,6 +297,20 @@ class Utils {
|
|
|
296
297
|
result.sort((a, b) => a[0].name.localeCompare(b[0].name));
|
|
297
298
|
return result;
|
|
298
299
|
}
|
|
300
|
+
static getAuthMap(spec) {
|
|
301
|
+
const authMap = {};
|
|
302
|
+
for (const url in spec.paths) {
|
|
303
|
+
for (const method in spec.paths[url]) {
|
|
304
|
+
const operation = spec.paths[url][method];
|
|
305
|
+
const authArray = Utils.getAuthArray(operation.security, spec);
|
|
306
|
+
if (authArray && authArray.length > 0) {
|
|
307
|
+
const currentAuth = authArray[0][0];
|
|
308
|
+
authMap[operation.operationId] = currentAuth;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return authMap;
|
|
313
|
+
}
|
|
299
314
|
static getAuthInfo(spec) {
|
|
300
315
|
let authInfo = undefined;
|
|
301
316
|
for (const url in spec.paths) {
|
|
@@ -1720,7 +1735,7 @@ function inferProperties(card) {
|
|
|
1720
1735
|
|
|
1721
1736
|
// Copyright (c) Microsoft Corporation.
|
|
1722
1737
|
class ManifestUpdater {
|
|
1723
|
-
static updateManifestWithAiPlugin(manifestPath, outputSpecPath, apiPluginFilePath, spec, options,
|
|
1738
|
+
static updateManifestWithAiPlugin(manifestPath, outputSpecPath, apiPluginFilePath, spec, options, authMap, existingPluginManifestInfo) {
|
|
1724
1739
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1725
1740
|
const manifest = yield fs__default['default'].readJSON(manifestPath);
|
|
1726
1741
|
const apiPluginRelativePath = ManifestUpdater.getRelativePath(manifestPath, apiPluginFilePath);
|
|
@@ -1751,7 +1766,7 @@ class ManifestUpdater {
|
|
|
1751
1766
|
}
|
|
1752
1767
|
const appName = this.removeEnvs(manifest.name.short);
|
|
1753
1768
|
const specRelativePath = ManifestUpdater.getRelativePath(manifestPath, outputSpecPath);
|
|
1754
|
-
const [apiPlugin, warnings] = yield ManifestUpdater.generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName,
|
|
1769
|
+
const [apiPlugin, warnings] = yield ManifestUpdater.generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authMap, options, existingPluginManifestInfo);
|
|
1755
1770
|
return [manifest, apiPlugin, warnings];
|
|
1756
1771
|
});
|
|
1757
1772
|
}
|
|
@@ -1774,29 +1789,14 @@ class ManifestUpdater {
|
|
|
1774
1789
|
throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(schema)), exports.ErrorType.UpdateManifestFailed);
|
|
1775
1790
|
}
|
|
1776
1791
|
}
|
|
1777
|
-
static generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName,
|
|
1792
|
+
static generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authMap, options, existingPluginManifestInfo) {
|
|
1778
1793
|
var _a, _b, _c, _d;
|
|
1779
1794
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1780
1795
|
const warnings = [];
|
|
1781
1796
|
const functions = [];
|
|
1782
|
-
const
|
|
1797
|
+
const functionNamesMap = {};
|
|
1783
1798
|
const conversationStarters = [];
|
|
1784
1799
|
const paths = spec.paths;
|
|
1785
|
-
const pluginAuthObj = {
|
|
1786
|
-
type: "None",
|
|
1787
|
-
};
|
|
1788
|
-
if (authInfo) {
|
|
1789
|
-
if (Utils.isOAuthWithAuthCodeFlow(authInfo.authScheme)) {
|
|
1790
|
-
pluginAuthObj.type = "OAuthPluginVault";
|
|
1791
|
-
}
|
|
1792
|
-
else if (Utils.isBearerTokenAuth(authInfo.authScheme)) {
|
|
1793
|
-
pluginAuthObj.type = "ApiKeyPluginVault";
|
|
1794
|
-
}
|
|
1795
|
-
if (pluginAuthObj.type !== "None") {
|
|
1796
|
-
const safeRegistrationIdName = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix[authInfo.authScheme.type]}`);
|
|
1797
|
-
pluginAuthObj.reference_id = `\${{${safeRegistrationIdName}}}`;
|
|
1798
|
-
}
|
|
1799
|
-
}
|
|
1800
1800
|
for (const pathUrl in paths) {
|
|
1801
1801
|
const pathItem = paths[pathUrl];
|
|
1802
1802
|
if (pathItem) {
|
|
@@ -1879,7 +1879,29 @@ class ManifestUpdater {
|
|
|
1879
1879
|
}
|
|
1880
1880
|
}
|
|
1881
1881
|
functions.push(funcObj);
|
|
1882
|
-
|
|
1882
|
+
const authInfo = authMap[operationId];
|
|
1883
|
+
let key = "None";
|
|
1884
|
+
let authName = "None";
|
|
1885
|
+
if (authInfo) {
|
|
1886
|
+
if (Utils.isOAuthWithAuthCodeFlow(authInfo.authScheme)) {
|
|
1887
|
+
key = "OAuthPluginVault";
|
|
1888
|
+
authName = authInfo.name;
|
|
1889
|
+
}
|
|
1890
|
+
else if (Utils.isBearerTokenAuth(authInfo.authScheme) ||
|
|
1891
|
+
Utils.isAPIKeyAuthButNotInCookie(authInfo.authScheme)) {
|
|
1892
|
+
key = "ApiKeyPluginVault";
|
|
1893
|
+
authName = authInfo.name;
|
|
1894
|
+
}
|
|
1895
|
+
}
|
|
1896
|
+
if (functionNamesMap[key]) {
|
|
1897
|
+
functionNamesMap[key].functionNames.push(safeFunctionName);
|
|
1898
|
+
}
|
|
1899
|
+
else {
|
|
1900
|
+
functionNamesMap[key] = {
|
|
1901
|
+
functionNames: [safeFunctionName],
|
|
1902
|
+
authName: authName,
|
|
1903
|
+
};
|
|
1904
|
+
}
|
|
1883
1905
|
const conversationStarterStr = (summary !== null && summary !== void 0 ? summary : description).slice(0, ConstantString.ConversationStarterMaxLens);
|
|
1884
1906
|
if (conversationStarterStr) {
|
|
1885
1907
|
conversationStarters.push(conversationStarterStr);
|
|
@@ -1889,6 +1911,12 @@ class ManifestUpdater {
|
|
|
1889
1911
|
}
|
|
1890
1912
|
}
|
|
1891
1913
|
}
|
|
1914
|
+
if (Object.keys(functionNamesMap).length === 0) {
|
|
1915
|
+
functionNamesMap["None"] = {
|
|
1916
|
+
functionNames: [],
|
|
1917
|
+
authName: "None",
|
|
1918
|
+
};
|
|
1919
|
+
}
|
|
1892
1920
|
let apiPlugin;
|
|
1893
1921
|
if (yield fs__default['default'].pathExists(apiPluginFilePath)) {
|
|
1894
1922
|
apiPlugin = yield fs__default['default'].readJSON(apiPluginFilePath);
|
|
@@ -1924,24 +1952,35 @@ class ManifestUpdater {
|
|
|
1924
1952
|
const relativePath = ManifestUpdater.getRelativePath(existingPluginManifestInfo.manifestPath, existingPluginManifestInfo.specPath);
|
|
1925
1953
|
apiPlugin.runtimes = apiPlugin.runtimes.filter((runtime) => runtime.spec.url !== relativePath);
|
|
1926
1954
|
}
|
|
1927
|
-
const
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1955
|
+
for (const authType in functionNamesMap) {
|
|
1956
|
+
const pluginAuthObj = {
|
|
1957
|
+
type: authType,
|
|
1958
|
+
};
|
|
1959
|
+
const authName = functionNamesMap[authType].authName;
|
|
1960
|
+
if (pluginAuthObj.type !== "None") {
|
|
1961
|
+
const safeRegistrationIdName = Utils.getSafeRegistrationIdEnvName(`${authName}_${ConstantString.RegistrationIdPostfix}`);
|
|
1962
|
+
pluginAuthObj.reference_id = `\${{${safeRegistrationIdName}}}`;
|
|
1963
|
+
}
|
|
1964
|
+
const functionNamesInfo = functionNamesMap[authType];
|
|
1965
|
+
const index = apiPlugin.runtimes.findIndex((runtime) => {
|
|
1966
|
+
var _a, _b;
|
|
1967
|
+
return runtime.spec.url === specRelativePath &&
|
|
1968
|
+
runtime.type === "OpenApi" &&
|
|
1969
|
+
((_b = (_a = runtime.auth) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : "None") === authType;
|
|
1941
1970
|
});
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1971
|
+
if (index === -1) {
|
|
1972
|
+
apiPlugin.runtimes.push({
|
|
1973
|
+
type: "OpenApi",
|
|
1974
|
+
auth: pluginAuthObj,
|
|
1975
|
+
spec: {
|
|
1976
|
+
url: specRelativePath,
|
|
1977
|
+
},
|
|
1978
|
+
run_for_functions: functionNamesInfo.functionNames,
|
|
1979
|
+
});
|
|
1980
|
+
}
|
|
1981
|
+
else {
|
|
1982
|
+
apiPlugin.runtimes[index].run_for_functions = functionNamesInfo.functionNames;
|
|
1983
|
+
}
|
|
1945
1984
|
}
|
|
1946
1985
|
if (!apiPlugin.name_for_human) {
|
|
1947
1986
|
apiPlugin.name_for_human = appName;
|
|
@@ -1984,7 +2023,7 @@ class ManifestUpdater {
|
|
|
1984
2023
|
};
|
|
1985
2024
|
if (authInfo) {
|
|
1986
2025
|
const auth = authInfo.authScheme;
|
|
1987
|
-
const safeRegistrationIdName = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix
|
|
2026
|
+
const safeRegistrationIdName = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix}`);
|
|
1988
2027
|
if (Utils.isAPIKeyAuth(auth) || Utils.isBearerTokenAuth(auth)) {
|
|
1989
2028
|
composeExtension.authorization = {
|
|
1990
2029
|
authType: "apiSecretServiceAuth",
|
|
@@ -2114,6 +2153,7 @@ class SpecParser {
|
|
|
2114
2153
|
};
|
|
2115
2154
|
this.pathOrSpec = pathOrDoc;
|
|
2116
2155
|
this.parser = new SwaggerParser__default['default']();
|
|
2156
|
+
this.refParser = new jsonSchemaRefParser.$RefParser();
|
|
2117
2157
|
this.options = Object.assign(Object.assign({}, this.defaultOptions), (options !== null && options !== void 0 ? options : {}));
|
|
2118
2158
|
}
|
|
2119
2159
|
/**
|
|
@@ -2127,12 +2167,15 @@ class SpecParser {
|
|
|
2127
2167
|
let hash = "";
|
|
2128
2168
|
try {
|
|
2129
2169
|
yield this.loadSpec();
|
|
2130
|
-
if (!this.
|
|
2170
|
+
if (!this.refParser.$refs.circular) {
|
|
2131
2171
|
yield this.parser.validate(this.spec);
|
|
2132
2172
|
}
|
|
2133
2173
|
else {
|
|
2174
|
+
// The following code hangs for Graph API, support will be added when SwaggerParser is updated.
|
|
2175
|
+
/*
|
|
2134
2176
|
const clonedUnResolveSpec = JSON.parse(JSON.stringify(this.unResolveSpec));
|
|
2135
|
-
|
|
2177
|
+
await this.parser.validate(clonedUnResolveSpec);
|
|
2178
|
+
*/
|
|
2136
2179
|
}
|
|
2137
2180
|
}
|
|
2138
2181
|
catch (e) {
|
|
@@ -2160,7 +2203,7 @@ class SpecParser {
|
|
|
2160
2203
|
};
|
|
2161
2204
|
}
|
|
2162
2205
|
// Remote reference not supported
|
|
2163
|
-
const refPaths = this.
|
|
2206
|
+
const refPaths = this.refParser.$refs.paths();
|
|
2164
2207
|
// refPaths [0] is the current spec file path
|
|
2165
2208
|
if (refPaths.length > 1) {
|
|
2166
2209
|
errors.push({
|
|
@@ -2295,7 +2338,7 @@ class SpecParser {
|
|
|
2295
2338
|
throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
|
|
2296
2339
|
}
|
|
2297
2340
|
const clonedUnResolveSpec = JSON.parse(JSON.stringify(newUnResolvedSpec));
|
|
2298
|
-
const newSpec =
|
|
2341
|
+
const newSpec = yield this.deReferenceSpec(clonedUnResolveSpec);
|
|
2299
2342
|
return [newUnResolvedSpec, newSpec];
|
|
2300
2343
|
}
|
|
2301
2344
|
catch (err) {
|
|
@@ -2306,6 +2349,12 @@ class SpecParser {
|
|
|
2306
2349
|
}
|
|
2307
2350
|
});
|
|
2308
2351
|
}
|
|
2352
|
+
deReferenceSpec(spec) {
|
|
2353
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2354
|
+
const result = yield this.refParser.dereference(spec);
|
|
2355
|
+
return result;
|
|
2356
|
+
});
|
|
2357
|
+
}
|
|
2309
2358
|
/**
|
|
2310
2359
|
* Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
|
|
2311
2360
|
* @param manifestPath A file path of the Teams app manifest file to update.
|
|
@@ -2323,13 +2372,21 @@ class SpecParser {
|
|
|
2323
2372
|
const newSpecs = yield this.getFilteredSpecs(filter, signal);
|
|
2324
2373
|
const newUnResolvedSpec = newSpecs[0];
|
|
2325
2374
|
const newSpec = newSpecs[1];
|
|
2326
|
-
const authInfo = Utils.getAuthInfo(newSpec);
|
|
2327
2375
|
const paths = newUnResolvedSpec.paths;
|
|
2328
2376
|
for (const pathUrl in paths) {
|
|
2329
2377
|
const operations = paths[pathUrl];
|
|
2330
2378
|
for (const method in operations) {
|
|
2331
2379
|
const operationItem = operations[method];
|
|
2332
2380
|
const operationId = operationItem.operationId;
|
|
2381
|
+
const containsSpecialCharacters = /[^a-zA-Z0-9_]/.test(operationId);
|
|
2382
|
+
if (containsSpecialCharacters) {
|
|
2383
|
+
operationItem.operationId = operationId.replace(/[^a-zA-Z0-9]/g, "_");
|
|
2384
|
+
result.warnings.push({
|
|
2385
|
+
type: exports.WarningType.OperationIdContainsSpecialCharacters,
|
|
2386
|
+
content: Utils.format(ConstantString.OperationIdContainsSpecialCharacters, operationId, operationItem.operationId),
|
|
2387
|
+
data: operationId,
|
|
2388
|
+
});
|
|
2389
|
+
}
|
|
2333
2390
|
const authArray = Utils.getAuthArray(operationItem.security, newSpec);
|
|
2334
2391
|
if (Utils.isNotSupportedAuth(authArray)) {
|
|
2335
2392
|
result.warnings.push({
|
|
@@ -2338,16 +2395,6 @@ class SpecParser {
|
|
|
2338
2395
|
data: operationId,
|
|
2339
2396
|
});
|
|
2340
2397
|
}
|
|
2341
|
-
const containsSpecialCharacters = /[^a-zA-Z0-9_]/.test(operationId);
|
|
2342
|
-
if (!containsSpecialCharacters) {
|
|
2343
|
-
continue;
|
|
2344
|
-
}
|
|
2345
|
-
operationItem.operationId = operationId.replace(/[^a-zA-Z0-9]/g, "_");
|
|
2346
|
-
result.warnings.push({
|
|
2347
|
-
type: exports.WarningType.OperationIdContainsSpecialCharacters,
|
|
2348
|
-
content: Utils.format(ConstantString.OperationIdContainsSpecialCharacters, operationId, operationItem.operationId),
|
|
2349
|
-
data: operationId,
|
|
2350
|
-
});
|
|
2351
2398
|
}
|
|
2352
2399
|
}
|
|
2353
2400
|
yield this.saveFilterSpec(outputSpecPath, newUnResolvedSpec);
|
|
@@ -2360,7 +2407,8 @@ class SpecParser {
|
|
|
2360
2407
|
specPath: this.pathOrSpec,
|
|
2361
2408
|
}
|
|
2362
2409
|
: undefined;
|
|
2363
|
-
const
|
|
2410
|
+
const authMap = Utils.getAuthMap(newSpec);
|
|
2411
|
+
const [updatedManifest, apiPlugin, warnings] = yield ManifestUpdater.updateManifestWithAiPlugin(manifestPath, outputSpecPath, pluginFilePath, newSpec, this.options, authMap, existingPluginManifestInfo);
|
|
2364
2412
|
result.warnings.push(...warnings);
|
|
2365
2413
|
yield fs__default['default'].outputJSON(manifestPath, updatedManifest, { spaces: 4 });
|
|
2366
2414
|
yield fs__default['default'].outputJSON(pluginFilePath, apiPlugin, { spaces: 4 });
|
|
@@ -2452,7 +2500,7 @@ class SpecParser {
|
|
|
2452
2500
|
this.isSwaggerFile = true;
|
|
2453
2501
|
}
|
|
2454
2502
|
const clonedUnResolveSpec = JSON.parse(JSON.stringify(this.unResolveSpec));
|
|
2455
|
-
this.spec =
|
|
2503
|
+
this.spec = yield this.deReferenceSpec(clonedUnResolveSpec);
|
|
2456
2504
|
}
|
|
2457
2505
|
});
|
|
2458
2506
|
}
|