@azure-tools/typespec-ts 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/dist/src/index.d.ts +1 -5
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +148 -78
- package/dist/src/index.js.map +1 -1
- package/dist/src/lib.d.ts.map +1 -1
- package/dist/src/lib.js +4 -2
- package/dist/src/lib.js.map +1 -1
- package/dist/src/modular/buildClassicalClient.d.ts +1 -1
- package/dist/src/modular/buildClassicalClient.d.ts.map +1 -1
- package/dist/src/modular/buildClassicalClient.js +7 -6
- package/dist/src/modular/buildClassicalClient.js.map +1 -1
- package/dist/src/modular/buildClientContext.d.ts +1 -1
- package/dist/src/modular/buildClientContext.d.ts.map +1 -1
- package/dist/src/modular/buildClientContext.js +16 -7
- package/dist/src/modular/buildClientContext.js.map +1 -1
- package/dist/src/modular/buildCodeModel.d.ts.map +1 -1
- package/dist/src/modular/buildCodeModel.js +6 -6
- package/dist/src/modular/buildCodeModel.js.map +1 -1
- package/dist/src/modular/buildOperations.d.ts +2 -1
- package/dist/src/modular/buildOperations.d.ts.map +1 -1
- package/dist/src/modular/buildOperations.js +19 -25
- package/dist/src/modular/buildOperations.js.map +1 -1
- package/dist/src/modular/buildProjectFiles.d.ts +2 -2
- package/dist/src/modular/buildProjectFiles.d.ts.map +1 -1
- package/dist/src/modular/buildProjectFiles.js +284 -145
- package/dist/src/modular/buildProjectFiles.js.map +1 -1
- package/dist/src/modular/buildRootIndex.d.ts.map +1 -1
- package/dist/src/modular/buildRootIndex.js +5 -5
- package/dist/src/modular/buildRootIndex.js.map +1 -1
- package/dist/src/modular/buildSubpathIndex.d.ts.map +1 -1
- package/dist/src/modular/buildSubpathIndex.js +9 -2
- package/dist/src/modular/buildSubpathIndex.js.map +1 -1
- package/dist/src/modular/emitModels.d.ts +2 -1
- package/dist/src/modular/emitModels.d.ts.map +1 -1
- package/dist/src/modular/emitModels.js +36 -7
- package/dist/src/modular/emitModels.js.map +1 -1
- package/dist/src/modular/helpers/clientHelpers.d.ts.map +1 -1
- package/dist/src/modular/helpers/clientHelpers.js +5 -3
- package/dist/src/modular/helpers/clientHelpers.js.map +1 -1
- package/dist/src/modular/helpers/docsHelpers.d.ts +3 -0
- package/dist/src/modular/helpers/docsHelpers.d.ts.map +1 -0
- package/dist/src/modular/helpers/docsHelpers.js +10 -0
- package/dist/src/modular/helpers/docsHelpers.js.map +1 -0
- package/dist/src/modular/helpers/operationHelpers.d.ts +10 -3
- package/dist/src/modular/helpers/operationHelpers.d.ts.map +1 -1
- package/dist/src/modular/helpers/operationHelpers.js +162 -35
- package/dist/src/modular/helpers/operationHelpers.js.map +1 -1
- package/dist/src/modular/helpers/typeHelpers.d.ts.map +1 -1
- package/dist/src/modular/helpers/typeHelpers.js +6 -0
- package/dist/src/modular/helpers/typeHelpers.js.map +1 -1
- package/dist/src/transform/transform.d.ts +5 -8
- package/dist/src/transform/transform.d.ts.map +1 -1
- package/dist/src/transform/transform.js +23 -13
- package/dist/src/transform/transform.js.map +1 -1
- package/dist/src/transform/transformApiVersionInfo.d.ts +2 -1
- package/dist/src/transform/transformApiVersionInfo.d.ts.map +1 -1
- package/dist/src/transform/transformApiVersionInfo.js.map +1 -1
- package/dist/src/transform/transformHelperFunctionDetails.d.ts +2 -1
- package/dist/src/transform/transformHelperFunctionDetails.d.ts.map +1 -1
- package/dist/src/transform/transformHelperFunctionDetails.js +1 -6
- package/dist/src/transform/transformHelperFunctionDetails.js.map +1 -1
- package/dist/src/transform/transformParameters.d.ts +2 -2
- package/dist/src/transform/transformParameters.d.ts.map +1 -1
- package/dist/src/transform/transformParameters.js +4 -1
- package/dist/src/transform/transformParameters.js.map +1 -1
- package/dist/src/transform/transformPaths.d.ts +2 -2
- package/dist/src/transform/transformPaths.d.ts.map +1 -1
- package/dist/src/transform/transformPaths.js.map +1 -1
- package/dist/src/transform/transformResponses.d.ts +2 -2
- package/dist/src/transform/transformResponses.d.ts.map +1 -1
- package/dist/src/transform/transformResponses.js +5 -1
- package/dist/src/transform/transformResponses.js.map +1 -1
- package/dist/src/transform/transformSchemas.d.ts +2 -2
- package/dist/src/transform/transformSchemas.d.ts.map +1 -1
- package/dist/src/transform/transformSchemas.js.map +1 -1
- package/dist/src/transform/transformTelemetryInfo.d.ts +4 -0
- package/dist/src/transform/transformTelemetryInfo.d.ts.map +1 -0
- package/dist/src/transform/transformTelemetryInfo.js +42 -0
- package/dist/src/transform/transformTelemetryInfo.js.map +1 -0
- package/dist/src/transform/transfromRLCOptions.d.ts +4 -2
- package/dist/src/transform/transfromRLCOptions.d.ts.map +1 -1
- package/dist/src/transform/transfromRLCOptions.js +27 -13
- package/dist/src/transform/transfromRLCOptions.js.map +1 -1
- package/dist/src/utils/clientUtils.d.ts +2 -1
- package/dist/src/utils/clientUtils.d.ts.map +1 -1
- package/dist/src/utils/clientUtils.js.map +1 -1
- package/dist/src/utils/interfaces.d.ts +13 -0
- package/dist/src/utils/interfaces.d.ts.map +1 -0
- package/dist/src/utils/interfaces.js +2 -0
- package/dist/src/utils/interfaces.js.map +1 -0
- package/dist/src/utils/modelUtils.d.ts +1 -1
- package/dist/src/utils/modelUtils.d.ts.map +1 -1
- package/dist/src/utils/modelUtils.js +14 -9
- package/dist/src/utils/modelUtils.js.map +1 -1
- package/dist/src/utils/operationUtil.d.ts +4 -4
- package/dist/src/utils/operationUtil.d.ts.map +1 -1
- package/dist/src/utils/operationUtil.js +1 -1
- package/dist/src/utils/operationUtil.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +28 -18
- package/src/index.ts +231 -129
- package/src/lib.ts +4 -2
- package/src/modular/buildClassicalClient.ts +10 -7
- package/src/modular/buildClientContext.ts +18 -8
- package/src/modular/buildCodeModel.ts +7 -9
- package/src/modular/buildOperations.ts +25 -32
- package/src/modular/buildProjectFiles.ts +329 -162
- package/src/modular/buildRootIndex.ts +5 -7
- package/src/modular/buildSubpathIndex.ts +9 -2
- package/src/modular/emitModels.ts +47 -5
- package/src/modular/helpers/clientHelpers.ts +5 -3
- package/src/modular/helpers/docsHelpers.ts +10 -0
- package/src/modular/helpers/operationHelpers.ts +277 -36
- package/src/modular/helpers/typeHelpers.ts +6 -0
- package/src/transform/transform.ts +24 -31
- package/src/transform/transformApiVersionInfo.ts +1 -1
- package/src/transform/transformHelperFunctionDetails.ts +2 -7
- package/src/transform/transformParameters.ts +15 -12
- package/src/transform/transformPaths.ts +5 -5
- package/src/transform/transformResponses.ts +10 -6
- package/src/transform/transformSchemas.ts +2 -2
- package/src/transform/transformTelemetryInfo.ts +72 -0
- package/src/transform/transfromRLCOptions.ts +34 -15
- package/src/utils/clientUtils.ts +2 -4
- package/src/utils/interfaces.ts +14 -0
- package/src/utils/modelUtils.ts +17 -8
- package/src/utils/operationUtil.ts +5 -6
- package/dist/src/modular/helpers/fixmeHelpers.d.ts +0 -2
- package/dist/src/modular/helpers/fixmeHelpers.d.ts.map +0 -1
- package/dist/src/modular/helpers/fixmeHelpers.js +0 -4
- package/dist/src/modular/helpers/fixmeHelpers.js.map +0 -1
- package/dist/src/modular/helpers/parameterHelpers.d.ts +0 -3
- package/dist/src/modular/helpers/parameterHelpers.d.ts.map +0 -1
- package/dist/src/modular/helpers/parameterHelpers.js +0 -16
- package/dist/src/modular/helpers/parameterHelpers.js.map +0 -1
- package/src/modular/helpers/fixmeHelpers.ts +0 -3
- package/src/modular/helpers/parameterHelpers.ts +0 -17
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { Project, SourceFile } from "ts-morph";
|
|
2
2
|
import { getType } from "./helpers/typeHelpers.js";
|
|
3
|
-
import { ModularCodeModel, Type } from "./modularCodeModel.js";
|
|
3
|
+
import { Client, ModularCodeModel, Type } from "./modularCodeModel.js";
|
|
4
4
|
import * as path from "path";
|
|
5
|
+
import { getDocsFromDescription } from "./helpers/docsHelpers.js";
|
|
6
|
+
import { buildOperationOptions } from "./buildOperations.js";
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
* This function creates the file containing all the models defined in TypeSpec
|
|
@@ -13,7 +15,7 @@ export function buildModels(
|
|
|
13
15
|
subfolder: string = ""
|
|
14
16
|
): SourceFile {
|
|
15
17
|
const modelsFile = project.createSourceFile(
|
|
16
|
-
path.join(`${srcPath}
|
|
18
|
+
path.join(`${srcPath}/`, subfolder, `models/models.ts`)
|
|
17
19
|
);
|
|
18
20
|
|
|
19
21
|
// We are generating both models and enums here
|
|
@@ -48,7 +50,7 @@ export function buildModels(
|
|
|
48
50
|
name: model.name!,
|
|
49
51
|
isExported: true,
|
|
50
52
|
docs: [
|
|
51
|
-
model.description
|
|
53
|
+
...getDocsFromDescription(model.description),
|
|
52
54
|
// If it is a fixed enum we don't need to list the known values in the docs as the
|
|
53
55
|
// output will be a literal union which is self documenting
|
|
54
56
|
model.isFixed
|
|
@@ -68,7 +70,7 @@ export function buildModels(
|
|
|
68
70
|
modelsFile.addInterface({
|
|
69
71
|
name: model.name,
|
|
70
72
|
isExported: true,
|
|
71
|
-
docs:
|
|
73
|
+
docs: getDocsFromDescription(model.description),
|
|
72
74
|
properties: properties.map((p) => {
|
|
73
75
|
const propertyMetadata = getType(p.type);
|
|
74
76
|
let propertyTypeName = propertyMetadata.name;
|
|
@@ -82,7 +84,7 @@ export function buildModels(
|
|
|
82
84
|
}
|
|
83
85
|
return {
|
|
84
86
|
name: `"${p.clientName}"`,
|
|
85
|
-
docs:
|
|
87
|
+
docs: getDocsFromDescription(p.description),
|
|
86
88
|
hasQuestionToken: p.optional,
|
|
87
89
|
isReadonly: p.readonly,
|
|
88
90
|
type: propertyTypeName
|
|
@@ -117,3 +119,43 @@ function isAzureCoreError(t: Type) {
|
|
|
117
119
|
t.isCoreErrorType === true
|
|
118
120
|
);
|
|
119
121
|
}
|
|
122
|
+
|
|
123
|
+
export function buildModelsOptions(
|
|
124
|
+
client: Client,
|
|
125
|
+
project: Project,
|
|
126
|
+
srcPath: string = "src",
|
|
127
|
+
subfolder: string = ""
|
|
128
|
+
) {
|
|
129
|
+
const modelOptionsFile = project.createSourceFile(
|
|
130
|
+
`${srcPath}/${subfolder}/models/options.ts`,
|
|
131
|
+
undefined,
|
|
132
|
+
{
|
|
133
|
+
overwrite: true
|
|
134
|
+
}
|
|
135
|
+
);
|
|
136
|
+
for (const operationGroup of client.operationGroups) {
|
|
137
|
+
operationGroup.operations.forEach((o) => {
|
|
138
|
+
buildOperationOptions(o, modelOptionsFile);
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
modelOptionsFile.addImportDeclarations([
|
|
142
|
+
{
|
|
143
|
+
moduleSpecifier: "@azure-rest/core-client",
|
|
144
|
+
namedImports: ["OperationOptions"]
|
|
145
|
+
}
|
|
146
|
+
]);
|
|
147
|
+
|
|
148
|
+
modelOptionsFile.fixMissingImports();
|
|
149
|
+
modelOptionsFile
|
|
150
|
+
.getImportDeclarations()
|
|
151
|
+
.filter((id) => {
|
|
152
|
+
return (
|
|
153
|
+
id.isModuleSpecifierRelative() &&
|
|
154
|
+
!id.getModuleSpecifierValue().endsWith(".js")
|
|
155
|
+
);
|
|
156
|
+
})
|
|
157
|
+
.map((id) => {
|
|
158
|
+
id.setModuleSpecifier(id.getModuleSpecifierValue() + ".js");
|
|
159
|
+
return id;
|
|
160
|
+
});
|
|
161
|
+
}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { OptionalKind, ParameterDeclarationStructure } from "ts-morph";
|
|
2
2
|
import { Client } from "../modularCodeModel.js";
|
|
3
|
-
import {
|
|
3
|
+
import { getType } from "./typeHelpers.js";
|
|
4
|
+
import { getClientName } from "./namingHelpers.js";
|
|
4
5
|
|
|
5
6
|
export function getClientParameters(
|
|
6
7
|
client: Client
|
|
7
8
|
): OptionalKind<ParameterDeclarationStructure>[] {
|
|
8
|
-
const {
|
|
9
|
+
const { parameters } = client;
|
|
10
|
+
const name = getClientName(client);
|
|
9
11
|
const optionsParam = {
|
|
10
12
|
name: "options",
|
|
11
13
|
type: `${name}ClientOptions`,
|
|
@@ -22,7 +24,7 @@ export function getClientParameters(
|
|
|
22
24
|
.map<OptionalKind<ParameterDeclarationStructure>>((p) => {
|
|
23
25
|
return {
|
|
24
26
|
name: p.clientName,
|
|
25
|
-
type:
|
|
27
|
+
type: getType(p.type).name
|
|
26
28
|
};
|
|
27
29
|
}),
|
|
28
30
|
optionsParam
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function getFixmeForMultilineDocs(fixme: string[]): string[] {
|
|
2
|
+
return fixme.map((fixme) => ` @fixme ${fixme}`);
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function getDocsFromDescription(description?: string): string[] {
|
|
6
|
+
if (!description || description.trim().length === 0) {
|
|
7
|
+
return [];
|
|
8
|
+
}
|
|
9
|
+
return [description];
|
|
10
|
+
}
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
import { toPascalCase } from "../../utils/casingUtils.js";
|
|
7
7
|
import {
|
|
8
8
|
BodyParameter,
|
|
9
|
+
ModularCodeModel,
|
|
9
10
|
Operation,
|
|
10
11
|
Parameter,
|
|
11
12
|
Property,
|
|
@@ -20,7 +21,10 @@ import {
|
|
|
20
21
|
normalizeName
|
|
21
22
|
} from "@azure-tools/rlc-common";
|
|
22
23
|
import { getOperationName } from "./namingHelpers.js";
|
|
23
|
-
import {
|
|
24
|
+
import {
|
|
25
|
+
getFixmeForMultilineDocs,
|
|
26
|
+
getDocsFromDescription
|
|
27
|
+
} from "./docsHelpers.js";
|
|
24
28
|
|
|
25
29
|
function getRLCResponseType(rlcResponse?: OperationResponse) {
|
|
26
30
|
if (!rlcResponse?.responses) {
|
|
@@ -41,11 +45,9 @@ function getRLCResponseType(rlcResponse?: OperationResponse) {
|
|
|
41
45
|
|
|
42
46
|
export function getSendPrivateFunction(
|
|
43
47
|
operation: Operation,
|
|
44
|
-
clientType: string
|
|
48
|
+
clientType: string,
|
|
49
|
+
importSet: Map<string, Set<string>>
|
|
45
50
|
): OptionalKind<FunctionDeclarationStructure> {
|
|
46
|
-
if (operation.name === "uploadTestFile") {
|
|
47
|
-
operation;
|
|
48
|
-
}
|
|
49
51
|
const parameters = getOperationSignatureParameters(operation, clientType);
|
|
50
52
|
const { name } = getOperationName(operation);
|
|
51
53
|
|
|
@@ -65,7 +67,8 @@ export function getSendPrivateFunction(
|
|
|
65
67
|
`return context.path("${operationPath}", ${getPathParameters(
|
|
66
68
|
operation
|
|
67
69
|
)}).${operationMethod}({...operationOptionsToRequestParameters(options), ${getRequestParameters(
|
|
68
|
-
operation
|
|
70
|
+
operation,
|
|
71
|
+
importSet
|
|
69
72
|
)}});`
|
|
70
73
|
);
|
|
71
74
|
|
|
@@ -78,7 +81,8 @@ export function getSendPrivateFunction(
|
|
|
78
81
|
export function getDeserializePrivateFunction(
|
|
79
82
|
operation: Operation,
|
|
80
83
|
needSubClient: boolean,
|
|
81
|
-
needUnexpectedHelper: boolean
|
|
84
|
+
needUnexpectedHelper: boolean,
|
|
85
|
+
importSet: Map<string, Set<string>>
|
|
82
86
|
): OptionalKind<FunctionDeclarationStructure> {
|
|
83
87
|
const { name } = getOperationName(operation);
|
|
84
88
|
|
|
@@ -126,12 +130,21 @@ export function getDeserializePrivateFunction(
|
|
|
126
130
|
statements.push(`return result.body`);
|
|
127
131
|
} else if (response?.type?.elementType) {
|
|
128
132
|
statements.push(
|
|
129
|
-
`return ${deserializeResponseValue(
|
|
133
|
+
`return ${deserializeResponseValue(
|
|
134
|
+
response.type,
|
|
135
|
+
"result.body",
|
|
136
|
+
importSet,
|
|
137
|
+
response.type.nullable !== undefined ? !response.type.nullable : false
|
|
138
|
+
)}`
|
|
130
139
|
);
|
|
131
140
|
} else if (response?.type?.properties) {
|
|
132
141
|
statements.push(
|
|
133
142
|
`return {`,
|
|
134
|
-
getResponseMapping(
|
|
143
|
+
getResponseMapping(
|
|
144
|
+
response.type.properties ?? [],
|
|
145
|
+
"result.body",
|
|
146
|
+
importSet
|
|
147
|
+
).join(","),
|
|
135
148
|
`}`
|
|
136
149
|
);
|
|
137
150
|
} else if (returnType.type === "void") {
|
|
@@ -223,7 +236,10 @@ export function getOperationFunction(
|
|
|
223
236
|
|
|
224
237
|
const { name, fixme = [] } = getOperationName(operation);
|
|
225
238
|
const functionStatement: OptionalKind<FunctionDeclarationStructure> = {
|
|
226
|
-
docs: [
|
|
239
|
+
docs: [
|
|
240
|
+
...getDocsFromDescription(operation.description),
|
|
241
|
+
...getFixmeForMultilineDocs(fixme)
|
|
242
|
+
],
|
|
227
243
|
isAsync: true,
|
|
228
244
|
isExported: true,
|
|
229
245
|
name: normalizeName(operation.name, NameType.Operation, true),
|
|
@@ -255,7 +271,10 @@ export function getOperationOptionsName(operation: Operation) {
|
|
|
255
271
|
* RLC internally. This will translate High Level parameters into the RLC ones.
|
|
256
272
|
* Figuring out what goes in headers, body, path and qsp.
|
|
257
273
|
*/
|
|
258
|
-
function getRequestParameters(
|
|
274
|
+
function getRequestParameters(
|
|
275
|
+
operation: Operation,
|
|
276
|
+
importSet: Map<string, Set<string>>
|
|
277
|
+
): string {
|
|
259
278
|
if (!operation.parameters) {
|
|
260
279
|
return "";
|
|
261
280
|
}
|
|
@@ -277,7 +296,9 @@ function getRequestParameters(operation: Operation): string {
|
|
|
277
296
|
|
|
278
297
|
for (const param of operationParameters) {
|
|
279
298
|
if (param.location === "header" || param.location === "query") {
|
|
280
|
-
parametersImplementation[param.location].push(
|
|
299
|
+
parametersImplementation[param.location].push(
|
|
300
|
+
getParameterMap(param, importSet)
|
|
301
|
+
);
|
|
281
302
|
}
|
|
282
303
|
}
|
|
283
304
|
|
|
@@ -299,30 +320,60 @@ function getRequestParameters(operation: Operation): string {
|
|
|
299
320
|
)}},`;
|
|
300
321
|
}
|
|
301
322
|
|
|
302
|
-
paramStr = `${paramStr}${buildBodyParameter(
|
|
323
|
+
paramStr = `${paramStr}${buildBodyParameter(
|
|
324
|
+
operation.bodyParameter,
|
|
325
|
+
importSet
|
|
326
|
+
)}`;
|
|
303
327
|
|
|
304
328
|
return paramStr;
|
|
305
329
|
}
|
|
306
330
|
|
|
307
|
-
function buildBodyParameter(
|
|
331
|
+
function buildBodyParameter(
|
|
332
|
+
bodyParameter: BodyParameter | undefined,
|
|
333
|
+
importSet: Map<string, Set<string>>
|
|
334
|
+
) {
|
|
308
335
|
if (!bodyParameter) {
|
|
309
336
|
return "";
|
|
310
337
|
}
|
|
311
338
|
|
|
312
339
|
if (bodyParameter.type.type === "model") {
|
|
313
340
|
const bodyParts: string[] = [];
|
|
341
|
+
let hasSerializeBody = false;
|
|
314
342
|
for (const param of bodyParameter?.type.properties?.filter(
|
|
315
343
|
(p) => !p.readonly
|
|
316
344
|
) ?? []) {
|
|
317
|
-
|
|
345
|
+
if (param.type.type === "model" && isRequired(param)) {
|
|
346
|
+
hasSerializeBody = true;
|
|
347
|
+
bodyParts.push(
|
|
348
|
+
...getRequestModelMapping(param.type, param.clientName, importSet)
|
|
349
|
+
);
|
|
350
|
+
} else {
|
|
351
|
+
bodyParts.push(getParameterMap(param, importSet));
|
|
352
|
+
}
|
|
318
353
|
}
|
|
319
354
|
|
|
320
355
|
if (bodyParameter && bodyParameter.type.properties) {
|
|
321
|
-
|
|
356
|
+
if (hasSerializeBody) {
|
|
357
|
+
return `\nbody: {"${bodyParameter.restApiName}": {${bodyParts.join(
|
|
358
|
+
",\n"
|
|
359
|
+
)}}},`;
|
|
360
|
+
} else {
|
|
361
|
+
return `\nbody: {${bodyParts.join(",\n")}},`;
|
|
362
|
+
}
|
|
322
363
|
}
|
|
323
364
|
}
|
|
324
365
|
|
|
325
366
|
if (bodyParameter.type.type === "list") {
|
|
367
|
+
if (bodyParameter.type.elementType?.type === "model") {
|
|
368
|
+
const bodyParts = getRequestModelMapping(
|
|
369
|
+
bodyParameter.type.elementType,
|
|
370
|
+
"p",
|
|
371
|
+
importSet
|
|
372
|
+
);
|
|
373
|
+
return `\nbody: (${bodyParameter.clientName} ?? []).map((p) => { return {
|
|
374
|
+
${bodyParts.join(", ")}
|
|
375
|
+
};}),`;
|
|
376
|
+
}
|
|
326
377
|
return `\nbody: ${bodyParameter.clientName},`;
|
|
327
378
|
}
|
|
328
379
|
|
|
@@ -336,21 +387,24 @@ function buildBodyParameter(bodyParameter: BodyParameter | undefined) {
|
|
|
336
387
|
/**
|
|
337
388
|
* This function helps with renames, translating client names to rest api names
|
|
338
389
|
*/
|
|
339
|
-
function getParameterMap(
|
|
390
|
+
function getParameterMap(
|
|
391
|
+
param: Parameter | Property,
|
|
392
|
+
importSet: Map<string, Set<string>>
|
|
393
|
+
): string {
|
|
340
394
|
if (isConstant(param)) {
|
|
341
395
|
return getConstantValue(param);
|
|
342
396
|
}
|
|
343
397
|
|
|
344
398
|
if (isOptionalWithouDefault(param)) {
|
|
345
|
-
return getOptionalWithoutDefault(param);
|
|
399
|
+
return getOptionalWithoutDefault(param, importSet);
|
|
346
400
|
}
|
|
347
401
|
|
|
348
402
|
if (isOptionalWithDefault(param)) {
|
|
349
|
-
return getOptionalWithDefault(param);
|
|
403
|
+
return getOptionalWithDefault(param, importSet);
|
|
350
404
|
}
|
|
351
405
|
|
|
352
406
|
if (isRequired(param)) {
|
|
353
|
-
return getRequired(param);
|
|
407
|
+
return getRequired(param, importSet);
|
|
354
408
|
}
|
|
355
409
|
|
|
356
410
|
throw new Error(`Parameter ${param.clientName} is not supported`);
|
|
@@ -388,7 +442,14 @@ function isRequired(param: Parameter | Property): param is RequiredType {
|
|
|
388
442
|
return !param.optional;
|
|
389
443
|
}
|
|
390
444
|
|
|
391
|
-
function getRequired(param: RequiredType) {
|
|
445
|
+
function getRequired(param: RequiredType, importSet: Map<string, Set<string>>) {
|
|
446
|
+
if (param.type.type === "model") {
|
|
447
|
+
return `"${param.restApiName}": ${getRequestModelMapping(
|
|
448
|
+
param.type,
|
|
449
|
+
param.clientName,
|
|
450
|
+
importSet
|
|
451
|
+
).join(",")}`;
|
|
452
|
+
}
|
|
392
453
|
return `"${param.restApiName}": ${param.clientName}`;
|
|
393
454
|
}
|
|
394
455
|
|
|
@@ -423,7 +484,17 @@ function isOptionalWithouDefault(
|
|
|
423
484
|
): param is OptionalWithoutDefaultType {
|
|
424
485
|
return Boolean(param.optional && !param.clientDefaultValue);
|
|
425
486
|
}
|
|
426
|
-
function getOptionalWithoutDefault(
|
|
487
|
+
function getOptionalWithoutDefault(
|
|
488
|
+
param: OptionalWithoutDefaultType,
|
|
489
|
+
importSet: Map<string, Set<string>>
|
|
490
|
+
) {
|
|
491
|
+
if (param.type.type === "model") {
|
|
492
|
+
return `"${param.restApiName}": {${getRequestModelMapping(
|
|
493
|
+
param.type,
|
|
494
|
+
"options?." + param.clientName + "?",
|
|
495
|
+
importSet
|
|
496
|
+
).join(", ")}}`;
|
|
497
|
+
}
|
|
427
498
|
return `"${param.restApiName}": options?.${param.clientName}`;
|
|
428
499
|
}
|
|
429
500
|
|
|
@@ -436,7 +507,17 @@ function isOptionalWithDefault(
|
|
|
436
507
|
return Boolean(param.clientDefaultValue);
|
|
437
508
|
}
|
|
438
509
|
|
|
439
|
-
function getOptionalWithDefault(
|
|
510
|
+
function getOptionalWithDefault(
|
|
511
|
+
param: OptionalWithDefaultType,
|
|
512
|
+
importSet: Map<string, Set<string>>
|
|
513
|
+
) {
|
|
514
|
+
if (param.type.type === "model") {
|
|
515
|
+
return `"${param.restApiName}": {${getRequestModelMapping(
|
|
516
|
+
param.type,
|
|
517
|
+
"options?." + param.clientName,
|
|
518
|
+
importSet
|
|
519
|
+
).join(", ")}} ?? ${getQuotedValue(param)}`;
|
|
520
|
+
}
|
|
440
521
|
return `"${param.restApiName}": options.${
|
|
441
522
|
param.clientName
|
|
442
523
|
} ?? ${getQuotedValue(param)}`;
|
|
@@ -500,29 +581,94 @@ function getNullableCheck(name: string, type: Type) {
|
|
|
500
581
|
|
|
501
582
|
return `${name} === null ? null :`;
|
|
502
583
|
}
|
|
584
|
+
|
|
585
|
+
/**
|
|
586
|
+
*
|
|
587
|
+
* This function helps translating an HLC request to RLC request,
|
|
588
|
+
* extracting properties from body and headers and building the RLC response object
|
|
589
|
+
*/
|
|
590
|
+
function getRequestModelMapping(
|
|
591
|
+
modelPropertyType: Type,
|
|
592
|
+
propertyPath: string = "body",
|
|
593
|
+
importSet: Map<string, Set<string>>
|
|
594
|
+
) {
|
|
595
|
+
if (!modelPropertyType.properties || !modelPropertyType.properties) {
|
|
596
|
+
return [];
|
|
597
|
+
}
|
|
598
|
+
const props: string[] = [];
|
|
599
|
+
const properties: Property[] = modelPropertyType.properties;
|
|
600
|
+
for (const property of properties) {
|
|
601
|
+
if (property.readonly) {
|
|
602
|
+
continue;
|
|
603
|
+
}
|
|
604
|
+
const propertyFullName = `${propertyPath}.${property.restApiName}`;
|
|
605
|
+
if (property.type.type === "model") {
|
|
606
|
+
let definition;
|
|
607
|
+
if (property.type.isCoreErrorType) {
|
|
608
|
+
definition = `"${property.restApiName}": ${getNullableCheck(
|
|
609
|
+
propertyFullName,
|
|
610
|
+
property.type
|
|
611
|
+
)} ${
|
|
612
|
+
!property.optional ? "" : `!${propertyFullName} ? undefined :`
|
|
613
|
+
} ${propertyFullName}`;
|
|
614
|
+
} else {
|
|
615
|
+
definition = `"${property.restApiName}": ${getNullableCheck(
|
|
616
|
+
propertyFullName,
|
|
617
|
+
property.type
|
|
618
|
+
)} ${
|
|
619
|
+
!property.optional ? "" : `!${propertyFullName} ? undefined :`
|
|
620
|
+
} {${getRequestModelMapping(
|
|
621
|
+
property.type,
|
|
622
|
+
`${propertyPath}.${property.restApiName}${
|
|
623
|
+
property.optional ? "?" : ""
|
|
624
|
+
}`,
|
|
625
|
+
importSet
|
|
626
|
+
)}}`;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
props.push(definition);
|
|
630
|
+
} else {
|
|
631
|
+
const dot = propertyPath.endsWith("?") ? "." : "";
|
|
632
|
+
const restValue = `${
|
|
633
|
+
propertyPath ? `${propertyPath}${dot}` : `${dot}`
|
|
634
|
+
}["${property.clientName}"]`;
|
|
635
|
+
props.push(
|
|
636
|
+
`"${property.restApiName}": ${serializeRequestValue(
|
|
637
|
+
property.type,
|
|
638
|
+
restValue,
|
|
639
|
+
importSet
|
|
640
|
+
)}`
|
|
641
|
+
);
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
return props;
|
|
646
|
+
}
|
|
647
|
+
|
|
503
648
|
/**
|
|
504
649
|
* This function helps translating an RLC response to an HLC response,
|
|
505
650
|
* extracting properties from body and headers and building the HLC response object
|
|
506
651
|
*/
|
|
507
|
-
function getResponseMapping(
|
|
652
|
+
export function getResponseMapping(
|
|
508
653
|
properties: Property[],
|
|
509
|
-
propertyPath: string = "result.body"
|
|
654
|
+
propertyPath: string = "result.body",
|
|
655
|
+
importSet: Map<string, Set<string>>
|
|
510
656
|
) {
|
|
511
657
|
const props: string[] = [];
|
|
512
658
|
for (const property of properties) {
|
|
513
659
|
// TODO: Do we need to also add headers in the result type?
|
|
514
|
-
const propertyFullName = `${propertyPath}.${property.
|
|
660
|
+
const propertyFullName = `${propertyPath}.${property.restApiName}`;
|
|
515
661
|
if (property.type.type === "model") {
|
|
516
662
|
let definition;
|
|
517
663
|
if (property.type.isCoreErrorType) {
|
|
518
|
-
definition = `"${property.
|
|
664
|
+
definition = `"${property.clientName}": ${getNullableCheck(
|
|
519
665
|
propertyFullName,
|
|
520
666
|
property.type
|
|
521
667
|
)} ${
|
|
522
668
|
!property.optional ? "" : `!${propertyFullName} ? undefined :`
|
|
523
669
|
} ${propertyFullName}`;
|
|
524
670
|
} else {
|
|
525
|
-
definition = `"${property.
|
|
671
|
+
definition = `"${property.clientName}": ${getNullableCheck(
|
|
526
672
|
propertyFullName,
|
|
527
673
|
property.type
|
|
528
674
|
)} ${
|
|
@@ -531,7 +677,8 @@ function getResponseMapping(
|
|
|
531
677
|
property.type.properties ?? [],
|
|
532
678
|
`${propertyPath}.${property.restApiName}${
|
|
533
679
|
property.optional ? "?" : ""
|
|
534
|
-
}
|
|
680
|
+
}`,
|
|
681
|
+
importSet
|
|
535
682
|
)}}`;
|
|
536
683
|
}
|
|
537
684
|
|
|
@@ -544,7 +691,9 @@ function getResponseMapping(
|
|
|
544
691
|
props.push(
|
|
545
692
|
`"${property.clientName}": ${deserializeResponseValue(
|
|
546
693
|
property.type,
|
|
547
|
-
restValue
|
|
694
|
+
restValue,
|
|
695
|
+
importSet,
|
|
696
|
+
property.optional !== undefined ? !property.optional : false
|
|
548
697
|
)}`
|
|
549
698
|
);
|
|
550
699
|
}
|
|
@@ -558,29 +707,100 @@ function getResponseMapping(
|
|
|
558
707
|
* We need to drill down into Array elements to make sure that the element type is
|
|
559
708
|
* deserialized correctly
|
|
560
709
|
*/
|
|
561
|
-
function deserializeResponseValue(
|
|
710
|
+
function deserializeResponseValue(
|
|
711
|
+
type: Type,
|
|
712
|
+
restValue: string,
|
|
713
|
+
importSet: Map<string, Set<string>>,
|
|
714
|
+
required: boolean
|
|
715
|
+
): string {
|
|
716
|
+
const coreUtilSet = importSet.get("@azure/core-util");
|
|
562
717
|
switch (type.type) {
|
|
563
718
|
case "datetime":
|
|
564
|
-
return
|
|
565
|
-
|
|
566
|
-
|
|
719
|
+
return required
|
|
720
|
+
? `new Date(${restValue})`
|
|
721
|
+
: `${restValue} !== undefined? new Date(${restValue}): undefined`;
|
|
722
|
+
case "combined":
|
|
723
|
+
return `${restValue} as any`;
|
|
567
724
|
case "list":
|
|
568
725
|
if (type.elementType?.type === "model") {
|
|
569
726
|
return `(${restValue} ?? []).map(p => ({${getResponseMapping(
|
|
570
727
|
type.elementType?.properties ?? [],
|
|
571
|
-
"p"
|
|
728
|
+
"p",
|
|
729
|
+
importSet
|
|
572
730
|
)}}))`;
|
|
573
731
|
} else if (
|
|
574
732
|
type.elementType?.properties?.some((p) => needsDeserialize(p.type))
|
|
575
733
|
) {
|
|
576
734
|
return `(${restValue} ?? []).map(p => ${deserializeResponseValue(
|
|
577
735
|
type.elementType!,
|
|
578
|
-
"p"
|
|
736
|
+
"p",
|
|
737
|
+
importSet,
|
|
738
|
+
required
|
|
579
739
|
)})`;
|
|
580
740
|
} else {
|
|
581
741
|
return restValue;
|
|
582
742
|
}
|
|
743
|
+
case "byte-array":
|
|
744
|
+
if (!coreUtilSet) {
|
|
745
|
+
importSet.set(
|
|
746
|
+
"@azure/core-util",
|
|
747
|
+
new Set<string>().add("stringToUint8Array")
|
|
748
|
+
);
|
|
749
|
+
} else {
|
|
750
|
+
coreUtilSet.add("stringToUint8Array");
|
|
751
|
+
}
|
|
752
|
+
return `typeof ${restValue} === 'string'
|
|
753
|
+
? stringToUint8Array(${restValue}, "${type.format ?? "base64"}")
|
|
754
|
+
: ${restValue}`;
|
|
755
|
+
default:
|
|
756
|
+
return restValue;
|
|
757
|
+
}
|
|
758
|
+
}
|
|
583
759
|
|
|
760
|
+
/**
|
|
761
|
+
* This function helps converting strings into JS complex types recursively.
|
|
762
|
+
* We need to drill down into Array elements to make sure that the element type is
|
|
763
|
+
* deserialized correctly
|
|
764
|
+
*/
|
|
765
|
+
function serializeRequestValue(
|
|
766
|
+
type: Type,
|
|
767
|
+
restValue: string,
|
|
768
|
+
importSet: Map<string, Set<string>> = new Map<string, Set<string>>()
|
|
769
|
+
): string {
|
|
770
|
+
const coreUtilSet = importSet.get("@azure/core-util");
|
|
771
|
+
switch (type.type) {
|
|
772
|
+
case "datetime":
|
|
773
|
+
return `${restValue} !== undefined ? new Date(${restValue}): undefined`;
|
|
774
|
+
case "list":
|
|
775
|
+
if (type.elementType?.type === "model") {
|
|
776
|
+
return `(${restValue} ?? []).map(p => ({${getResponseMapping(
|
|
777
|
+
type.elementType?.properties ?? [],
|
|
778
|
+
"p",
|
|
779
|
+
importSet
|
|
780
|
+
)}}))`;
|
|
781
|
+
} else if (
|
|
782
|
+
type.elementType?.properties?.some((p) => needsDeserialize(p.type))
|
|
783
|
+
) {
|
|
784
|
+
return `(${restValue} ?? []).map(p => ${serializeRequestValue(
|
|
785
|
+
type.elementType!,
|
|
786
|
+
"p",
|
|
787
|
+
importSet
|
|
788
|
+
)})`;
|
|
789
|
+
} else {
|
|
790
|
+
return restValue;
|
|
791
|
+
}
|
|
792
|
+
case "byte-array":
|
|
793
|
+
if (!coreUtilSet) {
|
|
794
|
+
importSet.set(
|
|
795
|
+
"@azure/core-util",
|
|
796
|
+
new Set<string>().add("uint8ArrayToString")
|
|
797
|
+
);
|
|
798
|
+
} else {
|
|
799
|
+
coreUtilSet.add("uint8ArrayToString");
|
|
800
|
+
}
|
|
801
|
+
return `${restValue} !== undefined ? uint8ArrayToString(${restValue}, "${
|
|
802
|
+
type.format ?? "base64"
|
|
803
|
+
}"): undefined`;
|
|
584
804
|
default:
|
|
585
805
|
return restValue;
|
|
586
806
|
}
|
|
@@ -589,3 +809,24 @@ function deserializeResponseValue(type: Type, restValue: string): string {
|
|
|
589
809
|
function needsDeserialize(type?: Type) {
|
|
590
810
|
return type?.type === "datetime" || type?.type === "model";
|
|
591
811
|
}
|
|
812
|
+
|
|
813
|
+
export function hasLROOperation(codeModel: ModularCodeModel) {
|
|
814
|
+
return (codeModel.clients ?? []).some((c) =>
|
|
815
|
+
(c.operationGroups ?? []).some((og) =>
|
|
816
|
+
(og.operations ?? []).some(
|
|
817
|
+
(op) => op.discriminator === "lro" || op.discriminator === "lropaging"
|
|
818
|
+
)
|
|
819
|
+
)
|
|
820
|
+
);
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
export function hasPagingOperation(codeModel: ModularCodeModel) {
|
|
824
|
+
return (codeModel.clients ?? []).some((c) =>
|
|
825
|
+
(c.operationGroups ?? []).some((og) =>
|
|
826
|
+
(og.operations ?? []).some(
|
|
827
|
+
(op) =>
|
|
828
|
+
op.discriminator === "paging" || op.discriminator === "lropaging"
|
|
829
|
+
)
|
|
830
|
+
)
|
|
831
|
+
);
|
|
832
|
+
}
|
|
@@ -23,6 +23,12 @@ export function getType(type: Type): TypeMetadata {
|
|
|
23
23
|
originModule: "@azure/core-auth",
|
|
24
24
|
isRelative: false
|
|
25
25
|
};
|
|
26
|
+
case "OAuth2":
|
|
27
|
+
return {
|
|
28
|
+
name: "TokenCredential",
|
|
29
|
+
originModule: "@azure/core-auth",
|
|
30
|
+
isRelative: false
|
|
31
|
+
};
|
|
26
32
|
case "boolean":
|
|
27
33
|
return { name: getNullableType(type.type, type) };
|
|
28
34
|
case "constant": {
|