@microsoft/m365-spec-parser 0.1.1-alpha.78701ec6a.0 → 0.1.1-alpha.7fe3da414.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 +449 -125
- package/dist/index.esm2017.js.map +1 -1
- package/dist/index.esm2017.mjs +579 -225
- package/dist/index.esm2017.mjs.map +1 -1
- package/dist/index.esm5.js +453 -125
- package/dist/index.esm5.js.map +1 -1
- package/dist/index.node.cjs.js +585 -224
- package/dist/index.node.cjs.js.map +1 -1
- package/dist/src/constants.d.ts +5 -1
- package/dist/src/index.browser.d.ts +2 -1
- package/dist/src/index.d.ts +2 -1
- package/dist/src/interfaces.d.ts +76 -18
- package/dist/src/manifestUpdater.d.ts +9 -4
- package/dist/src/specFilter.d.ts +2 -1
- package/dist/src/specParser.browser.d.ts +16 -1
- package/dist/src/specParser.d.ts +16 -3
- package/dist/src/utils.d.ts +24 -19
- package/package.json +4 -4
package/dist/index.esm2017.js
CHANGED
|
@@ -15,7 +15,8 @@ var ErrorType;
|
|
|
15
15
|
ErrorType["NoExtraAPICanBeAdded"] = "no-extra-api-can-be-added";
|
|
16
16
|
ErrorType["ResolveServerUrlFailed"] = "resolve-server-url-failed";
|
|
17
17
|
ErrorType["SwaggerNotSupported"] = "swagger-not-supported";
|
|
18
|
-
ErrorType["
|
|
18
|
+
ErrorType["MultipleAuthNotSupported"] = "multiple-auth-not-supported";
|
|
19
|
+
ErrorType["SpecVersionNotSupported"] = "spec-version-not-supported";
|
|
19
20
|
ErrorType["ListFailed"] = "list-failed";
|
|
20
21
|
ErrorType["listSupportedAPIInfoFailed"] = "list-supported-api-info-failed";
|
|
21
22
|
ErrorType["FilterSpecFailed"] = "filter-spec-failed";
|
|
@@ -23,6 +24,22 @@ var ErrorType;
|
|
|
23
24
|
ErrorType["GenerateAdaptiveCardFailed"] = "generate-adaptive-card-failed";
|
|
24
25
|
ErrorType["GenerateFailed"] = "generate-failed";
|
|
25
26
|
ErrorType["ValidateFailed"] = "validate-failed";
|
|
27
|
+
ErrorType["GetSpecFailed"] = "get-spec-failed";
|
|
28
|
+
ErrorType["AuthTypeIsNotSupported"] = "auth-type-is-not-supported";
|
|
29
|
+
ErrorType["MissingOperationId"] = "missing-operation-id";
|
|
30
|
+
ErrorType["PostBodyContainMultipleMediaTypes"] = "post-body-contain-multiple-media-types";
|
|
31
|
+
ErrorType["ResponseContainMultipleMediaTypes"] = "response-contain-multiple-media-types";
|
|
32
|
+
ErrorType["ResponseJsonIsEmpty"] = "response-json-is-empty";
|
|
33
|
+
ErrorType["PostBodySchemaIsNotJson"] = "post-body-schema-is-not-json";
|
|
34
|
+
ErrorType["PostBodyContainsRequiredUnsupportedSchema"] = "post-body-contains-required-unsupported-schema";
|
|
35
|
+
ErrorType["ParamsContainRequiredUnsupportedSchema"] = "params-contain-required-unsupported-schema";
|
|
36
|
+
ErrorType["ParamsContainsNestedObject"] = "params-contains-nested-object";
|
|
37
|
+
ErrorType["RequestBodyContainsNestedObject"] = "request-body-contains-nested-object";
|
|
38
|
+
ErrorType["ExceededRequiredParamsLimit"] = "exceeded-required-params-limit";
|
|
39
|
+
ErrorType["NoParameter"] = "no-parameter";
|
|
40
|
+
ErrorType["NoAPIInfo"] = "no-api-info";
|
|
41
|
+
ErrorType["MethodNotAllowed"] = "method-not-allowed";
|
|
42
|
+
ErrorType["UrlPathNotExist"] = "url-path-not-exist";
|
|
26
43
|
ErrorType["Cancelled"] = "cancelled";
|
|
27
44
|
ErrorType["Unknown"] = "unknown";
|
|
28
45
|
})(ErrorType || (ErrorType = {}));
|
|
@@ -45,7 +62,13 @@ var ValidationStatus;
|
|
|
45
62
|
ValidationStatus[ValidationStatus["Valid"] = 0] = "Valid";
|
|
46
63
|
ValidationStatus[ValidationStatus["Warning"] = 1] = "Warning";
|
|
47
64
|
ValidationStatus[ValidationStatus["Error"] = 2] = "Error";
|
|
48
|
-
})(ValidationStatus || (ValidationStatus = {}));
|
|
65
|
+
})(ValidationStatus || (ValidationStatus = {}));
|
|
66
|
+
var ProjectType;
|
|
67
|
+
(function (ProjectType) {
|
|
68
|
+
ProjectType[ProjectType["Copilot"] = 0] = "Copilot";
|
|
69
|
+
ProjectType[ProjectType["SME"] = 1] = "SME";
|
|
70
|
+
ProjectType[ProjectType["TeamsAi"] = 2] = "TeamsAi";
|
|
71
|
+
})(ProjectType || (ProjectType = {}));
|
|
49
72
|
|
|
50
73
|
// Copyright (c) Microsoft Corporation.
|
|
51
74
|
class SpecParserError extends Error {
|
|
@@ -72,7 +95,9 @@ ConstantString.ResolveServerUrlFailed = "Unable to resolve the server URL: pleas
|
|
|
72
95
|
ConstantString.OperationOnlyContainsOptionalParam = "Operation %s contains multiple optional parameters. The first optional parameter is used for this command.";
|
|
73
96
|
ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converted to OpenAPI 3.0.";
|
|
74
97
|
ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
|
|
75
|
-
ConstantString.
|
|
98
|
+
ConstantString.SpecVersionNotSupported = "Unsupported OpenAPI version %s. Please use version 3.0.x.";
|
|
99
|
+
ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
|
|
100
|
+
ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
|
|
76
101
|
ConstantString.WrappedCardVersion = "devPreview";
|
|
77
102
|
ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
|
|
78
103
|
ConstantString.WrappedCardResponseLayout = "list";
|
|
@@ -84,6 +109,7 @@ ConstantString.AdaptiveCardType = "AdaptiveCard";
|
|
|
84
109
|
ConstantString.TextBlockType = "TextBlock";
|
|
85
110
|
ConstantString.ContainerType = "Container";
|
|
86
111
|
ConstantString.RegistrationIdPostfix = "REGISTRATION_ID";
|
|
112
|
+
ConstantString.OAuthRegistrationIdPostFix = "OAUTH_REGISTRATION_ID";
|
|
87
113
|
ConstantString.ResponseCodeFor20X = [
|
|
88
114
|
"200",
|
|
89
115
|
"201",
|
|
@@ -143,15 +169,28 @@ ConstantString.FullDescriptionMaxLens = 4000;
|
|
|
143
169
|
ConstantString.CommandDescriptionMaxLens = 128;
|
|
144
170
|
ConstantString.ParameterDescriptionMaxLens = 128;
|
|
145
171
|
ConstantString.CommandTitleMaxLens = 32;
|
|
146
|
-
ConstantString.ParameterTitleMaxLens = 32;
|
|
172
|
+
ConstantString.ParameterTitleMaxLens = 32;
|
|
173
|
+
ConstantString.SMERequiredParamsMaxNum = 5;
|
|
147
174
|
|
|
148
175
|
// Copyright (c) Microsoft Corporation.
|
|
149
176
|
class Utils {
|
|
150
|
-
static
|
|
177
|
+
static hasNestedObjectInSchema(schema) {
|
|
178
|
+
if (schema.type === "object") {
|
|
179
|
+
for (const property in schema.properties) {
|
|
180
|
+
const nestedSchema = schema.properties[property];
|
|
181
|
+
if (nestedSchema.type === "object") {
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
static checkParameters(paramObject, isCopilot) {
|
|
151
189
|
const paramResult = {
|
|
152
190
|
requiredNum: 0,
|
|
153
191
|
optionalNum: 0,
|
|
154
192
|
isValid: true,
|
|
193
|
+
reason: [],
|
|
155
194
|
};
|
|
156
195
|
if (!paramObject) {
|
|
157
196
|
return paramResult;
|
|
@@ -159,10 +198,25 @@ class Utils {
|
|
|
159
198
|
for (let i = 0; i < paramObject.length; i++) {
|
|
160
199
|
const param = paramObject[i];
|
|
161
200
|
const schema = param.schema;
|
|
201
|
+
if (isCopilot && this.hasNestedObjectInSchema(schema)) {
|
|
202
|
+
paramResult.isValid = false;
|
|
203
|
+
paramResult.reason.push(ErrorType.ParamsContainsNestedObject);
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
162
206
|
const isRequiredWithoutDefault = param.required && schema.default === undefined;
|
|
207
|
+
if (isCopilot) {
|
|
208
|
+
if (isRequiredWithoutDefault) {
|
|
209
|
+
paramResult.requiredNum = paramResult.requiredNum + 1;
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
paramResult.optionalNum = paramResult.optionalNum + 1;
|
|
213
|
+
}
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
163
216
|
if (param.in === "header" || param.in === "cookie") {
|
|
164
217
|
if (isRequiredWithoutDefault) {
|
|
165
218
|
paramResult.isValid = false;
|
|
219
|
+
paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
|
|
166
220
|
}
|
|
167
221
|
continue;
|
|
168
222
|
}
|
|
@@ -172,6 +226,7 @@ class Utils {
|
|
|
172
226
|
schema.type !== "integer") {
|
|
173
227
|
if (isRequiredWithoutDefault) {
|
|
174
228
|
paramResult.isValid = false;
|
|
229
|
+
paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
|
|
175
230
|
}
|
|
176
231
|
continue;
|
|
177
232
|
}
|
|
@@ -186,17 +241,23 @@ class Utils {
|
|
|
186
241
|
}
|
|
187
242
|
return paramResult;
|
|
188
243
|
}
|
|
189
|
-
static checkPostBody(schema, isRequired = false) {
|
|
244
|
+
static checkPostBody(schema, isRequired = false, isCopilot = false) {
|
|
190
245
|
var _a;
|
|
191
246
|
const paramResult = {
|
|
192
247
|
requiredNum: 0,
|
|
193
248
|
optionalNum: 0,
|
|
194
249
|
isValid: true,
|
|
250
|
+
reason: [],
|
|
195
251
|
};
|
|
196
252
|
if (Object.keys(schema).length === 0) {
|
|
197
253
|
return paramResult;
|
|
198
254
|
}
|
|
199
255
|
const isRequiredWithoutDefault = isRequired && schema.default === undefined;
|
|
256
|
+
if (isCopilot && this.hasNestedObjectInSchema(schema)) {
|
|
257
|
+
paramResult.isValid = false;
|
|
258
|
+
paramResult.reason = [ErrorType.RequestBodyContainsNestedObject];
|
|
259
|
+
return paramResult;
|
|
260
|
+
}
|
|
200
261
|
if (schema.type === "string" ||
|
|
201
262
|
schema.type === "integer" ||
|
|
202
263
|
schema.type === "boolean" ||
|
|
@@ -215,19 +276,24 @@ class Utils {
|
|
|
215
276
|
if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
|
|
216
277
|
isRequired = true;
|
|
217
278
|
}
|
|
218
|
-
const result = Utils.checkPostBody(properties[property], isRequired);
|
|
279
|
+
const result = Utils.checkPostBody(properties[property], isRequired, isCopilot);
|
|
219
280
|
paramResult.requiredNum += result.requiredNum;
|
|
220
281
|
paramResult.optionalNum += result.optionalNum;
|
|
221
282
|
paramResult.isValid = paramResult.isValid && result.isValid;
|
|
283
|
+
paramResult.reason.push(...result.reason);
|
|
222
284
|
}
|
|
223
285
|
}
|
|
224
286
|
else {
|
|
225
|
-
if (isRequiredWithoutDefault) {
|
|
287
|
+
if (isRequiredWithoutDefault && !isCopilot) {
|
|
226
288
|
paramResult.isValid = false;
|
|
289
|
+
paramResult.reason.push(ErrorType.PostBodyContainsRequiredUnsupportedSchema);
|
|
227
290
|
}
|
|
228
291
|
}
|
|
229
292
|
return paramResult;
|
|
230
293
|
}
|
|
294
|
+
static containMultipleMediaTypes(bodyObject) {
|
|
295
|
+
return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
|
|
296
|
+
}
|
|
231
297
|
/**
|
|
232
298
|
* Checks if the given API is supported.
|
|
233
299
|
* @param {string} method - The HTTP method of the API.
|
|
@@ -242,106 +308,137 @@ class Utils {
|
|
|
242
308
|
* 5. response body should be “application/json” and not empty, and response code should be 20X
|
|
243
309
|
* 6. only support request body with “application/json” content type
|
|
244
310
|
*/
|
|
245
|
-
static isSupportedApi(method, path, spec,
|
|
246
|
-
|
|
311
|
+
static isSupportedApi(method, path, spec, options) {
|
|
312
|
+
var _a;
|
|
313
|
+
const result = { isValid: true, reason: [] };
|
|
247
314
|
method = method.toLocaleLowerCase();
|
|
248
|
-
if (
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
315
|
+
if (options.allowMethods && !options.allowMethods.includes(method)) {
|
|
316
|
+
result.isValid = false;
|
|
317
|
+
result.reason.push(ErrorType.MethodNotAllowed);
|
|
318
|
+
return result;
|
|
319
|
+
}
|
|
320
|
+
const pathObj = spec.paths[path];
|
|
321
|
+
if (!pathObj || !pathObj[method]) {
|
|
322
|
+
result.isValid = false;
|
|
323
|
+
result.reason.push(ErrorType.UrlPathNotExist);
|
|
324
|
+
return result;
|
|
325
|
+
}
|
|
326
|
+
const securities = pathObj[method].security;
|
|
327
|
+
const isTeamsAi = options.projectType === ProjectType.TeamsAi;
|
|
328
|
+
const isCopilot = options.projectType === ProjectType.Copilot;
|
|
329
|
+
// Teams AI project doesn't care about auth, it will use authProvider for user to implement
|
|
330
|
+
if (!isTeamsAi) {
|
|
331
|
+
const authArray = Utils.getAuthArray(securities, spec);
|
|
332
|
+
const authCheckResult = Utils.isSupportedAuth(authArray, options);
|
|
333
|
+
if (!authCheckResult.isValid) {
|
|
334
|
+
result.reason.push(...authCheckResult.reason);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
const operationObject = pathObj[method];
|
|
338
|
+
if (!options.allowMissingId && !operationObject.operationId) {
|
|
339
|
+
result.reason.push(ErrorType.MissingOperationId);
|
|
340
|
+
}
|
|
341
|
+
const rootServer = spec.servers && spec.servers[0];
|
|
342
|
+
const methodServer = spec.paths[path].servers && ((_a = spec.paths[path]) === null || _a === void 0 ? void 0 : _a.servers[0]);
|
|
343
|
+
const operationServer = operationObject.servers && operationObject.servers[0];
|
|
344
|
+
const serverUrl = operationServer || methodServer || rootServer;
|
|
345
|
+
if (!serverUrl) {
|
|
346
|
+
result.reason.push(ErrorType.NoServerInformation);
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
const serverValidateResult = Utils.checkServerUrl([serverUrl]);
|
|
350
|
+
result.reason.push(...serverValidateResult.map((item) => item.type));
|
|
351
|
+
}
|
|
352
|
+
const paramObject = operationObject.parameters;
|
|
353
|
+
const requestBody = operationObject.requestBody;
|
|
354
|
+
const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
|
|
355
|
+
if (!isTeamsAi && Utils.containMultipleMediaTypes(requestBody)) {
|
|
356
|
+
result.reason.push(ErrorType.PostBodyContainMultipleMediaTypes);
|
|
357
|
+
}
|
|
358
|
+
const { json, multipleMediaType } = Utils.getResponseJson(operationObject, isTeamsAi);
|
|
359
|
+
if (multipleMediaType && !isTeamsAi) {
|
|
360
|
+
result.reason.push(ErrorType.ResponseContainMultipleMediaTypes);
|
|
361
|
+
}
|
|
362
|
+
else if (Object.keys(json).length === 0) {
|
|
363
|
+
result.reason.push(ErrorType.ResponseJsonIsEmpty);
|
|
364
|
+
}
|
|
365
|
+
// Teams AI project doesn't care about request parameters/body
|
|
366
|
+
if (!isTeamsAi) {
|
|
367
|
+
let requestBodyParamResult = {
|
|
368
|
+
requiredNum: 0,
|
|
369
|
+
optionalNum: 0,
|
|
370
|
+
isValid: true,
|
|
371
|
+
reason: [],
|
|
372
|
+
};
|
|
373
|
+
if (requestJsonBody) {
|
|
374
|
+
const requestBodySchema = requestJsonBody.schema;
|
|
375
|
+
if (isCopilot && requestBodySchema.type !== "object") {
|
|
376
|
+
result.reason.push(ErrorType.PostBodySchemaIsNotJson);
|
|
282
377
|
}
|
|
283
|
-
|
|
284
|
-
if (!
|
|
285
|
-
|
|
378
|
+
requestBodyParamResult = Utils.checkPostBody(requestBodySchema, requestBody.required, isCopilot);
|
|
379
|
+
if (!requestBodyParamResult.isValid && requestBodyParamResult.reason) {
|
|
380
|
+
result.reason.push(...requestBodyParamResult.reason);
|
|
286
381
|
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
382
|
+
}
|
|
383
|
+
const paramResult = Utils.checkParameters(paramObject, isCopilot);
|
|
384
|
+
if (!paramResult.isValid && paramResult.reason) {
|
|
385
|
+
result.reason.push(...paramResult.reason);
|
|
386
|
+
}
|
|
387
|
+
// Copilot support arbitrary parameters
|
|
388
|
+
if (!isCopilot && paramResult.isValid && requestBodyParamResult.isValid) {
|
|
389
|
+
const totalRequiredParams = requestBodyParamResult.requiredNum + paramResult.requiredNum;
|
|
390
|
+
const totalParams = totalRequiredParams + requestBodyParamResult.optionalNum + paramResult.optionalNum;
|
|
391
|
+
if (totalRequiredParams > 1) {
|
|
392
|
+
if (!options.allowMultipleParameters ||
|
|
393
|
+
totalRequiredParams > ConstantString.SMERequiredParamsMaxNum) {
|
|
394
|
+
result.reason.push(ErrorType.ExceededRequiredParamsLimit);
|
|
291
395
|
}
|
|
292
|
-
return false;
|
|
293
396
|
}
|
|
294
|
-
else if (
|
|
295
|
-
|
|
296
|
-
paramResult.requiredNum +
|
|
297
|
-
paramResult.optionalNum ===
|
|
298
|
-
0) {
|
|
299
|
-
return false;
|
|
300
|
-
}
|
|
301
|
-
else {
|
|
302
|
-
return true;
|
|
397
|
+
else if (totalParams === 0) {
|
|
398
|
+
result.reason.push(ErrorType.NoParameter);
|
|
303
399
|
}
|
|
304
400
|
}
|
|
305
401
|
}
|
|
306
|
-
|
|
402
|
+
if (result.reason.length > 0) {
|
|
403
|
+
result.isValid = false;
|
|
404
|
+
}
|
|
405
|
+
return result;
|
|
307
406
|
}
|
|
308
|
-
static isSupportedAuth(
|
|
309
|
-
if (
|
|
310
|
-
return true;
|
|
407
|
+
static isSupportedAuth(authSchemeArray, options) {
|
|
408
|
+
if (authSchemeArray.length === 0) {
|
|
409
|
+
return { isValid: true, reason: [] };
|
|
311
410
|
}
|
|
312
|
-
if (allowAPIKeyAuth || allowOauth2) {
|
|
411
|
+
if (options.allowAPIKeyAuth || options.allowOauth2 || options.allowBearerTokenAuth) {
|
|
313
412
|
// Currently we don't support multiple auth in one operation
|
|
314
|
-
if (
|
|
315
|
-
return
|
|
413
|
+
if (authSchemeArray.length > 0 && authSchemeArray.every((auths) => auths.length > 1)) {
|
|
414
|
+
return {
|
|
415
|
+
isValid: false,
|
|
416
|
+
reason: [ErrorType.MultipleAuthNotSupported],
|
|
417
|
+
};
|
|
316
418
|
}
|
|
317
|
-
for (const auths of
|
|
419
|
+
for (const auths of authSchemeArray) {
|
|
318
420
|
if (auths.length === 1) {
|
|
319
|
-
if (
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
allowOauth2 &&
|
|
324
|
-
Utils.isBearerTokenAuth(auths[0].authSchema)) {
|
|
325
|
-
return true;
|
|
326
|
-
}
|
|
327
|
-
else if (allowAPIKeyAuth &&
|
|
328
|
-
allowOauth2 &&
|
|
329
|
-
(Utils.isAPIKeyAuth(auths[0].authSchema) ||
|
|
330
|
-
Utils.isBearerTokenAuth(auths[0].authSchema))) {
|
|
331
|
-
return true;
|
|
421
|
+
if ((options.allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authScheme)) ||
|
|
422
|
+
(options.allowOauth2 && Utils.isOAuthWithAuthCodeFlow(auths[0].authScheme)) ||
|
|
423
|
+
(options.allowBearerTokenAuth && Utils.isBearerTokenAuth(auths[0].authScheme))) {
|
|
424
|
+
return { isValid: true, reason: [] };
|
|
332
425
|
}
|
|
333
426
|
}
|
|
334
427
|
}
|
|
335
428
|
}
|
|
336
|
-
return false;
|
|
429
|
+
return { isValid: false, reason: [ErrorType.AuthTypeIsNotSupported] };
|
|
337
430
|
}
|
|
338
|
-
static
|
|
339
|
-
return
|
|
431
|
+
static isBearerTokenAuth(authScheme) {
|
|
432
|
+
return authScheme.type === "http" && authScheme.scheme === "bearer";
|
|
340
433
|
}
|
|
341
|
-
static
|
|
342
|
-
return
|
|
343
|
-
|
|
344
|
-
|
|
434
|
+
static isAPIKeyAuth(authScheme) {
|
|
435
|
+
return authScheme.type === "apiKey";
|
|
436
|
+
}
|
|
437
|
+
static isOAuthWithAuthCodeFlow(authScheme) {
|
|
438
|
+
if (authScheme.type === "oauth2" && authScheme.flows && authScheme.flows.authorizationCode) {
|
|
439
|
+
return true;
|
|
440
|
+
}
|
|
441
|
+
return false;
|
|
345
442
|
}
|
|
346
443
|
static getAuthArray(securities, spec) {
|
|
347
444
|
var _a;
|
|
@@ -354,7 +451,7 @@ class Utils {
|
|
|
354
451
|
for (const name in security) {
|
|
355
452
|
const auth = securitySchemas[name];
|
|
356
453
|
authArray.push({
|
|
357
|
-
|
|
454
|
+
authScheme: auth,
|
|
358
455
|
name: name,
|
|
359
456
|
});
|
|
360
457
|
}
|
|
@@ -369,21 +466,28 @@ class Utils {
|
|
|
369
466
|
static updateFirstLetter(str) {
|
|
370
467
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
371
468
|
}
|
|
372
|
-
static getResponseJson(operationObject) {
|
|
469
|
+
static getResponseJson(operationObject, isTeamsAiProject = false) {
|
|
373
470
|
var _a, _b;
|
|
374
471
|
let json = {};
|
|
472
|
+
let multipleMediaType = false;
|
|
375
473
|
for (const code of ConstantString.ResponseCodeFor20X) {
|
|
376
474
|
const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
|
|
377
|
-
const mediaTypesCount = Object.keys((responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) || {}).length;
|
|
378
|
-
if (mediaTypesCount > 1) {
|
|
379
|
-
return {};
|
|
380
|
-
}
|
|
381
475
|
if ((_b = responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) === null || _b === void 0 ? void 0 : _b["application/json"]) {
|
|
476
|
+
multipleMediaType = false;
|
|
382
477
|
json = responseObject.content["application/json"];
|
|
383
|
-
|
|
478
|
+
if (Utils.containMultipleMediaTypes(responseObject)) {
|
|
479
|
+
multipleMediaType = true;
|
|
480
|
+
if (isTeamsAiProject) {
|
|
481
|
+
break;
|
|
482
|
+
}
|
|
483
|
+
json = {};
|
|
484
|
+
}
|
|
485
|
+
else {
|
|
486
|
+
break;
|
|
487
|
+
}
|
|
384
488
|
}
|
|
385
489
|
}
|
|
386
|
-
return json;
|
|
490
|
+
return { json, multipleMediaType };
|
|
387
491
|
}
|
|
388
492
|
static convertPathToCamelCase(path) {
|
|
389
493
|
const pathSegments = path.split(/[./{]/);
|
|
@@ -403,10 +507,10 @@ class Utils {
|
|
|
403
507
|
return undefined;
|
|
404
508
|
}
|
|
405
509
|
}
|
|
406
|
-
static
|
|
510
|
+
static resolveEnv(str) {
|
|
407
511
|
const placeHolderReg = /\${{\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*}}/g;
|
|
408
|
-
let matches = placeHolderReg.exec(
|
|
409
|
-
let
|
|
512
|
+
let matches = placeHolderReg.exec(str);
|
|
513
|
+
let newStr = str;
|
|
410
514
|
while (matches != null) {
|
|
411
515
|
const envVar = matches[1];
|
|
412
516
|
const envVal = process.env[envVar];
|
|
@@ -414,17 +518,17 @@ class Utils {
|
|
|
414
518
|
throw new Error(Utils.format(ConstantString.ResolveServerUrlFailed, envVar));
|
|
415
519
|
}
|
|
416
520
|
else {
|
|
417
|
-
|
|
521
|
+
newStr = newStr.replace(matches[0], envVal);
|
|
418
522
|
}
|
|
419
|
-
matches = placeHolderReg.exec(
|
|
523
|
+
matches = placeHolderReg.exec(str);
|
|
420
524
|
}
|
|
421
|
-
return
|
|
525
|
+
return newStr;
|
|
422
526
|
}
|
|
423
527
|
static checkServerUrl(servers) {
|
|
424
528
|
const errors = [];
|
|
425
529
|
let serverUrl;
|
|
426
530
|
try {
|
|
427
|
-
serverUrl = Utils.
|
|
531
|
+
serverUrl = Utils.resolveEnv(servers[0].url);
|
|
428
532
|
}
|
|
429
533
|
catch (err) {
|
|
430
534
|
errors.push({
|
|
@@ -454,7 +558,8 @@ class Utils {
|
|
|
454
558
|
}
|
|
455
559
|
return errors;
|
|
456
560
|
}
|
|
457
|
-
static validateServer(spec,
|
|
561
|
+
static validateServer(spec, options) {
|
|
562
|
+
var _a;
|
|
458
563
|
const errors = [];
|
|
459
564
|
let hasTopLevelServers = false;
|
|
460
565
|
let hasPathLevelServers = false;
|
|
@@ -475,7 +580,7 @@ class Utils {
|
|
|
475
580
|
}
|
|
476
581
|
for (const method in methods) {
|
|
477
582
|
const operationObject = methods[method];
|
|
478
|
-
if (
|
|
583
|
+
if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
|
|
479
584
|
if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
|
|
480
585
|
hasOperationLevelServers = true;
|
|
481
586
|
const serverErrors = Utils.checkServerUrl(operationObject.servers);
|
|
@@ -518,6 +623,7 @@ class Utils {
|
|
|
518
623
|
Utils.updateParameterWithInputType(schema, parameter);
|
|
519
624
|
}
|
|
520
625
|
if (isRequired && schema.default === undefined) {
|
|
626
|
+
parameter.isRequired = true;
|
|
521
627
|
requiredParams.push(parameter);
|
|
522
628
|
}
|
|
523
629
|
else {
|
|
@@ -562,7 +668,7 @@ class Utils {
|
|
|
562
668
|
param.value = schema.default;
|
|
563
669
|
}
|
|
564
670
|
}
|
|
565
|
-
static parseApiInfo(operationItem,
|
|
671
|
+
static parseApiInfo(operationItem, options) {
|
|
566
672
|
var _a, _b;
|
|
567
673
|
const requiredParams = [];
|
|
568
674
|
const optionalParams = [];
|
|
@@ -576,11 +682,12 @@ class Utils {
|
|
|
576
682
|
description: ((_a = param.description) !== null && _a !== void 0 ? _a : "").slice(0, ConstantString.ParameterDescriptionMaxLens),
|
|
577
683
|
};
|
|
578
684
|
const schema = param.schema;
|
|
579
|
-
if (allowMultipleParameters && schema) {
|
|
685
|
+
if (options.allowMultipleParameters && schema) {
|
|
580
686
|
Utils.updateParameterWithInputType(schema, parameter);
|
|
581
687
|
}
|
|
582
688
|
if (param.in !== "header" && param.in !== "cookie") {
|
|
583
689
|
if (param.required && (schema === null || schema === void 0 ? void 0 : schema.default) === undefined) {
|
|
690
|
+
parameter.isRequired = true;
|
|
584
691
|
requiredParams.push(parameter);
|
|
585
692
|
}
|
|
586
693
|
else {
|
|
@@ -594,7 +701,7 @@ class Utils {
|
|
|
594
701
|
const requestJson = requestBody.content["application/json"];
|
|
595
702
|
if (Object.keys(requestJson).length !== 0) {
|
|
596
703
|
const schema = requestJson.schema;
|
|
597
|
-
const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", allowMultipleParameters, requestBody.required);
|
|
704
|
+
const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", !!options.allowMultipleParameters, requestBody.required);
|
|
598
705
|
requiredParams.push(...requiredP);
|
|
599
706
|
optionalParams.push(...optionalP);
|
|
600
707
|
}
|
|
@@ -625,32 +732,37 @@ class Utils {
|
|
|
625
732
|
}
|
|
626
733
|
return [command, warning];
|
|
627
734
|
}
|
|
628
|
-
static
|
|
735
|
+
static listAPIs(spec, options) {
|
|
736
|
+
var _a;
|
|
629
737
|
const paths = spec.paths;
|
|
630
738
|
const result = {};
|
|
631
739
|
for (const path in paths) {
|
|
632
740
|
const methods = paths[path];
|
|
633
741
|
for (const method in methods) {
|
|
634
|
-
|
|
635
|
-
if (
|
|
636
|
-
const
|
|
637
|
-
result[`${method.toUpperCase()} ${path}`] =
|
|
742
|
+
const operationObject = methods[method];
|
|
743
|
+
if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
|
|
744
|
+
const validateResult = Utils.isSupportedApi(method, path, spec, options);
|
|
745
|
+
result[`${method.toUpperCase()} ${path}`] = {
|
|
746
|
+
operation: operationObject,
|
|
747
|
+
isValid: validateResult.isValid,
|
|
748
|
+
reason: validateResult.reason,
|
|
749
|
+
};
|
|
638
750
|
}
|
|
639
751
|
}
|
|
640
752
|
}
|
|
641
753
|
return result;
|
|
642
754
|
}
|
|
643
|
-
static validateSpec(spec, parser, isSwaggerFile,
|
|
755
|
+
static validateSpec(spec, parser, isSwaggerFile, options) {
|
|
644
756
|
const errors = [];
|
|
645
757
|
const warnings = [];
|
|
758
|
+
const apiMap = Utils.listAPIs(spec, options);
|
|
646
759
|
if (isSwaggerFile) {
|
|
647
760
|
warnings.push({
|
|
648
761
|
type: WarningType.ConvertSwaggerToOpenAPI,
|
|
649
762
|
content: ConstantString.ConvertSwaggerToOpenAPI,
|
|
650
763
|
});
|
|
651
764
|
}
|
|
652
|
-
|
|
653
|
-
const serverErrors = Utils.validateServer(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2);
|
|
765
|
+
const serverErrors = Utils.validateServer(spec, options);
|
|
654
766
|
errors.push(...serverErrors);
|
|
655
767
|
// Remote reference not supported
|
|
656
768
|
const refPaths = parser.$refs.paths();
|
|
@@ -663,8 +775,8 @@ class Utils {
|
|
|
663
775
|
});
|
|
664
776
|
}
|
|
665
777
|
// No supported API
|
|
666
|
-
const
|
|
667
|
-
if (
|
|
778
|
+
const validAPIs = Object.entries(apiMap).filter(([, value]) => value.isValid);
|
|
779
|
+
if (validAPIs.length === 0) {
|
|
668
780
|
errors.push({
|
|
669
781
|
type: ErrorType.NoSupportedApi,
|
|
670
782
|
content: ConstantString.NoSupportedApi,
|
|
@@ -673,8 +785,8 @@ class Utils {
|
|
|
673
785
|
// OperationId missing
|
|
674
786
|
const apisMissingOperationId = [];
|
|
675
787
|
for (const key in apiMap) {
|
|
676
|
-
const
|
|
677
|
-
if (!
|
|
788
|
+
const { operation } = apiMap[key];
|
|
789
|
+
if (!operation.operationId) {
|
|
678
790
|
apisMissingOperationId.push(key);
|
|
679
791
|
}
|
|
680
792
|
}
|
|
@@ -715,6 +827,19 @@ class Utils {
|
|
|
715
827
|
}
|
|
716
828
|
return safeRegistrationIdEnvName;
|
|
717
829
|
}
|
|
830
|
+
static getAllAPICount(spec) {
|
|
831
|
+
let count = 0;
|
|
832
|
+
const paths = spec.paths;
|
|
833
|
+
for (const path in paths) {
|
|
834
|
+
const methods = paths[path];
|
|
835
|
+
for (const method in methods) {
|
|
836
|
+
if (ConstantString.AllOperationMethods.includes(method)) {
|
|
837
|
+
count++;
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
return count;
|
|
842
|
+
}
|
|
718
843
|
}
|
|
719
844
|
|
|
720
845
|
// Copyright (c) Microsoft Corporation.
|
|
@@ -733,7 +858,10 @@ class SpecParser {
|
|
|
733
858
|
allowSwagger: false,
|
|
734
859
|
allowAPIKeyAuth: false,
|
|
735
860
|
allowMultipleParameters: false,
|
|
861
|
+
allowBearerTokenAuth: false,
|
|
736
862
|
allowOauth2: false,
|
|
863
|
+
allowMethods: ["get", "post"],
|
|
864
|
+
projectType: ProjectType.SME,
|
|
737
865
|
};
|
|
738
866
|
this.pathOrSpec = pathOrDoc;
|
|
739
867
|
this.parser = new SwaggerParser();
|
|
@@ -770,7 +898,7 @@ class SpecParser {
|
|
|
770
898
|
],
|
|
771
899
|
};
|
|
772
900
|
}
|
|
773
|
-
return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options
|
|
901
|
+
return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options);
|
|
774
902
|
}
|
|
775
903
|
catch (err) {
|
|
776
904
|
throw new SpecParserError(err.toString(), ErrorType.ValidateFailed);
|
|
@@ -789,7 +917,7 @@ class SpecParser {
|
|
|
789
917
|
if (!operationId) {
|
|
790
918
|
continue;
|
|
791
919
|
}
|
|
792
|
-
const [command, warning] = Utils.parseApiInfo(pathObjectItem, this.options
|
|
920
|
+
const [command, warning] = Utils.parseApiInfo(pathObjectItem, this.options);
|
|
793
921
|
const apiInfo = {
|
|
794
922
|
method: method,
|
|
795
923
|
path: path,
|
|
@@ -818,12 +946,32 @@ class SpecParser {
|
|
|
818
946
|
async list() {
|
|
819
947
|
throw new Error("Method not implemented.");
|
|
820
948
|
}
|
|
949
|
+
/**
|
|
950
|
+
* Generate specs according to the filters.
|
|
951
|
+
* @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
|
|
952
|
+
*/
|
|
953
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
954
|
+
async getFilteredSpecs(filter, signal) {
|
|
955
|
+
throw new Error("Method not implemented.");
|
|
956
|
+
}
|
|
957
|
+
/**
|
|
958
|
+
* Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
|
|
959
|
+
* @param manifestPath A file path of the Teams app manifest file to update.
|
|
960
|
+
* @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
|
|
961
|
+
* @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
|
|
962
|
+
* @param pluginFilePath File path of the api plugin file to generate.
|
|
963
|
+
*/
|
|
964
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
965
|
+
async generateForCopilot(manifestPath, filter, outputSpecPath, pluginFilePath, signal) {
|
|
966
|
+
throw new Error("Method not implemented.");
|
|
967
|
+
}
|
|
821
968
|
/**
|
|
822
969
|
* Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
|
|
823
970
|
* @param manifestPath A file path of the Teams app manifest file to update.
|
|
824
971
|
* @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
|
|
825
972
|
* @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
|
|
826
973
|
* @param adaptiveCardFolder Folder path where the Adaptive Card files will be generated. If not specified or empty, Adaptive Card files will not be generated.
|
|
974
|
+
* @param isMe Boolean that indicates whether the project is an Messaging Extension. For Messaging Extension, composeExtensions will be added in Teams app manifest.
|
|
827
975
|
*/
|
|
828
976
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
829
977
|
async generate(manifestPath, filter, outputSpecPath, adaptiveCardFolder, signal) {
|
|
@@ -843,11 +991,187 @@ class SpecParser {
|
|
|
843
991
|
if (this.apiMap !== undefined) {
|
|
844
992
|
return this.apiMap;
|
|
845
993
|
}
|
|
846
|
-
const result =
|
|
994
|
+
const result = this.listSupportedAPIs(spec, this.options);
|
|
847
995
|
this.apiMap = result;
|
|
848
996
|
return result;
|
|
849
997
|
}
|
|
998
|
+
listSupportedAPIs(spec, options) {
|
|
999
|
+
var _a;
|
|
1000
|
+
const paths = spec.paths;
|
|
1001
|
+
const result = {};
|
|
1002
|
+
for (const path in paths) {
|
|
1003
|
+
const methods = paths[path];
|
|
1004
|
+
for (const method in methods) {
|
|
1005
|
+
const operationObject = methods[method];
|
|
1006
|
+
if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
|
|
1007
|
+
const validateResult = Utils.isSupportedApi(method, path, spec, options);
|
|
1008
|
+
if (validateResult.isValid) {
|
|
1009
|
+
result[`${method.toUpperCase()} ${path}`] = operationObject;
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
return result;
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
// Copyright (c) Microsoft Corporation.
|
|
1019
|
+
class AdaptiveCardGenerator {
|
|
1020
|
+
static generateAdaptiveCard(operationItem) {
|
|
1021
|
+
try {
|
|
1022
|
+
const { json } = Utils.getResponseJson(operationItem);
|
|
1023
|
+
let cardBody = [];
|
|
1024
|
+
let schema = json.schema;
|
|
1025
|
+
let jsonPath = "$";
|
|
1026
|
+
if (schema && Object.keys(schema).length > 0) {
|
|
1027
|
+
jsonPath = AdaptiveCardGenerator.getResponseJsonPathFromSchema(schema);
|
|
1028
|
+
if (jsonPath !== "$") {
|
|
1029
|
+
schema = schema.properties[jsonPath];
|
|
1030
|
+
}
|
|
1031
|
+
cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "");
|
|
1032
|
+
}
|
|
1033
|
+
// if no schema, try to use example value
|
|
1034
|
+
if (cardBody.length === 0 && (json.examples || json.example)) {
|
|
1035
|
+
cardBody = [
|
|
1036
|
+
{
|
|
1037
|
+
type: ConstantString.TextBlockType,
|
|
1038
|
+
text: "${jsonStringify($root)}",
|
|
1039
|
+
wrap: true,
|
|
1040
|
+
},
|
|
1041
|
+
];
|
|
1042
|
+
}
|
|
1043
|
+
// if no example value, use default success response
|
|
1044
|
+
if (cardBody.length === 0) {
|
|
1045
|
+
cardBody = [
|
|
1046
|
+
{
|
|
1047
|
+
type: ConstantString.TextBlockType,
|
|
1048
|
+
text: "success",
|
|
1049
|
+
wrap: true,
|
|
1050
|
+
},
|
|
1051
|
+
];
|
|
1052
|
+
}
|
|
1053
|
+
const fullCard = {
|
|
1054
|
+
type: ConstantString.AdaptiveCardType,
|
|
1055
|
+
$schema: ConstantString.AdaptiveCardSchema,
|
|
1056
|
+
version: ConstantString.AdaptiveCardVersion,
|
|
1057
|
+
body: cardBody,
|
|
1058
|
+
};
|
|
1059
|
+
return [fullCard, jsonPath];
|
|
1060
|
+
}
|
|
1061
|
+
catch (err) {
|
|
1062
|
+
throw new SpecParserError(err.toString(), ErrorType.GenerateAdaptiveCardFailed);
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
static generateCardFromResponse(schema, name, parentArrayName = "") {
|
|
1066
|
+
if (schema.type === "array") {
|
|
1067
|
+
// schema.items can be arbitrary object: schema { type: array, items: {} }
|
|
1068
|
+
if (Object.keys(schema.items).length === 0) {
|
|
1069
|
+
return [
|
|
1070
|
+
{
|
|
1071
|
+
type: ConstantString.TextBlockType,
|
|
1072
|
+
text: name ? `${name}: \${jsonStringify(${name})}` : "result: ${jsonStringify($root)}",
|
|
1073
|
+
wrap: true,
|
|
1074
|
+
},
|
|
1075
|
+
];
|
|
1076
|
+
}
|
|
1077
|
+
const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name);
|
|
1078
|
+
const template = {
|
|
1079
|
+
type: ConstantString.ContainerType,
|
|
1080
|
+
$data: name ? `\${${name}}` : "${$root}",
|
|
1081
|
+
items: Array(),
|
|
1082
|
+
};
|
|
1083
|
+
template.items.push(...obj);
|
|
1084
|
+
return [template];
|
|
1085
|
+
}
|
|
1086
|
+
// some schema may not contain type but contain properties
|
|
1087
|
+
if (schema.type === "object" || (!schema.type && schema.properties)) {
|
|
1088
|
+
const { properties } = schema;
|
|
1089
|
+
const result = [];
|
|
1090
|
+
for (const property in properties) {
|
|
1091
|
+
const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName);
|
|
1092
|
+
result.push(...obj);
|
|
1093
|
+
}
|
|
1094
|
+
if (schema.additionalProperties) {
|
|
1095
|
+
// TODO: better ways to handler warnings.
|
|
1096
|
+
console.warn(ConstantString.AdditionalPropertiesNotSupported);
|
|
1097
|
+
}
|
|
1098
|
+
return result;
|
|
1099
|
+
}
|
|
1100
|
+
if (schema.type === "string" ||
|
|
1101
|
+
schema.type === "integer" ||
|
|
1102
|
+
schema.type === "boolean" ||
|
|
1103
|
+
schema.type === "number") {
|
|
1104
|
+
if (!AdaptiveCardGenerator.isImageUrlProperty(schema, name, parentArrayName)) {
|
|
1105
|
+
// string in root: "ddd"
|
|
1106
|
+
let text = "result: ${$root}";
|
|
1107
|
+
if (name) {
|
|
1108
|
+
// object { id: "1" }
|
|
1109
|
+
text = `${name}: \${if(${name}, ${name}, 'N/A')}`;
|
|
1110
|
+
if (parentArrayName) {
|
|
1111
|
+
// object types inside array: { tags: ["id": 1, "name": "name"] }
|
|
1112
|
+
text = `${parentArrayName}.${text}`;
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
else if (parentArrayName) {
|
|
1116
|
+
// string array: photoUrls: ["1", "2"]
|
|
1117
|
+
text = `${parentArrayName}: ` + "${$data}";
|
|
1118
|
+
}
|
|
1119
|
+
return [
|
|
1120
|
+
{
|
|
1121
|
+
type: ConstantString.TextBlockType,
|
|
1122
|
+
text,
|
|
1123
|
+
wrap: true,
|
|
1124
|
+
},
|
|
1125
|
+
];
|
|
1126
|
+
}
|
|
1127
|
+
else {
|
|
1128
|
+
if (name) {
|
|
1129
|
+
return [
|
|
1130
|
+
{
|
|
1131
|
+
type: "Image",
|
|
1132
|
+
url: `\${${name}}`,
|
|
1133
|
+
$when: `\${${name} != null}`,
|
|
1134
|
+
},
|
|
1135
|
+
];
|
|
1136
|
+
}
|
|
1137
|
+
else {
|
|
1138
|
+
return [
|
|
1139
|
+
{
|
|
1140
|
+
type: "Image",
|
|
1141
|
+
url: "${$data}",
|
|
1142
|
+
$when: "${$data != null}",
|
|
1143
|
+
},
|
|
1144
|
+
];
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
if (schema.oneOf || schema.anyOf || schema.not || schema.allOf) {
|
|
1149
|
+
throw new Error(Utils.format(ConstantString.SchemaNotSupported, JSON.stringify(schema)));
|
|
1150
|
+
}
|
|
1151
|
+
throw new Error(Utils.format(ConstantString.UnknownSchema, JSON.stringify(schema)));
|
|
1152
|
+
}
|
|
1153
|
+
// Find the first array property in the response schema object with the well-known name
|
|
1154
|
+
static getResponseJsonPathFromSchema(schema) {
|
|
1155
|
+
if (schema.type === "object" || (!schema.type && schema.properties)) {
|
|
1156
|
+
const { properties } = schema;
|
|
1157
|
+
for (const property in properties) {
|
|
1158
|
+
const schema = properties[property];
|
|
1159
|
+
if (schema.type === "array" &&
|
|
1160
|
+
Utils.isWellKnownName(property, ConstantString.WellknownResultNames)) {
|
|
1161
|
+
return property;
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
return "$";
|
|
1166
|
+
}
|
|
1167
|
+
static isImageUrlProperty(schema, name, parentArrayName) {
|
|
1168
|
+
const propertyName = name ? name : parentArrayName;
|
|
1169
|
+
return (!!propertyName &&
|
|
1170
|
+
schema.type === "string" &&
|
|
1171
|
+
Utils.isWellKnownName(propertyName, ConstantString.WellknownImageName) &&
|
|
1172
|
+
(propertyName.toLocaleLowerCase().indexOf("url") >= 0 || schema.format === "uri"));
|
|
1173
|
+
}
|
|
850
1174
|
}
|
|
851
1175
|
|
|
852
|
-
export { ConstantString, ErrorType, SpecParser, SpecParserError, Utils, ValidationStatus, WarningType };
|
|
1176
|
+
export { AdaptiveCardGenerator, ConstantString, ErrorType, SpecParser, SpecParserError, Utils, ValidationStatus, WarningType };
|
|
853
1177
|
//# sourceMappingURL=index.esm2017.js.map
|