@azure-tools/typespec-autorest 0.42.0-dev.3 → 0.42.0-dev.5
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/src/emit.d.ts +22 -0
- package/dist/src/emit.d.ts.map +1 -0
- package/dist/src/emit.js +114 -0
- package/dist/src/emit.js.map +1 -0
- package/dist/src/index.d.ts +4 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/lib.d.ts +117 -1
- package/dist/src/lib.d.ts.map +1 -1
- package/dist/src/lib.js +1 -1
- package/dist/src/lib.js.map +1 -1
- package/dist/src/openapi.d.ts +26 -19
- package/dist/src/openapi.d.ts.map +1 -1
- package/dist/src/openapi.js +239 -347
- package/dist/src/openapi.js.map +1 -1
- package/dist/src/{types.d.ts → openapi2-document.d.ts} +1 -1
- package/dist/src/openapi2-document.d.ts.map +1 -0
- package/dist/src/openapi2-document.js +2 -0
- package/dist/src/openapi2-document.js.map +1 -0
- package/dist/src/utils.d.ts +9 -6
- package/dist/src/utils.d.ts.map +1 -1
- package/dist/src/utils.js +10 -4
- package/dist/src/utils.js.map +1 -1
- package/package.json +3 -3
- package/dist/src/types.d.ts.map +0 -1
- package/dist/src/types.js +0 -2
- package/dist/src/types.js.map +0 -1
package/dist/src/openapi.js
CHANGED
|
@@ -1,44 +1,14 @@
|
|
|
1
1
|
import { extractLroStates, getArmResourceIdentifierConfig, getAsEmbeddingVector, getLroMetadata, getPagedResult, getUnionAsEnum, isFixed, } from "@azure-tools/typespec-azure-core";
|
|
2
|
-
import {
|
|
3
|
-
import { NoTarget, SyntaxKind,
|
|
2
|
+
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, stringTemplateToString, } from "@typespec/compiler";
|
|
4
|
+
import { TwoLevelMap } from "@typespec/compiler/utils";
|
|
4
5
|
import { Visibility, createMetadataInfo, getAllHttpServices, getAuthentication, getHeaderFieldOptions, getQueryParamOptions, getServers, getStatusCodeDescription, getVisibilitySuffix, isContentTypeHeader, isSharedRoute, reportIfNoRoutes, resolveRequestVisibility, } from "@typespec/http";
|
|
5
6
|
import { checkDuplicateTypeName, getExtensions, getExternalDocs, getOpenAPITypeName, getParameterKey, isReadonlyProperty, resolveInfo, shouldInline, } from "@typespec/openapi";
|
|
6
|
-
import { buildVersionProjections } from "@typespec/versioning";
|
|
7
7
|
import { AutorestOpenAPISchema } from "./autorest-openapi-schema.js";
|
|
8
8
|
import { getExamples, getRef } from "./decorators.js";
|
|
9
9
|
import { sortWithJsonSchema } from "./json-schema-sorter/sorter.js";
|
|
10
|
-
import {
|
|
11
|
-
import { resolveOperationId } from "./utils.js";
|
|
12
|
-
const defaultOptions = {
|
|
13
|
-
"output-file": "{azure-resource-provider-folder}/{service-name}/{version-status}/{version}/openapi.json",
|
|
14
|
-
"new-line": "lf",
|
|
15
|
-
"include-x-typespec-name": "never",
|
|
16
|
-
};
|
|
17
|
-
export async function $onEmit(context) {
|
|
18
|
-
const resolvedOptions = { ...defaultOptions, ...context.options };
|
|
19
|
-
const tcgcSdkContext = createSdkContext(context, "@azure-tools/typespec-autorest");
|
|
20
|
-
const armTypesDir = interpolatePath(resolvedOptions["arm-types-dir"] ?? "{project-root}/../../common-types/resource-management", {
|
|
21
|
-
"project-root": context.program.projectRoot,
|
|
22
|
-
"emitter-output-dir": context.emitterOutputDir,
|
|
23
|
-
});
|
|
24
|
-
const options = {
|
|
25
|
-
outputFile: resolvedOptions["output-file"],
|
|
26
|
-
outputDir: context.emitterOutputDir,
|
|
27
|
-
azureResourceProviderFolder: resolvedOptions["azure-resource-provider-folder"],
|
|
28
|
-
examplesDirectory: resolvedOptions["examples-directory"],
|
|
29
|
-
version: resolvedOptions["version"],
|
|
30
|
-
newLine: resolvedOptions["new-line"],
|
|
31
|
-
omitUnreachableTypes: resolvedOptions["omit-unreachable-types"],
|
|
32
|
-
includeXTypeSpecName: resolvedOptions["include-x-typespec-name"],
|
|
33
|
-
armTypesDir,
|
|
34
|
-
useReadOnlyStatusSchema: resolvedOptions["use-read-only-status-schema"],
|
|
35
|
-
};
|
|
36
|
-
const emitter = createOAPIEmitter(context.program, tcgcSdkContext, options);
|
|
37
|
-
await emitter.emitOpenAPI();
|
|
38
|
-
}
|
|
39
|
-
function getEmitterDetails(program) {
|
|
40
|
-
return [{ emitter: "@azure-tools/typespec-autorest" }];
|
|
41
|
-
}
|
|
10
|
+
import { createDiagnostic, reportDiagnostic } from "./lib.js";
|
|
11
|
+
import { getClientName, resolveOperationId } from "./utils.js";
|
|
42
12
|
/**
|
|
43
13
|
* Represents a node that will hold a JSON reference. The value is computed
|
|
44
14
|
* at the end so that we can defer decisions about the name that is
|
|
@@ -51,113 +21,111 @@ class Ref {
|
|
|
51
21
|
return this.value;
|
|
52
22
|
}
|
|
53
23
|
}
|
|
54
|
-
function
|
|
55
|
-
const
|
|
56
|
-
tracer.trace("options", JSON.stringify(options, null, 2));
|
|
24
|
+
export async function getOpenAPIForService(context, options) {
|
|
25
|
+
const { program, service } = context;
|
|
57
26
|
const typeNameOptions = {
|
|
58
27
|
// shorten type names by removing TypeSpec and service namespace
|
|
59
28
|
namespaceFilter(ns) {
|
|
60
29
|
return !isService(program, ns);
|
|
61
30
|
},
|
|
62
31
|
};
|
|
63
|
-
|
|
64
|
-
|
|
32
|
+
const info = resolveInfo(program, service.type);
|
|
33
|
+
const auth = processAuth(service.type);
|
|
34
|
+
const root = {
|
|
35
|
+
swagger: "2.0",
|
|
36
|
+
info: {
|
|
37
|
+
title: "(title)",
|
|
38
|
+
...info,
|
|
39
|
+
version: context.version ?? info?.version ?? "0000-00-00",
|
|
40
|
+
"x-typespec-generated": [{ emitter: "@azure-tools/typespec-autorest" }],
|
|
41
|
+
},
|
|
42
|
+
schemes: ["https"],
|
|
43
|
+
...resolveHost(program, service.type),
|
|
44
|
+
externalDocs: getExternalDocs(program, service.type),
|
|
45
|
+
produces: [], // Pre-initialize produces and consumes so that
|
|
46
|
+
consumes: [], // they show up at the top of the document
|
|
47
|
+
security: auth?.security,
|
|
48
|
+
securityDefinitions: auth?.securitySchemes ?? {},
|
|
49
|
+
tags: [],
|
|
50
|
+
paths: {},
|
|
51
|
+
"x-ms-paths": {},
|
|
52
|
+
definitions: {},
|
|
53
|
+
parameters: {},
|
|
54
|
+
};
|
|
65
55
|
let currentEndpoint;
|
|
66
56
|
let currentConsumes;
|
|
67
57
|
let currentProduces;
|
|
68
|
-
|
|
58
|
+
const metadataInfo = createMetadataInfo(program, {
|
|
59
|
+
canonicalVisibility: Visibility.Read,
|
|
60
|
+
canShareProperty: canSharePropertyUsingReadonlyOrXMSMutability,
|
|
61
|
+
});
|
|
69
62
|
// Keep a map of all Types+Visibility combinations that were encountered
|
|
70
63
|
// that need schema definitions.
|
|
71
|
-
|
|
64
|
+
const pendingSchemas = new TwoLevelMap();
|
|
72
65
|
// Reuse a single ref object per Type+Visibility combination.
|
|
73
|
-
|
|
66
|
+
const refs = new TwoLevelMap();
|
|
74
67
|
// Keep track of inline types still in the process of having their schema computed
|
|
75
68
|
// This is used to detect cycles in inline types, which is an
|
|
76
|
-
|
|
69
|
+
const inProgressInlineTypes = new Set();
|
|
77
70
|
// Map model properties that represent shared parameters to their parameter
|
|
78
71
|
// definition that will go in #/parameters. Inlined parameters do not go in
|
|
79
72
|
// this map.
|
|
80
|
-
|
|
73
|
+
const params = new Map();
|
|
81
74
|
// Keep track of models that have had properties spread into parameters. We won't
|
|
82
75
|
// consider these unreferenced when emitting unreferenced types.
|
|
83
|
-
|
|
76
|
+
const paramModels = new Set();
|
|
84
77
|
// De-dupe the per-endpoint tags that will be added into the #/tags
|
|
85
|
-
|
|
78
|
+
const tags = new Set();
|
|
86
79
|
// The set of produces/consumes values found in all operations
|
|
87
80
|
const globalProduces = new Set(["application/json"]);
|
|
88
81
|
const globalConsumes = new Set(["application/json"]);
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
return {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
externalDocs: getExternalDocs(program, service.type),
|
|
137
|
-
produces: [], // Pre-initialize produces and consumes so that
|
|
138
|
-
consumes: [], // they show up at the top of the document
|
|
139
|
-
security: auth?.security,
|
|
140
|
-
securityDefinitions: auth?.securitySchemes ?? {},
|
|
141
|
-
tags: [],
|
|
142
|
-
paths: {},
|
|
143
|
-
"x-ms-paths": {},
|
|
144
|
-
definitions: {},
|
|
145
|
-
parameters: {},
|
|
146
|
-
};
|
|
147
|
-
pendingSchemas = new TwoLevelMap();
|
|
148
|
-
refs = new TwoLevelMap();
|
|
149
|
-
metadataInfo = createMetadataInfo(program, {
|
|
150
|
-
canonicalVisibility: Visibility.Read,
|
|
151
|
-
canShareProperty: canSharePropertyUsingReadonlyOrXMSMutability,
|
|
152
|
-
});
|
|
153
|
-
inProgressInlineTypes = new Set();
|
|
154
|
-
params = new Map();
|
|
155
|
-
paramModels = new Set();
|
|
156
|
-
tags = new Set();
|
|
157
|
-
operationExamplesMap = new Map();
|
|
158
|
-
operationIdsWithExample = new Set();
|
|
159
|
-
outputFile = resolveOutputFile(program, service, multipleService, options, version);
|
|
160
|
-
}
|
|
82
|
+
const operationIdsWithExample = new Set();
|
|
83
|
+
const [exampleMap, diagnostics] = await loadExamples(program.host, options, context.version);
|
|
84
|
+
program.reportDiagnostics(diagnostics);
|
|
85
|
+
const services = ignoreDiagnostics(getAllHttpServices(program));
|
|
86
|
+
const routes = services[0].operations;
|
|
87
|
+
reportIfNoRoutes(program, routes);
|
|
88
|
+
routes.forEach(emitOperation);
|
|
89
|
+
emitParameters();
|
|
90
|
+
emitSchemas(service.type);
|
|
91
|
+
emitTags();
|
|
92
|
+
// Finalize global produces/consumes
|
|
93
|
+
if (globalProduces.size > 0) {
|
|
94
|
+
root.produces = [...globalProduces.values()];
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
delete root.produces;
|
|
98
|
+
}
|
|
99
|
+
if (globalConsumes.size > 0) {
|
|
100
|
+
root.consumes = [...globalConsumes.values()];
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
delete root.consumes;
|
|
104
|
+
}
|
|
105
|
+
// Clean up empty entries
|
|
106
|
+
if (root["x-ms-paths"] && Object.keys(root["x-ms-paths"]).length === 0) {
|
|
107
|
+
delete root["x-ms-paths"];
|
|
108
|
+
}
|
|
109
|
+
if (root.security && Object.keys(root.security).length === 0) {
|
|
110
|
+
delete root["security"];
|
|
111
|
+
}
|
|
112
|
+
if (root.securityDefinitions && Object.keys(root.securityDefinitions).length === 0) {
|
|
113
|
+
delete root["securityDefinitions"];
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
document: root,
|
|
117
|
+
operationExamples: [...operationIdsWithExample]
|
|
118
|
+
.map((operationId) => {
|
|
119
|
+
const data = exampleMap.get(operationId);
|
|
120
|
+
if (data) {
|
|
121
|
+
return { operationId, examples: Object.values(data) };
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
})
|
|
127
|
+
.filter((x) => x),
|
|
128
|
+
};
|
|
161
129
|
function resolveHost(program, namespace) {
|
|
162
130
|
const servers = getServers(program, namespace);
|
|
163
131
|
if (servers === undefined) {
|
|
@@ -192,7 +160,10 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
192
160
|
}
|
|
193
161
|
const parameters = [];
|
|
194
162
|
for (const prop of server.parameters.values()) {
|
|
195
|
-
const param = getOpenAPI2Parameter(prop, "path",
|
|
163
|
+
const param = getOpenAPI2Parameter(prop, "path", {
|
|
164
|
+
visibility: Visibility.Read,
|
|
165
|
+
ignoreMetadataAnnotations: false,
|
|
166
|
+
});
|
|
196
167
|
if (prop.type.kind === "Scalar" &&
|
|
197
168
|
ignoreDiagnostics(program.checker.isTypeAssignableTo(prop.type.projectionBase ?? prop.type, program.checker.getStdType("url"), prop.type))) {
|
|
198
169
|
param["x-ms-skip-url-encoding"] = true;
|
|
@@ -207,83 +178,6 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
207
178
|
},
|
|
208
179
|
};
|
|
209
180
|
}
|
|
210
|
-
async function emitOpenAPIFromVersion(service, multipleService, version) {
|
|
211
|
-
initializeEmitter(service, multipleService, version);
|
|
212
|
-
try {
|
|
213
|
-
await loadExamples(version);
|
|
214
|
-
const services = ignoreDiagnostics(getAllHttpServices(program));
|
|
215
|
-
const routes = services[0].operations;
|
|
216
|
-
reportIfNoRoutes(program, routes);
|
|
217
|
-
routes.forEach(emitOperation);
|
|
218
|
-
emitParameters();
|
|
219
|
-
emitSchemas(service.type);
|
|
220
|
-
emitTags();
|
|
221
|
-
// Finalize global produces/consumes
|
|
222
|
-
if (globalProduces.size > 0) {
|
|
223
|
-
root.produces = [...globalProduces.values()];
|
|
224
|
-
}
|
|
225
|
-
else {
|
|
226
|
-
delete root.produces;
|
|
227
|
-
}
|
|
228
|
-
if (globalConsumes.size > 0) {
|
|
229
|
-
root.consumes = [...globalConsumes.values()];
|
|
230
|
-
}
|
|
231
|
-
else {
|
|
232
|
-
delete root.consumes;
|
|
233
|
-
}
|
|
234
|
-
// Clean up empty entries
|
|
235
|
-
if (root["x-ms-paths"] && Object.keys(root["x-ms-paths"]).length === 0) {
|
|
236
|
-
delete root["x-ms-paths"];
|
|
237
|
-
}
|
|
238
|
-
if (root.security && Object.keys(root.security).length === 0) {
|
|
239
|
-
delete root["security"];
|
|
240
|
-
}
|
|
241
|
-
if (root.securityDefinitions && Object.keys(root.securityDefinitions).length === 0) {
|
|
242
|
-
delete root["securityDefinitions"];
|
|
243
|
-
}
|
|
244
|
-
if (!program.compilerOptions.noEmit && !program.hasError()) {
|
|
245
|
-
// Sort the document
|
|
246
|
-
const sortedRoot = sortOpenAPIDocument(root);
|
|
247
|
-
// Write out the OpenAPI document to the output path
|
|
248
|
-
await emitFile(program, {
|
|
249
|
-
path: outputFile,
|
|
250
|
-
content: prettierOutput(JSON.stringify(sortedRoot, null, 2)),
|
|
251
|
-
newLine: options.newLine,
|
|
252
|
-
});
|
|
253
|
-
// Copy examples to the output directory
|
|
254
|
-
if (options.examplesDirectory && operationIdsWithExample.size > 0) {
|
|
255
|
-
const examplesPath = resolvePath(getDirectoryPath(outputFile), "examples");
|
|
256
|
-
const exampleDir = version
|
|
257
|
-
? resolvePath(options.examplesDirectory, version)
|
|
258
|
-
: resolvePath(options.examplesDirectory);
|
|
259
|
-
await program.host.mkdirp(examplesPath);
|
|
260
|
-
for (const operationId of operationIdsWithExample) {
|
|
261
|
-
const examples = operationExamplesMap.get(operationId);
|
|
262
|
-
if (examples) {
|
|
263
|
-
for (const [_, fileName] of Object.entries(examples)) {
|
|
264
|
-
const content = await program.host.readFile(resolvePath(exampleDir, fileName));
|
|
265
|
-
await emitFile(program, {
|
|
266
|
-
path: resolvePath(examplesPath, fileName),
|
|
267
|
-
content: content.text,
|
|
268
|
-
newLine: options.newLine,
|
|
269
|
-
});
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
catch (err) {
|
|
277
|
-
if (err instanceof ErrorTypeFoundError) {
|
|
278
|
-
// Return early, there must be a parse error if an ErrorType was
|
|
279
|
-
// inserted into the TypeSpec output
|
|
280
|
-
return;
|
|
281
|
-
}
|
|
282
|
-
else {
|
|
283
|
-
throw err;
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
181
|
function parseNextLinkName(paged) {
|
|
288
182
|
const pathComponents = paged.nextLinkSegments;
|
|
289
183
|
if (pathComponents) {
|
|
@@ -415,7 +309,7 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
415
309
|
currentEndpoint["x-ms-examples"] = examples.reduce((acc, example) => ({ ...acc, [example.title]: { $ref: example.pathOrUri } }), {});
|
|
416
310
|
}
|
|
417
311
|
if (options.examplesDirectory) {
|
|
418
|
-
const examples =
|
|
312
|
+
const examples = exampleMap.get(currentEndpoint.operationId);
|
|
419
313
|
if (examples && currentEndpoint.operationId) {
|
|
420
314
|
operationIdsWithExample.add(currentEndpoint.operationId);
|
|
421
315
|
currentEndpoint["x-ms-examples"] = currentEndpoint["x-ms-examples"] || {};
|
|
@@ -536,19 +430,24 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
536
430
|
}
|
|
537
431
|
}
|
|
538
432
|
if (data.body) {
|
|
539
|
-
if (body && body !== data.body.type) {
|
|
433
|
+
if (body && body.type !== data.body.type) {
|
|
540
434
|
reportDiagnostic(program, {
|
|
541
435
|
code: "duplicate-body-types",
|
|
542
436
|
target: response.type,
|
|
543
437
|
});
|
|
544
438
|
}
|
|
545
|
-
body = data.body
|
|
439
|
+
body = data.body;
|
|
546
440
|
contentTypes.push(...data.body.contentTypes);
|
|
547
441
|
}
|
|
548
442
|
}
|
|
549
443
|
if (body) {
|
|
550
|
-
const isBinary = contentTypes.every((t) => isBinaryPayload(body, t));
|
|
551
|
-
openapiResponse.schema = isBinary
|
|
444
|
+
const isBinary = contentTypes.every((t) => isBinaryPayload(body.type, t));
|
|
445
|
+
openapiResponse.schema = isBinary
|
|
446
|
+
? { type: "file" }
|
|
447
|
+
: getSchemaOrRef(body.type, {
|
|
448
|
+
visibility: Visibility.Read,
|
|
449
|
+
ignoreMetadataAnnotations: body.isExplicit && body.containsMetadataAnnotations,
|
|
450
|
+
});
|
|
552
451
|
}
|
|
553
452
|
for (const contentType of contentTypes) {
|
|
554
453
|
currentProduces.add(contentType);
|
|
@@ -557,7 +456,10 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
557
456
|
}
|
|
558
457
|
function getResponseHeader(prop) {
|
|
559
458
|
const header = {};
|
|
560
|
-
populateParameter(header, prop, "header",
|
|
459
|
+
populateParameter(header, prop, "header", {
|
|
460
|
+
visibility: Visibility.Read,
|
|
461
|
+
ignoreMetadataAnnotations: false,
|
|
462
|
+
});
|
|
561
463
|
delete header.in;
|
|
562
464
|
delete header.name;
|
|
563
465
|
delete header.required;
|
|
@@ -570,9 +472,9 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
570
472
|
if (getRootLength(absoluteRef) === 0) {
|
|
571
473
|
return absoluteRef; // It is already relative.
|
|
572
474
|
}
|
|
573
|
-
return getRelativePathFromDirectory(getDirectoryPath(outputFile), absoluteRef, false);
|
|
475
|
+
return getRelativePathFromDirectory(getDirectoryPath(context.outputFile), absoluteRef, false);
|
|
574
476
|
}
|
|
575
|
-
function getSchemaOrRef(type,
|
|
477
|
+
function getSchemaOrRef(type, schemaContext) {
|
|
576
478
|
const refUrl = getRef(program, type, { version: context.version, service: context.service });
|
|
577
479
|
if (refUrl) {
|
|
578
480
|
return {
|
|
@@ -602,12 +504,12 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
602
504
|
}
|
|
603
505
|
}
|
|
604
506
|
if (type.kind === "ModelProperty") {
|
|
605
|
-
return resolveProperty(type,
|
|
507
|
+
return resolveProperty(type, schemaContext);
|
|
606
508
|
}
|
|
607
|
-
type = metadataInfo.getEffectivePayloadType(type, visibility);
|
|
509
|
+
type = metadataInfo.getEffectivePayloadType(type, schemaContext.visibility);
|
|
608
510
|
const name = getOpenAPITypeName(program, type, typeNameOptions);
|
|
609
511
|
if (shouldInline(program, type)) {
|
|
610
|
-
const schema = getSchemaForInlineType(type, name,
|
|
512
|
+
const schema = getSchemaForInlineType(type, name, schemaContext);
|
|
611
513
|
if (schema === undefined && isErrorType(type)) {
|
|
612
514
|
// Exit early so that syntax errors are exposed. This error will
|
|
613
515
|
// be caught and handled in emitOpenAPI.
|
|
@@ -621,18 +523,18 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
621
523
|
}
|
|
622
524
|
else {
|
|
623
525
|
// Use shared schema when type is not transformed by visibility from the canonical read visibility.
|
|
624
|
-
if (!metadataInfo.isTransformed(type, visibility)) {
|
|
625
|
-
|
|
526
|
+
if (!metadataInfo.isTransformed(type, schemaContext.visibility)) {
|
|
527
|
+
schemaContext = { ...schemaContext, visibility: Visibility.Read };
|
|
626
528
|
}
|
|
627
|
-
const pending = pendingSchemas.getOrAdd(type, visibility, () => ({
|
|
529
|
+
const pending = pendingSchemas.getOrAdd(type, schemaContext.visibility, () => ({
|
|
628
530
|
type,
|
|
629
|
-
visibility,
|
|
630
|
-
ref: refs.getOrAdd(type, visibility, () => new Ref()),
|
|
531
|
+
visibility: schemaContext.visibility,
|
|
532
|
+
ref: refs.getOrAdd(type, schemaContext.visibility, () => new Ref()),
|
|
631
533
|
}));
|
|
632
534
|
return { $ref: pending.ref };
|
|
633
535
|
}
|
|
634
536
|
}
|
|
635
|
-
function getSchemaForInlineType(type, name,
|
|
537
|
+
function getSchemaForInlineType(type, name, context) {
|
|
636
538
|
if (inProgressInlineTypes.has(type)) {
|
|
637
539
|
reportDiagnostic(program, {
|
|
638
540
|
code: "inline-cycle",
|
|
@@ -642,7 +544,7 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
642
544
|
return {};
|
|
643
545
|
}
|
|
644
546
|
inProgressInlineTypes.add(type);
|
|
645
|
-
const schema = getSchemaForType(type,
|
|
547
|
+
const schema = getSchemaForType(type, context);
|
|
646
548
|
inProgressInlineTypes.delete(type);
|
|
647
549
|
return schema;
|
|
648
550
|
}
|
|
@@ -685,11 +587,6 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
685
587
|
// `resolveEncodedName` will return the original name if no @encodedName so we have to do that check
|
|
686
588
|
return encodedName === type.name ? viaProjection ?? type.name : encodedName;
|
|
687
589
|
}
|
|
688
|
-
function getClientName(type) {
|
|
689
|
-
const viaProjection = getProjectedName(program, type, "client");
|
|
690
|
-
const clientName = getClientNameOverride(tcgcSdkContext, type);
|
|
691
|
-
return clientName ?? viaProjection ?? type.name;
|
|
692
|
-
}
|
|
693
590
|
function emitEndpointParameters(methodParams, visibility) {
|
|
694
591
|
const consumes = methodParams.body?.contentTypes ?? [];
|
|
695
592
|
for (const httpOpParam of methodParams.parameters) {
|
|
@@ -701,7 +598,7 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
701
598
|
if (httpOpParam.type === "header" && isContentTypeHeader(program, httpOpParam.param)) {
|
|
702
599
|
continue;
|
|
703
600
|
}
|
|
704
|
-
emitParameter(httpOpParam.param, httpOpParam.type, visibility, httpOpParam.name);
|
|
601
|
+
emitParameter(httpOpParam.param, httpOpParam.type, { visibility, ignoreMetadataAnnotations: false }, httpOpParam.name);
|
|
705
602
|
}
|
|
706
603
|
if (consumes.length === 0 && methodParams.body) {
|
|
707
604
|
// we didn't find an explicit content type anywhere, so infer from body.
|
|
@@ -714,21 +611,25 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
714
611
|
}
|
|
715
612
|
if (methodParams.body && !isVoidType(methodParams.body.type)) {
|
|
716
613
|
const isBinary = isBinaryPayload(methodParams.body.type, consumes);
|
|
614
|
+
const schemaContext = {
|
|
615
|
+
visibility,
|
|
616
|
+
ignoreMetadataAnnotations: methodParams.body.isExplicit && methodParams.body.containsMetadataAnnotations,
|
|
617
|
+
};
|
|
717
618
|
const schema = isBinary
|
|
718
619
|
? { type: "string", format: "binary" }
|
|
719
|
-
: getSchemaOrRef(methodParams.body.type,
|
|
620
|
+
: getSchemaOrRef(methodParams.body.type, schemaContext);
|
|
720
621
|
if (currentConsumes.has("multipart/form-data")) {
|
|
721
622
|
const bodyModelType = methodParams.body.type;
|
|
722
623
|
// Assert, this should never happen. Rest library guard against that.
|
|
723
624
|
compilerAssert(bodyModelType.kind === "Model", "Body should always be a Model.");
|
|
724
625
|
if (bodyModelType) {
|
|
725
626
|
for (const param of bodyModelType.properties.values()) {
|
|
726
|
-
emitParameter(param, "formData",
|
|
627
|
+
emitParameter(param, "formData", schemaContext, getJsonName(param));
|
|
727
628
|
}
|
|
728
629
|
}
|
|
729
630
|
}
|
|
730
631
|
else if (methodParams.body.parameter) {
|
|
731
|
-
emitParameter(methodParams.body.parameter, "body", visibility, getJsonName(methodParams.body.parameter), schema);
|
|
632
|
+
emitParameter(methodParams.body.parameter, "body", { visibility, ignoreMetadataAnnotations: false }, getJsonName(methodParams.body.parameter), schema);
|
|
732
633
|
}
|
|
733
634
|
else {
|
|
734
635
|
currentEndpoint.parameters.push({
|
|
@@ -755,7 +656,7 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
755
656
|
}
|
|
756
657
|
return undefined;
|
|
757
658
|
}
|
|
758
|
-
function emitParameter(param, kind,
|
|
659
|
+
function emitParameter(param, kind, schemaContext, name, typeOverride) {
|
|
759
660
|
if (isNeverType(param.type)) {
|
|
760
661
|
return;
|
|
761
662
|
}
|
|
@@ -763,11 +664,11 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
763
664
|
currentEndpoint.parameters.push(ph);
|
|
764
665
|
// If the parameter already has a $ref, don't bother populating it
|
|
765
666
|
if (!("$ref" in ph)) {
|
|
766
|
-
populateParameter(ph, param, kind,
|
|
667
|
+
populateParameter(ph, param, kind, schemaContext, name, typeOverride);
|
|
767
668
|
}
|
|
768
669
|
}
|
|
769
|
-
function getSchemaForPrimitiveItems(type,
|
|
770
|
-
const fullSchema = getSchemaForType(type,
|
|
670
|
+
function getSchemaForPrimitiveItems(type, schemaContext, paramName, multipart) {
|
|
671
|
+
const fullSchema = getSchemaForType(type, schemaContext);
|
|
771
672
|
if (fullSchema === undefined) {
|
|
772
673
|
return undefined;
|
|
773
674
|
}
|
|
@@ -781,7 +682,7 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
781
682
|
}
|
|
782
683
|
return fullSchema;
|
|
783
684
|
}
|
|
784
|
-
function getFormDataSchema(type,
|
|
685
|
+
function getFormDataSchema(type, schemaContext, paramName) {
|
|
785
686
|
if (isBytes(type)) {
|
|
786
687
|
return { type: "file" };
|
|
787
688
|
}
|
|
@@ -790,7 +691,7 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
790
691
|
if (isBytes(elementType)) {
|
|
791
692
|
return { type: "array", items: { type: "string", format: "binary" } };
|
|
792
693
|
}
|
|
793
|
-
const schema = getSchemaForPrimitiveItems(elementType,
|
|
694
|
+
const schema = getSchemaForPrimitiveItems(elementType, schemaContext, paramName, true);
|
|
794
695
|
if (schema === undefined) {
|
|
795
696
|
return undefined;
|
|
796
697
|
}
|
|
@@ -801,14 +702,14 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
801
702
|
};
|
|
802
703
|
}
|
|
803
704
|
else {
|
|
804
|
-
const schema = getSchemaForPrimitiveItems(type,
|
|
705
|
+
const schema = getSchemaForPrimitiveItems(type, schemaContext, paramName, true);
|
|
805
706
|
if (schema === undefined) {
|
|
806
707
|
return undefined;
|
|
807
708
|
}
|
|
808
709
|
return schema;
|
|
809
710
|
}
|
|
810
711
|
}
|
|
811
|
-
function getOpenAPI2Parameter(param, kind,
|
|
712
|
+
function getOpenAPI2Parameter(param, kind, schemaContext, name, bodySchema) {
|
|
812
713
|
const ph = {
|
|
813
714
|
name: name ?? param.name,
|
|
814
715
|
in: kind,
|
|
@@ -826,7 +727,7 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
826
727
|
ph.schema = bodySchema;
|
|
827
728
|
}
|
|
828
729
|
else if (ph.in === "formData") {
|
|
829
|
-
Object.assign(ph, getFormDataSchema(param.type,
|
|
730
|
+
Object.assign(ph, getFormDataSchema(param.type, schemaContext, ph.name));
|
|
830
731
|
}
|
|
831
732
|
else {
|
|
832
733
|
const collectionFormat = (kind === "query"
|
|
@@ -843,13 +744,13 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
843
744
|
if (param.type.kind === "Model" && isArrayModelType(program, param.type)) {
|
|
844
745
|
ph.type = "array";
|
|
845
746
|
const schema = {
|
|
846
|
-
...getSchemaForPrimitiveItems(param.type.indexer.value,
|
|
747
|
+
...getSchemaForPrimitiveItems(param.type.indexer.value, schemaContext, ph.name),
|
|
847
748
|
};
|
|
848
749
|
delete schema.description;
|
|
849
750
|
ph.items = schema;
|
|
850
751
|
}
|
|
851
752
|
else {
|
|
852
|
-
Object.assign(ph, getSchemaForPrimitiveItems(param.type,
|
|
753
|
+
Object.assign(ph, getSchemaForPrimitiveItems(param.type, schemaContext, ph.name));
|
|
853
754
|
}
|
|
854
755
|
}
|
|
855
756
|
attachExtensions(param, ph);
|
|
@@ -860,8 +761,8 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
860
761
|
Object.assign(ph, applyIntrinsicDecorators(param, { type: ph.type, format: ph.format }));
|
|
861
762
|
return ph;
|
|
862
763
|
}
|
|
863
|
-
function populateParameter(ph, param, kind,
|
|
864
|
-
Object.assign(ph, getOpenAPI2Parameter(param, kind,
|
|
764
|
+
function populateParameter(ph, param, kind, schemaContext, name, bodySchema) {
|
|
765
|
+
Object.assign(ph, getOpenAPI2Parameter(param, kind, schemaContext, name, bodySchema));
|
|
865
766
|
}
|
|
866
767
|
function emitParameters() {
|
|
867
768
|
for (const [property, param] of params) {
|
|
@@ -910,7 +811,10 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
910
811
|
for (const [visibility, pending] of group) {
|
|
911
812
|
processedSchemas.getOrAdd(type, visibility, () => ({
|
|
912
813
|
...pending,
|
|
913
|
-
schema: getSchemaForType(type,
|
|
814
|
+
schema: getSchemaForType(type, {
|
|
815
|
+
visibility: visibility,
|
|
816
|
+
ignoreMetadataAnnotations: false,
|
|
817
|
+
}),
|
|
914
818
|
}));
|
|
915
819
|
}
|
|
916
820
|
pendingSchemas.delete(type);
|
|
@@ -920,7 +824,7 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
920
824
|
function processUnreferencedSchemas() {
|
|
921
825
|
const addSchema = (type) => {
|
|
922
826
|
if (!processedSchemas.has(type) && !paramModels.has(type) && !shouldInline(program, type)) {
|
|
923
|
-
getSchemaOrRef(type, Visibility.Read);
|
|
827
|
+
getSchemaOrRef(type, { visibility: Visibility.Read, ignoreMetadataAnnotations: false });
|
|
924
828
|
}
|
|
925
829
|
};
|
|
926
830
|
const skipSubNamespaces = isGlobalNamespace(program, serviceNamespace);
|
|
@@ -938,67 +842,7 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
938
842
|
root.tags.push({ name: tag });
|
|
939
843
|
}
|
|
940
844
|
}
|
|
941
|
-
|
|
942
|
-
if (options.examplesDirectory) {
|
|
943
|
-
const exampleDir = version
|
|
944
|
-
? resolvePath(options.examplesDirectory, version)
|
|
945
|
-
: resolvePath(options.examplesDirectory);
|
|
946
|
-
try {
|
|
947
|
-
if (!(await program.host.stat(exampleDir)).isDirectory())
|
|
948
|
-
return;
|
|
949
|
-
}
|
|
950
|
-
catch (err) {
|
|
951
|
-
reportDiagnostic(program, {
|
|
952
|
-
code: "example-loading",
|
|
953
|
-
messageId: "noDirectory",
|
|
954
|
-
format: { directory: exampleDir },
|
|
955
|
-
target: NoTarget,
|
|
956
|
-
});
|
|
957
|
-
return;
|
|
958
|
-
}
|
|
959
|
-
const exampleFiles = await program.host.readDir(exampleDir);
|
|
960
|
-
for (const fileName of exampleFiles) {
|
|
961
|
-
try {
|
|
962
|
-
const exampleFile = await program.host.readFile(resolvePath(exampleDir, fileName));
|
|
963
|
-
const example = JSON.parse(exampleFile.text);
|
|
964
|
-
if (!example.operationId || !example.title) {
|
|
965
|
-
reportDiagnostic(program, {
|
|
966
|
-
code: "example-loading",
|
|
967
|
-
messageId: "noOperationId",
|
|
968
|
-
format: { filename: fileName },
|
|
969
|
-
target: NoTarget,
|
|
970
|
-
});
|
|
971
|
-
continue;
|
|
972
|
-
}
|
|
973
|
-
if (!operationExamplesMap.has(example.operationId)) {
|
|
974
|
-
operationExamplesMap.set(example.operationId, {});
|
|
975
|
-
}
|
|
976
|
-
const examples = operationExamplesMap.get(example.operationId);
|
|
977
|
-
if (example.title in examples) {
|
|
978
|
-
reportDiagnostic(program, {
|
|
979
|
-
code: "duplicate-example-file",
|
|
980
|
-
target: NoTarget,
|
|
981
|
-
format: {
|
|
982
|
-
filename: fileName,
|
|
983
|
-
operationId: example.operationId,
|
|
984
|
-
title: example.title,
|
|
985
|
-
},
|
|
986
|
-
});
|
|
987
|
-
}
|
|
988
|
-
examples[example.title] = fileName;
|
|
989
|
-
}
|
|
990
|
-
catch (err) {
|
|
991
|
-
reportDiagnostic(program, {
|
|
992
|
-
code: "example-loading",
|
|
993
|
-
messageId: "default",
|
|
994
|
-
format: { filename: fileName, error: err?.toString() ?? "" },
|
|
995
|
-
target: NoTarget,
|
|
996
|
-
});
|
|
997
|
-
}
|
|
998
|
-
}
|
|
999
|
-
}
|
|
1000
|
-
}
|
|
1001
|
-
function getSchemaForType(type, visibility) {
|
|
845
|
+
function getSchemaForType(type, schemaContext) {
|
|
1002
846
|
const builtinType = getSchemaForLiterals(type);
|
|
1003
847
|
if (builtinType !== undefined) {
|
|
1004
848
|
return builtinType;
|
|
@@ -1007,15 +851,15 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
1007
851
|
case "Intrinsic":
|
|
1008
852
|
return getSchemaForIntrinsicType(type);
|
|
1009
853
|
case "Model":
|
|
1010
|
-
return getSchemaForModel(type,
|
|
854
|
+
return getSchemaForModel(type, schemaContext);
|
|
1011
855
|
case "ModelProperty":
|
|
1012
|
-
return getSchemaForType(type.type,
|
|
856
|
+
return getSchemaForType(type.type, schemaContext);
|
|
1013
857
|
case "Scalar":
|
|
1014
858
|
return getSchemaForScalar(type);
|
|
1015
859
|
case "Union":
|
|
1016
|
-
return getSchemaForUnion(type,
|
|
860
|
+
return getSchemaForUnion(type, schemaContext);
|
|
1017
861
|
case "UnionVariant":
|
|
1018
|
-
return getSchemaForUnionVariant(type,
|
|
862
|
+
return getSchemaForUnionVariant(type, schemaContext);
|
|
1019
863
|
case "Enum":
|
|
1020
864
|
return getSchemaForEnum(type);
|
|
1021
865
|
case "Tuple":
|
|
@@ -1114,7 +958,7 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
1114
958
|
}
|
|
1115
959
|
return applyIntrinsicDecorators(union, schema);
|
|
1116
960
|
}
|
|
1117
|
-
function getSchemaForUnion(union,
|
|
961
|
+
function getSchemaForUnion(union, schemaContext) {
|
|
1118
962
|
const nonNullOptions = [...union.variants.values()]
|
|
1119
963
|
.map((x) => x.type)
|
|
1120
964
|
.filter((t) => !isNullType(t));
|
|
@@ -1126,7 +970,7 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
1126
970
|
if (nonNullOptions.length === 1) {
|
|
1127
971
|
const type = nonNullOptions[0];
|
|
1128
972
|
// Get the schema for the model type
|
|
1129
|
-
const schema = getSchemaOrRef(type,
|
|
973
|
+
const schema = getSchemaOrRef(type, schemaContext);
|
|
1130
974
|
if (schema.$ref) {
|
|
1131
975
|
if (type.kind === "Model") {
|
|
1132
976
|
return { type: "object", allOf: [schema], "x-nullable": nullable };
|
|
@@ -1159,8 +1003,8 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
1159
1003
|
return (getExtensions(program, array).has("x-ms-identifiers") ||
|
|
1160
1004
|
getProperty(array.indexer.value, "id"));
|
|
1161
1005
|
}
|
|
1162
|
-
function getSchemaForUnionVariant(variant,
|
|
1163
|
-
return getSchemaForType(variant.type,
|
|
1006
|
+
function getSchemaForUnionVariant(variant, schemaContext) {
|
|
1007
|
+
return getSchemaForType(variant.type, schemaContext);
|
|
1164
1008
|
}
|
|
1165
1009
|
function getDefaultValue(type) {
|
|
1166
1010
|
switch (type.kind) {
|
|
@@ -1220,8 +1064,8 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
1220
1064
|
}
|
|
1221
1065
|
return undefined;
|
|
1222
1066
|
}
|
|
1223
|
-
function getSchemaForModel(model,
|
|
1224
|
-
const array = getArrayType(model,
|
|
1067
|
+
function getSchemaForModel(model, schemaContext) {
|
|
1068
|
+
const array = getArrayType(model, schemaContext);
|
|
1225
1069
|
if (array) {
|
|
1226
1070
|
return array;
|
|
1227
1071
|
}
|
|
@@ -1240,12 +1084,12 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
1240
1084
|
}
|
|
1241
1085
|
const properties = {};
|
|
1242
1086
|
if (isRecordModelType(program, model)) {
|
|
1243
|
-
modelSchema.additionalProperties = getSchemaOrRef(model.indexer.value,
|
|
1087
|
+
modelSchema.additionalProperties = getSchemaOrRef(model.indexer.value, schemaContext);
|
|
1244
1088
|
}
|
|
1245
1089
|
const derivedModels = model.derivedModels.filter(includeDerivedModel);
|
|
1246
1090
|
// getSchemaOrRef on all children to push them into components.schemas
|
|
1247
1091
|
for (const child of derivedModels) {
|
|
1248
|
-
getSchemaOrRef(child,
|
|
1092
|
+
getSchemaOrRef(child, schemaContext);
|
|
1249
1093
|
}
|
|
1250
1094
|
const discriminator = getDiscriminator(program, model);
|
|
1251
1095
|
if (discriminator) {
|
|
@@ -1262,7 +1106,7 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
1262
1106
|
}
|
|
1263
1107
|
applyExternalDocs(model, modelSchema);
|
|
1264
1108
|
for (const prop of model.properties.values()) {
|
|
1265
|
-
if (!metadataInfo.isPayloadProperty(prop, visibility)) {
|
|
1109
|
+
if (!metadataInfo.isPayloadProperty(prop, schemaContext.visibility, schemaContext.ignoreMetadataAnnotations)) {
|
|
1266
1110
|
continue;
|
|
1267
1111
|
}
|
|
1268
1112
|
if (isNeverType(prop.type)) {
|
|
@@ -1270,7 +1114,7 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
1270
1114
|
continue;
|
|
1271
1115
|
}
|
|
1272
1116
|
const jsonName = getJsonName(prop);
|
|
1273
|
-
const clientName = getClientName(prop);
|
|
1117
|
+
const clientName = getClientName(context, prop);
|
|
1274
1118
|
const description = getDoc(program, prop);
|
|
1275
1119
|
// if this property is a discriminator property, remove it to keep autorest validation happy
|
|
1276
1120
|
if (model.baseModel) {
|
|
@@ -1279,14 +1123,15 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
1279
1123
|
continue;
|
|
1280
1124
|
}
|
|
1281
1125
|
}
|
|
1282
|
-
if (!metadataInfo.isOptional(prop, visibility) ||
|
|
1126
|
+
if (!metadataInfo.isOptional(prop, schemaContext.visibility) ||
|
|
1127
|
+
prop.name === discriminator?.propertyName) {
|
|
1283
1128
|
if (!modelSchema.required) {
|
|
1284
1129
|
modelSchema.required = [];
|
|
1285
1130
|
}
|
|
1286
1131
|
modelSchema.required.push(jsonName);
|
|
1287
1132
|
}
|
|
1288
1133
|
// Apply decorators on the property to the type's schema
|
|
1289
|
-
properties[jsonName] = resolveProperty(prop,
|
|
1134
|
+
properties[jsonName] = resolveProperty(prop, schemaContext);
|
|
1290
1135
|
const property = properties[jsonName];
|
|
1291
1136
|
if (jsonName !== clientName) {
|
|
1292
1137
|
property["x-ms-client-name"] = clientName;
|
|
@@ -1331,11 +1176,11 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
1331
1176
|
Object.keys(properties).length === 0) {
|
|
1332
1177
|
// Take the base model schema but carry across the documentation property
|
|
1333
1178
|
// that we set before
|
|
1334
|
-
const baseSchema = getSchemaForType(model.baseModel,
|
|
1179
|
+
const baseSchema = getSchemaForType(model.baseModel, schemaContext);
|
|
1335
1180
|
Object.assign(modelSchema, baseSchema, { description: modelSchema.description });
|
|
1336
1181
|
}
|
|
1337
1182
|
else if (model.baseModel) {
|
|
1338
|
-
const baseSchema = getSchemaOrRef(model.baseModel,
|
|
1183
|
+
const baseSchema = getSchemaOrRef(model.baseModel, schemaContext);
|
|
1339
1184
|
modelSchema.allOf = [baseSchema];
|
|
1340
1185
|
}
|
|
1341
1186
|
if (Object.keys(properties).length > 0) {
|
|
@@ -1357,7 +1202,7 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
1357
1202
|
}
|
|
1358
1203
|
return true;
|
|
1359
1204
|
}
|
|
1360
|
-
function resolveProperty(prop,
|
|
1205
|
+
function resolveProperty(prop, context) {
|
|
1361
1206
|
let propSchema;
|
|
1362
1207
|
if (prop.type.kind === "Enum" && prop.default) {
|
|
1363
1208
|
propSchema = getSchemaForEnum(prop.type);
|
|
@@ -1368,11 +1213,11 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
1368
1213
|
propSchema = getSchemaForUnionEnum(prop.type, asEnum);
|
|
1369
1214
|
}
|
|
1370
1215
|
else {
|
|
1371
|
-
propSchema = getSchemaOrRef(prop.type,
|
|
1216
|
+
propSchema = getSchemaOrRef(prop.type, context);
|
|
1372
1217
|
}
|
|
1373
1218
|
}
|
|
1374
1219
|
else {
|
|
1375
|
-
propSchema = getSchemaOrRef(prop.type,
|
|
1220
|
+
propSchema = getSchemaOrRef(prop.type, context);
|
|
1376
1221
|
}
|
|
1377
1222
|
return applyIntrinsicDecorators(prop, propSchema);
|
|
1378
1223
|
}
|
|
@@ -1492,7 +1337,7 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
1492
1337
|
}
|
|
1493
1338
|
}
|
|
1494
1339
|
if (typespecType.kind === "ModelProperty" &&
|
|
1495
|
-
shouldFlattenProperty(tcgcSdkContext, typespecType)) {
|
|
1340
|
+
shouldFlattenProperty(context.tcgcSdkContext, typespecType)) {
|
|
1496
1341
|
newTarget["x-ms-client-flatten"] = true;
|
|
1497
1342
|
}
|
|
1498
1343
|
attachExtensions(typespecType, newTarget);
|
|
@@ -1603,11 +1448,14 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
1603
1448
|
/**
|
|
1604
1449
|
* If the model is an array model return the OpenAPI2Schema for the array type.
|
|
1605
1450
|
*/
|
|
1606
|
-
function getArrayType(typespecType,
|
|
1451
|
+
function getArrayType(typespecType, context) {
|
|
1607
1452
|
if (isArrayModelType(program, typespecType)) {
|
|
1608
1453
|
const array = {
|
|
1609
1454
|
type: "array",
|
|
1610
|
-
items: getSchemaOrRef(typespecType.indexer.value,
|
|
1455
|
+
items: getSchemaOrRef(typespecType.indexer.value, {
|
|
1456
|
+
...context,
|
|
1457
|
+
visibility: context.visibility | Visibility.Item,
|
|
1458
|
+
}),
|
|
1611
1459
|
};
|
|
1612
1460
|
if (!ifArrayItemContainsIdentifier(program, typespecType)) {
|
|
1613
1461
|
array["x-ms-identifiers"] = [];
|
|
@@ -1766,7 +1614,7 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
1766
1614
|
reportDiagnostic(program, {
|
|
1767
1615
|
code: "unsupported-auth",
|
|
1768
1616
|
format: { authType: auth.type },
|
|
1769
|
-
target:
|
|
1617
|
+
target: service.type,
|
|
1770
1618
|
});
|
|
1771
1619
|
return undefined;
|
|
1772
1620
|
}
|
|
@@ -1787,9 +1635,6 @@ function createOAPIEmitter(program, tcgcSdkContext, options) {
|
|
|
1787
1635
|
}
|
|
1788
1636
|
}
|
|
1789
1637
|
}
|
|
1790
|
-
function prettierOutput(output) {
|
|
1791
|
-
return output + "\n";
|
|
1792
|
-
}
|
|
1793
1638
|
class ErrorTypeFoundError extends Error {
|
|
1794
1639
|
constructor() {
|
|
1795
1640
|
super("Error type found in evaluated TypeSpec output");
|
|
@@ -1801,24 +1646,71 @@ export function sortOpenAPIDocument(doc) {
|
|
|
1801
1646
|
const sorted = sortWithJsonSchema(unsorted, AutorestOpenAPISchema, "#/$defs/AutorestOpenAPISchema");
|
|
1802
1647
|
return sorted;
|
|
1803
1648
|
}
|
|
1804
|
-
function
|
|
1805
|
-
const
|
|
1806
|
-
if (
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
:
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1649
|
+
async function loadExamples(host, options, version) {
|
|
1650
|
+
const diagnostics = createDiagnosticCollector();
|
|
1651
|
+
if (!options.examplesDirectory) {
|
|
1652
|
+
return diagnostics.wrap(new Map());
|
|
1653
|
+
}
|
|
1654
|
+
const exampleDir = version
|
|
1655
|
+
? resolvePath(options.examplesDirectory, version)
|
|
1656
|
+
: resolvePath(options.examplesDirectory);
|
|
1657
|
+
try {
|
|
1658
|
+
if (!(await host.stat(exampleDir)).isDirectory())
|
|
1659
|
+
return diagnostics.wrap(new Map());
|
|
1660
|
+
}
|
|
1661
|
+
catch (err) {
|
|
1662
|
+
diagnostics.add(createDiagnostic({
|
|
1663
|
+
code: "example-loading",
|
|
1664
|
+
messageId: "noDirectory",
|
|
1665
|
+
format: { directory: exampleDir },
|
|
1666
|
+
target: NoTarget,
|
|
1667
|
+
}));
|
|
1668
|
+
return diagnostics.wrap(new Map());
|
|
1669
|
+
}
|
|
1670
|
+
const map = new Map();
|
|
1671
|
+
const exampleFiles = await host.readDir(exampleDir);
|
|
1672
|
+
for (const fileName of exampleFiles) {
|
|
1673
|
+
try {
|
|
1674
|
+
const exampleFile = await host.readFile(resolvePath(exampleDir, fileName));
|
|
1675
|
+
const example = JSON.parse(exampleFile.text);
|
|
1676
|
+
if (!example.operationId || !example.title) {
|
|
1677
|
+
diagnostics.add(createDiagnostic({
|
|
1678
|
+
code: "example-loading",
|
|
1679
|
+
messageId: "noOperationId",
|
|
1680
|
+
format: { filename: fileName },
|
|
1681
|
+
target: NoTarget,
|
|
1682
|
+
}));
|
|
1683
|
+
continue;
|
|
1684
|
+
}
|
|
1685
|
+
if (!map.has(example.operationId)) {
|
|
1686
|
+
map.set(example.operationId, {});
|
|
1687
|
+
}
|
|
1688
|
+
const examples = map.get(example.operationId);
|
|
1689
|
+
if (example.title in examples) {
|
|
1690
|
+
diagnostics.add(createDiagnostic({
|
|
1691
|
+
code: "duplicate-example-file",
|
|
1692
|
+
target: NoTarget,
|
|
1693
|
+
format: {
|
|
1694
|
+
filename: fileName,
|
|
1695
|
+
operationId: example.operationId,
|
|
1696
|
+
title: example.title,
|
|
1697
|
+
},
|
|
1698
|
+
}));
|
|
1699
|
+
}
|
|
1700
|
+
examples[example.title] = {
|
|
1701
|
+
file: exampleFile,
|
|
1702
|
+
data: example,
|
|
1703
|
+
};
|
|
1704
|
+
}
|
|
1705
|
+
catch (err) {
|
|
1706
|
+
diagnostics.add(createDiagnostic({
|
|
1707
|
+
code: "example-loading",
|
|
1708
|
+
messageId: "default",
|
|
1709
|
+
format: { filename: fileName, error: err?.toString() ?? "" },
|
|
1710
|
+
target: NoTarget,
|
|
1711
|
+
}));
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1714
|
+
return diagnostics.wrap(new Map());
|
|
1823
1715
|
}
|
|
1824
1716
|
//# sourceMappingURL=openapi.js.map
|