@azure-tools/typespec-autorest 0.43.0-dev.0 → 0.43.0-dev.11
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/README.md +6 -0
- package/dist/src/decorators.d.ts +2 -23
- package/dist/src/decorators.d.ts.map +1 -1
- package/dist/src/decorators.js +2 -18
- package/dist/src/decorators.js.map +1 -1
- package/dist/src/emit.d.ts +3 -2
- package/dist/src/emit.d.ts.map +1 -1
- package/dist/src/emit.js +94 -39
- package/dist/src/emit.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/lib.d.ts +5 -0
- package/dist/src/lib.d.ts.map +1 -1
- package/dist/src/lib.js +7 -0
- package/dist/src/lib.js.map +1 -1
- package/dist/src/openapi.d.ts +7 -15
- package/dist/src/openapi.d.ts.map +1 -1
- package/dist/src/openapi.js +227 -88
- package/dist/src/openapi.js.map +1 -1
- package/dist/src/openapi2-document.d.ts +19 -2
- package/dist/src/openapi2-document.d.ts.map +1 -1
- package/dist/src/types.d.ts +48 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/package.json +9 -7
- package/schema/dist/schema.js +1 -1
package/dist/src/openapi.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { extractLroStates, getArmResourceIdentifierConfig, getAsEmbeddingVector, getLroMetadata, getPagedResult, getUnionAsEnum,
|
|
1
|
+
import { FinalStateValue, extractLroStates, getArmResourceIdentifierConfig, getAsEmbeddingVector, getLroMetadata, getPagedResult, getUnionAsEnum, } from "@azure-tools/typespec-azure-core";
|
|
2
|
+
import { getArmCommonTypeOpenAPIRef, isArmCommonType, } from "@azure-tools/typespec-azure-resource-manager";
|
|
2
3
|
import { shouldFlattenProperty } from "@azure-tools/typespec-client-generator-core";
|
|
3
|
-
import { NoTarget, SyntaxKind, compilerAssert, createDiagnosticCollector, getAllTags, getDirectoryPath, getDiscriminator, getDoc, getEncode, getFormat, getKnownValues, getMaxItems, getMaxLength, getMaxValue, getMinItems, getMinLength, getMinValue, getPattern, getProjectedName, getProperty, getPropertyType, getRelativePathFromDirectory, getRootLength, getSummary, getVisibility, ignoreDiagnostics, interpolatePath, isArrayModelType, isDeprecated, isErrorModel, isErrorType, isGlobalNamespace, isNeverType, isNullType, isNumericType, isRecordModelType, isSecret, isService, isStringType, isTemplateDeclaration, isTemplateDeclarationOrInstance, isVoidType, navigateTypesInNamespace, resolveEncodedName, resolvePath,
|
|
4
|
+
import { NoTarget, SyntaxKind, compilerAssert, createDiagnosticCollector, explainStringTemplateNotSerializable, getAllTags, getDirectoryPath, getDiscriminator, getDoc, getEncode, getFormat, getKnownValues, getMaxItems, getMaxLength, getMaxValue, getMinItems, getMinLength, getMinValue, getPattern, getProjectedName, getProperty, getPropertyType, getRelativePathFromDirectory, getRootLength, getSummary, getVisibility, ignoreDiagnostics, interpolatePath, isArrayModelType, isDeprecated, isErrorModel, isErrorType, isGlobalNamespace, isNeverType, isNullType, isNumericType, isRecordModelType, isSecret, isService, isStringType, isTemplateDeclaration, isTemplateDeclarationOrInstance, isVoidType, navigateTypesInNamespace, resolveEncodedName, resolvePath, } from "@typespec/compiler";
|
|
4
5
|
import { TwoLevelMap } from "@typespec/compiler/utils";
|
|
5
6
|
import { Visibility, createMetadataInfo, getAllHttpServices, getAuthentication, getHeaderFieldOptions, getQueryParamOptions, getServers, getStatusCodeDescription, getVisibilitySuffix, isContentTypeHeader, isSharedRoute, reportIfNoRoutes, resolveRequestVisibility, } from "@typespec/http";
|
|
6
7
|
import { checkDuplicateTypeName, getExtensions, getExternalDocs, getOpenAPITypeName, getParameterKey, isReadonlyProperty, resolveInfo, shouldInline, } from "@typespec/openapi";
|
|
@@ -126,6 +127,7 @@ export async function getOpenAPIForService(context, options) {
|
|
|
126
127
|
}
|
|
127
128
|
})
|
|
128
129
|
.filter((x) => x),
|
|
130
|
+
outputFile: context.outputFile,
|
|
129
131
|
};
|
|
130
132
|
function resolveHost(program, namespace) {
|
|
131
133
|
const servers = getServers(program, namespace);
|
|
@@ -238,6 +240,40 @@ export async function getOpenAPIForService(context, options) {
|
|
|
238
240
|
// strip everything from the key including and after the ?
|
|
239
241
|
return path.replace(/\/?\?.*/, "");
|
|
240
242
|
}
|
|
243
|
+
function getFinalStateVia(metadata) {
|
|
244
|
+
switch (metadata.finalStateVia) {
|
|
245
|
+
case FinalStateValue.azureAsyncOperation:
|
|
246
|
+
return "azure-async-operation";
|
|
247
|
+
case FinalStateValue.location:
|
|
248
|
+
return "location";
|
|
249
|
+
case FinalStateValue.operationLocation:
|
|
250
|
+
return "operation-location";
|
|
251
|
+
case FinalStateValue.originalUri:
|
|
252
|
+
return "original-uri";
|
|
253
|
+
default:
|
|
254
|
+
return undefined;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
function getFinalStateSchema(metadata) {
|
|
258
|
+
if (metadata.finalResult !== undefined &&
|
|
259
|
+
metadata.finalResult !== "void" &&
|
|
260
|
+
metadata.finalResult.name.length > 0) {
|
|
261
|
+
const model = metadata.finalResult;
|
|
262
|
+
const schemaOrRef = resolveExternalRef(metadata.finalResult);
|
|
263
|
+
if (schemaOrRef !== undefined) {
|
|
264
|
+
const ref = new Ref();
|
|
265
|
+
ref.value = schemaOrRef.$ref;
|
|
266
|
+
return { "final-state-schema": ref };
|
|
267
|
+
}
|
|
268
|
+
const pending = pendingSchemas.getOrAdd(metadata.finalResult, Visibility.Read, () => ({
|
|
269
|
+
type: model,
|
|
270
|
+
visibility: Visibility.Read,
|
|
271
|
+
ref: refs.getOrAdd(model, Visibility.Read, () => new Ref()),
|
|
272
|
+
}));
|
|
273
|
+
return { "final-state-schema": pending.ref };
|
|
274
|
+
}
|
|
275
|
+
return undefined;
|
|
276
|
+
}
|
|
241
277
|
function emitOperation(operation) {
|
|
242
278
|
let { path: fullPath, operation: op, verb, parameters } = operation;
|
|
243
279
|
let pathsObject = root.paths;
|
|
@@ -294,6 +330,22 @@ export async function getOpenAPIForService(context, options) {
|
|
|
294
330
|
// which does have LRO metadata.
|
|
295
331
|
if (lroMetadata !== undefined && operation.verb !== "get") {
|
|
296
332
|
currentEndpoint["x-ms-long-running-operation"] = true;
|
|
333
|
+
if (options.emitLroOptions !== "none") {
|
|
334
|
+
const finalState = getFinalStateVia(lroMetadata);
|
|
335
|
+
if (finalState !== undefined) {
|
|
336
|
+
const finalSchema = getFinalStateSchema(lroMetadata);
|
|
337
|
+
let lroOptions = {
|
|
338
|
+
"final-state-via": finalState,
|
|
339
|
+
};
|
|
340
|
+
if (finalSchema !== undefined && options.emitLroOptions === "all") {
|
|
341
|
+
lroOptions = {
|
|
342
|
+
"final-state-via": finalState,
|
|
343
|
+
...finalSchema,
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
currentEndpoint["x-ms-long-running-operation-options"] = lroOptions;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
297
349
|
}
|
|
298
350
|
// Extract paged metadata from Azure.Core.Page
|
|
299
351
|
extractPagedMetadata(program, operation);
|
|
@@ -442,19 +494,27 @@ export async function getOpenAPIForService(context, options) {
|
|
|
442
494
|
}
|
|
443
495
|
}
|
|
444
496
|
if (body) {
|
|
445
|
-
|
|
446
|
-
openapiResponse.schema = isBinary
|
|
447
|
-
? { type: "file" }
|
|
448
|
-
: getSchemaOrRef(body.type, {
|
|
449
|
-
visibility: Visibility.Read,
|
|
450
|
-
ignoreMetadataAnnotations: body.isExplicit && body.containsMetadataAnnotations,
|
|
451
|
-
});
|
|
497
|
+
openapiResponse.schema = getSchemaForResponseBody(body, contentTypes);
|
|
452
498
|
}
|
|
453
499
|
for (const contentType of contentTypes) {
|
|
454
500
|
currentProduces.add(contentType);
|
|
455
501
|
}
|
|
456
502
|
currentEndpoint.responses[statusCode] = openapiResponse;
|
|
457
503
|
}
|
|
504
|
+
function getSchemaForResponseBody(body, contentTypes) {
|
|
505
|
+
const isBinary = contentTypes.every((t) => isBinaryPayload(body.type, t));
|
|
506
|
+
if (isBinary) {
|
|
507
|
+
return { type: "file" };
|
|
508
|
+
}
|
|
509
|
+
if (body.bodyKind === "multipart") {
|
|
510
|
+
// OpenAPI2 doesn't support multipart responses, so we just return a string schema
|
|
511
|
+
return { type: "string" };
|
|
512
|
+
}
|
|
513
|
+
return getSchemaOrRef(body.type, {
|
|
514
|
+
visibility: Visibility.Read,
|
|
515
|
+
ignoreMetadataAnnotations: body.isExplicit && body.containsMetadataAnnotations,
|
|
516
|
+
});
|
|
517
|
+
}
|
|
458
518
|
function getResponseHeader(prop) {
|
|
459
519
|
const header = {};
|
|
460
520
|
populateParameter(header, prop, "header", {
|
|
@@ -466,7 +526,7 @@ export async function getOpenAPIForService(context, options) {
|
|
|
466
526
|
delete header.required;
|
|
467
527
|
return header;
|
|
468
528
|
}
|
|
469
|
-
function
|
|
529
|
+
function expandRef(ref) {
|
|
470
530
|
const absoluteRef = interpolatePath(ref, {
|
|
471
531
|
"arm-types-dir": options.armTypesDir,
|
|
472
532
|
});
|
|
@@ -475,13 +535,31 @@ export async function getOpenAPIForService(context, options) {
|
|
|
475
535
|
}
|
|
476
536
|
return getRelativePathFromDirectory(getDirectoryPath(context.outputFile), absoluteRef, false);
|
|
477
537
|
}
|
|
478
|
-
function
|
|
479
|
-
const refUrl = getRef(program, type
|
|
538
|
+
function resolveExternalRef(type) {
|
|
539
|
+
const refUrl = getRef(program, type);
|
|
480
540
|
if (refUrl) {
|
|
481
541
|
return {
|
|
482
|
-
$ref:
|
|
542
|
+
$ref: expandRef(refUrl),
|
|
483
543
|
};
|
|
484
544
|
}
|
|
545
|
+
if (isArmCommonType(type) && (type.kind === "Model" || type.kind === "ModelProperty")) {
|
|
546
|
+
const ref = getArmCommonTypeOpenAPIRef(program, type, {
|
|
547
|
+
version: context.version,
|
|
548
|
+
service: context.service,
|
|
549
|
+
});
|
|
550
|
+
if (ref) {
|
|
551
|
+
return {
|
|
552
|
+
$ref: expandRef(ref),
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
return undefined;
|
|
557
|
+
}
|
|
558
|
+
function getSchemaOrRef(type, schemaContext) {
|
|
559
|
+
const ref = resolveExternalRef(type);
|
|
560
|
+
if (ref) {
|
|
561
|
+
return ref;
|
|
562
|
+
}
|
|
485
563
|
if (type.kind === "Scalar" && program.checker.isStdType(type)) {
|
|
486
564
|
return getSchemaForScalar(type);
|
|
487
565
|
}
|
|
@@ -560,14 +638,9 @@ export async function getOpenAPIForService(context, options) {
|
|
|
560
638
|
property = property.sourceProperty;
|
|
561
639
|
}
|
|
562
640
|
}
|
|
563
|
-
const
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
});
|
|
567
|
-
if (refUrl) {
|
|
568
|
-
return {
|
|
569
|
-
$ref: resolveRef(refUrl),
|
|
570
|
-
};
|
|
641
|
+
const ref = resolveExternalRef(property);
|
|
642
|
+
if (ref) {
|
|
643
|
+
return ref;
|
|
571
644
|
}
|
|
572
645
|
const parameter = params.get(property);
|
|
573
646
|
if (parameter) {
|
|
@@ -611,33 +684,66 @@ export async function getOpenAPIForService(context, options) {
|
|
|
611
684
|
currentConsumes.add(consume);
|
|
612
685
|
}
|
|
613
686
|
if (methodParams.body && !isVoidType(methodParams.body.type)) {
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
687
|
+
emitBodyParameters(methodParams.body, visibility);
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
function emitBodyParameters(body, visibility) {
|
|
691
|
+
switch (body.bodyKind) {
|
|
692
|
+
case "single":
|
|
693
|
+
emitSingleBodyParameters(body, visibility);
|
|
694
|
+
break;
|
|
695
|
+
case "multipart":
|
|
696
|
+
emitMultipartBodyParameters(body, visibility);
|
|
697
|
+
break;
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
function emitSingleBodyParameters(body, visibility) {
|
|
701
|
+
const isBinary = isBinaryPayload(body.type, body.contentTypes);
|
|
702
|
+
const schemaContext = {
|
|
703
|
+
visibility,
|
|
704
|
+
ignoreMetadataAnnotations: body.isExplicit && body.containsMetadataAnnotations,
|
|
705
|
+
};
|
|
706
|
+
const schema = isBinary
|
|
707
|
+
? { type: "string", format: "binary" }
|
|
708
|
+
: getSchemaOrRef(body.type, schemaContext);
|
|
709
|
+
if (currentConsumes.has("multipart/form-data")) {
|
|
710
|
+
const bodyModelType = body.type;
|
|
711
|
+
// Assert, this should never happen. Rest library guard against that.
|
|
712
|
+
compilerAssert(bodyModelType.kind === "Model", "Body should always be a Model.");
|
|
713
|
+
if (bodyModelType) {
|
|
714
|
+
for (const param of bodyModelType.properties.values()) {
|
|
715
|
+
emitParameter(param, "formData", schemaContext, getJsonName(param));
|
|
630
716
|
}
|
|
631
717
|
}
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
}
|
|
635
|
-
|
|
718
|
+
}
|
|
719
|
+
else if (body.property) {
|
|
720
|
+
emitParameter(body.property, "body", { visibility, ignoreMetadataAnnotations: false }, getJsonName(body.property), schema);
|
|
721
|
+
}
|
|
722
|
+
else {
|
|
723
|
+
currentEndpoint.parameters.push({
|
|
724
|
+
name: "body",
|
|
725
|
+
in: "body",
|
|
726
|
+
schema,
|
|
727
|
+
required: true,
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
function emitMultipartBodyParameters(body, visibility) {
|
|
732
|
+
for (const [index, part] of body.parts.entries()) {
|
|
733
|
+
const partName = part.name ?? `part${index}`;
|
|
734
|
+
let schema = getFormDataSchema(part.body.type, { visibility, ignoreMetadataAnnotations: false }, partName);
|
|
735
|
+
if (schema) {
|
|
736
|
+
if (part.multi) {
|
|
737
|
+
schema = {
|
|
738
|
+
type: "array",
|
|
739
|
+
items: schema.type === "file" ? { type: "string", format: "binary" } : schema,
|
|
740
|
+
};
|
|
741
|
+
}
|
|
636
742
|
currentEndpoint.parameters.push({
|
|
637
|
-
name:
|
|
638
|
-
in: "
|
|
639
|
-
|
|
640
|
-
|
|
743
|
+
name: partName,
|
|
744
|
+
in: "formData",
|
|
745
|
+
required: !part.optional,
|
|
746
|
+
...schema,
|
|
641
747
|
});
|
|
642
748
|
}
|
|
643
749
|
}
|
|
@@ -720,8 +826,8 @@ export async function getOpenAPIForService(context, options) {
|
|
|
720
826
|
if (param.name !== ph.name) {
|
|
721
827
|
ph["x-ms-client-name"] = param.name;
|
|
722
828
|
}
|
|
723
|
-
if (param.
|
|
724
|
-
ph.default = getDefaultValue(param.
|
|
829
|
+
if (param.defaultValue) {
|
|
830
|
+
ph.default = getDefaultValue(param.defaultValue);
|
|
725
831
|
}
|
|
726
832
|
if (ph.in === "body") {
|
|
727
833
|
compilerAssert(bodySchema, "bodySchema argument is required to populate body parameter");
|
|
@@ -848,13 +954,13 @@ export async function getOpenAPIForService(context, options) {
|
|
|
848
954
|
}
|
|
849
955
|
return false;
|
|
850
956
|
}
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
return false;
|
|
957
|
+
}
|
|
958
|
+
function isVersionEnum(program, enumObj) {
|
|
959
|
+
const [_, map] = getVersionsForEnum(program, enumObj);
|
|
960
|
+
if (map !== undefined && map.getVersions()[0].enumMember.enum === enumObj) {
|
|
961
|
+
return true;
|
|
857
962
|
}
|
|
963
|
+
return false;
|
|
858
964
|
}
|
|
859
965
|
function emitTags() {
|
|
860
966
|
for (const tag of tags) {
|
|
@@ -903,6 +1009,29 @@ export async function getOpenAPIForService(context, options) {
|
|
|
903
1009
|
});
|
|
904
1010
|
return {};
|
|
905
1011
|
}
|
|
1012
|
+
/**
|
|
1013
|
+
* Version enum is special so we we just render the current version with modelAsString: true
|
|
1014
|
+
*/
|
|
1015
|
+
function getSchemaForVersionEnum(e, currentVersion) {
|
|
1016
|
+
const member = [...e.members.values()].find((x) => (x.value ?? x.name) === currentVersion);
|
|
1017
|
+
compilerAssert(member, `Version enum ${e.name} does not have a member for ${currentVersion}.`, e);
|
|
1018
|
+
return {
|
|
1019
|
+
type: "string",
|
|
1020
|
+
description: getDoc(program, e),
|
|
1021
|
+
enum: [member.value ?? member.name],
|
|
1022
|
+
"x-ms-enum": {
|
|
1023
|
+
name: e.name,
|
|
1024
|
+
modelAsString: true,
|
|
1025
|
+
values: [
|
|
1026
|
+
{
|
|
1027
|
+
name: member.name,
|
|
1028
|
+
value: member.value ?? member.name,
|
|
1029
|
+
description: getDoc(program, member),
|
|
1030
|
+
},
|
|
1031
|
+
],
|
|
1032
|
+
},
|
|
1033
|
+
};
|
|
1034
|
+
}
|
|
906
1035
|
function getSchemaForEnum(e) {
|
|
907
1036
|
const values = [];
|
|
908
1037
|
if (e.members.size === 0) {
|
|
@@ -919,6 +1048,10 @@ export async function getOpenAPIForService(context, options) {
|
|
|
919
1048
|
values.push(option.value ?? option.name);
|
|
920
1049
|
}
|
|
921
1050
|
}
|
|
1051
|
+
// If we are rendering a specific version and trying to render the version enum we should treat it specially to only include the current version.
|
|
1052
|
+
if (isVersionEnum(program, e) && context.version) {
|
|
1053
|
+
return getSchemaForVersionEnum(e, context.version);
|
|
1054
|
+
}
|
|
922
1055
|
const schema = { type, description: getDoc(program, e) };
|
|
923
1056
|
if (values.length > 0) {
|
|
924
1057
|
schema.enum = values;
|
|
@@ -1025,33 +1158,25 @@ export async function getOpenAPIForService(context, options) {
|
|
|
1025
1158
|
function getSchemaForUnionVariant(variant, schemaContext) {
|
|
1026
1159
|
return getSchemaForType(variant.type, schemaContext);
|
|
1027
1160
|
}
|
|
1028
|
-
function getDefaultValue(
|
|
1029
|
-
switch (
|
|
1030
|
-
case "
|
|
1031
|
-
return
|
|
1032
|
-
case "
|
|
1033
|
-
return
|
|
1034
|
-
case "
|
|
1035
|
-
return
|
|
1036
|
-
case "
|
|
1037
|
-
return
|
|
1038
|
-
case "
|
|
1039
|
-
return
|
|
1040
|
-
case "
|
|
1041
|
-
return
|
|
1042
|
-
? null
|
|
1043
|
-
: reportDiagnostic(program, {
|
|
1044
|
-
code: "invalid-default",
|
|
1045
|
-
format: { type: type.kind },
|
|
1046
|
-
target: type,
|
|
1047
|
-
});
|
|
1048
|
-
case "UnionVariant":
|
|
1049
|
-
return getDefaultValue(type.type);
|
|
1161
|
+
function getDefaultValue(defaultType) {
|
|
1162
|
+
switch (defaultType.valueKind) {
|
|
1163
|
+
case "StringValue":
|
|
1164
|
+
return defaultType.value;
|
|
1165
|
+
case "NumericValue":
|
|
1166
|
+
return defaultType.value.asNumber() ?? undefined;
|
|
1167
|
+
case "BooleanValue":
|
|
1168
|
+
return defaultType.value;
|
|
1169
|
+
case "ArrayValue":
|
|
1170
|
+
return defaultType.values.map((x) => getDefaultValue(x));
|
|
1171
|
+
case "NullValue":
|
|
1172
|
+
return null;
|
|
1173
|
+
case "EnumValue":
|
|
1174
|
+
return defaultType.value.value ?? defaultType.value.name;
|
|
1050
1175
|
default:
|
|
1051
1176
|
reportDiagnostic(program, {
|
|
1052
1177
|
code: "invalid-default",
|
|
1053
|
-
format: { type:
|
|
1054
|
-
target:
|
|
1178
|
+
format: { type: defaultType.valueKind },
|
|
1179
|
+
target: defaultType,
|
|
1055
1180
|
});
|
|
1056
1181
|
}
|
|
1057
1182
|
}
|
|
@@ -1123,6 +1248,7 @@ export async function getOpenAPIForService(context, options) {
|
|
|
1123
1248
|
modelSchema.required = [propertyName];
|
|
1124
1249
|
}
|
|
1125
1250
|
}
|
|
1251
|
+
applySummary(model, modelSchema);
|
|
1126
1252
|
applyExternalDocs(model, modelSchema);
|
|
1127
1253
|
for (const prop of model.properties.values()) {
|
|
1128
1254
|
if (!metadataInfo.isPayloadProperty(prop, schemaContext.visibility, schemaContext.ignoreMetadataAnnotations)) {
|
|
@@ -1158,8 +1284,9 @@ export async function getOpenAPIForService(context, options) {
|
|
|
1158
1284
|
if (description) {
|
|
1159
1285
|
property.description = description;
|
|
1160
1286
|
}
|
|
1161
|
-
|
|
1162
|
-
|
|
1287
|
+
applySummary(prop, property);
|
|
1288
|
+
if (prop.defaultValue && !("$ref" in property)) {
|
|
1289
|
+
property.default = getDefaultValue(prop.defaultValue);
|
|
1163
1290
|
}
|
|
1164
1291
|
if (isReadonlyProperty(program, prop)) {
|
|
1165
1292
|
property.readOnly = true;
|
|
@@ -1223,10 +1350,10 @@ export async function getOpenAPIForService(context, options) {
|
|
|
1223
1350
|
}
|
|
1224
1351
|
function resolveProperty(prop, context) {
|
|
1225
1352
|
let propSchema;
|
|
1226
|
-
if (prop.type.kind === "Enum" && prop.
|
|
1353
|
+
if (prop.type.kind === "Enum" && prop.defaultValue) {
|
|
1227
1354
|
propSchema = getSchemaForEnum(prop.type);
|
|
1228
1355
|
}
|
|
1229
|
-
else if (prop.type.kind === "Union" && prop.
|
|
1356
|
+
else if (prop.type.kind === "Union" && prop.defaultValue) {
|
|
1230
1357
|
const [asEnum, _] = getUnionAsEnum(prop.type);
|
|
1231
1358
|
if (asEnum) {
|
|
1232
1359
|
propSchema = getSchemaForUnionEnum(prop.type, asEnum);
|
|
@@ -1283,6 +1410,10 @@ export async function getOpenAPIForService(context, options) {
|
|
|
1283
1410
|
if (docStr) {
|
|
1284
1411
|
newTarget.description = docStr;
|
|
1285
1412
|
}
|
|
1413
|
+
const title = getSummary(program, typespecType);
|
|
1414
|
+
if (title) {
|
|
1415
|
+
target.title = title;
|
|
1416
|
+
}
|
|
1286
1417
|
const formatStr = getFormat(program, typespecType);
|
|
1287
1418
|
if (isString && formatStr) {
|
|
1288
1419
|
const allowedStringFormats = [
|
|
@@ -1402,6 +1533,12 @@ export async function getOpenAPIForService(context, options) {
|
|
|
1402
1533
|
return encodeAsFormat ?? encoding;
|
|
1403
1534
|
}
|
|
1404
1535
|
}
|
|
1536
|
+
function applySummary(typespecType, target) {
|
|
1537
|
+
const summary = getSummary(program, typespecType);
|
|
1538
|
+
if (summary) {
|
|
1539
|
+
target.title = summary;
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1405
1542
|
function applyExternalDocs(typespecType, target) {
|
|
1406
1543
|
const externalDocs = getExternalDocs(program, typespecType);
|
|
1407
1544
|
if (externalDocs) {
|
|
@@ -1412,7 +1549,7 @@ export async function getOpenAPIForService(context, options) {
|
|
|
1412
1549
|
if (type.node && type.node.parent && type.node.parent.kind === SyntaxKind.ModelStatement) {
|
|
1413
1550
|
schema["x-ms-enum"] = {
|
|
1414
1551
|
name: type.node.parent.id.sv,
|
|
1415
|
-
modelAsString:
|
|
1552
|
+
modelAsString: false,
|
|
1416
1553
|
};
|
|
1417
1554
|
}
|
|
1418
1555
|
else if (type.kind === "String") {
|
|
@@ -1423,7 +1560,7 @@ export async function getOpenAPIForService(context, options) {
|
|
|
1423
1560
|
else if (type.kind === "Enum") {
|
|
1424
1561
|
schema["x-ms-enum"] = {
|
|
1425
1562
|
name: type.name,
|
|
1426
|
-
modelAsString:
|
|
1563
|
+
modelAsString: false,
|
|
1427
1564
|
};
|
|
1428
1565
|
const values = [];
|
|
1429
1566
|
let foundCustom = false;
|
|
@@ -1445,12 +1582,14 @@ export async function getOpenAPIForService(context, options) {
|
|
|
1445
1582
|
return schema;
|
|
1446
1583
|
}
|
|
1447
1584
|
function getSchemaForStringTemplate(stringTemplate) {
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1585
|
+
if (stringTemplate.stringValue === undefined) {
|
|
1586
|
+
program.reportDiagnostics(explainStringTemplateNotSerializable(stringTemplate).map((x) => ({
|
|
1587
|
+
...x,
|
|
1588
|
+
severity: "warning",
|
|
1589
|
+
})));
|
|
1451
1590
|
return { type: "string" };
|
|
1452
1591
|
}
|
|
1453
|
-
return { type: "string", enum: [
|
|
1592
|
+
return { type: "string", enum: [stringTemplate.stringValue] };
|
|
1454
1593
|
}
|
|
1455
1594
|
function getSchemaForLiterals(typespecType) {
|
|
1456
1595
|
switch (typespecType.kind) {
|
|
@@ -1662,7 +1801,7 @@ class ErrorTypeFoundError extends Error {
|
|
|
1662
1801
|
export function sortOpenAPIDocument(doc) {
|
|
1663
1802
|
// Doing this to make sure the classes with toJSON are resolved.
|
|
1664
1803
|
const unsorted = JSON.parse(JSON.stringify(doc));
|
|
1665
|
-
const sorted = sortWithJsonSchema(unsorted, AutorestOpenAPISchema
|
|
1804
|
+
const sorted = sortWithJsonSchema(unsorted, AutorestOpenAPISchema);
|
|
1666
1805
|
return sorted;
|
|
1667
1806
|
}
|
|
1668
1807
|
async function loadExamples(host, options, version) {
|