@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.esm5.js
CHANGED
|
@@ -45,7 +45,8 @@ var ErrorType;
|
|
|
45
45
|
ErrorType["NoExtraAPICanBeAdded"] = "no-extra-api-can-be-added";
|
|
46
46
|
ErrorType["ResolveServerUrlFailed"] = "resolve-server-url-failed";
|
|
47
47
|
ErrorType["SwaggerNotSupported"] = "swagger-not-supported";
|
|
48
|
-
ErrorType["
|
|
48
|
+
ErrorType["MultipleAuthNotSupported"] = "multiple-auth-not-supported";
|
|
49
|
+
ErrorType["SpecVersionNotSupported"] = "spec-version-not-supported";
|
|
49
50
|
ErrorType["ListFailed"] = "list-failed";
|
|
50
51
|
ErrorType["listSupportedAPIInfoFailed"] = "list-supported-api-info-failed";
|
|
51
52
|
ErrorType["FilterSpecFailed"] = "filter-spec-failed";
|
|
@@ -53,6 +54,22 @@ var ErrorType;
|
|
|
53
54
|
ErrorType["GenerateAdaptiveCardFailed"] = "generate-adaptive-card-failed";
|
|
54
55
|
ErrorType["GenerateFailed"] = "generate-failed";
|
|
55
56
|
ErrorType["ValidateFailed"] = "validate-failed";
|
|
57
|
+
ErrorType["GetSpecFailed"] = "get-spec-failed";
|
|
58
|
+
ErrorType["AuthTypeIsNotSupported"] = "auth-type-is-not-supported";
|
|
59
|
+
ErrorType["MissingOperationId"] = "missing-operation-id";
|
|
60
|
+
ErrorType["PostBodyContainMultipleMediaTypes"] = "post-body-contain-multiple-media-types";
|
|
61
|
+
ErrorType["ResponseContainMultipleMediaTypes"] = "response-contain-multiple-media-types";
|
|
62
|
+
ErrorType["ResponseJsonIsEmpty"] = "response-json-is-empty";
|
|
63
|
+
ErrorType["PostBodySchemaIsNotJson"] = "post-body-schema-is-not-json";
|
|
64
|
+
ErrorType["PostBodyContainsRequiredUnsupportedSchema"] = "post-body-contains-required-unsupported-schema";
|
|
65
|
+
ErrorType["ParamsContainRequiredUnsupportedSchema"] = "params-contain-required-unsupported-schema";
|
|
66
|
+
ErrorType["ParamsContainsNestedObject"] = "params-contains-nested-object";
|
|
67
|
+
ErrorType["RequestBodyContainsNestedObject"] = "request-body-contains-nested-object";
|
|
68
|
+
ErrorType["ExceededRequiredParamsLimit"] = "exceeded-required-params-limit";
|
|
69
|
+
ErrorType["NoParameter"] = "no-parameter";
|
|
70
|
+
ErrorType["NoAPIInfo"] = "no-api-info";
|
|
71
|
+
ErrorType["MethodNotAllowed"] = "method-not-allowed";
|
|
72
|
+
ErrorType["UrlPathNotExist"] = "url-path-not-exist";
|
|
56
73
|
ErrorType["Cancelled"] = "cancelled";
|
|
57
74
|
ErrorType["Unknown"] = "unknown";
|
|
58
75
|
})(ErrorType || (ErrorType = {}));
|
|
@@ -75,7 +92,13 @@ var ValidationStatus;
|
|
|
75
92
|
ValidationStatus[ValidationStatus["Valid"] = 0] = "Valid";
|
|
76
93
|
ValidationStatus[ValidationStatus["Warning"] = 1] = "Warning";
|
|
77
94
|
ValidationStatus[ValidationStatus["Error"] = 2] = "Error";
|
|
78
|
-
})(ValidationStatus || (ValidationStatus = {}));
|
|
95
|
+
})(ValidationStatus || (ValidationStatus = {}));
|
|
96
|
+
var ProjectType;
|
|
97
|
+
(function (ProjectType) {
|
|
98
|
+
ProjectType[ProjectType["Copilot"] = 0] = "Copilot";
|
|
99
|
+
ProjectType[ProjectType["SME"] = 1] = "SME";
|
|
100
|
+
ProjectType[ProjectType["TeamsAi"] = 2] = "TeamsAi";
|
|
101
|
+
})(ProjectType || (ProjectType = {}));
|
|
79
102
|
|
|
80
103
|
// Copyright (c) Microsoft Corporation.
|
|
81
104
|
class SpecParserError extends Error {
|
|
@@ -102,7 +125,9 @@ ConstantString.ResolveServerUrlFailed = "Unable to resolve the server URL: pleas
|
|
|
102
125
|
ConstantString.OperationOnlyContainsOptionalParam = "Operation %s contains multiple optional parameters. The first optional parameter is used for this command.";
|
|
103
126
|
ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converted to OpenAPI 3.0.";
|
|
104
127
|
ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
|
|
105
|
-
ConstantString.
|
|
128
|
+
ConstantString.SpecVersionNotSupported = "Unsupported OpenAPI version %s. Please use version 3.0.x.";
|
|
129
|
+
ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
|
|
130
|
+
ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
|
|
106
131
|
ConstantString.WrappedCardVersion = "devPreview";
|
|
107
132
|
ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
|
|
108
133
|
ConstantString.WrappedCardResponseLayout = "list";
|
|
@@ -114,6 +139,7 @@ ConstantString.AdaptiveCardType = "AdaptiveCard";
|
|
|
114
139
|
ConstantString.TextBlockType = "TextBlock";
|
|
115
140
|
ConstantString.ContainerType = "Container";
|
|
116
141
|
ConstantString.RegistrationIdPostfix = "REGISTRATION_ID";
|
|
142
|
+
ConstantString.OAuthRegistrationIdPostFix = "OAUTH_REGISTRATION_ID";
|
|
117
143
|
ConstantString.ResponseCodeFor20X = [
|
|
118
144
|
"200",
|
|
119
145
|
"201",
|
|
@@ -173,15 +199,28 @@ ConstantString.FullDescriptionMaxLens = 4000;
|
|
|
173
199
|
ConstantString.CommandDescriptionMaxLens = 128;
|
|
174
200
|
ConstantString.ParameterDescriptionMaxLens = 128;
|
|
175
201
|
ConstantString.CommandTitleMaxLens = 32;
|
|
176
|
-
ConstantString.ParameterTitleMaxLens = 32;
|
|
202
|
+
ConstantString.ParameterTitleMaxLens = 32;
|
|
203
|
+
ConstantString.SMERequiredParamsMaxNum = 5;
|
|
177
204
|
|
|
178
205
|
// Copyright (c) Microsoft Corporation.
|
|
179
206
|
class Utils {
|
|
180
|
-
static
|
|
207
|
+
static hasNestedObjectInSchema(schema) {
|
|
208
|
+
if (schema.type === "object") {
|
|
209
|
+
for (const property in schema.properties) {
|
|
210
|
+
const nestedSchema = schema.properties[property];
|
|
211
|
+
if (nestedSchema.type === "object") {
|
|
212
|
+
return true;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
static checkParameters(paramObject, isCopilot) {
|
|
181
219
|
const paramResult = {
|
|
182
220
|
requiredNum: 0,
|
|
183
221
|
optionalNum: 0,
|
|
184
222
|
isValid: true,
|
|
223
|
+
reason: [],
|
|
185
224
|
};
|
|
186
225
|
if (!paramObject) {
|
|
187
226
|
return paramResult;
|
|
@@ -189,10 +228,25 @@ class Utils {
|
|
|
189
228
|
for (let i = 0; i < paramObject.length; i++) {
|
|
190
229
|
const param = paramObject[i];
|
|
191
230
|
const schema = param.schema;
|
|
231
|
+
if (isCopilot && this.hasNestedObjectInSchema(schema)) {
|
|
232
|
+
paramResult.isValid = false;
|
|
233
|
+
paramResult.reason.push(ErrorType.ParamsContainsNestedObject);
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
192
236
|
const isRequiredWithoutDefault = param.required && schema.default === undefined;
|
|
237
|
+
if (isCopilot) {
|
|
238
|
+
if (isRequiredWithoutDefault) {
|
|
239
|
+
paramResult.requiredNum = paramResult.requiredNum + 1;
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
paramResult.optionalNum = paramResult.optionalNum + 1;
|
|
243
|
+
}
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
193
246
|
if (param.in === "header" || param.in === "cookie") {
|
|
194
247
|
if (isRequiredWithoutDefault) {
|
|
195
248
|
paramResult.isValid = false;
|
|
249
|
+
paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
|
|
196
250
|
}
|
|
197
251
|
continue;
|
|
198
252
|
}
|
|
@@ -202,6 +256,7 @@ class Utils {
|
|
|
202
256
|
schema.type !== "integer") {
|
|
203
257
|
if (isRequiredWithoutDefault) {
|
|
204
258
|
paramResult.isValid = false;
|
|
259
|
+
paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
|
|
205
260
|
}
|
|
206
261
|
continue;
|
|
207
262
|
}
|
|
@@ -216,17 +271,23 @@ class Utils {
|
|
|
216
271
|
}
|
|
217
272
|
return paramResult;
|
|
218
273
|
}
|
|
219
|
-
static checkPostBody(schema, isRequired = false) {
|
|
274
|
+
static checkPostBody(schema, isRequired = false, isCopilot = false) {
|
|
220
275
|
var _a;
|
|
221
276
|
const paramResult = {
|
|
222
277
|
requiredNum: 0,
|
|
223
278
|
optionalNum: 0,
|
|
224
279
|
isValid: true,
|
|
280
|
+
reason: [],
|
|
225
281
|
};
|
|
226
282
|
if (Object.keys(schema).length === 0) {
|
|
227
283
|
return paramResult;
|
|
228
284
|
}
|
|
229
285
|
const isRequiredWithoutDefault = isRequired && schema.default === undefined;
|
|
286
|
+
if (isCopilot && this.hasNestedObjectInSchema(schema)) {
|
|
287
|
+
paramResult.isValid = false;
|
|
288
|
+
paramResult.reason = [ErrorType.RequestBodyContainsNestedObject];
|
|
289
|
+
return paramResult;
|
|
290
|
+
}
|
|
230
291
|
if (schema.type === "string" ||
|
|
231
292
|
schema.type === "integer" ||
|
|
232
293
|
schema.type === "boolean" ||
|
|
@@ -245,19 +306,24 @@ class Utils {
|
|
|
245
306
|
if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
|
|
246
307
|
isRequired = true;
|
|
247
308
|
}
|
|
248
|
-
const result = Utils.checkPostBody(properties[property], isRequired);
|
|
309
|
+
const result = Utils.checkPostBody(properties[property], isRequired, isCopilot);
|
|
249
310
|
paramResult.requiredNum += result.requiredNum;
|
|
250
311
|
paramResult.optionalNum += result.optionalNum;
|
|
251
312
|
paramResult.isValid = paramResult.isValid && result.isValid;
|
|
313
|
+
paramResult.reason.push(...result.reason);
|
|
252
314
|
}
|
|
253
315
|
}
|
|
254
316
|
else {
|
|
255
|
-
if (isRequiredWithoutDefault) {
|
|
317
|
+
if (isRequiredWithoutDefault && !isCopilot) {
|
|
256
318
|
paramResult.isValid = false;
|
|
319
|
+
paramResult.reason.push(ErrorType.PostBodyContainsRequiredUnsupportedSchema);
|
|
257
320
|
}
|
|
258
321
|
}
|
|
259
322
|
return paramResult;
|
|
260
323
|
}
|
|
324
|
+
static containMultipleMediaTypes(bodyObject) {
|
|
325
|
+
return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
|
|
326
|
+
}
|
|
261
327
|
/**
|
|
262
328
|
* Checks if the given API is supported.
|
|
263
329
|
* @param {string} method - The HTTP method of the API.
|
|
@@ -272,106 +338,137 @@ class Utils {
|
|
|
272
338
|
* 5. response body should be “application/json” and not empty, and response code should be 20X
|
|
273
339
|
* 6. only support request body with “application/json” content type
|
|
274
340
|
*/
|
|
275
|
-
static isSupportedApi(method, path, spec,
|
|
276
|
-
|
|
341
|
+
static isSupportedApi(method, path, spec, options) {
|
|
342
|
+
var _a;
|
|
343
|
+
const result = { isValid: true, reason: [] };
|
|
277
344
|
method = method.toLocaleLowerCase();
|
|
278
|
-
if (
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
345
|
+
if (options.allowMethods && !options.allowMethods.includes(method)) {
|
|
346
|
+
result.isValid = false;
|
|
347
|
+
result.reason.push(ErrorType.MethodNotAllowed);
|
|
348
|
+
return result;
|
|
349
|
+
}
|
|
350
|
+
const pathObj = spec.paths[path];
|
|
351
|
+
if (!pathObj || !pathObj[method]) {
|
|
352
|
+
result.isValid = false;
|
|
353
|
+
result.reason.push(ErrorType.UrlPathNotExist);
|
|
354
|
+
return result;
|
|
355
|
+
}
|
|
356
|
+
const securities = pathObj[method].security;
|
|
357
|
+
const isTeamsAi = options.projectType === ProjectType.TeamsAi;
|
|
358
|
+
const isCopilot = options.projectType === ProjectType.Copilot;
|
|
359
|
+
// Teams AI project doesn't care about auth, it will use authProvider for user to implement
|
|
360
|
+
if (!isTeamsAi) {
|
|
361
|
+
const authArray = Utils.getAuthArray(securities, spec);
|
|
362
|
+
const authCheckResult = Utils.isSupportedAuth(authArray, options);
|
|
363
|
+
if (!authCheckResult.isValid) {
|
|
364
|
+
result.reason.push(...authCheckResult.reason);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
const operationObject = pathObj[method];
|
|
368
|
+
if (!options.allowMissingId && !operationObject.operationId) {
|
|
369
|
+
result.reason.push(ErrorType.MissingOperationId);
|
|
370
|
+
}
|
|
371
|
+
const rootServer = spec.servers && spec.servers[0];
|
|
372
|
+
const methodServer = spec.paths[path].servers && ((_a = spec.paths[path]) === null || _a === void 0 ? void 0 : _a.servers[0]);
|
|
373
|
+
const operationServer = operationObject.servers && operationObject.servers[0];
|
|
374
|
+
const serverUrl = operationServer || methodServer || rootServer;
|
|
375
|
+
if (!serverUrl) {
|
|
376
|
+
result.reason.push(ErrorType.NoServerInformation);
|
|
377
|
+
}
|
|
378
|
+
else {
|
|
379
|
+
const serverValidateResult = Utils.checkServerUrl([serverUrl]);
|
|
380
|
+
result.reason.push(...serverValidateResult.map((item) => item.type));
|
|
381
|
+
}
|
|
382
|
+
const paramObject = operationObject.parameters;
|
|
383
|
+
const requestBody = operationObject.requestBody;
|
|
384
|
+
const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
|
|
385
|
+
if (!isTeamsAi && Utils.containMultipleMediaTypes(requestBody)) {
|
|
386
|
+
result.reason.push(ErrorType.PostBodyContainMultipleMediaTypes);
|
|
387
|
+
}
|
|
388
|
+
const { json, multipleMediaType } = Utils.getResponseJson(operationObject, isTeamsAi);
|
|
389
|
+
if (multipleMediaType && !isTeamsAi) {
|
|
390
|
+
result.reason.push(ErrorType.ResponseContainMultipleMediaTypes);
|
|
391
|
+
}
|
|
392
|
+
else if (Object.keys(json).length === 0) {
|
|
393
|
+
result.reason.push(ErrorType.ResponseJsonIsEmpty);
|
|
394
|
+
}
|
|
395
|
+
// Teams AI project doesn't care about request parameters/body
|
|
396
|
+
if (!isTeamsAi) {
|
|
397
|
+
let requestBodyParamResult = {
|
|
398
|
+
requiredNum: 0,
|
|
399
|
+
optionalNum: 0,
|
|
400
|
+
isValid: true,
|
|
401
|
+
reason: [],
|
|
402
|
+
};
|
|
403
|
+
if (requestJsonBody) {
|
|
404
|
+
const requestBodySchema = requestJsonBody.schema;
|
|
405
|
+
if (isCopilot && requestBodySchema.type !== "object") {
|
|
406
|
+
result.reason.push(ErrorType.PostBodySchemaIsNotJson);
|
|
312
407
|
}
|
|
313
|
-
|
|
314
|
-
if (!
|
|
315
|
-
|
|
408
|
+
requestBodyParamResult = Utils.checkPostBody(requestBodySchema, requestBody.required, isCopilot);
|
|
409
|
+
if (!requestBodyParamResult.isValid && requestBodyParamResult.reason) {
|
|
410
|
+
result.reason.push(...requestBodyParamResult.reason);
|
|
316
411
|
}
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
412
|
+
}
|
|
413
|
+
const paramResult = Utils.checkParameters(paramObject, isCopilot);
|
|
414
|
+
if (!paramResult.isValid && paramResult.reason) {
|
|
415
|
+
result.reason.push(...paramResult.reason);
|
|
416
|
+
}
|
|
417
|
+
// Copilot support arbitrary parameters
|
|
418
|
+
if (!isCopilot && paramResult.isValid && requestBodyParamResult.isValid) {
|
|
419
|
+
const totalRequiredParams = requestBodyParamResult.requiredNum + paramResult.requiredNum;
|
|
420
|
+
const totalParams = totalRequiredParams + requestBodyParamResult.optionalNum + paramResult.optionalNum;
|
|
421
|
+
if (totalRequiredParams > 1) {
|
|
422
|
+
if (!options.allowMultipleParameters ||
|
|
423
|
+
totalRequiredParams > ConstantString.SMERequiredParamsMaxNum) {
|
|
424
|
+
result.reason.push(ErrorType.ExceededRequiredParamsLimit);
|
|
321
425
|
}
|
|
322
|
-
return false;
|
|
323
|
-
}
|
|
324
|
-
else if (requestBodyParamResult.requiredNum +
|
|
325
|
-
requestBodyParamResult.optionalNum +
|
|
326
|
-
paramResult.requiredNum +
|
|
327
|
-
paramResult.optionalNum ===
|
|
328
|
-
0) {
|
|
329
|
-
return false;
|
|
330
426
|
}
|
|
331
|
-
else {
|
|
332
|
-
|
|
427
|
+
else if (totalParams === 0) {
|
|
428
|
+
result.reason.push(ErrorType.NoParameter);
|
|
333
429
|
}
|
|
334
430
|
}
|
|
335
431
|
}
|
|
336
|
-
|
|
432
|
+
if (result.reason.length > 0) {
|
|
433
|
+
result.isValid = false;
|
|
434
|
+
}
|
|
435
|
+
return result;
|
|
337
436
|
}
|
|
338
|
-
static isSupportedAuth(
|
|
339
|
-
if (
|
|
340
|
-
return true;
|
|
437
|
+
static isSupportedAuth(authSchemeArray, options) {
|
|
438
|
+
if (authSchemeArray.length === 0) {
|
|
439
|
+
return { isValid: true, reason: [] };
|
|
341
440
|
}
|
|
342
|
-
if (allowAPIKeyAuth || allowOauth2) {
|
|
441
|
+
if (options.allowAPIKeyAuth || options.allowOauth2 || options.allowBearerTokenAuth) {
|
|
343
442
|
// Currently we don't support multiple auth in one operation
|
|
344
|
-
if (
|
|
345
|
-
return
|
|
443
|
+
if (authSchemeArray.length > 0 && authSchemeArray.every((auths) => auths.length > 1)) {
|
|
444
|
+
return {
|
|
445
|
+
isValid: false,
|
|
446
|
+
reason: [ErrorType.MultipleAuthNotSupported],
|
|
447
|
+
};
|
|
346
448
|
}
|
|
347
|
-
for (const auths of
|
|
449
|
+
for (const auths of authSchemeArray) {
|
|
348
450
|
if (auths.length === 1) {
|
|
349
|
-
if (
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
allowOauth2 &&
|
|
354
|
-
Utils.isBearerTokenAuth(auths[0].authSchema)) {
|
|
355
|
-
return true;
|
|
356
|
-
}
|
|
357
|
-
else if (allowAPIKeyAuth &&
|
|
358
|
-
allowOauth2 &&
|
|
359
|
-
(Utils.isAPIKeyAuth(auths[0].authSchema) ||
|
|
360
|
-
Utils.isBearerTokenAuth(auths[0].authSchema))) {
|
|
361
|
-
return true;
|
|
451
|
+
if ((options.allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authScheme)) ||
|
|
452
|
+
(options.allowOauth2 && Utils.isOAuthWithAuthCodeFlow(auths[0].authScheme)) ||
|
|
453
|
+
(options.allowBearerTokenAuth && Utils.isBearerTokenAuth(auths[0].authScheme))) {
|
|
454
|
+
return { isValid: true, reason: [] };
|
|
362
455
|
}
|
|
363
456
|
}
|
|
364
457
|
}
|
|
365
458
|
}
|
|
366
|
-
return false;
|
|
459
|
+
return { isValid: false, reason: [ErrorType.AuthTypeIsNotSupported] };
|
|
367
460
|
}
|
|
368
|
-
static
|
|
369
|
-
return
|
|
461
|
+
static isBearerTokenAuth(authScheme) {
|
|
462
|
+
return authScheme.type === "http" && authScheme.scheme === "bearer";
|
|
370
463
|
}
|
|
371
|
-
static
|
|
372
|
-
return
|
|
373
|
-
|
|
374
|
-
|
|
464
|
+
static isAPIKeyAuth(authScheme) {
|
|
465
|
+
return authScheme.type === "apiKey";
|
|
466
|
+
}
|
|
467
|
+
static isOAuthWithAuthCodeFlow(authScheme) {
|
|
468
|
+
if (authScheme.type === "oauth2" && authScheme.flows && authScheme.flows.authorizationCode) {
|
|
469
|
+
return true;
|
|
470
|
+
}
|
|
471
|
+
return false;
|
|
375
472
|
}
|
|
376
473
|
static getAuthArray(securities, spec) {
|
|
377
474
|
var _a;
|
|
@@ -384,7 +481,7 @@ class Utils {
|
|
|
384
481
|
for (const name in security) {
|
|
385
482
|
const auth = securitySchemas[name];
|
|
386
483
|
authArray.push({
|
|
387
|
-
|
|
484
|
+
authScheme: auth,
|
|
388
485
|
name: name,
|
|
389
486
|
});
|
|
390
487
|
}
|
|
@@ -399,21 +496,28 @@ class Utils {
|
|
|
399
496
|
static updateFirstLetter(str) {
|
|
400
497
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
401
498
|
}
|
|
402
|
-
static getResponseJson(operationObject) {
|
|
499
|
+
static getResponseJson(operationObject, isTeamsAiProject = false) {
|
|
403
500
|
var _a, _b;
|
|
404
501
|
let json = {};
|
|
502
|
+
let multipleMediaType = false;
|
|
405
503
|
for (const code of ConstantString.ResponseCodeFor20X) {
|
|
406
504
|
const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
|
|
407
|
-
const mediaTypesCount = Object.keys((responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) || {}).length;
|
|
408
|
-
if (mediaTypesCount > 1) {
|
|
409
|
-
return {};
|
|
410
|
-
}
|
|
411
505
|
if ((_b = responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) === null || _b === void 0 ? void 0 : _b["application/json"]) {
|
|
506
|
+
multipleMediaType = false;
|
|
412
507
|
json = responseObject.content["application/json"];
|
|
413
|
-
|
|
508
|
+
if (Utils.containMultipleMediaTypes(responseObject)) {
|
|
509
|
+
multipleMediaType = true;
|
|
510
|
+
if (isTeamsAiProject) {
|
|
511
|
+
break;
|
|
512
|
+
}
|
|
513
|
+
json = {};
|
|
514
|
+
}
|
|
515
|
+
else {
|
|
516
|
+
break;
|
|
517
|
+
}
|
|
414
518
|
}
|
|
415
519
|
}
|
|
416
|
-
return json;
|
|
520
|
+
return { json, multipleMediaType };
|
|
417
521
|
}
|
|
418
522
|
static convertPathToCamelCase(path) {
|
|
419
523
|
const pathSegments = path.split(/[./{]/);
|
|
@@ -433,10 +537,10 @@ class Utils {
|
|
|
433
537
|
return undefined;
|
|
434
538
|
}
|
|
435
539
|
}
|
|
436
|
-
static
|
|
540
|
+
static resolveEnv(str) {
|
|
437
541
|
const placeHolderReg = /\${{\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*}}/g;
|
|
438
|
-
let matches = placeHolderReg.exec(
|
|
439
|
-
let
|
|
542
|
+
let matches = placeHolderReg.exec(str);
|
|
543
|
+
let newStr = str;
|
|
440
544
|
while (matches != null) {
|
|
441
545
|
const envVar = matches[1];
|
|
442
546
|
const envVal = process.env[envVar];
|
|
@@ -444,17 +548,17 @@ class Utils {
|
|
|
444
548
|
throw new Error(Utils.format(ConstantString.ResolveServerUrlFailed, envVar));
|
|
445
549
|
}
|
|
446
550
|
else {
|
|
447
|
-
|
|
551
|
+
newStr = newStr.replace(matches[0], envVal);
|
|
448
552
|
}
|
|
449
|
-
matches = placeHolderReg.exec(
|
|
553
|
+
matches = placeHolderReg.exec(str);
|
|
450
554
|
}
|
|
451
|
-
return
|
|
555
|
+
return newStr;
|
|
452
556
|
}
|
|
453
557
|
static checkServerUrl(servers) {
|
|
454
558
|
const errors = [];
|
|
455
559
|
let serverUrl;
|
|
456
560
|
try {
|
|
457
|
-
serverUrl = Utils.
|
|
561
|
+
serverUrl = Utils.resolveEnv(servers[0].url);
|
|
458
562
|
}
|
|
459
563
|
catch (err) {
|
|
460
564
|
errors.push({
|
|
@@ -484,7 +588,8 @@ class Utils {
|
|
|
484
588
|
}
|
|
485
589
|
return errors;
|
|
486
590
|
}
|
|
487
|
-
static validateServer(spec,
|
|
591
|
+
static validateServer(spec, options) {
|
|
592
|
+
var _a;
|
|
488
593
|
const errors = [];
|
|
489
594
|
let hasTopLevelServers = false;
|
|
490
595
|
let hasPathLevelServers = false;
|
|
@@ -505,7 +610,7 @@ class Utils {
|
|
|
505
610
|
}
|
|
506
611
|
for (const method in methods) {
|
|
507
612
|
const operationObject = methods[method];
|
|
508
|
-
if (
|
|
613
|
+
if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
|
|
509
614
|
if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
|
|
510
615
|
hasOperationLevelServers = true;
|
|
511
616
|
const serverErrors = Utils.checkServerUrl(operationObject.servers);
|
|
@@ -548,6 +653,7 @@ class Utils {
|
|
|
548
653
|
Utils.updateParameterWithInputType(schema, parameter);
|
|
549
654
|
}
|
|
550
655
|
if (isRequired && schema.default === undefined) {
|
|
656
|
+
parameter.isRequired = true;
|
|
551
657
|
requiredParams.push(parameter);
|
|
552
658
|
}
|
|
553
659
|
else {
|
|
@@ -592,7 +698,7 @@ class Utils {
|
|
|
592
698
|
param.value = schema.default;
|
|
593
699
|
}
|
|
594
700
|
}
|
|
595
|
-
static parseApiInfo(operationItem,
|
|
701
|
+
static parseApiInfo(operationItem, options) {
|
|
596
702
|
var _a, _b;
|
|
597
703
|
const requiredParams = [];
|
|
598
704
|
const optionalParams = [];
|
|
@@ -606,11 +712,12 @@ class Utils {
|
|
|
606
712
|
description: ((_a = param.description) !== null && _a !== void 0 ? _a : "").slice(0, ConstantString.ParameterDescriptionMaxLens),
|
|
607
713
|
};
|
|
608
714
|
const schema = param.schema;
|
|
609
|
-
if (allowMultipleParameters && schema) {
|
|
715
|
+
if (options.allowMultipleParameters && schema) {
|
|
610
716
|
Utils.updateParameterWithInputType(schema, parameter);
|
|
611
717
|
}
|
|
612
718
|
if (param.in !== "header" && param.in !== "cookie") {
|
|
613
719
|
if (param.required && (schema === null || schema === void 0 ? void 0 : schema.default) === undefined) {
|
|
720
|
+
parameter.isRequired = true;
|
|
614
721
|
requiredParams.push(parameter);
|
|
615
722
|
}
|
|
616
723
|
else {
|
|
@@ -624,7 +731,7 @@ class Utils {
|
|
|
624
731
|
const requestJson = requestBody.content["application/json"];
|
|
625
732
|
if (Object.keys(requestJson).length !== 0) {
|
|
626
733
|
const schema = requestJson.schema;
|
|
627
|
-
const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", allowMultipleParameters, requestBody.required);
|
|
734
|
+
const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", !!options.allowMultipleParameters, requestBody.required);
|
|
628
735
|
requiredParams.push(...requiredP);
|
|
629
736
|
optionalParams.push(...optionalP);
|
|
630
737
|
}
|
|
@@ -655,32 +762,37 @@ class Utils {
|
|
|
655
762
|
}
|
|
656
763
|
return [command, warning];
|
|
657
764
|
}
|
|
658
|
-
static
|
|
765
|
+
static listAPIs(spec, options) {
|
|
766
|
+
var _a;
|
|
659
767
|
const paths = spec.paths;
|
|
660
768
|
const result = {};
|
|
661
769
|
for (const path in paths) {
|
|
662
770
|
const methods = paths[path];
|
|
663
771
|
for (const method in methods) {
|
|
664
|
-
|
|
665
|
-
if (
|
|
666
|
-
const
|
|
667
|
-
result[`${method.toUpperCase()} ${path}`] =
|
|
772
|
+
const operationObject = methods[method];
|
|
773
|
+
if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
|
|
774
|
+
const validateResult = Utils.isSupportedApi(method, path, spec, options);
|
|
775
|
+
result[`${method.toUpperCase()} ${path}`] = {
|
|
776
|
+
operation: operationObject,
|
|
777
|
+
isValid: validateResult.isValid,
|
|
778
|
+
reason: validateResult.reason,
|
|
779
|
+
};
|
|
668
780
|
}
|
|
669
781
|
}
|
|
670
782
|
}
|
|
671
783
|
return result;
|
|
672
784
|
}
|
|
673
|
-
static validateSpec(spec, parser, isSwaggerFile,
|
|
785
|
+
static validateSpec(spec, parser, isSwaggerFile, options) {
|
|
674
786
|
const errors = [];
|
|
675
787
|
const warnings = [];
|
|
788
|
+
const apiMap = Utils.listAPIs(spec, options);
|
|
676
789
|
if (isSwaggerFile) {
|
|
677
790
|
warnings.push({
|
|
678
791
|
type: WarningType.ConvertSwaggerToOpenAPI,
|
|
679
792
|
content: ConstantString.ConvertSwaggerToOpenAPI,
|
|
680
793
|
});
|
|
681
794
|
}
|
|
682
|
-
|
|
683
|
-
const serverErrors = Utils.validateServer(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2);
|
|
795
|
+
const serverErrors = Utils.validateServer(spec, options);
|
|
684
796
|
errors.push(...serverErrors);
|
|
685
797
|
// Remote reference not supported
|
|
686
798
|
const refPaths = parser.$refs.paths();
|
|
@@ -693,8 +805,8 @@ class Utils {
|
|
|
693
805
|
});
|
|
694
806
|
}
|
|
695
807
|
// No supported API
|
|
696
|
-
const
|
|
697
|
-
if (
|
|
808
|
+
const validAPIs = Object.entries(apiMap).filter(([, value]) => value.isValid);
|
|
809
|
+
if (validAPIs.length === 0) {
|
|
698
810
|
errors.push({
|
|
699
811
|
type: ErrorType.NoSupportedApi,
|
|
700
812
|
content: ConstantString.NoSupportedApi,
|
|
@@ -703,8 +815,8 @@ class Utils {
|
|
|
703
815
|
// OperationId missing
|
|
704
816
|
const apisMissingOperationId = [];
|
|
705
817
|
for (const key in apiMap) {
|
|
706
|
-
const
|
|
707
|
-
if (!
|
|
818
|
+
const { operation } = apiMap[key];
|
|
819
|
+
if (!operation.operationId) {
|
|
708
820
|
apisMissingOperationId.push(key);
|
|
709
821
|
}
|
|
710
822
|
}
|
|
@@ -745,6 +857,19 @@ class Utils {
|
|
|
745
857
|
}
|
|
746
858
|
return safeRegistrationIdEnvName;
|
|
747
859
|
}
|
|
860
|
+
static getAllAPICount(spec) {
|
|
861
|
+
let count = 0;
|
|
862
|
+
const paths = spec.paths;
|
|
863
|
+
for (const path in paths) {
|
|
864
|
+
const methods = paths[path];
|
|
865
|
+
for (const method in methods) {
|
|
866
|
+
if (ConstantString.AllOperationMethods.includes(method)) {
|
|
867
|
+
count++;
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
return count;
|
|
872
|
+
}
|
|
748
873
|
}
|
|
749
874
|
|
|
750
875
|
// Copyright (c) Microsoft Corporation.
|
|
@@ -763,7 +888,10 @@ class SpecParser {
|
|
|
763
888
|
allowSwagger: false,
|
|
764
889
|
allowAPIKeyAuth: false,
|
|
765
890
|
allowMultipleParameters: false,
|
|
891
|
+
allowBearerTokenAuth: false,
|
|
766
892
|
allowOauth2: false,
|
|
893
|
+
allowMethods: ["get", "post"],
|
|
894
|
+
projectType: ProjectType.SME,
|
|
767
895
|
};
|
|
768
896
|
this.pathOrSpec = pathOrDoc;
|
|
769
897
|
this.parser = new SwaggerParser();
|
|
@@ -801,7 +929,7 @@ class SpecParser {
|
|
|
801
929
|
],
|
|
802
930
|
};
|
|
803
931
|
}
|
|
804
|
-
return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options
|
|
932
|
+
return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options);
|
|
805
933
|
}
|
|
806
934
|
catch (err) {
|
|
807
935
|
throw new SpecParserError(err.toString(), ErrorType.ValidateFailed);
|
|
@@ -822,7 +950,7 @@ class SpecParser {
|
|
|
822
950
|
if (!operationId) {
|
|
823
951
|
continue;
|
|
824
952
|
}
|
|
825
|
-
const [command, warning] = Utils.parseApiInfo(pathObjectItem, this.options
|
|
953
|
+
const [command, warning] = Utils.parseApiInfo(pathObjectItem, this.options);
|
|
826
954
|
const apiInfo = {
|
|
827
955
|
method: method,
|
|
828
956
|
path: path,
|
|
@@ -854,12 +982,36 @@ class SpecParser {
|
|
|
854
982
|
throw new Error("Method not implemented.");
|
|
855
983
|
});
|
|
856
984
|
}
|
|
985
|
+
/**
|
|
986
|
+
* Generate specs according to the filters.
|
|
987
|
+
* @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
|
|
988
|
+
*/
|
|
989
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
990
|
+
getFilteredSpecs(filter, signal) {
|
|
991
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
992
|
+
throw new Error("Method not implemented.");
|
|
993
|
+
});
|
|
994
|
+
}
|
|
995
|
+
/**
|
|
996
|
+
* Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
|
|
997
|
+
* @param manifestPath A file path of the Teams app manifest file to update.
|
|
998
|
+
* @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
|
|
999
|
+
* @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
|
|
1000
|
+
* @param pluginFilePath File path of the api plugin file to generate.
|
|
1001
|
+
*/
|
|
1002
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
1003
|
+
generateForCopilot(manifestPath, filter, outputSpecPath, pluginFilePath, signal) {
|
|
1004
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1005
|
+
throw new Error("Method not implemented.");
|
|
1006
|
+
});
|
|
1007
|
+
}
|
|
857
1008
|
/**
|
|
858
1009
|
* Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
|
|
859
1010
|
* @param manifestPath A file path of the Teams app manifest file to update.
|
|
860
1011
|
* @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
|
|
861
1012
|
* @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
|
|
862
1013
|
* @param adaptiveCardFolder Folder path where the Adaptive Card files will be generated. If not specified or empty, Adaptive Card files will not be generated.
|
|
1014
|
+
* @param isMe Boolean that indicates whether the project is an Messaging Extension. For Messaging Extension, composeExtensions will be added in Teams app manifest.
|
|
863
1015
|
*/
|
|
864
1016
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
865
1017
|
generate(manifestPath, filter, outputSpecPath, adaptiveCardFolder, signal) {
|
|
@@ -883,11 +1035,187 @@ class SpecParser {
|
|
|
883
1035
|
if (this.apiMap !== undefined) {
|
|
884
1036
|
return this.apiMap;
|
|
885
1037
|
}
|
|
886
|
-
const result =
|
|
1038
|
+
const result = this.listSupportedAPIs(spec, this.options);
|
|
887
1039
|
this.apiMap = result;
|
|
888
1040
|
return result;
|
|
889
1041
|
}
|
|
1042
|
+
listSupportedAPIs(spec, options) {
|
|
1043
|
+
var _a;
|
|
1044
|
+
const paths = spec.paths;
|
|
1045
|
+
const result = {};
|
|
1046
|
+
for (const path in paths) {
|
|
1047
|
+
const methods = paths[path];
|
|
1048
|
+
for (const method in methods) {
|
|
1049
|
+
const operationObject = methods[method];
|
|
1050
|
+
if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
|
|
1051
|
+
const validateResult = Utils.isSupportedApi(method, path, spec, options);
|
|
1052
|
+
if (validateResult.isValid) {
|
|
1053
|
+
result[`${method.toUpperCase()} ${path}`] = operationObject;
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
return result;
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
// Copyright (c) Microsoft Corporation.
|
|
1063
|
+
class AdaptiveCardGenerator {
|
|
1064
|
+
static generateAdaptiveCard(operationItem) {
|
|
1065
|
+
try {
|
|
1066
|
+
const { json } = Utils.getResponseJson(operationItem);
|
|
1067
|
+
let cardBody = [];
|
|
1068
|
+
let schema = json.schema;
|
|
1069
|
+
let jsonPath = "$";
|
|
1070
|
+
if (schema && Object.keys(schema).length > 0) {
|
|
1071
|
+
jsonPath = AdaptiveCardGenerator.getResponseJsonPathFromSchema(schema);
|
|
1072
|
+
if (jsonPath !== "$") {
|
|
1073
|
+
schema = schema.properties[jsonPath];
|
|
1074
|
+
}
|
|
1075
|
+
cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "");
|
|
1076
|
+
}
|
|
1077
|
+
// if no schema, try to use example value
|
|
1078
|
+
if (cardBody.length === 0 && (json.examples || json.example)) {
|
|
1079
|
+
cardBody = [
|
|
1080
|
+
{
|
|
1081
|
+
type: ConstantString.TextBlockType,
|
|
1082
|
+
text: "${jsonStringify($root)}",
|
|
1083
|
+
wrap: true,
|
|
1084
|
+
},
|
|
1085
|
+
];
|
|
1086
|
+
}
|
|
1087
|
+
// if no example value, use default success response
|
|
1088
|
+
if (cardBody.length === 0) {
|
|
1089
|
+
cardBody = [
|
|
1090
|
+
{
|
|
1091
|
+
type: ConstantString.TextBlockType,
|
|
1092
|
+
text: "success",
|
|
1093
|
+
wrap: true,
|
|
1094
|
+
},
|
|
1095
|
+
];
|
|
1096
|
+
}
|
|
1097
|
+
const fullCard = {
|
|
1098
|
+
type: ConstantString.AdaptiveCardType,
|
|
1099
|
+
$schema: ConstantString.AdaptiveCardSchema,
|
|
1100
|
+
version: ConstantString.AdaptiveCardVersion,
|
|
1101
|
+
body: cardBody,
|
|
1102
|
+
};
|
|
1103
|
+
return [fullCard, jsonPath];
|
|
1104
|
+
}
|
|
1105
|
+
catch (err) {
|
|
1106
|
+
throw new SpecParserError(err.toString(), ErrorType.GenerateAdaptiveCardFailed);
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
static generateCardFromResponse(schema, name, parentArrayName = "") {
|
|
1110
|
+
if (schema.type === "array") {
|
|
1111
|
+
// schema.items can be arbitrary object: schema { type: array, items: {} }
|
|
1112
|
+
if (Object.keys(schema.items).length === 0) {
|
|
1113
|
+
return [
|
|
1114
|
+
{
|
|
1115
|
+
type: ConstantString.TextBlockType,
|
|
1116
|
+
text: name ? `${name}: \${jsonStringify(${name})}` : "result: ${jsonStringify($root)}",
|
|
1117
|
+
wrap: true,
|
|
1118
|
+
},
|
|
1119
|
+
];
|
|
1120
|
+
}
|
|
1121
|
+
const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name);
|
|
1122
|
+
const template = {
|
|
1123
|
+
type: ConstantString.ContainerType,
|
|
1124
|
+
$data: name ? `\${${name}}` : "${$root}",
|
|
1125
|
+
items: Array(),
|
|
1126
|
+
};
|
|
1127
|
+
template.items.push(...obj);
|
|
1128
|
+
return [template];
|
|
1129
|
+
}
|
|
1130
|
+
// some schema may not contain type but contain properties
|
|
1131
|
+
if (schema.type === "object" || (!schema.type && schema.properties)) {
|
|
1132
|
+
const { properties } = schema;
|
|
1133
|
+
const result = [];
|
|
1134
|
+
for (const property in properties) {
|
|
1135
|
+
const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName);
|
|
1136
|
+
result.push(...obj);
|
|
1137
|
+
}
|
|
1138
|
+
if (schema.additionalProperties) {
|
|
1139
|
+
// TODO: better ways to handler warnings.
|
|
1140
|
+
console.warn(ConstantString.AdditionalPropertiesNotSupported);
|
|
1141
|
+
}
|
|
1142
|
+
return result;
|
|
1143
|
+
}
|
|
1144
|
+
if (schema.type === "string" ||
|
|
1145
|
+
schema.type === "integer" ||
|
|
1146
|
+
schema.type === "boolean" ||
|
|
1147
|
+
schema.type === "number") {
|
|
1148
|
+
if (!AdaptiveCardGenerator.isImageUrlProperty(schema, name, parentArrayName)) {
|
|
1149
|
+
// string in root: "ddd"
|
|
1150
|
+
let text = "result: ${$root}";
|
|
1151
|
+
if (name) {
|
|
1152
|
+
// object { id: "1" }
|
|
1153
|
+
text = `${name}: \${if(${name}, ${name}, 'N/A')}`;
|
|
1154
|
+
if (parentArrayName) {
|
|
1155
|
+
// object types inside array: { tags: ["id": 1, "name": "name"] }
|
|
1156
|
+
text = `${parentArrayName}.${text}`;
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
else if (parentArrayName) {
|
|
1160
|
+
// string array: photoUrls: ["1", "2"]
|
|
1161
|
+
text = `${parentArrayName}: ` + "${$data}";
|
|
1162
|
+
}
|
|
1163
|
+
return [
|
|
1164
|
+
{
|
|
1165
|
+
type: ConstantString.TextBlockType,
|
|
1166
|
+
text,
|
|
1167
|
+
wrap: true,
|
|
1168
|
+
},
|
|
1169
|
+
];
|
|
1170
|
+
}
|
|
1171
|
+
else {
|
|
1172
|
+
if (name) {
|
|
1173
|
+
return [
|
|
1174
|
+
{
|
|
1175
|
+
type: "Image",
|
|
1176
|
+
url: `\${${name}}`,
|
|
1177
|
+
$when: `\${${name} != null}`,
|
|
1178
|
+
},
|
|
1179
|
+
];
|
|
1180
|
+
}
|
|
1181
|
+
else {
|
|
1182
|
+
return [
|
|
1183
|
+
{
|
|
1184
|
+
type: "Image",
|
|
1185
|
+
url: "${$data}",
|
|
1186
|
+
$when: "${$data != null}",
|
|
1187
|
+
},
|
|
1188
|
+
];
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
if (schema.oneOf || schema.anyOf || schema.not || schema.allOf) {
|
|
1193
|
+
throw new Error(Utils.format(ConstantString.SchemaNotSupported, JSON.stringify(schema)));
|
|
1194
|
+
}
|
|
1195
|
+
throw new Error(Utils.format(ConstantString.UnknownSchema, JSON.stringify(schema)));
|
|
1196
|
+
}
|
|
1197
|
+
// Find the first array property in the response schema object with the well-known name
|
|
1198
|
+
static getResponseJsonPathFromSchema(schema) {
|
|
1199
|
+
if (schema.type === "object" || (!schema.type && schema.properties)) {
|
|
1200
|
+
const { properties } = schema;
|
|
1201
|
+
for (const property in properties) {
|
|
1202
|
+
const schema = properties[property];
|
|
1203
|
+
if (schema.type === "array" &&
|
|
1204
|
+
Utils.isWellKnownName(property, ConstantString.WellknownResultNames)) {
|
|
1205
|
+
return property;
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
return "$";
|
|
1210
|
+
}
|
|
1211
|
+
static isImageUrlProperty(schema, name, parentArrayName) {
|
|
1212
|
+
const propertyName = name ? name : parentArrayName;
|
|
1213
|
+
return (!!propertyName &&
|
|
1214
|
+
schema.type === "string" &&
|
|
1215
|
+
Utils.isWellKnownName(propertyName, ConstantString.WellknownImageName) &&
|
|
1216
|
+
(propertyName.toLocaleLowerCase().indexOf("url") >= 0 || schema.format === "uri"));
|
|
1217
|
+
}
|
|
890
1218
|
}
|
|
891
1219
|
|
|
892
|
-
export { ConstantString, ErrorType, SpecParser, SpecParserError, Utils, ValidationStatus, WarningType };
|
|
1220
|
+
export { AdaptiveCardGenerator, ConstantString, ErrorType, SpecParser, SpecParserError, Utils, ValidationStatus, WarningType };
|
|
893
1221
|
//# sourceMappingURL=index.esm5.js.map
|