@azure-tools/typespec-ts 0.36.0 → 0.37.0-alpha.20241230.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 +14 -0
- package/dist/src/contextManager.d.ts +1 -2
- package/dist/src/contextManager.d.ts.map +1 -1
- package/dist/src/contextManager.js.map +1 -1
- package/dist/src/framework/load-static-helpers.d.ts +2 -1
- package/dist/src/framework/load-static-helpers.d.ts.map +1 -1
- package/dist/src/framework/load-static-helpers.js +17 -0
- package/dist/src/framework/load-static-helpers.js.map +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +31 -29
- package/dist/src/index.js.map +1 -1
- package/dist/src/lib.js +1 -1
- package/dist/src/lib.js.map +1 -1
- package/dist/src/metaTree.d.ts +0 -5
- package/dist/src/metaTree.d.ts.map +1 -1
- package/dist/src/modular/buildClassicalClient.d.ts +3 -2
- package/dist/src/modular/buildClassicalClient.d.ts.map +1 -1
- package/dist/src/modular/buildClassicalClient.js +64 -62
- package/dist/src/modular/buildClassicalClient.js.map +1 -1
- package/dist/src/modular/buildClassicalOperationGroups.d.ts +3 -2
- package/dist/src/modular/buildClassicalOperationGroups.d.ts.map +1 -1
- package/dist/src/modular/buildClassicalOperationGroups.js +35 -27
- package/dist/src/modular/buildClassicalOperationGroups.js.map +1 -1
- package/dist/src/modular/buildClientContext.d.ts +4 -3
- package/dist/src/modular/buildClientContext.d.ts.map +1 -1
- package/dist/src/modular/buildClientContext.js +84 -35
- package/dist/src/modular/buildClientContext.js.map +1 -1
- package/dist/src/modular/buildModularOptions.d.ts +7 -0
- package/dist/src/modular/buildModularOptions.d.ts.map +1 -0
- package/dist/src/modular/buildModularOptions.js +16 -0
- package/dist/src/modular/buildModularOptions.js.map +1 -0
- package/dist/src/modular/buildOperations.d.ts +6 -4
- package/dist/src/modular/buildOperations.d.ts.map +1 -1
- package/dist/src/modular/buildOperations.js +56 -55
- package/dist/src/modular/buildOperations.js.map +1 -1
- package/dist/src/modular/buildProjectFiles.d.ts +3 -2
- package/dist/src/modular/buildProjectFiles.d.ts.map +1 -1
- package/dist/src/modular/buildProjectFiles.js +18 -16
- package/dist/src/modular/buildProjectFiles.js.map +1 -1
- package/dist/src/modular/buildRestorePoller.d.ts +4 -2
- package/dist/src/modular/buildRestorePoller.d.ts.map +1 -1
- package/dist/src/modular/buildRestorePoller.js +22 -18
- package/dist/src/modular/buildRestorePoller.js.map +1 -1
- package/dist/src/modular/buildRootIndex.d.ts +4 -3
- package/dist/src/modular/buildRootIndex.d.ts.map +1 -1
- package/dist/src/modular/buildRootIndex.js +40 -31
- package/dist/src/modular/buildRootIndex.js.map +1 -1
- package/dist/src/modular/buildSubpathIndex.d.ts +4 -2
- package/dist/src/modular/buildSubpathIndex.d.ts.map +1 -1
- package/dist/src/modular/buildSubpathIndex.js +8 -5
- package/dist/src/modular/buildSubpathIndex.js.map +1 -1
- package/dist/src/modular/emitLoggerFile.d.ts +2 -3
- package/dist/src/modular/emitLoggerFile.d.ts.map +1 -1
- package/dist/src/modular/emitLoggerFile.js +4 -4
- package/dist/src/modular/emitLoggerFile.js.map +1 -1
- package/dist/src/modular/emitModels.d.ts +1 -2
- package/dist/src/modular/emitModels.d.ts.map +1 -1
- package/dist/src/modular/emitModels.js +10 -3
- package/dist/src/modular/emitModels.js.map +1 -1
- package/dist/src/modular/emitModelsOptions.d.ts +3 -24
- package/dist/src/modular/emitModelsOptions.d.ts.map +1 -1
- package/dist/src/modular/emitModelsOptions.js +10 -86
- package/dist/src/modular/emitModelsOptions.js.map +1 -1
- package/dist/src/modular/emitSamples.js +2 -1
- package/dist/src/modular/emitSamples.js.map +1 -1
- package/dist/src/modular/helpers/classicalOperationHelpers.d.ts +3 -3
- package/dist/src/modular/helpers/classicalOperationHelpers.d.ts.map +1 -1
- package/dist/src/modular/helpers/classicalOperationHelpers.js +40 -50
- package/dist/src/modular/helpers/classicalOperationHelpers.js.map +1 -1
- package/dist/src/modular/helpers/clientHelpers.d.ts +11 -8
- package/dist/src/modular/helpers/clientHelpers.d.ts.map +1 -1
- package/dist/src/modular/helpers/clientHelpers.js +87 -60
- package/dist/src/modular/helpers/clientHelpers.js.map +1 -1
- package/dist/src/modular/helpers/namingHelpers.d.ts +4 -7
- package/dist/src/modular/helpers/namingHelpers.d.ts.map +1 -1
- package/dist/src/modular/helpers/namingHelpers.js +3 -26
- package/dist/src/modular/helpers/namingHelpers.js.map +1 -1
- package/dist/src/modular/helpers/operationHelpers.d.ts +21 -20
- package/dist/src/modular/helpers/operationHelpers.d.ts.map +1 -1
- package/dist/src/modular/helpers/operationHelpers.js +336 -291
- package/dist/src/modular/helpers/operationHelpers.js.map +1 -1
- package/dist/src/modular/helpers/typeHelpers.d.ts +4 -25
- package/dist/src/modular/helpers/typeHelpers.d.ts.map +1 -1
- package/dist/src/modular/helpers/typeHelpers.js +6 -218
- package/dist/src/modular/helpers/typeHelpers.js.map +1 -1
- package/dist/src/modular/interfaces.d.ts +15 -8
- package/dist/src/modular/interfaces.d.ts.map +1 -1
- package/dist/src/modular/serialization/buildDeserializerFunction.d.ts.map +1 -1
- package/dist/src/modular/serialization/buildDeserializerFunction.js +1 -2
- package/dist/src/modular/serialization/buildDeserializerFunction.js.map +1 -1
- package/dist/src/modular/serialization/buildSerializerFunction.d.ts.map +1 -1
- package/dist/src/modular/serialization/buildSerializerFunction.js +1 -2
- package/dist/src/modular/serialization/buildSerializerFunction.js.map +1 -1
- package/dist/src/modular/serialization/serializeUtils.d.ts +8 -5
- package/dist/src/modular/serialization/serializeUtils.d.ts.map +1 -1
- package/dist/src/modular/serialization/serializeUtils.js +22 -22
- package/dist/src/modular/serialization/serializeUtils.js.map +1 -1
- package/dist/src/utils/clientUtils.d.ts +3 -1
- package/dist/src/utils/clientUtils.d.ts.map +1 -1
- package/dist/src/utils/clientUtils.js +10 -0
- package/dist/src/utils/clientUtils.js.map +1 -1
- package/dist/src/utils/operationUtil.d.ts +6 -2
- package/dist/src/utils/operationUtil.d.ts.map +1 -1
- package/dist/src/utils/operationUtil.js +66 -7
- package/dist/src/utils/operationUtil.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/contextManager.ts +1 -2
- package/src/framework/load-static-helpers.ts +24 -1
- package/src/index.ts +65 -37
- package/src/lib.ts +1 -1
- package/src/metaTree.ts +0 -6
- package/src/modular/buildClassicalClient.ts +97 -99
- package/src/modular/buildClassicalOperationGroups.ts +53 -47
- package/src/modular/buildClientContext.ts +101 -44
- package/src/modular/buildModularOptions.ts +27 -0
- package/src/modular/buildOperations.ts +91 -78
- package/src/modular/buildProjectFiles.ts +24 -21
- package/src/modular/buildRestorePoller.ts +39 -23
- package/src/modular/buildRootIndex.ts +51 -42
- package/src/modular/buildSubpathIndex.ts +16 -7
- package/src/modular/emitLoggerFile.ts +12 -10
- package/src/modular/emitModels.ts +15 -7
- package/src/modular/emitModelsOptions.ts +18 -125
- package/src/modular/emitSamples.ts +2 -3
- package/src/modular/helpers/classicalOperationHelpers.ts +50 -75
- package/src/modular/helpers/clientHelpers.ts +107 -73
- package/src/modular/helpers/namingHelpers.ts +6 -65
- package/src/modular/helpers/operationHelpers.ts +506 -384
- package/src/modular/helpers/typeHelpers.ts +11 -267
- package/src/modular/interfaces.ts +16 -8
- package/src/modular/serialization/buildDeserializerFunction.ts +1 -6
- package/src/modular/serialization/buildSerializerFunction.ts +1 -2
- package/src/modular/serialization/serializeUtils.ts +31 -30
- package/src/utils/clientUtils.ts +23 -1
- package/src/utils/operationUtil.ts +106 -14
- package/dist/src/modular/buildCodeModel.d.ts +0 -34
- package/dist/src/modular/buildCodeModel.d.ts.map +0 -1
- package/dist/src/modular/buildCodeModel.js +0 -1489
- package/dist/src/modular/buildCodeModel.js.map +0 -1
- package/dist/src/modular/modularCodeModel.d.ts +0 -166
- package/dist/src/modular/modularCodeModel.d.ts.map +0 -1
- package/dist/src/modular/modularCodeModel.js +0 -2
- package/dist/src/modular/modularCodeModel.js.map +0 -1
- package/src/modular/buildCodeModel.ts +0 -1965
- package/src/modular/modularCodeModel.ts +0 -211
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
BodyParameter,
|
|
3
|
-
Client,
|
|
4
|
-
ModularCodeModel,
|
|
5
|
-
Operation,
|
|
6
|
-
Parameter,
|
|
7
|
-
Property,
|
|
8
|
-
Type
|
|
9
|
-
} from "../modularCodeModel.js";
|
|
10
1
|
import {
|
|
11
2
|
FunctionDeclarationStructure,
|
|
12
3
|
OptionalKind,
|
|
@@ -14,11 +5,17 @@ import {
|
|
|
14
5
|
} from "ts-morph";
|
|
15
6
|
import { NoTarget, Program } from "@typespec/compiler";
|
|
16
7
|
import { PagingHelpers, PollingHelpers } from "../static-helpers-metadata.js";
|
|
17
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
getNullableValidType,
|
|
10
|
+
isSpreadBodyParameter,
|
|
11
|
+
isTypeNullable
|
|
12
|
+
} from "./typeHelpers.js";
|
|
18
13
|
import { getClassicalLayerPrefix, getOperationName } from "./namingHelpers.js";
|
|
19
14
|
import {
|
|
20
15
|
getCollectionFormatHelper,
|
|
21
|
-
hasCollectionFormatInfo
|
|
16
|
+
hasCollectionFormatInfo,
|
|
17
|
+
isBinaryPayload,
|
|
18
|
+
ServiceOperation
|
|
22
19
|
} from "../../utils/operationUtil.js";
|
|
23
20
|
import {
|
|
24
21
|
isNormalUnion,
|
|
@@ -31,7 +28,7 @@ import {
|
|
|
31
28
|
import { toPascalCase } from "../../utils/casingUtils.js";
|
|
32
29
|
|
|
33
30
|
import { AzurePollingDependencies } from "../external-dependencies.js";
|
|
34
|
-
import { NameType } from "@azure-tools/rlc-common";
|
|
31
|
+
import { NameType, normalizeName } from "@azure-tools/rlc-common";
|
|
35
32
|
import { buildModelDeserializer } from "../serialization/buildDeserializerFunction.js";
|
|
36
33
|
import { buildModelSerializer } from "../serialization/buildSerializerFunction.js";
|
|
37
34
|
import { refkey } from "../../framework/refkey.js";
|
|
@@ -40,17 +37,38 @@ import { resolveReference } from "../../framework/reference.js";
|
|
|
40
37
|
import { useDependencies } from "../../framework/hooks/useDependencies.js";
|
|
41
38
|
import { useSdkTypes } from "../../framework/hooks/sdkTypes.js";
|
|
42
39
|
import { isAzureCoreErrorType } from "../../utils/modelUtils.js";
|
|
43
|
-
import {
|
|
40
|
+
import {
|
|
41
|
+
getTypeExpression,
|
|
42
|
+
normalizeModelPropertyName
|
|
43
|
+
} from "../type-expressions/get-type-expression.js";
|
|
44
44
|
import { SdkContext } from "../../utils/interfaces.js";
|
|
45
|
+
import {
|
|
46
|
+
isReadOnly,
|
|
47
|
+
SdkBodyParameter,
|
|
48
|
+
SdkClientType,
|
|
49
|
+
SdkConstantType,
|
|
50
|
+
SdkHttpOperation,
|
|
51
|
+
SdkHttpParameter,
|
|
52
|
+
SdkLroPagingServiceMethod,
|
|
53
|
+
SdkLroServiceMethod,
|
|
54
|
+
SdkMethod,
|
|
55
|
+
SdkModelPropertyType,
|
|
56
|
+
SdkModelType,
|
|
57
|
+
SdkPagingServiceMethod,
|
|
58
|
+
SdkServiceParameter,
|
|
59
|
+
SdkType
|
|
60
|
+
} from "@azure-tools/typespec-client-generator-core";
|
|
45
61
|
|
|
46
62
|
export function getSendPrivateFunction(
|
|
47
63
|
dpgContext: SdkContext,
|
|
48
|
-
|
|
64
|
+
client: SdkClientType<SdkHttpOperation>,
|
|
65
|
+
method: [string[], ServiceOperation],
|
|
49
66
|
clientType: string
|
|
50
67
|
): OptionalKind<FunctionDeclarationStructure> {
|
|
68
|
+
const operation = method[1];
|
|
51
69
|
const parameters = getOperationSignatureParameters(
|
|
52
70
|
dpgContext,
|
|
53
|
-
|
|
71
|
+
method,
|
|
54
72
|
clientType
|
|
55
73
|
);
|
|
56
74
|
const { name } = getOperationName(operation);
|
|
@@ -64,20 +82,31 @@ export function getSendPrivateFunction(
|
|
|
64
82
|
returnType: resolveReference(dependencies.StreamableMethod)
|
|
65
83
|
};
|
|
66
84
|
|
|
67
|
-
const operationPath = operation.
|
|
68
|
-
const operationMethod = operation.
|
|
69
|
-
const optionalParamName = parameters
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
85
|
+
const operationPath = operation.operation.path;
|
|
86
|
+
const operationMethod = operation.operation.verb.toLowerCase();
|
|
87
|
+
const optionalParamName = getOptionalParamsName(parameters);
|
|
88
|
+
const hasQueryApiVersion = operation.operation.parameters.some(
|
|
89
|
+
(p) => p.isApiVersionParam && p.onClient && p.kind === "query"
|
|
90
|
+
);
|
|
91
|
+
const hasClientApiVersion = client.initialization.properties.some(
|
|
92
|
+
(p) => p.isApiVersionParam && p.onClient && p.kind === "method"
|
|
93
|
+
);
|
|
73
94
|
const statements: string[] = [];
|
|
95
|
+
if (hasClientApiVersion && !hasQueryApiVersion) {
|
|
96
|
+
statements.push(
|
|
97
|
+
`context.pipeline.removePolicy({ name: "ClientApiVersionPolicy"});`
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
74
101
|
statements.push(
|
|
75
102
|
`return context.path("${operationPath}", ${getPathParameters(
|
|
76
103
|
dpgContext,
|
|
77
|
-
operation
|
|
104
|
+
operation,
|
|
105
|
+
optionalParamName
|
|
78
106
|
)}).${operationMethod}({...${resolveReference(dependencies.operationOptionsToRequestParameters)}(${optionalParamName}), ${getRequestParameters(
|
|
79
107
|
dpgContext,
|
|
80
|
-
operation
|
|
108
|
+
operation,
|
|
109
|
+
optionalParamName
|
|
81
110
|
)}});`
|
|
82
111
|
);
|
|
83
112
|
|
|
@@ -89,7 +118,7 @@ export function getSendPrivateFunction(
|
|
|
89
118
|
|
|
90
119
|
export function getDeserializePrivateFunction(
|
|
91
120
|
context: SdkContext,
|
|
92
|
-
operation:
|
|
121
|
+
operation: ServiceOperation
|
|
93
122
|
): OptionalKind<FunctionDeclarationStructure> {
|
|
94
123
|
const { name } = getOperationName(operation);
|
|
95
124
|
const dependencies = useDependencies();
|
|
@@ -108,14 +137,15 @@ export function getDeserializePrivateFunction(
|
|
|
108
137
|
|
|
109
138
|
// TODO: Support operation overloads
|
|
110
139
|
// TODO: Support multiple responses
|
|
111
|
-
const response = operation.
|
|
140
|
+
const response = operation.response;
|
|
141
|
+
const restResponse = operation.operation.responses[0];
|
|
112
142
|
let returnType;
|
|
113
|
-
if (isLroOnly && operation.
|
|
143
|
+
if (isLroOnly && operation.operation.verb.toLowerCase() !== "patch") {
|
|
114
144
|
returnType = buildLroReturnType(context, operation);
|
|
115
|
-
} else if (response
|
|
145
|
+
} else if (response.type && restResponse) {
|
|
116
146
|
returnType = {
|
|
117
|
-
name:
|
|
118
|
-
type: getTypeExpression(context,
|
|
147
|
+
name: (restResponse as any).name ?? "",
|
|
148
|
+
type: getTypeExpression(context, restResponse.type!)
|
|
119
149
|
};
|
|
120
150
|
} else {
|
|
121
151
|
returnType = { name: "", type: "void" };
|
|
@@ -142,16 +172,18 @@ export function getDeserializePrivateFunction(
|
|
|
142
172
|
"}"
|
|
143
173
|
);
|
|
144
174
|
const deserializedType = isLroOnly
|
|
145
|
-
? operation?.lroMetadata?.
|
|
146
|
-
:
|
|
147
|
-
|
|
175
|
+
? operation?.lroMetadata?.finalResponse?.result
|
|
176
|
+
: restResponse
|
|
177
|
+
? restResponse.type
|
|
178
|
+
: response.type;
|
|
179
|
+
const lroSubPath = isLroOnly
|
|
180
|
+
? operation?.lroMetadata?.finalResponse?.resultPath
|
|
181
|
+
: undefined;
|
|
148
182
|
|
|
149
183
|
const deserializePrefix = "result.body";
|
|
150
184
|
|
|
151
|
-
const deserializedRoot =
|
|
152
|
-
|
|
153
|
-
: `${deserializePrefix}`;
|
|
154
|
-
if (isLroOnly && hasLroSubPath) {
|
|
185
|
+
const deserializedRoot = `${deserializePrefix}${lroSubPath ? "." + lroSubPath : ""}`;
|
|
186
|
+
if (isLroOnly && lroSubPath) {
|
|
155
187
|
statements.push(
|
|
156
188
|
`if(${deserializedRoot.split(".").join("?.")} === undefined) {
|
|
157
189
|
throw createRestError(\`Expected a result in the response at position "${deserializedRoot}"\`, result);
|
|
@@ -160,10 +192,11 @@ export function getDeserializePrivateFunction(
|
|
|
160
192
|
);
|
|
161
193
|
}
|
|
162
194
|
|
|
163
|
-
if (deserializedType
|
|
195
|
+
if (deserializedType) {
|
|
196
|
+
const contentTypes = operation.operation.responses[0]?.contentTypes;
|
|
164
197
|
const deserializeFunctionName = buildModelDeserializer(
|
|
165
198
|
context,
|
|
166
|
-
deserializedType
|
|
199
|
+
deserializedType,
|
|
167
200
|
false,
|
|
168
201
|
true
|
|
169
202
|
);
|
|
@@ -177,21 +210,14 @@ export function getDeserializePrivateFunction(
|
|
|
177
210
|
context,
|
|
178
211
|
deserializedType,
|
|
179
212
|
deserializedRoot,
|
|
180
|
-
response.
|
|
213
|
+
isBinaryPayload(context, response.type!.__raw!, contentTypes!)
|
|
214
|
+
? "binary"
|
|
215
|
+
: getEncodeForType(deserializedType)
|
|
181
216
|
)}`
|
|
182
217
|
);
|
|
183
218
|
}
|
|
184
219
|
} else if (returnType.type === "void") {
|
|
185
220
|
statements.push("return;");
|
|
186
|
-
} else if (deserializedType) {
|
|
187
|
-
statements.push(
|
|
188
|
-
`return ${deserializeResponseValue(
|
|
189
|
-
context,
|
|
190
|
-
deserializedType,
|
|
191
|
-
deserializedRoot,
|
|
192
|
-
response.isBinaryPayload ? "binary" : deserializedType.format
|
|
193
|
-
)}`
|
|
194
|
-
);
|
|
195
221
|
} else {
|
|
196
222
|
statements.push("return;");
|
|
197
223
|
}
|
|
@@ -202,12 +228,22 @@ export function getDeserializePrivateFunction(
|
|
|
202
228
|
};
|
|
203
229
|
}
|
|
204
230
|
|
|
231
|
+
function getOptionalParamsName(
|
|
232
|
+
parameters: OptionalKind<ParameterDeclarationStructure>[]
|
|
233
|
+
) {
|
|
234
|
+
return (
|
|
235
|
+
parameters.filter((p) => p.type?.toString().endsWith("OptionalParams"))[0]
|
|
236
|
+
?.name ?? "options"
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
|
|
205
240
|
function getOperationSignatureParameters(
|
|
206
241
|
context: SdkContext,
|
|
207
|
-
|
|
242
|
+
method: [string[], ServiceOperation],
|
|
208
243
|
clientType: string
|
|
209
244
|
): OptionalKind<ParameterDeclarationStructure>[] {
|
|
210
|
-
const
|
|
245
|
+
const operation = method[1];
|
|
246
|
+
const optionsType = getOperationOptionsName(method, true);
|
|
211
247
|
const parameters: Map<
|
|
212
248
|
string,
|
|
213
249
|
OptionalKind<ParameterDeclarationStructure>
|
|
@@ -216,30 +252,31 @@ function getOperationSignatureParameters(
|
|
|
216
252
|
operation.parameters
|
|
217
253
|
.filter(
|
|
218
254
|
(p) =>
|
|
219
|
-
p.
|
|
220
|
-
p.type.
|
|
255
|
+
p.onClient === false &&
|
|
256
|
+
p.type.kind !== "constant" &&
|
|
257
|
+
operation.operation.parameters.filter((param) => {
|
|
258
|
+
return (
|
|
259
|
+
param.correspondingMethodParams.length === 1 &&
|
|
260
|
+
param.correspondingMethodParams[0] === p
|
|
261
|
+
);
|
|
262
|
+
})[0]?.kind !== "cookie" &&
|
|
221
263
|
p.clientDefaultValue === undefined &&
|
|
222
|
-
!p.optional
|
|
264
|
+
!p.optional &&
|
|
265
|
+
!(
|
|
266
|
+
p.isGeneratedName &&
|
|
267
|
+
(p.name === "contentType" || p.name === "accept")
|
|
268
|
+
) // skip tcgc generated contentType and accept header parameter
|
|
223
269
|
)
|
|
224
270
|
.map((p) => {
|
|
225
271
|
return {
|
|
226
|
-
name: p.
|
|
227
|
-
type: getTypeExpression(context, p.
|
|
272
|
+
name: p.name,
|
|
273
|
+
type: getTypeExpression(context, p.type)
|
|
228
274
|
};
|
|
229
275
|
})
|
|
230
276
|
.forEach((p) => {
|
|
231
277
|
parameters.set(p.name, p);
|
|
232
278
|
});
|
|
233
279
|
|
|
234
|
-
if (operation.bodyParameter && operation.bodyParameter.optional === false) {
|
|
235
|
-
parameters.set(operation.bodyParameter?.clientName, {
|
|
236
|
-
hasQuestionToken: operation.bodyParameter.optional,
|
|
237
|
-
...{
|
|
238
|
-
name: operation.bodyParameter.clientName,
|
|
239
|
-
type: getTypeExpression(context, operation.bodyParameter.type.tcgcType!)
|
|
240
|
-
}
|
|
241
|
-
});
|
|
242
|
-
}
|
|
243
280
|
// Add context as the first parameter
|
|
244
281
|
const contextParam = { name: "context", type: clientType };
|
|
245
282
|
|
|
@@ -260,47 +297,54 @@ function getOperationSignatureParameters(
|
|
|
260
297
|
*/
|
|
261
298
|
export function getOperationFunction(
|
|
262
299
|
context: SdkContext,
|
|
263
|
-
|
|
300
|
+
method: [string[], ServiceOperation],
|
|
264
301
|
clientType: string
|
|
265
302
|
): OptionalKind<FunctionDeclarationStructure> & { propertyName?: string } {
|
|
303
|
+
const operation = method[1];
|
|
304
|
+
// Extract required parameters
|
|
305
|
+
const parameters: OptionalKind<ParameterDeclarationStructure>[] =
|
|
306
|
+
getOperationSignatureParameters(context, method, clientType);
|
|
307
|
+
const optionalParamName = getOptionalParamsName(parameters);
|
|
266
308
|
if (isPagingOnlyOperation(operation)) {
|
|
267
309
|
// Case 1: paging-only operation
|
|
268
|
-
return getPagingOnlyOperationFunction(
|
|
310
|
+
return getPagingOnlyOperationFunction(
|
|
311
|
+
context,
|
|
312
|
+
[method[0], operation],
|
|
313
|
+
clientType
|
|
314
|
+
);
|
|
269
315
|
} else if (isLroOnlyOperation(operation)) {
|
|
270
316
|
// Case 2: lro-only operation
|
|
271
|
-
return getLroOnlyOperationFunction(
|
|
317
|
+
return getLroOnlyOperationFunction(
|
|
318
|
+
context,
|
|
319
|
+
[method[0], operation],
|
|
320
|
+
clientType,
|
|
321
|
+
optionalParamName
|
|
322
|
+
);
|
|
272
323
|
} else if (isLroAndPagingOperation(operation)) {
|
|
273
324
|
// Case 3: both paging + lro operation is not supported yet so handle them as normal operation and customization may be needed
|
|
274
325
|
// https://github.com/Azure/autorest.typescript/issues/2313
|
|
275
326
|
}
|
|
276
327
|
|
|
277
|
-
if (operation.name === "floatSeconds") {
|
|
278
|
-
operation;
|
|
279
|
-
}
|
|
280
|
-
// Extract required parameters
|
|
281
|
-
const parameters: OptionalKind<ParameterDeclarationStructure>[] =
|
|
282
|
-
getOperationSignatureParameters(context, operation, clientType);
|
|
283
328
|
// TODO: Support operation overloads
|
|
284
|
-
const response = operation.
|
|
329
|
+
const response = operation.response;
|
|
285
330
|
let returnType = { name: "", type: "void" };
|
|
286
|
-
if (response.type
|
|
287
|
-
const type =
|
|
288
|
-
extractPagingType(response.type, operation.itemName) ?? response.type;
|
|
331
|
+
if (response.type) {
|
|
332
|
+
const type = response.type;
|
|
289
333
|
returnType = {
|
|
290
|
-
name: type.name ?? "",
|
|
291
|
-
type: getTypeExpression(context, type
|
|
334
|
+
name: (type as any).name ?? "",
|
|
335
|
+
type: getTypeExpression(context, type!)
|
|
292
336
|
};
|
|
293
337
|
}
|
|
294
338
|
const { name, fixme = [] } = getOperationName(operation);
|
|
295
339
|
const functionStatement = {
|
|
296
340
|
docs: [
|
|
297
|
-
...getDocsFromDescription(operation.
|
|
341
|
+
...getDocsFromDescription(operation.doc),
|
|
298
342
|
...getFixmeForMultilineDocs(fixme)
|
|
299
343
|
],
|
|
300
344
|
isAsync: true,
|
|
301
345
|
isExported: true,
|
|
302
346
|
name,
|
|
303
|
-
propertyName: operation.name,
|
|
347
|
+
propertyName: normalizeName(operation.name, NameType.Property),
|
|
304
348
|
parameters,
|
|
305
349
|
returnType: `Promise<${returnType.type}>`
|
|
306
350
|
};
|
|
@@ -321,12 +365,14 @@ export function getOperationFunction(
|
|
|
321
365
|
|
|
322
366
|
function getLroOnlyOperationFunction(
|
|
323
367
|
context: SdkContext,
|
|
324
|
-
|
|
325
|
-
clientType: string
|
|
368
|
+
method: [string[], SdkLroServiceMethod<SdkHttpOperation>],
|
|
369
|
+
clientType: string,
|
|
370
|
+
optionalParamName: string = "options"
|
|
326
371
|
) {
|
|
372
|
+
const operation = method[1];
|
|
327
373
|
// Extract required parameters
|
|
328
374
|
const parameters: OptionalKind<ParameterDeclarationStructure>[] =
|
|
329
|
-
getOperationSignatureParameters(context,
|
|
375
|
+
getOperationSignatureParameters(context, method, clientType);
|
|
330
376
|
const returnType = buildLroReturnType(context, operation);
|
|
331
377
|
const { name, fixme = [] } = getOperationName(operation);
|
|
332
378
|
const pollerLikeReference = resolveReference(
|
|
@@ -337,13 +383,13 @@ function getLroOnlyOperationFunction(
|
|
|
337
383
|
);
|
|
338
384
|
const functionStatement = {
|
|
339
385
|
docs: [
|
|
340
|
-
...getDocsFromDescription(operation.
|
|
386
|
+
...getDocsFromDescription(operation.doc),
|
|
341
387
|
...getFixmeForMultilineDocs(fixme)
|
|
342
388
|
],
|
|
343
389
|
isAsync: false,
|
|
344
390
|
isExported: true,
|
|
345
391
|
name,
|
|
346
|
-
propertyName: operation.name,
|
|
392
|
+
propertyName: normalizeName(operation.name, NameType.Property),
|
|
347
393
|
parameters,
|
|
348
394
|
returnType: `${pollerLikeReference}<${operationStateReference}<${returnType.type}>, ${returnType.type}>`
|
|
349
395
|
};
|
|
@@ -351,17 +397,29 @@ function getLroOnlyOperationFunction(
|
|
|
351
397
|
const getLongRunningPollerReference = resolveReference(
|
|
352
398
|
PollingHelpers.GetLongRunningPoller
|
|
353
399
|
);
|
|
354
|
-
const
|
|
355
|
-
|
|
356
|
-
|
|
400
|
+
const lroMetadata =
|
|
401
|
+
operation.kind === "lro" || operation.kind === "lropaging"
|
|
402
|
+
? operation.lroMetadata
|
|
403
|
+
: undefined;
|
|
404
|
+
const allowedFinalLocation = [
|
|
405
|
+
"azure-async-operation",
|
|
406
|
+
"location",
|
|
407
|
+
"original-uri",
|
|
408
|
+
"operation-location"
|
|
409
|
+
];
|
|
410
|
+
const resourceLocationConfig =
|
|
411
|
+
lroMetadata?.finalStateVia &&
|
|
412
|
+
allowedFinalLocation.includes(lroMetadata?.finalStateVia)
|
|
413
|
+
? `resourceLocationConfig: "${lroMetadata?.finalStateVia}"`
|
|
414
|
+
: "";
|
|
357
415
|
const statements: string[] = [];
|
|
358
416
|
statements.push(`
|
|
359
417
|
|
|
360
418
|
return ${getLongRunningPollerReference}(context, _${name}Deserialize, ${getExpectedStatuses(
|
|
361
419
|
operation
|
|
362
420
|
)}, {
|
|
363
|
-
updateIntervalInMs:
|
|
364
|
-
abortSignal:
|
|
421
|
+
updateIntervalInMs: ${optionalParamName}?.updateIntervalInMs,
|
|
422
|
+
abortSignal: ${optionalParamName}?.abortSignal,
|
|
365
423
|
getInitialResponse: () => _${name}Send(${parameters
|
|
366
424
|
.map((p) => p.name)
|
|
367
425
|
.join(", ")}),
|
|
@@ -377,13 +435,16 @@ function getLroOnlyOperationFunction(
|
|
|
377
435
|
};
|
|
378
436
|
}
|
|
379
437
|
|
|
380
|
-
function buildLroReturnType(
|
|
438
|
+
function buildLroReturnType(
|
|
439
|
+
context: SdkContext,
|
|
440
|
+
operation: SdkLroServiceMethod<SdkHttpOperation>
|
|
441
|
+
) {
|
|
381
442
|
const metadata = operation.lroMetadata;
|
|
382
|
-
if (metadata !== undefined && metadata.
|
|
383
|
-
const type = metadata.
|
|
443
|
+
if (metadata !== undefined && metadata.finalResponse !== undefined) {
|
|
444
|
+
const type = metadata.finalResponse.result;
|
|
384
445
|
return {
|
|
385
446
|
name: type.name,
|
|
386
|
-
type: getTypeExpression(context, type
|
|
447
|
+
type: getTypeExpression(context, type)
|
|
387
448
|
};
|
|
388
449
|
}
|
|
389
450
|
return { name: "", type: "void" };
|
|
@@ -391,22 +452,22 @@ function buildLroReturnType(context: SdkContext, operation: Operation) {
|
|
|
391
452
|
|
|
392
453
|
function getPagingOnlyOperationFunction(
|
|
393
454
|
context: SdkContext,
|
|
394
|
-
|
|
455
|
+
method: [string[], SdkPagingServiceMethod<SdkHttpOperation>],
|
|
395
456
|
clientType: string
|
|
396
457
|
) {
|
|
458
|
+
const operation = method[1];
|
|
397
459
|
// Extract required parameters
|
|
398
460
|
const parameters: OptionalKind<ParameterDeclarationStructure>[] =
|
|
399
|
-
getOperationSignatureParameters(context,
|
|
461
|
+
getOperationSignatureParameters(context, method, clientType);
|
|
400
462
|
|
|
401
463
|
// TODO: Support operation overloads
|
|
402
|
-
const response = operation.
|
|
464
|
+
const response = operation.response;
|
|
403
465
|
let returnType = { name: "", type: "void" };
|
|
404
|
-
if (response.type
|
|
405
|
-
const type =
|
|
406
|
-
extractPagingType(response.type, operation.itemName) ?? response.type;
|
|
466
|
+
if (response.type && response.type.kind === "array") {
|
|
467
|
+
const type = response.type;
|
|
407
468
|
returnType = {
|
|
408
|
-
name: type.name ?? "",
|
|
409
|
-
type: getTypeExpression(context, type.
|
|
469
|
+
name: (type.valueType as any).name ?? "",
|
|
470
|
+
type: getTypeExpression(context, type.valueType)
|
|
410
471
|
};
|
|
411
472
|
}
|
|
412
473
|
const { name, fixme = [] } = getOperationName(operation);
|
|
@@ -418,24 +479,33 @@ function getPagingOnlyOperationFunction(
|
|
|
418
479
|
);
|
|
419
480
|
const functionStatement = {
|
|
420
481
|
docs: [
|
|
421
|
-
...getDocsFromDescription(operation.
|
|
482
|
+
...getDocsFromDescription(operation.doc),
|
|
422
483
|
...getFixmeForMultilineDocs(fixme)
|
|
423
484
|
],
|
|
424
485
|
isAsync: false,
|
|
425
486
|
isExported: true,
|
|
426
487
|
name,
|
|
427
|
-
propertyName: operation.name,
|
|
488
|
+
propertyName: normalizeName(operation.name, NameType.Property),
|
|
428
489
|
parameters,
|
|
429
490
|
returnType: `${pagedAsyncIterableIteratorReference}<${returnType.type}>`
|
|
430
491
|
};
|
|
431
492
|
|
|
432
493
|
const statements: string[] = [];
|
|
433
494
|
const options = [];
|
|
434
|
-
|
|
435
|
-
|
|
495
|
+
// TODO pending tcgc issue to fix https://github.com/Azure/typespec-azure/issues/1985
|
|
496
|
+
const itemName =
|
|
497
|
+
operation.response.resultPath !== "" && operation.response.resultPath
|
|
498
|
+
? operation.response.resultPath
|
|
499
|
+
: operation.__raw_paged_metadata?.itemsSegments
|
|
500
|
+
? operation.__raw_paged_metadata.itemsSegments[0]
|
|
501
|
+
: undefined;
|
|
502
|
+
if (itemName) {
|
|
503
|
+
options.push(`itemName: "${itemName}"`);
|
|
436
504
|
}
|
|
437
|
-
if (operation.
|
|
438
|
-
options.push(
|
|
505
|
+
if (operation.__raw_paged_metadata?.nextLinkSegments) {
|
|
506
|
+
options.push(
|
|
507
|
+
`nextLinkName: "${operation.__raw_paged_metadata.nextLinkSegments[0]}"`
|
|
508
|
+
);
|
|
439
509
|
}
|
|
440
510
|
statements.push(
|
|
441
511
|
`return ${buildPagedAsyncIteratorReference}(
|
|
@@ -453,31 +523,15 @@ function getPagingOnlyOperationFunction(
|
|
|
453
523
|
};
|
|
454
524
|
}
|
|
455
525
|
|
|
456
|
-
function extractPagingType(type: Type, itemName?: string): Type | undefined {
|
|
457
|
-
if (!itemName) {
|
|
458
|
-
return undefined;
|
|
459
|
-
}
|
|
460
|
-
const allProperties = [
|
|
461
|
-
...(type.properties ?? []),
|
|
462
|
-
...(type.parents ?? []).flatMap((p) => p.properties ?? [])
|
|
463
|
-
];
|
|
464
|
-
const prop = allProperties
|
|
465
|
-
.filter((prop) => prop.restApiName === itemName)
|
|
466
|
-
.map((prop) => prop.type);
|
|
467
|
-
if (prop.length === 0) {
|
|
468
|
-
return undefined;
|
|
469
|
-
}
|
|
470
|
-
return prop[0]?.type === "list" && prop[0].elementType
|
|
471
|
-
? prop[0].elementType
|
|
472
|
-
: undefined;
|
|
473
|
-
}
|
|
474
526
|
export function getOperationOptionsName(
|
|
475
|
-
|
|
527
|
+
method: [string[], ServiceOperation],
|
|
476
528
|
includeGroupName = false
|
|
477
529
|
) {
|
|
530
|
+
const prefixes = method[0];
|
|
531
|
+
const operation = method[1];
|
|
478
532
|
const prefix =
|
|
479
533
|
includeGroupName && operation.name.indexOf("_") === -1
|
|
480
|
-
? getClassicalLayerPrefix(
|
|
534
|
+
? getClassicalLayerPrefix(prefixes, NameType.Interface)
|
|
481
535
|
: "";
|
|
482
536
|
const optionName = `${prefix}${toPascalCase(operation.name)}OptionalParams`;
|
|
483
537
|
return optionName;
|
|
@@ -490,20 +544,22 @@ export function getOperationOptionsName(
|
|
|
490
544
|
*/
|
|
491
545
|
function getRequestParameters(
|
|
492
546
|
dpgContext: SdkContext,
|
|
493
|
-
operation:
|
|
547
|
+
operation: ServiceOperation,
|
|
548
|
+
optionalParamName: string = "options"
|
|
494
549
|
): string {
|
|
495
|
-
if (!operation.parameters) {
|
|
550
|
+
if (!operation.operation.parameters) {
|
|
496
551
|
return "";
|
|
497
552
|
}
|
|
498
|
-
const operationParameters = operation.parameters.filter(
|
|
499
|
-
(p) => p.
|
|
553
|
+
const operationParameters = operation.operation.parameters.filter(
|
|
554
|
+
(p) => (!p.onClient || p.isApiVersionParam) && !isContentType(p)
|
|
500
555
|
);
|
|
501
556
|
|
|
502
|
-
const contentTypeParameter =
|
|
557
|
+
const contentTypeParameter =
|
|
558
|
+
operation.operation.parameters.find(isContentType);
|
|
503
559
|
|
|
504
560
|
const parametersImplementation: Record<
|
|
505
561
|
"header" | "query" | "body",
|
|
506
|
-
{ paramMap: string; param:
|
|
562
|
+
{ paramMap: string; param: SdkServiceParameter }[]
|
|
507
563
|
> = {
|
|
508
564
|
header: [],
|
|
509
565
|
query: [],
|
|
@@ -511,13 +567,17 @@ function getRequestParameters(
|
|
|
511
567
|
};
|
|
512
568
|
|
|
513
569
|
for (const param of operationParameters) {
|
|
514
|
-
if (
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
570
|
+
if (param.kind === "header" || param.kind === "query") {
|
|
571
|
+
// skip tcgc generated contentType and accept non constant type header parameter
|
|
572
|
+
if (
|
|
573
|
+
param.isGeneratedName &&
|
|
574
|
+
!isConstant(param.type) &&
|
|
575
|
+
(param.name === "contentType" || param.name === "accept")
|
|
576
|
+
) {
|
|
577
|
+
continue;
|
|
578
|
+
}
|
|
579
|
+
parametersImplementation[param.kind].push({
|
|
580
|
+
paramMap: getParameterMap(dpgContext, param, optionalParamName),
|
|
521
581
|
param
|
|
522
582
|
});
|
|
523
583
|
}
|
|
@@ -526,13 +586,20 @@ function getRequestParameters(
|
|
|
526
586
|
let paramStr = "";
|
|
527
587
|
|
|
528
588
|
if (contentTypeParameter) {
|
|
529
|
-
paramStr = `${getContentTypeValue(contentTypeParameter)},`;
|
|
589
|
+
paramStr = `${getContentTypeValue(contentTypeParameter, optionalParamName)},`;
|
|
530
590
|
}
|
|
531
591
|
|
|
532
592
|
if (parametersImplementation.header.length) {
|
|
533
593
|
paramStr = `${paramStr}\nheaders: {${parametersImplementation.header
|
|
534
|
-
.map((i) =>
|
|
535
|
-
|
|
594
|
+
.map((i) =>
|
|
595
|
+
buildHeaderParameter(
|
|
596
|
+
dpgContext.program,
|
|
597
|
+
i.paramMap,
|
|
598
|
+
i.param,
|
|
599
|
+
optionalParamName
|
|
600
|
+
)
|
|
601
|
+
)
|
|
602
|
+
.join(",\n")}, ...${optionalParamName}.requestOptions?.headers },`;
|
|
536
603
|
}
|
|
537
604
|
|
|
538
605
|
if (parametersImplementation.query.length) {
|
|
@@ -541,14 +608,14 @@ function getRequestParameters(
|
|
|
541
608
|
.join(",\n")}},`;
|
|
542
609
|
}
|
|
543
610
|
if (
|
|
544
|
-
operation.
|
|
611
|
+
operation.operation.bodyParam === undefined &&
|
|
545
612
|
parametersImplementation.body.length
|
|
546
613
|
) {
|
|
547
614
|
paramStr = `${paramStr}\nbody: {${parametersImplementation.body
|
|
548
615
|
.map((i) => i.paramMap)
|
|
549
616
|
.join(",\n")}}`;
|
|
550
|
-
} else if (operation.
|
|
551
|
-
paramStr = `${paramStr}${buildBodyParameter(dpgContext, operation.
|
|
617
|
+
} else if (operation.operation.bodyParam !== undefined) {
|
|
618
|
+
paramStr = `${paramStr}${buildBodyParameter(dpgContext, operation.operation.bodyParam)}`;
|
|
552
619
|
}
|
|
553
620
|
return paramStr;
|
|
554
621
|
}
|
|
@@ -557,8 +624,10 @@ function getRequestParameters(
|
|
|
557
624
|
function buildHeaderParameter(
|
|
558
625
|
program: Program,
|
|
559
626
|
paramMap: string,
|
|
560
|
-
param:
|
|
627
|
+
param: SdkServiceParameter,
|
|
628
|
+
optionalParamName: string = "options"
|
|
561
629
|
): string {
|
|
630
|
+
const paramName = param.name;
|
|
562
631
|
if (!param.optional && isTypeNullable(param.type) === true) {
|
|
563
632
|
reportDiagnostic(program, {
|
|
564
633
|
code: "nullable-required-header",
|
|
@@ -568,10 +637,10 @@ function buildHeaderParameter(
|
|
|
568
637
|
}
|
|
569
638
|
const conditions = [];
|
|
570
639
|
if (param.optional) {
|
|
571
|
-
conditions.push(
|
|
640
|
+
conditions.push(`${optionalParamName}?.${paramName} !== undefined`);
|
|
572
641
|
}
|
|
573
642
|
if (isTypeNullable(param.type) === true) {
|
|
574
|
-
conditions.push(
|
|
643
|
+
conditions.push(`${optionalParamName}?.${paramName} !== null`);
|
|
575
644
|
}
|
|
576
645
|
return conditions.length > 0
|
|
577
646
|
? `...(${conditions.join(" && ")} ? {${paramMap}} : {})`
|
|
@@ -580,26 +649,30 @@ function buildHeaderParameter(
|
|
|
580
649
|
|
|
581
650
|
function buildBodyParameter(
|
|
582
651
|
context: SdkContext,
|
|
583
|
-
bodyParameter:
|
|
652
|
+
bodyParameter: SdkBodyParameter | undefined,
|
|
653
|
+
optionalParamName: string = "options"
|
|
584
654
|
) {
|
|
585
|
-
if (!bodyParameter || !bodyParameter.type
|
|
655
|
+
if (!bodyParameter || !bodyParameter.type) {
|
|
586
656
|
return "";
|
|
587
657
|
}
|
|
588
658
|
const serializerFunctionName = buildModelSerializer(
|
|
589
659
|
context,
|
|
590
|
-
bodyParameter.type
|
|
660
|
+
getNullableValidType(bodyParameter.type),
|
|
591
661
|
false,
|
|
592
662
|
true
|
|
593
663
|
);
|
|
594
664
|
|
|
665
|
+
const bodyParamName = normalizeName(bodyParameter.name, NameType.Parameter);
|
|
595
666
|
const bodyNameExpression = bodyParameter.optional
|
|
596
|
-
?
|
|
597
|
-
:
|
|
667
|
+
? `${optionalParamName}["${bodyParamName}"]`
|
|
668
|
+
: bodyParamName;
|
|
598
669
|
const nullOrUndefinedPrefix = getPropertySerializationPrefix(
|
|
670
|
+
context,
|
|
599
671
|
bodyParameter,
|
|
600
|
-
bodyParameter.optional ?
|
|
672
|
+
bodyParameter.optional ? optionalParamName : undefined
|
|
601
673
|
);
|
|
602
|
-
if
|
|
674
|
+
// if a model being used in both spread and non spread operation, we should only leverage the deserializer in non spread operation
|
|
675
|
+
if (serializerFunctionName && !isSpreadBodyParameter(bodyParameter)) {
|
|
603
676
|
return `\nbody: ${nullOrUndefinedPrefix}${serializerFunctionName}(${bodyNameExpression}),`;
|
|
604
677
|
} else if (isAzureCoreErrorType(context.program, bodyParameter.type.__raw)) {
|
|
605
678
|
return `\nbody: ${nullOrUndefinedPrefix}${bodyNameExpression},`;
|
|
@@ -609,9 +682,11 @@ function buildBodyParameter(
|
|
|
609
682
|
bodyParameter.type,
|
|
610
683
|
bodyNameExpression,
|
|
611
684
|
!bodyParameter.optional,
|
|
612
|
-
bodyParameter.
|
|
685
|
+
isBinaryPayload(context, bodyParameter.__raw!, bodyParameter.contentTypes)
|
|
686
|
+
? "binary"
|
|
687
|
+
: getEncodeForType(bodyParameter.type)
|
|
613
688
|
);
|
|
614
|
-
return `\nbody: ${serializedBody
|
|
689
|
+
return `\nbody: ${serializedBody.startsWith(nullOrUndefinedPrefix) ? "" : nullOrUndefinedPrefix}${serializedBody},`;
|
|
615
690
|
}
|
|
616
691
|
|
|
617
692
|
function getEncodingFormat(type: { format?: string }) {
|
|
@@ -629,208 +704,210 @@ function getEncodingFormat(type: { format?: string }) {
|
|
|
629
704
|
*/
|
|
630
705
|
export function getParameterMap(
|
|
631
706
|
context: SdkContext,
|
|
632
|
-
param:
|
|
707
|
+
param: SdkServiceParameter,
|
|
708
|
+
optionalParamName: string = "options"
|
|
633
709
|
): string {
|
|
634
|
-
if (isConstant(param)) {
|
|
635
|
-
return getConstantValue(param)
|
|
710
|
+
if (isConstant(param.type)) {
|
|
711
|
+
return `"${param.name}": ${getConstantValue(param.type)}`;
|
|
636
712
|
}
|
|
637
713
|
|
|
638
|
-
if (hasCollectionFormatInfo(
|
|
639
|
-
return getCollectionFormat(context, param
|
|
714
|
+
if (hasCollectionFormatInfo(param.kind, (param as any).collectionFormat)) {
|
|
715
|
+
return getCollectionFormat(context, param, optionalParamName);
|
|
640
716
|
}
|
|
641
717
|
|
|
642
718
|
// if the parameter or property is optional, we don't need to handle the default value
|
|
643
719
|
if (isOptional(param)) {
|
|
644
|
-
return getOptional(context, param);
|
|
720
|
+
return getOptional(context, param, optionalParamName);
|
|
645
721
|
}
|
|
646
722
|
|
|
647
723
|
if (isRequired(param)) {
|
|
648
724
|
return getRequired(context, param);
|
|
649
725
|
}
|
|
650
726
|
|
|
651
|
-
throw new Error(`Parameter ${param.
|
|
727
|
+
throw new Error(`Parameter ${param.name} is not supported`);
|
|
652
728
|
}
|
|
653
729
|
|
|
654
|
-
function getCollectionFormat(
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
730
|
+
function getCollectionFormat(
|
|
731
|
+
context: SdkContext,
|
|
732
|
+
param: SdkServiceParameter,
|
|
733
|
+
optionalParamName: string = "options"
|
|
734
|
+
) {
|
|
735
|
+
const serializedName = getPropertySerializedName(param);
|
|
736
|
+
const format = (param as any).collectionFormat;
|
|
737
|
+
const collectionInfo = getCollectionFormatHelper(param.kind, format ?? "");
|
|
659
738
|
if (!collectionInfo) {
|
|
660
739
|
throw "Has collection format info but without helper function detected";
|
|
661
740
|
}
|
|
662
|
-
const isMulti =
|
|
663
|
-
const additionalParam = isMulti ? `, "${
|
|
741
|
+
const isMulti = format.toLowerCase() === "multi";
|
|
742
|
+
const additionalParam = isMulti ? `, "${serializedName}"` : "";
|
|
664
743
|
if (!param.optional) {
|
|
665
|
-
return `"${
|
|
744
|
+
return `"${serializedName}": ${collectionInfo}(${serializeRequestValue(
|
|
666
745
|
context,
|
|
667
746
|
param.type,
|
|
668
|
-
param.
|
|
747
|
+
param.name,
|
|
669
748
|
true,
|
|
670
|
-
param.
|
|
749
|
+
getEncodeForType(param.type)
|
|
671
750
|
)}${additionalParam})`;
|
|
672
751
|
}
|
|
673
|
-
return `"${
|
|
674
|
-
param.
|
|
752
|
+
return `"${serializedName}": ${optionalParamName}?.${
|
|
753
|
+
param.name
|
|
675
754
|
} !== undefined ? ${collectionInfo}(${serializeRequestValue(
|
|
676
755
|
context,
|
|
677
756
|
param.type,
|
|
678
|
-
|
|
757
|
+
`${optionalParamName}?.${param.name}`,
|
|
679
758
|
false,
|
|
680
|
-
param.
|
|
759
|
+
getEncodeForType(param.type)
|
|
681
760
|
)}${additionalParam}): undefined`;
|
|
682
761
|
}
|
|
683
762
|
|
|
684
|
-
function isContentType(param:
|
|
763
|
+
function isContentType(param: SdkServiceParameter): boolean {
|
|
685
764
|
return (
|
|
686
|
-
param.
|
|
687
|
-
param.
|
|
765
|
+
param.kind === "header" &&
|
|
766
|
+
param.serializedName.toLowerCase() === "content-type"
|
|
688
767
|
);
|
|
689
768
|
}
|
|
690
769
|
|
|
691
|
-
function getContentTypeValue(
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
770
|
+
function getContentTypeValue(
|
|
771
|
+
param: SdkServiceParameter,
|
|
772
|
+
optionalParamName: string = "options"
|
|
773
|
+
) {
|
|
774
|
+
const defaultValue = param.clientDefaultValue;
|
|
775
|
+
// allow customers to customize the content type if it's guessed by tcgc.
|
|
776
|
+
if (isConstant(param.type)) {
|
|
777
|
+
return `contentType: ${getConstantValue(param.type)}`;
|
|
778
|
+
}
|
|
695
779
|
if (defaultValue) {
|
|
696
|
-
return `contentType:
|
|
780
|
+
return `contentType: ${optionalParamName}.${param.name} as any ?? "${defaultValue}"`;
|
|
697
781
|
} else {
|
|
698
782
|
return `contentType: ${
|
|
699
783
|
!param.optional
|
|
700
784
|
? "contentType"
|
|
701
|
-
:
|
|
785
|
+
: `${optionalParamName}.` + param.name + " as any"
|
|
702
786
|
}`;
|
|
703
787
|
}
|
|
704
788
|
}
|
|
705
789
|
|
|
706
|
-
|
|
707
|
-
type: { optional: false | undefined; value: string };
|
|
708
|
-
};
|
|
709
|
-
|
|
710
|
-
function isRequired(param: Parameter | Property): param is RequiredType {
|
|
790
|
+
function isRequired(param: SdkModelPropertyType) {
|
|
711
791
|
return !param.optional;
|
|
712
792
|
}
|
|
713
793
|
|
|
714
|
-
function getRequired(context: SdkContext, param:
|
|
715
|
-
|
|
794
|
+
function getRequired(context: SdkContext, param: SdkModelPropertyType) {
|
|
795
|
+
const serializedName = getPropertySerializedName(param);
|
|
796
|
+
const clientValue = `${param.onClient ? "context." : ""}${param.name}`;
|
|
797
|
+
if (param.type.kind === "model") {
|
|
716
798
|
const { propertiesStr } = getRequestModelMapping(
|
|
717
799
|
context,
|
|
718
|
-
param.type,
|
|
719
|
-
|
|
800
|
+
{ ...param.type, optional: param.optional },
|
|
801
|
+
clientValue
|
|
720
802
|
);
|
|
721
|
-
return `"${
|
|
803
|
+
return `"${serializedName}": { ${propertiesStr.join(",")} }`;
|
|
722
804
|
}
|
|
723
|
-
return `"${
|
|
805
|
+
return `"${serializedName}": ${serializeRequestValue(
|
|
724
806
|
context,
|
|
725
807
|
param.type,
|
|
726
|
-
|
|
808
|
+
clientValue,
|
|
727
809
|
true,
|
|
728
|
-
param.
|
|
729
|
-
(param as Parameter).location === "header" &&
|
|
730
|
-
param.type.type === "datetime"
|
|
731
|
-
? "headerDefault"
|
|
732
|
-
: param.format
|
|
810
|
+
getEncodeForType(param.type)
|
|
733
811
|
)}`;
|
|
734
812
|
}
|
|
735
813
|
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
}
|
|
739
|
-
|
|
740
|
-
function getConstantValue(param: ConstantType) {
|
|
741
|
-
const defaultValue =
|
|
742
|
-
param.clientDefaultValue ??
|
|
743
|
-
param.type.clientDefaultValue ??
|
|
744
|
-
param.type.value;
|
|
745
|
-
|
|
746
|
-
if (!defaultValue) {
|
|
747
|
-
throw new Error(
|
|
748
|
-
`Constant ${param.clientName} does not have a default value`
|
|
749
|
-
);
|
|
814
|
+
function getConstantValue(param: SdkConstantType) {
|
|
815
|
+
if (typeof param.value === "string") {
|
|
816
|
+
return `"${param.value}"`;
|
|
750
817
|
}
|
|
751
|
-
|
|
752
|
-
return `"${param.restApiName}": ${getType(param.type).name}`;
|
|
818
|
+
return `${param.value}`;
|
|
753
819
|
}
|
|
754
820
|
|
|
755
|
-
function isConstant(param:
|
|
756
|
-
return param.
|
|
821
|
+
function isConstant(param: SdkType): param is SdkConstantType {
|
|
822
|
+
return param.kind === "constant";
|
|
757
823
|
}
|
|
758
824
|
|
|
759
|
-
|
|
760
|
-
type: { optional: true };
|
|
761
|
-
};
|
|
762
|
-
|
|
763
|
-
function isOptional(param: Parameter | Property): param is OptionalType {
|
|
825
|
+
function isOptional(param: SdkModelPropertyType) {
|
|
764
826
|
return Boolean(param.optional);
|
|
765
827
|
}
|
|
766
828
|
|
|
767
|
-
function getOptional(
|
|
768
|
-
|
|
829
|
+
function getOptional(
|
|
830
|
+
context: SdkContext,
|
|
831
|
+
param: SdkHttpParameter,
|
|
832
|
+
optionalParamName: string
|
|
833
|
+
) {
|
|
834
|
+
const serializedName = getPropertySerializedName(param);
|
|
835
|
+
const paramName = `${param.onClient ? "context." : `${optionalParamName}?.`}${param.name}`;
|
|
836
|
+
if (param.type.kind === "model") {
|
|
769
837
|
const { propertiesStr, directAssignment } = getRequestModelMapping(
|
|
770
838
|
context,
|
|
771
|
-
param.type,
|
|
772
|
-
|
|
839
|
+
{ ...param.type, optional: param.optional },
|
|
840
|
+
paramName + "?."
|
|
773
841
|
);
|
|
774
842
|
const serializeContent =
|
|
775
843
|
directAssignment === true
|
|
776
844
|
? propertiesStr.join(",")
|
|
777
845
|
: `{${propertiesStr.join(",")}}`;
|
|
778
|
-
return `"${
|
|
846
|
+
return `"${serializedName}": ${serializeContent}`;
|
|
779
847
|
}
|
|
780
|
-
|
|
781
|
-
param.restApiName === "api-version" &&
|
|
782
|
-
(param as any).location === "query"
|
|
783
|
-
) {
|
|
784
|
-
return `"${param.restApiName}": ${
|
|
785
|
-
param.clientDefaultValue
|
|
786
|
-
? `options?.${param.clientName} ?? "${param.clientDefaultValue}"`
|
|
787
|
-
: `options?.${param.clientName}`
|
|
788
|
-
}`;
|
|
789
|
-
}
|
|
790
|
-
return `"${param.restApiName}": ${serializeRequestValue(
|
|
848
|
+
return `"${serializedName}": ${serializeRequestValue(
|
|
791
849
|
context,
|
|
792
850
|
param.type,
|
|
793
|
-
|
|
851
|
+
paramName,
|
|
794
852
|
false,
|
|
795
|
-
param.
|
|
796
|
-
(param as Parameter).location === "header" &&
|
|
797
|
-
param.type.type === "datetime"
|
|
798
|
-
? "headerDefault"
|
|
799
|
-
: param.format
|
|
853
|
+
getEncodeForType(param.type)
|
|
800
854
|
)}`;
|
|
801
855
|
}
|
|
802
856
|
|
|
857
|
+
/**
|
|
858
|
+
* Get the encode for SDK type
|
|
859
|
+
*/
|
|
860
|
+
function getEncodeForType(
|
|
861
|
+
type: SdkType | SdkHttpParameter | SdkModelPropertyType
|
|
862
|
+
) {
|
|
863
|
+
return (type as any).encode;
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
/**
|
|
867
|
+
* Get the optionality for SDK type
|
|
868
|
+
*/
|
|
869
|
+
function getOptionalForType(
|
|
870
|
+
type: SdkType | SdkHttpParameter | SdkModelPropertyType
|
|
871
|
+
) {
|
|
872
|
+
return (type as any).optional;
|
|
873
|
+
}
|
|
874
|
+
|
|
803
875
|
/**
|
|
804
876
|
* Builds the assignment for when a property or parameter has a default value
|
|
805
877
|
*/
|
|
806
|
-
function getDefaultValue(param:
|
|
807
|
-
return param.clientDefaultValue
|
|
878
|
+
function getDefaultValue(param: SdkServiceParameter) {
|
|
879
|
+
return param.clientDefaultValue;
|
|
808
880
|
}
|
|
809
881
|
|
|
810
882
|
/**
|
|
811
883
|
* Extracts the path parameters
|
|
812
884
|
*/
|
|
813
|
-
function getPathParameters(
|
|
814
|
-
|
|
885
|
+
function getPathParameters(
|
|
886
|
+
dpgContext: SdkContext,
|
|
887
|
+
operation: ServiceOperation,
|
|
888
|
+
optionalParamName: string = "options"
|
|
889
|
+
) {
|
|
890
|
+
if (!operation.operation.parameters) {
|
|
815
891
|
return "";
|
|
816
892
|
}
|
|
817
893
|
|
|
818
894
|
let pathParams = "";
|
|
819
|
-
for (const param of operation.parameters) {
|
|
820
|
-
if (param.
|
|
895
|
+
for (const param of operation.operation.parameters) {
|
|
896
|
+
if (param.kind === "path") {
|
|
821
897
|
// Path parameters cannot be optional
|
|
822
898
|
if (param.optional) {
|
|
823
899
|
reportDiagnostic(dpgContext.program, {
|
|
824
900
|
code: "optional-path-param",
|
|
825
901
|
target: NoTarget,
|
|
826
902
|
format: {
|
|
827
|
-
paramName: param
|
|
903
|
+
paramName: param
|
|
828
904
|
}
|
|
829
905
|
});
|
|
830
906
|
}
|
|
831
907
|
pathParams += `${pathParams !== "" ? "," : ""} ${getPathParamExpr(
|
|
832
908
|
param,
|
|
833
|
-
getDefaultValue(param)
|
|
909
|
+
getDefaultValue(param) as string,
|
|
910
|
+
optionalParamName
|
|
834
911
|
)}`;
|
|
835
912
|
}
|
|
836
913
|
}
|
|
@@ -838,19 +915,32 @@ function getPathParameters(dpgContext: SdkContext, operation: Operation) {
|
|
|
838
915
|
return pathParams;
|
|
839
916
|
}
|
|
840
917
|
|
|
841
|
-
function getPathParamExpr(
|
|
918
|
+
function getPathParamExpr(
|
|
919
|
+
param: SdkServiceParameter,
|
|
920
|
+
defaultValue?: string,
|
|
921
|
+
optionalParamName: string = "options"
|
|
922
|
+
) {
|
|
923
|
+
if (isConstant(param.type)) {
|
|
924
|
+
return getConstantValue(param.type);
|
|
925
|
+
}
|
|
926
|
+
const paramName = param.onClient
|
|
927
|
+
? `context.${param.name}`
|
|
928
|
+
: param.optional
|
|
929
|
+
? `${optionalParamName}["${param.name}"]`
|
|
930
|
+
: param.name;
|
|
842
931
|
const value = defaultValue
|
|
843
932
|
? typeof defaultValue === "string"
|
|
844
|
-
?
|
|
845
|
-
:
|
|
846
|
-
:
|
|
847
|
-
|
|
933
|
+
? `${paramName} ?? "${defaultValue}"`
|
|
934
|
+
: `${paramName} ?? ${defaultValue}`
|
|
935
|
+
: paramName;
|
|
936
|
+
// TODO allowReserved is not supported in Query and Header parameter yet.
|
|
937
|
+
if (param.kind === "path" && param.allowReserved === true) {
|
|
848
938
|
return `{value: ${value}, allowReserved: true}`;
|
|
849
939
|
}
|
|
850
940
|
return value;
|
|
851
941
|
}
|
|
852
942
|
|
|
853
|
-
function getNullableCheck(name: string, type:
|
|
943
|
+
function getNullableCheck(name: string, type: SdkType) {
|
|
854
944
|
if (!isTypeNullable(type)) {
|
|
855
945
|
return "";
|
|
856
946
|
}
|
|
@@ -869,42 +959,47 @@ interface RequestModelMappingResult {
|
|
|
869
959
|
}
|
|
870
960
|
export function getRequestModelMapping(
|
|
871
961
|
context: SdkContext,
|
|
872
|
-
modelPropertyType:
|
|
962
|
+
modelPropertyType: SdkModelType & { optional?: boolean },
|
|
873
963
|
propertyPath: string = "body"
|
|
874
964
|
): RequestModelMappingResult {
|
|
875
965
|
const props: string[] = [];
|
|
876
966
|
const allParents = getAllAncestors(modelPropertyType);
|
|
877
|
-
const properties:
|
|
967
|
+
const properties: SdkModelPropertyType[] =
|
|
878
968
|
getAllProperties(modelPropertyType, allParents) ?? [];
|
|
879
969
|
if (properties.length <= 0) {
|
|
880
970
|
return { propertiesStr: [] };
|
|
881
971
|
}
|
|
882
972
|
for (const property of properties) {
|
|
883
|
-
if (property.
|
|
973
|
+
if (property.kind === "property" && isReadOnly(property)) {
|
|
884
974
|
continue;
|
|
885
975
|
}
|
|
886
976
|
const dot = propertyPath.endsWith("?") ? "." : "";
|
|
887
|
-
|
|
977
|
+
const serializedName = getPropertySerializedName(property);
|
|
888
978
|
const propertyPathWithDot = `${propertyPath ? `${propertyPath}${dot}` : `${dot}`}`;
|
|
889
979
|
const nullOrUndefinedPrefix = getPropertySerializationPrefix(
|
|
980
|
+
context,
|
|
890
981
|
property,
|
|
891
982
|
propertyPath
|
|
892
983
|
);
|
|
893
984
|
|
|
894
|
-
const propertyFullName = getPropertyFullName(
|
|
985
|
+
const propertyFullName = getPropertyFullName(
|
|
986
|
+
context,
|
|
987
|
+
property,
|
|
988
|
+
propertyPathWithDot
|
|
989
|
+
);
|
|
895
990
|
const serializeFunctionName = buildModelSerializer(
|
|
896
991
|
context,
|
|
897
|
-
property.type
|
|
992
|
+
getNullableValidType(property.type),
|
|
898
993
|
false,
|
|
899
994
|
true
|
|
900
995
|
);
|
|
901
996
|
if (serializeFunctionName) {
|
|
902
997
|
props.push(
|
|
903
|
-
`"${
|
|
998
|
+
`"${serializedName}": ${nullOrUndefinedPrefix}${serializeFunctionName}(${propertyFullName})`
|
|
904
999
|
);
|
|
905
1000
|
} else if (isAzureCoreErrorType(context.program, property.type.__raw)) {
|
|
906
1001
|
props.push(
|
|
907
|
-
`"${
|
|
1002
|
+
`"${serializedName}": ${nullOrUndefinedPrefix}${propertyFullName}`
|
|
908
1003
|
);
|
|
909
1004
|
} else {
|
|
910
1005
|
const serializedValue = serializeRequestValue(
|
|
@@ -912,60 +1007,67 @@ export function getRequestModelMapping(
|
|
|
912
1007
|
property.type,
|
|
913
1008
|
propertyFullName,
|
|
914
1009
|
!property.optional,
|
|
915
|
-
property.
|
|
1010
|
+
getEncodeForType(property.type)
|
|
916
1011
|
);
|
|
917
|
-
props.push(`"${
|
|
1012
|
+
props.push(`"${serializedName}": ${serializedValue}`);
|
|
918
1013
|
}
|
|
919
1014
|
}
|
|
920
1015
|
|
|
921
1016
|
return { propertiesStr: props };
|
|
922
1017
|
}
|
|
923
1018
|
|
|
1019
|
+
function getPropertySerializedName(property: SdkModelPropertyType) {
|
|
1020
|
+
return property.kind !== "credential" && property.kind !== "method"
|
|
1021
|
+
? property.serializedName
|
|
1022
|
+
: property.name;
|
|
1023
|
+
}
|
|
1024
|
+
|
|
924
1025
|
/**
|
|
925
1026
|
* This function helps translating an RLC response to an HLC response,
|
|
926
1027
|
* extracting properties from body and headers and building the HLC response object
|
|
927
1028
|
*/
|
|
928
1029
|
export function getResponseMapping(
|
|
929
1030
|
context: SdkContext,
|
|
930
|
-
type:
|
|
1031
|
+
type: SdkType,
|
|
931
1032
|
propertyPath: string = "result.body"
|
|
932
1033
|
) {
|
|
933
|
-
const allParents = getAllAncestors(type);
|
|
934
|
-
const properties =
|
|
1034
|
+
const allParents = type.kind === "model" ? getAllAncestors(type) : [];
|
|
1035
|
+
const properties =
|
|
1036
|
+
type.kind === "model" ? getAllProperties(type, allParents) : [];
|
|
935
1037
|
const props: string[] = [];
|
|
936
1038
|
for (const property of properties) {
|
|
937
1039
|
const dot = propertyPath.endsWith("?") ? "." : "";
|
|
938
|
-
|
|
1040
|
+
const serializedName = getPropertySerializedName(property);
|
|
939
1041
|
const restValue = `${
|
|
940
1042
|
propertyPath ? `${propertyPath}${dot}` : `${dot}`
|
|
941
|
-
}["${
|
|
1043
|
+
}["${serializedName}"]`;
|
|
1044
|
+
|
|
942
1045
|
const nullOrUndefinedPrefix =
|
|
943
1046
|
property.optional || isTypeNullable(property.type)
|
|
944
1047
|
? `!${restValue}? ${restValue}: `
|
|
945
1048
|
: "";
|
|
946
1049
|
const deserializeFunctionName = buildModelDeserializer(
|
|
947
1050
|
context,
|
|
948
|
-
property.type
|
|
1051
|
+
getNullableValidType(property.type),
|
|
949
1052
|
false,
|
|
950
1053
|
true
|
|
951
1054
|
);
|
|
1055
|
+
const propertyName = normalizeModelPropertyName(context, property);
|
|
952
1056
|
if (deserializeFunctionName) {
|
|
953
1057
|
props.push(
|
|
954
|
-
|
|
1058
|
+
`${propertyName}: ${nullOrUndefinedPrefix}${deserializeFunctionName}(${restValue})`
|
|
955
1059
|
);
|
|
956
1060
|
} else if (isAzureCoreErrorType(context.program, property.type.__raw)) {
|
|
957
|
-
props.push(
|
|
958
|
-
`"${property.clientName}": ${nullOrUndefinedPrefix}${restValue}`
|
|
959
|
-
);
|
|
1061
|
+
props.push(`${propertyName}: ${nullOrUndefinedPrefix}${restValue}`);
|
|
960
1062
|
} else {
|
|
961
1063
|
const deserializeValue = deserializeResponseValue(
|
|
962
1064
|
context,
|
|
963
1065
|
property.type,
|
|
964
|
-
`${propertyPath}${dot}["${
|
|
965
|
-
property.
|
|
1066
|
+
`${propertyPath}${dot}["${serializedName}"]`,
|
|
1067
|
+
getEncodeForType(property.type)
|
|
966
1068
|
);
|
|
967
1069
|
props.push(
|
|
968
|
-
|
|
1070
|
+
`${propertyName}: ${deserializeValue === `${propertyPath}${dot}["${serializedName}"]` ? "" : nullOrUndefinedPrefix}${deserializeValue}`
|
|
969
1071
|
);
|
|
970
1072
|
}
|
|
971
1073
|
}
|
|
@@ -979,7 +1081,7 @@ export function getResponseMapping(
|
|
|
979
1081
|
*/
|
|
980
1082
|
export function serializeRequestValue(
|
|
981
1083
|
context: SdkContext,
|
|
982
|
-
type:
|
|
1084
|
+
type: SdkType,
|
|
983
1085
|
clientValue: string,
|
|
984
1086
|
required: boolean,
|
|
985
1087
|
format?: string
|
|
@@ -987,50 +1089,48 @@ export function serializeRequestValue(
|
|
|
987
1089
|
const getSdkType = useSdkTypes();
|
|
988
1090
|
const dependencies = useDependencies();
|
|
989
1091
|
const nullOrUndefinedPrefix =
|
|
990
|
-
isTypeNullable(type) || type
|
|
1092
|
+
isTypeNullable(type) || getOptionalForType(type) || !required
|
|
991
1093
|
? `!${clientValue}? ${clientValue}: `
|
|
992
1094
|
: "";
|
|
993
|
-
switch (type.
|
|
994
|
-
case "
|
|
995
|
-
switch (type.
|
|
1095
|
+
switch (type.kind) {
|
|
1096
|
+
case "utcDateTime":
|
|
1097
|
+
switch (type.encode ?? format) {
|
|
996
1098
|
case "rfc7231":
|
|
997
|
-
case "headerDefault":
|
|
998
1099
|
return `${nullOrUndefinedPrefix}${clientValue}.toUTCString()`;
|
|
999
1100
|
case "unixTimestamp":
|
|
1000
1101
|
return `${nullOrUndefinedPrefix}((${clientValue}.getTime() / 1000) | 0)`;
|
|
1001
1102
|
case "rfc3339":
|
|
1002
1103
|
default:
|
|
1003
|
-
return `${
|
|
1004
|
-
required ? "" : "?"
|
|
1005
|
-
}.toISOString()`;
|
|
1104
|
+
return `${nullOrUndefinedPrefix}${clientValue}.toISOString()`;
|
|
1006
1105
|
}
|
|
1007
|
-
case "
|
|
1106
|
+
case "array": {
|
|
1008
1107
|
const prefix = nullOrUndefinedPrefix + clientValue;
|
|
1009
|
-
if (type.
|
|
1108
|
+
if (type.valueType) {
|
|
1010
1109
|
const elementNullOrUndefinedPrefix =
|
|
1011
|
-
isTypeNullable(type.
|
|
1110
|
+
isTypeNullable(type.valueType) || getOptionalForType(type.valueType)
|
|
1012
1111
|
? "!p ? p : "
|
|
1013
1112
|
: "";
|
|
1014
1113
|
const serializeFunctionName = buildModelSerializer(
|
|
1015
1114
|
context,
|
|
1016
|
-
type.
|
|
1115
|
+
getNullableValidType(type.valueType),
|
|
1017
1116
|
false,
|
|
1018
1117
|
true
|
|
1019
1118
|
);
|
|
1020
1119
|
if (serializeFunctionName) {
|
|
1021
1120
|
return `${prefix}.map((p: any) => { return ${elementNullOrUndefinedPrefix}${serializeFunctionName}(p)})`;
|
|
1022
1121
|
} else if (
|
|
1023
|
-
isAzureCoreErrorType(context.program, type.
|
|
1122
|
+
isAzureCoreErrorType(context.program, type.valueType.__raw)
|
|
1024
1123
|
) {
|
|
1025
1124
|
return `${prefix}.map((p: any) => { return ${elementNullOrUndefinedPrefix}p})`;
|
|
1026
1125
|
} else {
|
|
1027
|
-
return `${prefix}.map((p: any) => { return ${elementNullOrUndefinedPrefix}${serializeRequestValue(context, type.
|
|
1126
|
+
return `${prefix}.map((p: any) => { return ${elementNullOrUndefinedPrefix}${serializeRequestValue(context, type.valueType, "p", true, getEncodeForType(type.valueType))}})`;
|
|
1028
1127
|
}
|
|
1029
1128
|
}
|
|
1030
1129
|
return clientValue;
|
|
1031
1130
|
}
|
|
1032
|
-
case "
|
|
1033
|
-
|
|
1131
|
+
case "bytes":
|
|
1132
|
+
// TODO https://github.com/Azure/typespec-azure/issues/1999
|
|
1133
|
+
if (format !== "binary" && format !== "bytes") {
|
|
1034
1134
|
const uint8ArrayToStringReference = resolveReference(
|
|
1035
1135
|
dependencies.uint8ArrayToString
|
|
1036
1136
|
);
|
|
@@ -1046,10 +1146,16 @@ export function serializeRequestValue(
|
|
|
1046
1146
|
}")`;
|
|
1047
1147
|
}
|
|
1048
1148
|
return clientValue;
|
|
1049
|
-
case "
|
|
1149
|
+
case "union":
|
|
1050
1150
|
if (isNormalUnion(type)) {
|
|
1051
1151
|
return `${clientValue}`;
|
|
1052
|
-
} else if (
|
|
1152
|
+
} else if (
|
|
1153
|
+
isSpecialHandledUnion({
|
|
1154
|
+
...type,
|
|
1155
|
+
isNonExhaustive:
|
|
1156
|
+
context.rlcOptions?.experimentalExtensibleEnums ?? false
|
|
1157
|
+
})
|
|
1158
|
+
) {
|
|
1053
1159
|
const sdkType = getSdkType(type.__raw!);
|
|
1054
1160
|
const serializerRefkey = refkey(sdkType, "serializer");
|
|
1055
1161
|
const serializeFunctionName = resolveReference(serializerRefkey);
|
|
@@ -1057,6 +1163,16 @@ export function serializeRequestValue(
|
|
|
1057
1163
|
} else {
|
|
1058
1164
|
return `${clientValue} as any`;
|
|
1059
1165
|
}
|
|
1166
|
+
case "model": // this is to build serialization logic for spread model types
|
|
1167
|
+
return `{${getRequestModelMapping(context, type, "").propertiesStr.join(",")}}`;
|
|
1168
|
+
case "nullable":
|
|
1169
|
+
return serializeRequestValue(
|
|
1170
|
+
context,
|
|
1171
|
+
type.type,
|
|
1172
|
+
clientValue,
|
|
1173
|
+
false,
|
|
1174
|
+
getEncodeForType(type.type)
|
|
1175
|
+
);
|
|
1060
1176
|
default:
|
|
1061
1177
|
if (clientValue === "constructorParam") {
|
|
1062
1178
|
return `${clientValue} as any`;
|
|
@@ -1072,7 +1188,7 @@ export function serializeRequestValue(
|
|
|
1072
1188
|
*/
|
|
1073
1189
|
export function deserializeResponseValue(
|
|
1074
1190
|
context: SdkContext,
|
|
1075
|
-
type:
|
|
1191
|
+
type: SdkType,
|
|
1076
1192
|
restValue: string,
|
|
1077
1193
|
format?: string
|
|
1078
1194
|
): string {
|
|
@@ -1081,25 +1197,25 @@ export function deserializeResponseValue(
|
|
|
1081
1197
|
dependencies.stringToUint8Array
|
|
1082
1198
|
);
|
|
1083
1199
|
const nullOrUndefinedPrefix =
|
|
1084
|
-
isTypeNullable(type) || type
|
|
1200
|
+
isTypeNullable(type) || getOptionalForType(type)
|
|
1085
1201
|
? `!${restValue}? ${restValue}: `
|
|
1086
1202
|
: "";
|
|
1087
|
-
switch (type.
|
|
1088
|
-
case "
|
|
1089
|
-
return `${nullOrUndefinedPrefix} new Date(${type.
|
|
1090
|
-
case "
|
|
1203
|
+
switch (type.kind) {
|
|
1204
|
+
case "utcDateTime":
|
|
1205
|
+
return `${nullOrUndefinedPrefix} new Date(${type.encode === "unixTimestamp" ? `${restValue} * 1000` : restValue})`;
|
|
1206
|
+
case "array": {
|
|
1091
1207
|
const prefix = nullOrUndefinedPrefix + restValue;
|
|
1092
1208
|
let elementNullOrUndefinedPrefix = "";
|
|
1093
1209
|
if (
|
|
1094
|
-
type.
|
|
1095
|
-
(isTypeNullable(type.
|
|
1210
|
+
type.valueType &&
|
|
1211
|
+
(isTypeNullable(type.valueType) || getOptionalForType(type.valueType))
|
|
1096
1212
|
) {
|
|
1097
1213
|
elementNullOrUndefinedPrefix = "!p ? p :";
|
|
1098
1214
|
}
|
|
1099
|
-
const deserializeFunctionName = type.
|
|
1215
|
+
const deserializeFunctionName = type.valueType
|
|
1100
1216
|
? buildModelDeserializer(
|
|
1101
1217
|
context,
|
|
1102
|
-
type.
|
|
1218
|
+
getNullableValidType(type.valueType),
|
|
1103
1219
|
false,
|
|
1104
1220
|
true
|
|
1105
1221
|
)
|
|
@@ -1107,29 +1223,34 @@ export function deserializeResponseValue(
|
|
|
1107
1223
|
if (deserializeFunctionName) {
|
|
1108
1224
|
return `${prefix}.map((p: any) => { return ${elementNullOrUndefinedPrefix}${deserializeFunctionName}(p)})`;
|
|
1109
1225
|
} else if (
|
|
1110
|
-
type.
|
|
1111
|
-
isAzureCoreErrorType(context.program, type.
|
|
1226
|
+
type.valueType &&
|
|
1227
|
+
isAzureCoreErrorType(context.program, type.valueType.__raw)
|
|
1112
1228
|
) {
|
|
1113
1229
|
return `${prefix}.map((p: any) => { return ${elementNullOrUndefinedPrefix}p})`;
|
|
1114
|
-
} else if (type.
|
|
1115
|
-
return `${prefix}.map((p: any) => { return ${elementNullOrUndefinedPrefix}${deserializeResponseValue(context, type.
|
|
1230
|
+
} else if (type.valueType) {
|
|
1231
|
+
return `${prefix}.map((p: any) => { return ${elementNullOrUndefinedPrefix}${deserializeResponseValue(context, type.valueType, "p", getEncodeForType(type.valueType))}})`;
|
|
1116
1232
|
} else {
|
|
1117
1233
|
return restValue;
|
|
1118
1234
|
}
|
|
1119
1235
|
}
|
|
1120
|
-
case "
|
|
1121
|
-
if (format !== "binary") {
|
|
1236
|
+
case "bytes":
|
|
1237
|
+
if (format !== "binary" && format !== "bytes") {
|
|
1122
1238
|
return `typeof ${restValue} === 'string'
|
|
1123
1239
|
? ${stringToUint8ArrayReference}(${restValue}, "${format ?? "base64"}")
|
|
1124
1240
|
: ${restValue}`;
|
|
1125
1241
|
}
|
|
1126
1242
|
return restValue;
|
|
1127
|
-
case "
|
|
1243
|
+
case "union":
|
|
1128
1244
|
if (isNormalUnion(type)) {
|
|
1129
1245
|
return `${restValue}`;
|
|
1130
1246
|
} else if (isSpecialHandledUnion(type)) {
|
|
1131
1247
|
const deserializeFunctionName = type
|
|
1132
|
-
? buildModelDeserializer(
|
|
1248
|
+
? buildModelDeserializer(
|
|
1249
|
+
context,
|
|
1250
|
+
getNullableValidType(type),
|
|
1251
|
+
false,
|
|
1252
|
+
true
|
|
1253
|
+
)
|
|
1133
1254
|
: undefined;
|
|
1134
1255
|
if (deserializeFunctionName) {
|
|
1135
1256
|
return `${deserializeFunctionName}(${restValue})`;
|
|
@@ -1139,94 +1260,97 @@ export function deserializeResponseValue(
|
|
|
1139
1260
|
} else {
|
|
1140
1261
|
return `${restValue} as any`;
|
|
1141
1262
|
}
|
|
1263
|
+
case "model": // generate deserialize logic for spread model types
|
|
1264
|
+
return `{${getResponseMapping(context, type, "").join(",")}}`;
|
|
1265
|
+
case "nullable":
|
|
1266
|
+
return deserializeResponseValue(
|
|
1267
|
+
context,
|
|
1268
|
+
type.type,
|
|
1269
|
+
restValue,
|
|
1270
|
+
getEncodeForType(type.type)
|
|
1271
|
+
);
|
|
1142
1272
|
default:
|
|
1143
1273
|
return restValue;
|
|
1144
1274
|
}
|
|
1145
1275
|
}
|
|
1146
1276
|
|
|
1147
|
-
export function isLroAndPagingOperation(
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
export function isLroOnlyOperation(op: Operation): boolean {
|
|
1152
|
-
return op.discriminator === "lro";
|
|
1277
|
+
export function isLroAndPagingOperation(
|
|
1278
|
+
op: SdkMethod<SdkHttpOperation>
|
|
1279
|
+
): op is SdkLroPagingServiceMethod<SdkHttpOperation> {
|
|
1280
|
+
return op.kind === "lropaging";
|
|
1153
1281
|
}
|
|
1154
1282
|
|
|
1155
|
-
export function
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
export function hasPagingOnlyOperation(
|
|
1160
|
-
codeModel: ModularCodeModel,
|
|
1161
|
-
needRLC?: boolean
|
|
1162
|
-
): boolean;
|
|
1163
|
-
export function hasPagingOnlyOperation(
|
|
1164
|
-
clientOrCodeModel: Client | ModularCodeModel,
|
|
1165
|
-
needRLC: boolean = false
|
|
1166
|
-
): boolean {
|
|
1167
|
-
let clients: Client[] = [];
|
|
1168
|
-
if ((clientOrCodeModel as any)?.operationGroups) {
|
|
1169
|
-
clients = [clientOrCodeModel as Client];
|
|
1170
|
-
} else if ((clientOrCodeModel as any)?.clients) {
|
|
1171
|
-
clients = (clientOrCodeModel as ModularCodeModel).clients;
|
|
1172
|
-
}
|
|
1173
|
-
return clients.some(
|
|
1174
|
-
(c) =>
|
|
1175
|
-
(needRLC ? c.rlcHelperDetails.hasPaging : false) ||
|
|
1176
|
-
(c.operationGroups ?? []).some((og) =>
|
|
1177
|
-
(og.operations ?? []).some(isPagingOnlyOperation)
|
|
1178
|
-
)
|
|
1179
|
-
);
|
|
1283
|
+
export function isLroOnlyOperation(
|
|
1284
|
+
op: SdkMethod<SdkHttpOperation>
|
|
1285
|
+
): op is SdkLroServiceMethod<SdkHttpOperation> {
|
|
1286
|
+
return op.kind === "lro";
|
|
1180
1287
|
}
|
|
1181
1288
|
|
|
1182
|
-
export function isPagingOnlyOperation(
|
|
1183
|
-
|
|
1289
|
+
export function isPagingOnlyOperation(
|
|
1290
|
+
op: SdkMethod<SdkHttpOperation>
|
|
1291
|
+
): op is SdkPagingServiceMethod<SdkHttpOperation> {
|
|
1292
|
+
return op.kind === "paging";
|
|
1184
1293
|
}
|
|
1185
1294
|
|
|
1186
|
-
export function getAllProperties(
|
|
1187
|
-
|
|
1295
|
+
export function getAllProperties(
|
|
1296
|
+
type: SdkType,
|
|
1297
|
+
parents?: SdkType[]
|
|
1298
|
+
): SdkModelPropertyType[] {
|
|
1299
|
+
const propertiesMap: Map<string, SdkModelPropertyType> = new Map();
|
|
1188
1300
|
if (!type) {
|
|
1189
1301
|
return [];
|
|
1190
1302
|
}
|
|
1191
1303
|
parents?.forEach((p) => {
|
|
1192
1304
|
getAllProperties(p).forEach((prop) => {
|
|
1193
|
-
propertiesMap.set(prop.
|
|
1305
|
+
propertiesMap.set(prop.name, prop);
|
|
1194
1306
|
});
|
|
1195
1307
|
});
|
|
1196
|
-
type.
|
|
1197
|
-
|
|
1198
|
-
|
|
1308
|
+
type.kind === "model" &&
|
|
1309
|
+
type.properties
|
|
1310
|
+
?.filter((p) => {
|
|
1311
|
+
return p.kind === "property";
|
|
1312
|
+
})
|
|
1313
|
+
.forEach((p) => {
|
|
1314
|
+
propertiesMap.set(p.name, p);
|
|
1315
|
+
});
|
|
1199
1316
|
return [...propertiesMap.values()];
|
|
1200
1317
|
}
|
|
1201
1318
|
|
|
1202
|
-
export function getAllAncestors(type:
|
|
1203
|
-
const ancestors:
|
|
1204
|
-
type
|
|
1205
|
-
ancestors.push(
|
|
1206
|
-
ancestors.push(...getAllAncestors(
|
|
1207
|
-
}
|
|
1319
|
+
export function getAllAncestors(type: SdkType): SdkType[] {
|
|
1320
|
+
const ancestors: SdkType[] = [];
|
|
1321
|
+
if (type.kind === "model" && type.baseModel) {
|
|
1322
|
+
ancestors.push(type.baseModel);
|
|
1323
|
+
ancestors.push(...getAllAncestors(type.baseModel));
|
|
1324
|
+
}
|
|
1208
1325
|
return ancestors;
|
|
1209
1326
|
}
|
|
1210
1327
|
|
|
1211
1328
|
export function getPropertySerializationPrefix(
|
|
1212
|
-
|
|
1329
|
+
context: SdkContext,
|
|
1330
|
+
property: SdkServiceParameter | SdkModelPropertyType,
|
|
1213
1331
|
propertyPath?: string
|
|
1214
1332
|
) {
|
|
1215
|
-
const propertyFullName = getPropertyFullName(
|
|
1216
|
-
if (
|
|
1217
|
-
return `!${propertyFullName}
|
|
1333
|
+
const propertyFullName = getPropertyFullName(context, property, propertyPath);
|
|
1334
|
+
if (property.optional || isTypeNullable(property.type)) {
|
|
1335
|
+
return `!${propertyFullName}? ${propertyFullName}:`;
|
|
1218
1336
|
}
|
|
1219
1337
|
|
|
1220
1338
|
return "";
|
|
1221
1339
|
}
|
|
1222
1340
|
|
|
1223
1341
|
export function getPropertyFullName(
|
|
1224
|
-
|
|
1342
|
+
context: SdkContext,
|
|
1343
|
+
property: SdkServiceParameter | SdkModelPropertyType,
|
|
1225
1344
|
propertyPath?: string
|
|
1226
1345
|
) {
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1346
|
+
const normalizedPropertyName = normalizeModelPropertyName(context, property)
|
|
1347
|
+
.replace(/^"/g, "")
|
|
1348
|
+
.replace(/"$/g, "");
|
|
1349
|
+
let fullName = normalizedPropertyName;
|
|
1350
|
+
if (propertyPath === "" && property.optional) {
|
|
1351
|
+
fullName = `options?.${normalizedPropertyName}`;
|
|
1352
|
+
} else if (propertyPath) {
|
|
1353
|
+
fullName = `${propertyPath}["${normalizedPropertyName}"]`;
|
|
1230
1354
|
}
|
|
1231
1355
|
return fullName;
|
|
1232
1356
|
}
|
|
@@ -1235,14 +1359,12 @@ export function getPropertyFullName(
|
|
|
1235
1359
|
* Get an expression representing an array of expected status codes for the operation
|
|
1236
1360
|
* @param operation The operation
|
|
1237
1361
|
*/
|
|
1238
|
-
export function getExpectedStatuses(operation:
|
|
1239
|
-
const statusCodes = operation.responses.
|
|
1240
|
-
x.statusCodes.filter((s) => s !== "default")
|
|
1241
|
-
);
|
|
1362
|
+
export function getExpectedStatuses(operation: ServiceOperation): string {
|
|
1363
|
+
const statusCodes = operation.operation.responses.map((x) => x.statusCodes);
|
|
1242
1364
|
// LROs may call the same path but with GET to get the operation status.
|
|
1243
1365
|
if (
|
|
1244
1366
|
isLroOnlyOperation(operation) &&
|
|
1245
|
-
operation.
|
|
1367
|
+
operation.operation.verb !== "get" &&
|
|
1246
1368
|
!statusCodes.includes(200)
|
|
1247
1369
|
) {
|
|
1248
1370
|
statusCodes.push(200);
|