@azure-tools/typespec-ts 0.17.0-alpha.20231010.1 → 0.17.1
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/CHANGELOG.md +12 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/modular/buildClassicalClient.d.ts.map +1 -1
- package/dist/src/modular/buildClassicalClient.js +16 -0
- package/dist/src/modular/buildClassicalClient.js.map +1 -1
- package/dist/src/modular/buildCodeModel.d.ts.map +1 -1
- package/dist/src/modular/buildCodeModel.js +9 -0
- package/dist/src/modular/buildCodeModel.js.map +1 -1
- package/dist/src/modular/buildProjectFiles.d.ts.map +1 -1
- package/dist/src/modular/buildProjectFiles.js +10 -5
- package/dist/src/modular/buildProjectFiles.js.map +1 -1
- package/dist/src/modular/emitModels.d.ts.map +1 -1
- package/dist/src/modular/emitModels.js +2 -1
- package/dist/src/modular/emitModels.js.map +1 -1
- package/dist/src/modular/helpers/typeHelpers.js +7 -7
- package/dist/src/modular/helpers/typeHelpers.js.map +1 -1
- package/dist/src/transform/transform.d.ts.map +1 -1
- package/dist/src/transform/transform.js +5 -1
- package/dist/src/transform/transform.js.map +1 -1
- package/dist/src/transform/transformParameters.js +2 -1
- package/dist/src/transform/transformParameters.js.map +1 -1
- package/dist/src/transform/transformSchemas.d.ts.map +1 -1
- package/dist/src/transform/transformSchemas.js +13 -11
- package/dist/src/transform/transformSchemas.js.map +1 -1
- package/dist/src/utils/emitUtil.d.ts.map +1 -1
- package/dist/src/utils/emitUtil.js +9 -3
- package/dist/src/utils/emitUtil.js.map +1 -1
- package/dist/src/utils/modelUtils.d.ts.map +1 -1
- package/dist/src/utils/modelUtils.js +135 -129
- package/dist/src/utils/modelUtils.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -5
- package/src/index.ts +8 -1
- package/src/modular/buildClassicalClient.ts +17 -0
- package/src/modular/buildCodeModel.ts +8 -0
- package/src/modular/buildProjectFiles.ts +11 -5
- package/src/modular/emitModels.ts +5 -1
- package/src/modular/helpers/typeHelpers.ts +1 -1
- package/src/transform/transform.ts +8 -2
- package/src/transform/transformParameters.ts +2 -1
- package/src/transform/transformSchemas.ts +7 -3
- package/src/utils/emitUtil.ts +9 -3
- package/src/utils/modelUtils.ts +148 -143
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@azure-tools/typespec-ts",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.1",
|
|
4
4
|
"description": "An experimental TypeSpec emitter for TypeScript RLC",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -33,7 +33,8 @@
|
|
|
33
33
|
"@azure/core-lro": "^2.5.4",
|
|
34
34
|
"@azure/core-rest-pipeline": "^1.12.0",
|
|
35
35
|
"@azure/logger": "^1.0.4",
|
|
36
|
-
"@azure/core-util": "^1.4.0"
|
|
36
|
+
"@azure/core-util": "^1.4.0",
|
|
37
|
+
"eslint-plugin-require-extensions": "0.1.3"
|
|
37
38
|
},
|
|
38
39
|
"peerDependencies": {
|
|
39
40
|
"@azure-tools/typespec-azure-core": ">=0.34.0 <1.0.0",
|
|
@@ -46,7 +47,7 @@
|
|
|
46
47
|
"dependencies": {
|
|
47
48
|
"prettier": "^2.6.1",
|
|
48
49
|
"tslib": "^2.3.1",
|
|
49
|
-
"@azure-tools/rlc-common": "^0.17.
|
|
50
|
+
"@azure-tools/rlc-common": "^0.17.1",
|
|
50
51
|
"ts-morph": "^15.1.0",
|
|
51
52
|
"fs-extra": "^11.1.0"
|
|
52
53
|
},
|
|
@@ -90,8 +91,8 @@
|
|
|
90
91
|
"generate-tsp-only:rlc": "ts-node ./test/commands/gen-cadl-ranch.ts --tag=rlc",
|
|
91
92
|
"generate-tsp-only:modular": "ts-node ./test/commands/gen-cadl-ranch.ts --tag=modular",
|
|
92
93
|
"integration-test:alone": "npm run integration-test:alone:rlc && npm run integration-test:alone:modular",
|
|
93
|
-
"integration-test:alone:rlc": "cross-env TS_NODE_PROJECT=tsconfig.
|
|
94
|
-
"integration-test:alone:modular": "cross-env TS_NODE_PROJECT=tsconfig.
|
|
94
|
+
"integration-test:alone:rlc": "cross-env TS_NODE_PROJECT=tsconfig.integration.json mocha -r ts-node/register --experimental-specifier-resolution=node --timeout 4000 ./test/integration/*.spec.ts",
|
|
95
|
+
"integration-test:alone:modular": "cross-env TS_NODE_PROJECT=tsconfig.integration.json mocha -r ts-node/register --experimental-specifier-resolution=node --timeout 4000 ./test/modularIntegration/*.spec.ts",
|
|
95
96
|
"stop-test-server": "npx cadl-ranch server stop",
|
|
96
97
|
"unit-test": "npm run unit-test:rlc && npm run unit-test:modular",
|
|
97
98
|
"unit-test:rlc": "cross-env TS_NODE_PROJECT=tsconfig.json mocha -r ts-node/register --experimental-specifier-resolution=node --experimental-modules=true --timeout 4000 './test/unit/**/*.spec.ts'",
|
package/src/index.ts
CHANGED
|
@@ -29,7 +29,8 @@ import {
|
|
|
29
29
|
buildLogger,
|
|
30
30
|
RLCOptions,
|
|
31
31
|
hasUnexpectedHelper,
|
|
32
|
-
RLCModel
|
|
32
|
+
RLCModel,
|
|
33
|
+
buildSamples
|
|
33
34
|
} from "@azure-tools/rlc-common";
|
|
34
35
|
import { transformRLCModel } from "./transform/transform.js";
|
|
35
36
|
import { emitContentByBuilder, emitModels } from "./utils/emitUtil.js";
|
|
@@ -137,6 +138,12 @@ export async function $onEmit(context: EmitContext) {
|
|
|
137
138
|
await emitContentByBuilder(program, buildPaginateHelper, rlcModels);
|
|
138
139
|
await emitContentByBuilder(program, buildPollingHelper, rlcModels);
|
|
139
140
|
await emitContentByBuilder(program, buildSerializeHelper, rlcModels);
|
|
141
|
+
await emitContentByBuilder(
|
|
142
|
+
program,
|
|
143
|
+
buildSamples,
|
|
144
|
+
rlcModels,
|
|
145
|
+
dpgContext.generationPathDetail?.metadataDir
|
|
146
|
+
);
|
|
140
147
|
}
|
|
141
148
|
}
|
|
142
149
|
|
|
@@ -62,6 +62,15 @@ export function buildClassicalClient(
|
|
|
62
62
|
});
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
// Add the pipeline member. This will be the pipeline from /api
|
|
66
|
+
clientClass.addProperty({
|
|
67
|
+
name: "pipeline",
|
|
68
|
+
type: "Pipeline",
|
|
69
|
+
scope: Scope.Public,
|
|
70
|
+
isReadonly: true,
|
|
71
|
+
docs: ["The pipeline used by this client to make requests"]
|
|
72
|
+
});
|
|
73
|
+
|
|
65
74
|
// TODO: We may need to generate constructor overloads at some point. Here we'd do that.
|
|
66
75
|
const constructor = clientClass.addConstructor({
|
|
67
76
|
docs: getDocsFromDescription(description),
|
|
@@ -72,7 +81,9 @@ export function buildClassicalClient(
|
|
|
72
81
|
.map((p) => p.name)
|
|
73
82
|
.join(",")})`
|
|
74
83
|
]);
|
|
84
|
+
constructor.addStatements(`this.pipeline = this._client.pipeline`);
|
|
75
85
|
importCredential(clientFile);
|
|
86
|
+
importPipeline(clientFile);
|
|
76
87
|
importAllModels(clientFile, srcPath, subfolder);
|
|
77
88
|
buildClientOperationGroups(client, clientClass, subfolder);
|
|
78
89
|
importAllApis(clientFile, srcPath, subfolder);
|
|
@@ -143,6 +154,12 @@ function importAllModels(
|
|
|
143
154
|
});
|
|
144
155
|
}
|
|
145
156
|
|
|
157
|
+
function importPipeline(clientSourceFile: SourceFile): void {
|
|
158
|
+
clientSourceFile.addImportDeclaration({
|
|
159
|
+
moduleSpecifier: "@azure/core-rest-pipeline",
|
|
160
|
+
namedImports: ["Pipeline"]
|
|
161
|
+
});
|
|
162
|
+
}
|
|
146
163
|
function buildClientOperationGroups(
|
|
147
164
|
client: Client,
|
|
148
165
|
clientClass: ClassDeclaration,
|
|
@@ -1052,6 +1052,14 @@ function emitCredential(auth: HttpAuth): Record<string, any> {
|
|
|
1052
1052
|
key: auth.name
|
|
1053
1053
|
}
|
|
1054
1054
|
};
|
|
1055
|
+
} else if (auth.type === "http") {
|
|
1056
|
+
credential_type = {
|
|
1057
|
+
type: "Key",
|
|
1058
|
+
policy: {
|
|
1059
|
+
type: "AzureKeyCredentialPolicy",
|
|
1060
|
+
key: "Authorization"
|
|
1061
|
+
}
|
|
1062
|
+
};
|
|
1055
1063
|
}
|
|
1056
1064
|
return credential_type;
|
|
1057
1065
|
}
|
|
@@ -206,10 +206,10 @@ export function emitPackage(
|
|
|
206
206
|
if (generateTest) {
|
|
207
207
|
packageInfo.module = `./dist-esm/src/index.js`;
|
|
208
208
|
packageInfo.devDependencies["@azure-tools/test-credential"] = "^1.0.0";
|
|
209
|
-
packageInfo.devDependencies["@azure/identity"] = "^
|
|
209
|
+
packageInfo.devDependencies["@azure/identity"] = "^3.3.0";
|
|
210
210
|
packageInfo.devDependencies["@azure-tools/test-recorder"] = "^3.0.0";
|
|
211
|
-
packageInfo.devDependencies["mocha"] = "^
|
|
212
|
-
packageInfo.devDependencies["@types/mocha"] = "^
|
|
211
|
+
packageInfo.devDependencies["mocha"] = "^10.0.0";
|
|
212
|
+
packageInfo.devDependencies["@types/mocha"] = "^10.0.0";
|
|
213
213
|
packageInfo.devDependencies["mocha-junit-reporter"] = "^1.18.0";
|
|
214
214
|
packageInfo.devDependencies["cross-env"] = "^7.0.2";
|
|
215
215
|
packageInfo.devDependencies["@types/chai"] = "^4.2.8";
|
|
@@ -242,12 +242,12 @@ export function emitPackage(
|
|
|
242
242
|
packageInfo.scripts["unit-test"] =
|
|
243
243
|
"npm run unit-test:node && npm run unit-test:browser";
|
|
244
244
|
packageInfo.scripts["unit-test:node"] =
|
|
245
|
-
'mocha
|
|
245
|
+
'mocha --full-trace "test/{,!(browser)/**/}*.spec.ts"';
|
|
246
246
|
packageInfo.scripts["unit-test:browser"] = "karma start --single-run";
|
|
247
247
|
packageInfo.scripts["integration-test:browser"] =
|
|
248
248
|
"karma start --single-run";
|
|
249
249
|
packageInfo.scripts["integration-test:node"] =
|
|
250
|
-
'nyc mocha
|
|
250
|
+
'nyc mocha --require source-map-support/register.js --timeout 5000000 --full-trace "dist-esm/test/{,!(browser)/**/}*.spec.js"';
|
|
251
251
|
packageInfo.scripts["integration-test"] =
|
|
252
252
|
"npm run integration-test:node && npm run integration-test:browser";
|
|
253
253
|
if (azureSdkForJs) {
|
|
@@ -265,6 +265,12 @@ export function emitPackage(
|
|
|
265
265
|
"./dist-esm/test/public/utils/env.js":
|
|
266
266
|
"./dist-esm/test/public/utils/env.browser.js"
|
|
267
267
|
};
|
|
268
|
+
|
|
269
|
+
packageInfo["mocha"] = {
|
|
270
|
+
extension: ["ts"],
|
|
271
|
+
timeout: "1200000",
|
|
272
|
+
loader: "ts-node/esm"
|
|
273
|
+
};
|
|
268
274
|
}
|
|
269
275
|
|
|
270
276
|
if (generateSample) {
|
|
@@ -139,7 +139,11 @@ export function buildModelsOptions(
|
|
|
139
139
|
client: Client
|
|
140
140
|
) {
|
|
141
141
|
const modelOptionsFile = codeModel.project.createSourceFile(
|
|
142
|
-
|
|
142
|
+
path.join(
|
|
143
|
+
codeModel.modularOptions.sourceRoot,
|
|
144
|
+
client.subfolder ?? "",
|
|
145
|
+
`models/options.ts`
|
|
146
|
+
),
|
|
143
147
|
undefined,
|
|
144
148
|
{
|
|
145
149
|
overwrite: true
|
|
@@ -38,7 +38,7 @@ export function getType(type: Type, format?: string): TypeMetadata {
|
|
|
38
38
|
case "boolean":
|
|
39
39
|
return { name: getNullableType(type.type, type) };
|
|
40
40
|
case "constant": {
|
|
41
|
-
let typeName: string = type.value ?? "undefined";
|
|
41
|
+
let typeName: string = type.value?.toString() ?? "undefined";
|
|
42
42
|
if (type.valueType?.type === "string") {
|
|
43
43
|
typeName = type.value ? `"${type.value}"` : "undefined";
|
|
44
44
|
}
|
|
@@ -35,6 +35,7 @@ import { transformApiVersionInfo } from "./transformApiVersionInfo.js";
|
|
|
35
35
|
import { getClientLroOverload } from "../utils/operationUtil.js";
|
|
36
36
|
import { transformTelemetryInfo } from "./transformTelemetryInfo.js";
|
|
37
37
|
import { SdkContext } from "../utils/interfaces.js";
|
|
38
|
+
import { transformSampleGroups } from "@azure-tools/rlc-common";
|
|
38
39
|
|
|
39
40
|
export async function transformRLCModel(
|
|
40
41
|
client: SdkClient,
|
|
@@ -60,7 +61,6 @@ export async function transformRLCModel(
|
|
|
60
61
|
const importSet = new Map<ImportKind, Set<string>>();
|
|
61
62
|
const paths: Paths = transformPaths(program, client, dpgContext);
|
|
62
63
|
const schemas: Schema[] = transformSchemas(program, client, dpgContext);
|
|
63
|
-
|
|
64
64
|
const responses: OperationResponse[] = transformToResponseTypes(
|
|
65
65
|
importSet,
|
|
66
66
|
client,
|
|
@@ -77,7 +77,7 @@ export async function transformRLCModel(
|
|
|
77
77
|
const urlInfo = transformUrlInfo(dpgContext);
|
|
78
78
|
const apiVersionInfo = transformApiVersionInfo(client, dpgContext, urlInfo);
|
|
79
79
|
const telemetryOptions = transformTelemetryInfo(dpgContext, client);
|
|
80
|
-
|
|
80
|
+
const model: RLCModel = {
|
|
81
81
|
srcPath,
|
|
82
82
|
libraryName,
|
|
83
83
|
paths,
|
|
@@ -91,6 +91,12 @@ export async function transformRLCModel(
|
|
|
91
91
|
urlInfo,
|
|
92
92
|
telemetryOptions
|
|
93
93
|
};
|
|
94
|
+
model.sampleGroups = transformSampleGroups(
|
|
95
|
+
model,
|
|
96
|
+
options?.generateSample ===
|
|
97
|
+
true /* Enable mock sample content if generateSample === true */
|
|
98
|
+
);
|
|
99
|
+
return model;
|
|
94
100
|
}
|
|
95
101
|
|
|
96
102
|
export function transformUrlInfo(dpgContext: SdkContext): UrlInfo | undefined {
|
|
@@ -304,7 +304,8 @@ function transformNormalBody(
|
|
|
304
304
|
name: "body",
|
|
305
305
|
type: overrideType ?? type,
|
|
306
306
|
required: parameters?.bodyParameter?.optional === false,
|
|
307
|
-
description: descriptions.join("\n\n")
|
|
307
|
+
description: descriptions.join("\n\n"),
|
|
308
|
+
oriSchema: schema
|
|
308
309
|
}
|
|
309
310
|
]
|
|
310
311
|
};
|
|
@@ -122,8 +122,12 @@ export function transformSchemas(
|
|
|
122
122
|
|
|
123
123
|
setModelMap(model, context);
|
|
124
124
|
const indexer = (model as Model).indexer;
|
|
125
|
-
if (
|
|
126
|
-
|
|
125
|
+
if (
|
|
126
|
+
indexer?.value &&
|
|
127
|
+
(!program.stateMap(modelKey).get(indexer?.value) ||
|
|
128
|
+
!program.stateMap(modelKey).get(indexer?.value)?.includes(context))
|
|
129
|
+
) {
|
|
130
|
+
getGeneratedModels(indexer.value, context);
|
|
127
131
|
}
|
|
128
132
|
for (const prop of model.properties) {
|
|
129
133
|
if (
|
|
@@ -131,7 +135,7 @@ export function transformSchemas(
|
|
|
131
135
|
(!program.stateMap(modelKey).get(prop[1].type) ||
|
|
132
136
|
!program.stateMap(modelKey).get(prop[1].type)?.includes(context))
|
|
133
137
|
) {
|
|
134
|
-
if (prop[1].type
|
|
138
|
+
if (isAzureCoreErrorType(prop[1].type)) {
|
|
135
139
|
continue;
|
|
136
140
|
}
|
|
137
141
|
getGeneratedModels(prop[1].type, context);
|
package/src/utils/emitUtil.ts
CHANGED
|
@@ -29,9 +29,15 @@ export async function emitContentByBuilder(
|
|
|
29
29
|
builderFnOrList = [builderFnOrList];
|
|
30
30
|
}
|
|
31
31
|
for (const builderFn of builderFnOrList) {
|
|
32
|
-
|
|
33
|
-
if (
|
|
34
|
-
|
|
32
|
+
let contentFiles: File[] | File | undefined = builderFn(rlcModels);
|
|
33
|
+
if (!contentFiles) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (!Array.isArray(contentFiles)) {
|
|
37
|
+
contentFiles = [contentFiles];
|
|
38
|
+
}
|
|
39
|
+
for (const file of contentFiles) {
|
|
40
|
+
await emitFile(file, program, emitterOutputDir);
|
|
35
41
|
}
|
|
36
42
|
}
|
|
37
43
|
}
|
package/src/utils/modelUtils.ts
CHANGED
|
@@ -41,7 +41,9 @@ import {
|
|
|
41
41
|
listServices,
|
|
42
42
|
Program,
|
|
43
43
|
getEncode,
|
|
44
|
-
EncodeData
|
|
44
|
+
EncodeData,
|
|
45
|
+
isRecordModelType,
|
|
46
|
+
isArrayModelType
|
|
45
47
|
} from "@typespec/compiler";
|
|
46
48
|
import { reportDiagnostic } from "../lib.js";
|
|
47
49
|
import {
|
|
@@ -134,7 +136,7 @@ export function getSchemaForType(
|
|
|
134
136
|
const program = dpgContext.program;
|
|
135
137
|
const type = getEffectiveModelFromType(program, typeInput);
|
|
136
138
|
|
|
137
|
-
const builtinType =
|
|
139
|
+
const builtinType = getSchemaForLiteral(type);
|
|
138
140
|
if (builtinType !== undefined) {
|
|
139
141
|
// add in description elements for types derived from primitive types (SecureString, etc.)
|
|
140
142
|
const doc = getDoc(program, type);
|
|
@@ -145,17 +147,19 @@ export function getSchemaForType(
|
|
|
145
147
|
}
|
|
146
148
|
if (type.kind === "Model") {
|
|
147
149
|
const schema = getSchemaForModel(dpgContext, type, usage, needRef) as any;
|
|
148
|
-
if (
|
|
149
|
-
if (
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
schema.
|
|
153
|
-
|
|
154
|
-
schema.
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
150
|
+
if (!isArrayModelType(program, type) && !isRecordModelType(program, type)) {
|
|
151
|
+
if (usage && usage.includes(SchemaContext.Output)) {
|
|
152
|
+
if (!schema.name || schema.name === "") {
|
|
153
|
+
//TODO: HANDLE ANONYMOUS
|
|
154
|
+
schema.outputTypeName =
|
|
155
|
+
schema.type === "object" ? "Record<string, any>" : "any";
|
|
156
|
+
schema.typeName =
|
|
157
|
+
schema.type === "object" ? "Record<string, unknown>" : "unknown";
|
|
158
|
+
schema.type = "unknown";
|
|
159
|
+
} else {
|
|
160
|
+
schema.outputTypeName = `${schema.name}Output`;
|
|
161
|
+
schema.typeName = `${schema.name}`;
|
|
162
|
+
}
|
|
159
163
|
}
|
|
160
164
|
}
|
|
161
165
|
schema.usage = usage;
|
|
@@ -418,6 +422,10 @@ function getSchemaForModel(
|
|
|
418
422
|
usage?: SchemaContext[],
|
|
419
423
|
needRef?: boolean
|
|
420
424
|
) {
|
|
425
|
+
if (isArrayModelType(dpgContext.program, model)) {
|
|
426
|
+
return getSchemaForArrayModel(dpgContext, model, usage!);
|
|
427
|
+
}
|
|
428
|
+
|
|
421
429
|
const program = dpgContext.program;
|
|
422
430
|
const overridedModelName =
|
|
423
431
|
getFriendlyName(program, model) ?? getProjectedName(program, model, "json");
|
|
@@ -443,7 +451,8 @@ function getSchemaForModel(
|
|
|
443
451
|
})
|
|
444
452
|
.join("") + "List";
|
|
445
453
|
}
|
|
446
|
-
|
|
454
|
+
|
|
455
|
+
const modelSchema: ObjectSchema = {
|
|
447
456
|
name: overridedModelName ?? name,
|
|
448
457
|
type: "object",
|
|
449
458
|
description: getDoc(program, model) ?? ""
|
|
@@ -455,7 +464,13 @@ function getSchemaForModel(
|
|
|
455
464
|
true /** shouldGuard */
|
|
456
465
|
);
|
|
457
466
|
|
|
467
|
+
if (modelSchema.name === "Record" && isRecordModelType(program, model)) {
|
|
468
|
+
return getSchemaForRecordModel(dpgContext, model, usage!);
|
|
469
|
+
}
|
|
458
470
|
modelSchema.typeName = modelSchema.name;
|
|
471
|
+
if (usage && usage.includes(SchemaContext.Output)) {
|
|
472
|
+
modelSchema.outputTypeName = modelSchema.name + "Output";
|
|
473
|
+
}
|
|
459
474
|
|
|
460
475
|
if (isAzureCoreErrorType(model)) {
|
|
461
476
|
modelSchema.fromCore = true;
|
|
@@ -489,6 +504,7 @@ function getSchemaForModel(
|
|
|
489
504
|
}
|
|
490
505
|
}
|
|
491
506
|
modelSchema.properties = {};
|
|
507
|
+
|
|
492
508
|
const derivedModels = model.derivedModels.filter(includeDerivedModel);
|
|
493
509
|
|
|
494
510
|
// getSchemaOrRef on all children to push them into components.schemas
|
|
@@ -545,6 +561,12 @@ function getSchemaForModel(
|
|
|
545
561
|
if (needRef) {
|
|
546
562
|
return modelSchema;
|
|
547
563
|
}
|
|
564
|
+
if (isRecordModelType(program, model)) {
|
|
565
|
+
modelSchema.parents = {
|
|
566
|
+
all: [getSchemaForRecordModel(dpgContext, model, usage!)],
|
|
567
|
+
immediate: [getSchemaForRecordModel(dpgContext, model, usage!)]
|
|
568
|
+
};
|
|
569
|
+
}
|
|
548
570
|
for (const [propName, prop] of model.properties) {
|
|
549
571
|
const restApiName = getProjectedName(program, prop, "json");
|
|
550
572
|
const name = `"${restApiName ?? propName}"`;
|
|
@@ -617,27 +639,7 @@ function getSchemaForModel(
|
|
|
617
639
|
modelSchema.properties[name] = newPropSchema;
|
|
618
640
|
}
|
|
619
641
|
|
|
620
|
-
|
|
621
|
-
// has no properties of its own, absorb the definition of the base model
|
|
622
|
-
// into this schema definition. The assumption here is that any model type
|
|
623
|
-
// defined like this is just meant to rename the underlying instance of a
|
|
624
|
-
// templated type.
|
|
625
|
-
if (
|
|
626
|
-
model.baseModel &&
|
|
627
|
-
model.baseModel.templateMapper &&
|
|
628
|
-
model.baseModel.templateMapper.args &&
|
|
629
|
-
model.baseModel.templateMapper.args.length > 0 &&
|
|
630
|
-
modelSchema.properties &&
|
|
631
|
-
Object.keys(modelSchema.properties).length === 0
|
|
632
|
-
) {
|
|
633
|
-
// Take the base model schema but carry across the documentation property
|
|
634
|
-
// that we set before
|
|
635
|
-
const baseSchema = getSchemaForType(dpgContext, model.baseModel, usage);
|
|
636
|
-
modelSchema = {
|
|
637
|
-
...baseSchema,
|
|
638
|
-
description: modelSchema.description
|
|
639
|
-
};
|
|
640
|
-
} else if (model.baseModel) {
|
|
642
|
+
if (model.baseModel) {
|
|
641
643
|
modelSchema.parents = {
|
|
642
644
|
all: [getSchemaForType(dpgContext, model.baseModel, usage, true)],
|
|
643
645
|
immediate: [getSchemaForType(dpgContext, model.baseModel, usage, true)]
|
|
@@ -647,20 +649,14 @@ function getSchemaForModel(
|
|
|
647
649
|
}
|
|
648
650
|
// Map an typespec type to an OA schema. Returns undefined when the resulting
|
|
649
651
|
// OA schema is just a regular object schema.
|
|
650
|
-
function
|
|
651
|
-
dpgContext: SdkContext,
|
|
652
|
-
type: Type,
|
|
653
|
-
usage?: SchemaContext[]
|
|
654
|
-
): any {
|
|
652
|
+
function getSchemaForLiteral(type: Type): any {
|
|
655
653
|
switch (type.kind) {
|
|
656
654
|
case "Number":
|
|
657
|
-
return { type: `${type.value}
|
|
655
|
+
return { type: `${type.value}`, isConstant: true };
|
|
658
656
|
case "String":
|
|
659
|
-
return { type: `"${type.value}"
|
|
657
|
+
return { type: `"${type.value}"`, isConstant: true };
|
|
660
658
|
case "Boolean":
|
|
661
|
-
return { type: `${type.value}
|
|
662
|
-
case "Model":
|
|
663
|
-
return mapTypeSpecStdTypeToTypeScript(dpgContext, type, usage);
|
|
659
|
+
return { type: `${type.value}`, isConstant: true };
|
|
664
660
|
}
|
|
665
661
|
if (type.kind === undefined) {
|
|
666
662
|
if (typeof type === "string") {
|
|
@@ -669,6 +665,7 @@ function mapTypeSpecTypeToTypeScript(
|
|
|
669
665
|
return { type: `${type}` };
|
|
670
666
|
}
|
|
671
667
|
}
|
|
668
|
+
return undefined;
|
|
672
669
|
}
|
|
673
670
|
function applyIntrinsicDecorators(
|
|
674
671
|
program: Program,
|
|
@@ -735,7 +732,7 @@ function applyIntrinsicDecorators(
|
|
|
735
732
|
function getSchemaForEnumMember(program: Program, e: EnumMember) {
|
|
736
733
|
const value = e.value ?? e.name;
|
|
737
734
|
const type = enumMemberType(e) === "string" ? `"${value}"` : `${value}`;
|
|
738
|
-
return { type, description: getDoc(program, e) };
|
|
735
|
+
return { type, description: getDoc(program, e), isConstant: true };
|
|
739
736
|
}
|
|
740
737
|
|
|
741
738
|
function getSchemaForEnum(program: Program, e: Enum) {
|
|
@@ -774,111 +771,119 @@ function enumMemberType(member: EnumMember) {
|
|
|
774
771
|
/**
|
|
775
772
|
* Map TypeSpec intrinsic models to open api definitions
|
|
776
773
|
*/
|
|
777
|
-
function
|
|
774
|
+
function getSchemaForArrayModel(
|
|
778
775
|
dpgContext: SdkContext,
|
|
779
776
|
type: Model,
|
|
780
|
-
usage
|
|
781
|
-
)
|
|
782
|
-
const program = dpgContext
|
|
783
|
-
const indexer =
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
}
|
|
811
|
-
} else if (isUnknownType(indexer.value!)) {
|
|
812
|
-
schema.typeName = `Record<string, ${
|
|
813
|
-
valueType.typeName ?? valueType.type
|
|
814
|
-
}>`;
|
|
815
|
-
if (usage && usage.includes(SchemaContext.Output)) {
|
|
816
|
-
schema.outputTypeName = `Record<string, ${
|
|
817
|
-
valueType.outputTypeName ?? valueType.type
|
|
818
|
-
}>`;
|
|
819
|
-
}
|
|
820
|
-
} else {
|
|
821
|
-
schema.typeName = `Record<string, ${getTypeName(valueType, [
|
|
822
|
-
SchemaContext.Input
|
|
823
|
-
])}>`;
|
|
824
|
-
schema.outputTypeName = `Record<string, ${getTypeName(valueType, [
|
|
825
|
-
SchemaContext.Output
|
|
826
|
-
])}>`;
|
|
827
|
-
}
|
|
828
|
-
} else if (name === "integer") {
|
|
829
|
-
schema = {
|
|
830
|
-
type: "array",
|
|
831
|
-
items: getSchemaForType(dpgContext, indexer.value!, usage, true),
|
|
832
|
-
description: getDoc(program, type)
|
|
833
|
-
};
|
|
834
|
-
if (
|
|
835
|
-
!program.checker.isStdType(indexer.value) &&
|
|
836
|
-
!isUnknownType(indexer.value!) &&
|
|
837
|
-
indexer.value?.kind &&
|
|
838
|
-
schema.items.name &&
|
|
839
|
-
!schema.items.enum
|
|
840
|
-
) {
|
|
841
|
-
schema.typeName = `Array<${schema.items.name}>`;
|
|
842
|
-
if (usage && usage.includes(SchemaContext.Output)) {
|
|
843
|
-
schema.outputTypeName = `Array<${schema.items.name}Output>`;
|
|
844
|
-
}
|
|
777
|
+
usage: SchemaContext[]
|
|
778
|
+
) {
|
|
779
|
+
const { program } = dpgContext;
|
|
780
|
+
const { indexer } = type;
|
|
781
|
+
let schema: any = {};
|
|
782
|
+
if (!indexer) {
|
|
783
|
+
return schema;
|
|
784
|
+
}
|
|
785
|
+
if (isArrayModelType(program, type)) {
|
|
786
|
+
schema = {
|
|
787
|
+
type: "array",
|
|
788
|
+
items: getSchemaForType(dpgContext, indexer.value!, usage, true),
|
|
789
|
+
description: getDoc(program, type)
|
|
790
|
+
};
|
|
791
|
+
if (
|
|
792
|
+
!program.checker.isStdType(indexer.value) &&
|
|
793
|
+
!isUnknownType(indexer.value!) &&
|
|
794
|
+
indexer.value?.kind &&
|
|
795
|
+
schema.items.name &&
|
|
796
|
+
!schema.items.enum
|
|
797
|
+
) {
|
|
798
|
+
schema.typeName = `Array<${schema.items.name}>`;
|
|
799
|
+
if (usage && usage.includes(SchemaContext.Output)) {
|
|
800
|
+
schema.outputTypeName = `Array<${schema.items.name}Output>`;
|
|
801
|
+
}
|
|
802
|
+
} else {
|
|
803
|
+
if (schema.items.typeName) {
|
|
804
|
+
if (schema.items.type === "dictionary") {
|
|
805
|
+
schema.typeName = `${schema.items.typeName}[]`;
|
|
806
|
+
} else if (schema.items.type === "union") {
|
|
807
|
+
schema.typeName = `(${schema.items.typeName})[]`;
|
|
845
808
|
} else {
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
)
|
|
863
|
-
schema.outputTypeName = schema.items.outputTypeName
|
|
864
|
-
.split("|")
|
|
865
|
-
.map((typeName: string) => {
|
|
866
|
-
return `${typeName}[]`;
|
|
867
|
-
})
|
|
868
|
-
.join(" | ");
|
|
869
|
-
}
|
|
870
|
-
}
|
|
871
|
-
} else if (schema.items.type.includes("|")) {
|
|
872
|
-
schema.typeName = `(${schema.items.type})[]`;
|
|
873
|
-
} else {
|
|
874
|
-
schema.typeName = `${schema.items.type}[]`;
|
|
809
|
+
schema.typeName = schema.items.typeName
|
|
810
|
+
.split("|")
|
|
811
|
+
.map((typeName: string) => {
|
|
812
|
+
return `${typeName}[]`;
|
|
813
|
+
})
|
|
814
|
+
.join(" | ");
|
|
815
|
+
if (
|
|
816
|
+
schema.items.outputTypeName &&
|
|
817
|
+
usage &&
|
|
818
|
+
usage.includes(SchemaContext.Output)
|
|
819
|
+
) {
|
|
820
|
+
schema.outputTypeName = schema.items.outputTypeName
|
|
821
|
+
.split("|")
|
|
822
|
+
.map((typeName: string) => {
|
|
823
|
+
return `${typeName}[]`;
|
|
824
|
+
})
|
|
825
|
+
.join(" | ");
|
|
875
826
|
}
|
|
876
827
|
}
|
|
828
|
+
} else if (schema.items.type.includes("|")) {
|
|
829
|
+
schema.typeName = `(${schema.items.type})[]`;
|
|
830
|
+
} else {
|
|
831
|
+
schema.typeName = `${schema.items.type}[]`;
|
|
877
832
|
}
|
|
833
|
+
}
|
|
834
|
+
schema.usage = usage;
|
|
835
|
+
return schema;
|
|
836
|
+
}
|
|
837
|
+
}
|
|
878
838
|
|
|
879
|
-
|
|
880
|
-
|
|
839
|
+
function getSchemaForRecordModel(
|
|
840
|
+
dpgContext: SdkContext,
|
|
841
|
+
type: Model,
|
|
842
|
+
usage: SchemaContext[]
|
|
843
|
+
) {
|
|
844
|
+
const { program } = dpgContext;
|
|
845
|
+
const { indexer } = type;
|
|
846
|
+
let schema: any = {};
|
|
847
|
+
if (!indexer) {
|
|
848
|
+
return schema;
|
|
849
|
+
}
|
|
850
|
+
if (isRecordModelType(program, type)) {
|
|
851
|
+
const valueType = getSchemaForType(dpgContext, indexer?.value, usage, true);
|
|
852
|
+
schema = {
|
|
853
|
+
type: "dictionary",
|
|
854
|
+
additionalProperties: valueType,
|
|
855
|
+
description: getDoc(program, type)
|
|
856
|
+
};
|
|
857
|
+
if (
|
|
858
|
+
!program.checker.isStdType(indexer.value) &&
|
|
859
|
+
!isUnknownType(indexer.value!) &&
|
|
860
|
+
!isUnionType(indexer.value!)
|
|
861
|
+
) {
|
|
862
|
+
schema.typeName = `Record<string, ${valueType.typeName}>`;
|
|
863
|
+
schema.valueTypeName = valueType.name;
|
|
864
|
+
if (usage && usage.includes(SchemaContext.Output)) {
|
|
865
|
+
schema.outputTypeName = `Record<string, ${valueType.outputTypeName}>`;
|
|
866
|
+
schema.outputValueTypeName = `${valueType.outputTypeName}`;
|
|
867
|
+
}
|
|
868
|
+
} else if (isUnknownType(indexer.value!)) {
|
|
869
|
+
schema.typeName = `Record<string, ${
|
|
870
|
+
valueType.typeName ?? valueType.type
|
|
871
|
+
}>`;
|
|
872
|
+
if (usage && usage.includes(SchemaContext.Output)) {
|
|
873
|
+
schema.outputTypeName = `Record<string, ${
|
|
874
|
+
valueType.outputTypeName ?? valueType.type
|
|
875
|
+
}>`;
|
|
876
|
+
}
|
|
877
|
+
} else {
|
|
878
|
+
schema.typeName = `Record<string, ${getTypeName(valueType, [
|
|
879
|
+
SchemaContext.Input
|
|
880
|
+
])}>`;
|
|
881
|
+
schema.outputTypeName = `Record<string, ${getTypeName(valueType, [
|
|
882
|
+
SchemaContext.Output
|
|
883
|
+
])}>`;
|
|
881
884
|
}
|
|
885
|
+
schema.usage = usage;
|
|
886
|
+
return schema;
|
|
882
887
|
}
|
|
883
888
|
}
|
|
884
889
|
|