@azure-tools/typespec-ts 0.48.0 → 0.48.1-alpha.20260127.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/index.d.ts.map +1 -1
- package/dist/src/index.js +20 -5
- package/dist/src/index.js.map +1 -1
- package/dist/src/modular/buildClientContext.d.ts.map +1 -1
- package/dist/src/modular/buildClientContext.js +7 -3
- package/dist/src/modular/buildClientContext.js.map +1 -1
- package/dist/src/modular/buildOperations.d.ts.map +1 -1
- package/dist/src/modular/buildOperations.js +24 -3
- package/dist/src/modular/buildOperations.js.map +1 -1
- package/dist/src/modular/emitModels.d.ts.map +1 -1
- package/dist/src/modular/emitModels.js +19 -0
- package/dist/src/modular/emitModels.js.map +1 -1
- package/dist/src/modular/emitSamples.js +2 -2
- package/dist/src/modular/emitSamples.js.map +1 -1
- package/dist/src/modular/helpers/clientHelpers.d.ts +2 -1
- package/dist/src/modular/helpers/clientHelpers.d.ts.map +1 -1
- package/dist/src/modular/helpers/clientHelpers.js +5 -2
- package/dist/src/modular/helpers/clientHelpers.js.map +1 -1
- package/dist/src/modular/helpers/operationHelpers.d.ts.map +1 -1
- package/dist/src/modular/helpers/operationHelpers.js +266 -43
- package/dist/src/modular/helpers/operationHelpers.js.map +1 -1
- package/dist/src/modular/serialization/buildXmlSerializerFunction.d.ts +32 -0
- package/dist/src/modular/serialization/buildXmlSerializerFunction.d.ts.map +1 -0
- package/dist/src/modular/serialization/buildXmlSerializerFunction.js +373 -0
- package/dist/src/modular/serialization/buildXmlSerializerFunction.js.map +1 -0
- package/dist/src/modular/static-helpers-metadata.d.ts +57 -0
- package/dist/src/modular/static-helpers-metadata.d.ts.map +1 -1
- package/dist/src/modular/static-helpers-metadata.js +57 -0
- package/dist/src/modular/static-helpers-metadata.js.map +1 -1
- package/dist/src/utils/clientUtils.d.ts.map +1 -1
- package/dist/src/utils/clientUtils.js +1 -0
- package/dist/src/utils/clientUtils.js.map +1 -1
- package/dist/src/utils/mediaTypes.d.ts +4 -0
- package/dist/src/utils/mediaTypes.d.ts.map +1 -1
- package/dist/src/utils/mediaTypes.js +10 -0
- package/dist/src/utils/mediaTypes.js.map +1 -1
- package/dist/src/utils/modelUtils.d.ts.map +1 -1
- package/dist/src/utils/modelUtils.js +3 -0
- package/dist/src/utils/modelUtils.js.map +1 -1
- package/dist/src/utils/operationUtil.d.ts +12 -0
- package/dist/src/utils/operationUtil.d.ts.map +1 -1
- package/dist/src/utils/operationUtil.js +22 -1
- package/dist/src/utils/operationUtil.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -7
- package/src/index.ts +20 -5
- package/src/modular/buildClientContext.ts +12 -5
- package/src/modular/buildOperations.ts +34 -3
- package/src/modular/emitModels.ts +43 -0
- package/src/modular/emitSamples.ts +2 -2
- package/src/modular/helpers/clientHelpers.ts +6 -2
- package/src/modular/helpers/operationHelpers.ts +377 -57
- package/src/modular/serialization/buildXmlSerializerFunction.ts +511 -0
- package/src/modular/static-helpers-metadata.ts +58 -0
- package/src/utils/clientUtils.ts +1 -0
- package/src/utils/mediaTypes.ts +12 -0
- package/src/utils/modelUtils.ts +3 -0
- package/src/utils/operationUtil.ts +34 -1
- package/static/static-helpers/serialization/xml-helpers.ts +596 -0
|
@@ -9,7 +9,8 @@ import {
|
|
|
9
9
|
PagingHelpers,
|
|
10
10
|
PollingHelpers,
|
|
11
11
|
SerializationHelpers,
|
|
12
|
-
UrlTemplateHelpers
|
|
12
|
+
UrlTemplateHelpers,
|
|
13
|
+
XmlHelpers
|
|
13
14
|
} from "../static-helpers-metadata.js";
|
|
14
15
|
import {
|
|
15
16
|
getNullableValidType,
|
|
@@ -21,6 +22,9 @@ import {
|
|
|
21
22
|
getCollectionFormatHelper,
|
|
22
23
|
hasCollectionFormatInfo,
|
|
23
24
|
isBinaryPayload,
|
|
25
|
+
isXmlPayload,
|
|
26
|
+
isMultipartPayload,
|
|
27
|
+
hasDualFormatSupport,
|
|
24
28
|
ServiceOperation,
|
|
25
29
|
getCollectionFormatParseHelper,
|
|
26
30
|
getCollectionFormatFromArrayEncoding,
|
|
@@ -46,6 +50,11 @@ import {
|
|
|
46
50
|
buildModelSerializer,
|
|
47
51
|
buildPropertySerializer
|
|
48
52
|
} from "../serialization/buildSerializerFunction.js";
|
|
53
|
+
import {
|
|
54
|
+
buildXmlModelSerializer,
|
|
55
|
+
buildXmlModelDeserializer,
|
|
56
|
+
hasXmlSerialization
|
|
57
|
+
} from "../serialization/buildXmlSerializerFunction.js";
|
|
49
58
|
import { refkey } from "../../framework/refkey.js";
|
|
50
59
|
import { reportDiagnostic } from "../../lib.js";
|
|
51
60
|
import { resolveReference } from "../../framework/reference.js";
|
|
@@ -63,6 +72,7 @@ import {
|
|
|
63
72
|
SdkBodyParameter,
|
|
64
73
|
SdkClientType,
|
|
65
74
|
SdkConstantType,
|
|
75
|
+
SdkEnumType,
|
|
66
76
|
SdkHttpOperation,
|
|
67
77
|
SdkHttpParameter,
|
|
68
78
|
SdkLroPagingServiceMethod,
|
|
@@ -76,6 +86,7 @@ import {
|
|
|
76
86
|
} from "@azure-tools/typespec-client-generator-core";
|
|
77
87
|
import { isMetadata } from "@typespec/http";
|
|
78
88
|
import { useContext } from "../../contextManager.js";
|
|
89
|
+
import { isExtensibleEnum } from "../type-expressions/get-enum-expression.js";
|
|
79
90
|
|
|
80
91
|
export function getSendPrivateFunction(
|
|
81
92
|
dpgContext: SdkContext,
|
|
@@ -158,16 +169,15 @@ export function getDeserializePrivateFunction(
|
|
|
158
169
|
type: PathUncheckedResponseReference
|
|
159
170
|
}
|
|
160
171
|
];
|
|
161
|
-
// TODO: Support LRO + paging operation
|
|
162
|
-
// https://github.com/Azure/autorest.typescript/issues/2313
|
|
163
172
|
const isLroOnly = isLroOnlyOperation(operation);
|
|
173
|
+
const isLroAndPaging = isLroAndPagingOperation(operation);
|
|
164
174
|
|
|
165
175
|
// TODO: Support operation overloads
|
|
166
176
|
// TODO: Support multiple responses
|
|
167
177
|
const response = operation.response;
|
|
168
178
|
const restResponse = operation.operation.responses[0];
|
|
169
179
|
let returnType;
|
|
170
|
-
if (isLroOnly) {
|
|
180
|
+
if (isLroOnly || isLroAndPaging) {
|
|
171
181
|
returnType = buildLroReturnType(context, operation);
|
|
172
182
|
} else if (response.type && restResponse) {
|
|
173
183
|
returnType = {
|
|
@@ -198,11 +208,12 @@ export function getDeserializePrivateFunction(
|
|
|
198
208
|
`${getExceptionThrowStatement(context, operation)}`,
|
|
199
209
|
"}"
|
|
200
210
|
);
|
|
201
|
-
const deserializedType =
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
211
|
+
const deserializedType =
|
|
212
|
+
isLroOnly || isLroAndPaging
|
|
213
|
+
? operation?.lroMetadata?.finalResponse?.result
|
|
214
|
+
: restResponse
|
|
215
|
+
? restResponse.type
|
|
216
|
+
: response.type;
|
|
206
217
|
const lroSubSegments = isLroOnly
|
|
207
218
|
? operation?.lroMetadata?.finalResponse?.resultSegments
|
|
208
219
|
: undefined;
|
|
@@ -229,31 +240,130 @@ export function getDeserializePrivateFunction(
|
|
|
229
240
|
}
|
|
230
241
|
|
|
231
242
|
if (deserializedType) {
|
|
232
|
-
const contentTypes = operation.operation.responses[0]?.contentTypes;
|
|
233
|
-
const
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
243
|
+
const contentTypes = operation.operation.responses[0]?.contentTypes ?? [];
|
|
244
|
+
const isXml = isXmlPayload(contentTypes);
|
|
245
|
+
const isDualFormat = hasDualFormatSupport(contentTypes);
|
|
246
|
+
const isMultipart = isMultipartPayload(contentTypes);
|
|
247
|
+
const useXmlDeserialization =
|
|
248
|
+
isXml &&
|
|
249
|
+
deserializedType.kind === "model" &&
|
|
250
|
+
hasXmlSerialization(deserializedType);
|
|
251
|
+
|
|
252
|
+
// Workaround for multipart response: cast return value as any due to lack of multipart response handling in core
|
|
253
|
+
const multipartCastSuffix = isMultipart ? " as any" : "";
|
|
254
|
+
|
|
255
|
+
// For dual-format responses, check content-type header at runtime
|
|
256
|
+
if (
|
|
257
|
+
isDualFormat &&
|
|
258
|
+
deserializedType.kind === "model" &&
|
|
259
|
+
hasXmlSerialization(deserializedType)
|
|
260
|
+
) {
|
|
261
|
+
const xmlDeserializerName = buildXmlModelDeserializer(
|
|
262
|
+
context,
|
|
263
|
+
deserializedType,
|
|
264
|
+
{
|
|
265
|
+
nameOnly: true,
|
|
266
|
+
skipDiscriminatedUnionSuffix: false
|
|
267
|
+
}
|
|
268
|
+
) as string | undefined;
|
|
269
|
+
const jsonDeserializerName = buildModelDeserializer(
|
|
270
|
+
context,
|
|
271
|
+
deserializedType,
|
|
272
|
+
{
|
|
273
|
+
nameOnly: true,
|
|
274
|
+
skipDiscriminatedUnionSuffix: false
|
|
275
|
+
}
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
if (xmlDeserializerName && jsonDeserializerName) {
|
|
279
|
+
const isXmlContentTypeRef = resolveReference(
|
|
280
|
+
XmlHelpers.isXmlContentType
|
|
281
|
+
);
|
|
282
|
+
statements.push(
|
|
283
|
+
`const responseContentType = result.headers?.["content-type"] ?? "";
|
|
284
|
+
if (${isXmlContentTypeRef}(responseContentType)) {
|
|
285
|
+
return ${xmlDeserializerName}(${deserializedRoot});
|
|
286
|
+
}
|
|
287
|
+
return ${jsonDeserializerName}(${deserializedRoot});`
|
|
288
|
+
);
|
|
289
|
+
} else {
|
|
290
|
+
// Fall back to JSON deserializer
|
|
291
|
+
const deserializeFunctionName = buildModelDeserializer(
|
|
292
|
+
context,
|
|
293
|
+
deserializedType,
|
|
294
|
+
{
|
|
295
|
+
nameOnly: true,
|
|
296
|
+
skipDiscriminatedUnionSuffix: false
|
|
297
|
+
}
|
|
298
|
+
);
|
|
299
|
+
if (deserializeFunctionName) {
|
|
300
|
+
statements.push(
|
|
301
|
+
`return ${deserializeFunctionName}(${deserializedRoot})`
|
|
302
|
+
);
|
|
303
|
+
}
|
|
239
304
|
}
|
|
240
|
-
)
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
305
|
+
} else if (useXmlDeserialization) {
|
|
306
|
+
// XML-only response
|
|
307
|
+
const xmlDeserializerName = buildXmlModelDeserializer(
|
|
308
|
+
context,
|
|
309
|
+
deserializedType,
|
|
310
|
+
{
|
|
311
|
+
nameOnly: true,
|
|
312
|
+
skipDiscriminatedUnionSuffix: false
|
|
313
|
+
}
|
|
314
|
+
) as string | undefined;
|
|
315
|
+
|
|
316
|
+
if (xmlDeserializerName) {
|
|
317
|
+
statements.push(`return ${xmlDeserializerName}(${deserializedRoot})`);
|
|
318
|
+
} else {
|
|
319
|
+
// Fall back to JSON deserializer if XML deserializer is not available
|
|
320
|
+
const deserializeFunctionName = buildModelDeserializer(
|
|
248
321
|
context,
|
|
249
322
|
deserializedType,
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
)
|
|
323
|
+
{
|
|
324
|
+
nameOnly: true,
|
|
325
|
+
skipDiscriminatedUnionSuffix: false
|
|
326
|
+
}
|
|
327
|
+
);
|
|
328
|
+
if (deserializeFunctionName) {
|
|
329
|
+
statements.push(
|
|
330
|
+
`return ${deserializeFunctionName}(${deserializedRoot})`
|
|
331
|
+
);
|
|
332
|
+
} else {
|
|
333
|
+
statements.push(`return ${deserializedRoot}`);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
} else {
|
|
337
|
+
// JSON response (default) - also handles multipart responses
|
|
338
|
+
const deserializeFunctionName = buildModelDeserializer(
|
|
339
|
+
context,
|
|
340
|
+
deserializedType,
|
|
341
|
+
{
|
|
342
|
+
nameOnly: true,
|
|
343
|
+
skipDiscriminatedUnionSuffix: false
|
|
344
|
+
}
|
|
256
345
|
);
|
|
346
|
+
if (deserializeFunctionName) {
|
|
347
|
+
statements.push(
|
|
348
|
+
`return ${deserializeFunctionName}(${deserializedRoot})${multipartCastSuffix}`
|
|
349
|
+
);
|
|
350
|
+
} else if (
|
|
351
|
+
isAzureCoreErrorType(context.program, deserializedType.__raw)
|
|
352
|
+
) {
|
|
353
|
+
statements.push(`return ${deserializedRoot}${multipartCastSuffix}`);
|
|
354
|
+
} else {
|
|
355
|
+
statements.push(
|
|
356
|
+
`return ${deserializeResponseValue(
|
|
357
|
+
context,
|
|
358
|
+
deserializedType,
|
|
359
|
+
deserializedRoot,
|
|
360
|
+
true,
|
|
361
|
+
isBinaryPayload(context, response.type!.__raw!, contentTypes)
|
|
362
|
+
? "binary"
|
|
363
|
+
: getEncodeForType(deserializedType)
|
|
364
|
+
)}${multipartCastSuffix}`
|
|
365
|
+
);
|
|
366
|
+
}
|
|
257
367
|
}
|
|
258
368
|
} else if (returnType.type === "void") {
|
|
259
369
|
statements.push("return;");
|
|
@@ -465,8 +575,13 @@ export function getOperationFunction(
|
|
|
465
575
|
optionalParamName
|
|
466
576
|
);
|
|
467
577
|
} else if (isLroAndPagingOperation(operation)) {
|
|
468
|
-
// Case 3: both paging + lro operation
|
|
469
|
-
|
|
578
|
+
// Case 3: both paging + lro operation
|
|
579
|
+
return getLroAndPagingOperationFunction(
|
|
580
|
+
context,
|
|
581
|
+
[method[0], operation],
|
|
582
|
+
clientType,
|
|
583
|
+
optionalParamName
|
|
584
|
+
);
|
|
470
585
|
}
|
|
471
586
|
|
|
472
587
|
// TODO: Support operation overloads
|
|
@@ -594,9 +709,99 @@ function getLroOnlyOperationFunction(
|
|
|
594
709
|
} as FunctionDeclarationStructure & { propertyName?: string };
|
|
595
710
|
}
|
|
596
711
|
|
|
712
|
+
function getLroAndPagingOperationFunction(
|
|
713
|
+
context: SdkContext,
|
|
714
|
+
method: [string[], SdkLroPagingServiceMethod<SdkHttpOperation>],
|
|
715
|
+
clientType: string,
|
|
716
|
+
optionalParamName: string = "options"
|
|
717
|
+
): FunctionDeclarationStructure & { propertyName?: string } {
|
|
718
|
+
const operation = method[1];
|
|
719
|
+
const parameters = getOperationSignatureParameters(
|
|
720
|
+
context,
|
|
721
|
+
method,
|
|
722
|
+
clientType
|
|
723
|
+
);
|
|
724
|
+
const { name, fixme = [] } = getOperationName(operation);
|
|
725
|
+
|
|
726
|
+
const returnType = buildLroPagingReturnType(context, operation);
|
|
727
|
+
|
|
728
|
+
// Build paging options from metadata
|
|
729
|
+
const pagingOptions = [
|
|
730
|
+
operation.response.resultSegments &&
|
|
731
|
+
`itemName: "${operation.response.resultSegments.map((p) => p.name).join(".")}"`,
|
|
732
|
+
operation.pagingMetadata.nextLinkSegments &&
|
|
733
|
+
`nextLinkName: "${operation.pagingMetadata.nextLinkSegments.map((p) => p.name).join(".")}"`,
|
|
734
|
+
operation.pagingMetadata.nextLinkVerb !== "GET" &&
|
|
735
|
+
`nextLinkMethod: "${operation.pagingMetadata.nextLinkVerb}"`
|
|
736
|
+
].filter(Boolean);
|
|
737
|
+
|
|
738
|
+
// Build LRO resource location config
|
|
739
|
+
const allowedLocations = [
|
|
740
|
+
"azure-async-operation",
|
|
741
|
+
"location",
|
|
742
|
+
"original-uri",
|
|
743
|
+
"operation-location"
|
|
744
|
+
];
|
|
745
|
+
const resourceLocationConfig =
|
|
746
|
+
operation.lroMetadata?.finalStateVia &&
|
|
747
|
+
allowedLocations.includes(operation.lroMetadata.finalStateVia)
|
|
748
|
+
? `resourceLocationConfig: "${operation.lroMetadata.finalStateVia}"`
|
|
749
|
+
: "";
|
|
750
|
+
|
|
751
|
+
// Resolve references
|
|
752
|
+
const refs = {
|
|
753
|
+
pagedIterator: resolveReference(PagingHelpers.PagedAsyncIterableIterator),
|
|
754
|
+
buildPaging: resolveReference(PagingHelpers.BuildPagedAsyncIterator),
|
|
755
|
+
getLroPoller: resolveReference(PollingHelpers.GetLongRunningPoller),
|
|
756
|
+
pollerLike: resolveReference(AzurePollingDependencies.PollerLike),
|
|
757
|
+
operationState: resolveReference(AzurePollingDependencies.OperationState),
|
|
758
|
+
pathResponse: resolveReference(useDependencies().PathUncheckedResponse)
|
|
759
|
+
};
|
|
760
|
+
|
|
761
|
+
const expectedStatuses = getExpectedStatuses(operation);
|
|
762
|
+
const paramList = parameters.map((p) => p.name).join(", ");
|
|
763
|
+
const pagingOptionsStr =
|
|
764
|
+
pagingOptions.length > 0 ? `,\n {${pagingOptions.join(", ")}}` : "";
|
|
765
|
+
|
|
766
|
+
return {
|
|
767
|
+
kind: StructureKind.Function,
|
|
768
|
+
docs: [
|
|
769
|
+
...getDocsFromDescription(operation.doc),
|
|
770
|
+
...getFixmeForMultilineDocs(fixme)
|
|
771
|
+
],
|
|
772
|
+
isAsync: false,
|
|
773
|
+
isExported: true,
|
|
774
|
+
name,
|
|
775
|
+
propertyName: normalizeName(operation.name, NameType.Property),
|
|
776
|
+
parameters,
|
|
777
|
+
returnType: `${refs.pagedIterator}<${returnType.type}>`,
|
|
778
|
+
statements: [
|
|
779
|
+
`
|
|
780
|
+
const initialPagingPoller = ${refs.getLroPoller}(context,
|
|
781
|
+
async (result: ${refs.pathResponse}) => result,
|
|
782
|
+
${expectedStatuses}, {
|
|
783
|
+
updateIntervalInMs: ${optionalParamName}?.updateIntervalInMs,
|
|
784
|
+
abortSignal: ${optionalParamName}?.abortSignal,
|
|
785
|
+
getInitialResponse: () => _${name}Send(${paramList}),
|
|
786
|
+
${resourceLocationConfig}
|
|
787
|
+
}) as ${refs.pollerLike}<${refs.operationState}<${refs.pathResponse}>, ${refs.pathResponse}>;
|
|
788
|
+
|
|
789
|
+
return ${refs.buildPaging}(
|
|
790
|
+
context,
|
|
791
|
+
async () => await initialPagingPoller,
|
|
792
|
+
_${name}Deserialize,
|
|
793
|
+
${expectedStatuses}${pagingOptionsStr}
|
|
794
|
+
);
|
|
795
|
+
`
|
|
796
|
+
]
|
|
797
|
+
};
|
|
798
|
+
}
|
|
799
|
+
|
|
597
800
|
function buildLroReturnType(
|
|
598
801
|
context: SdkContext,
|
|
599
|
-
operation:
|
|
802
|
+
operation:
|
|
803
|
+
| SdkLroServiceMethod<SdkHttpOperation>
|
|
804
|
+
| SdkLroPagingServiceMethod<SdkHttpOperation>
|
|
600
805
|
) {
|
|
601
806
|
const metadata = operation.lroMetadata;
|
|
602
807
|
if (metadata !== undefined && metadata.finalResponse !== undefined) {
|
|
@@ -609,6 +814,19 @@ function buildLroReturnType(
|
|
|
609
814
|
return { name: "", type: "void" };
|
|
610
815
|
}
|
|
611
816
|
|
|
817
|
+
function buildLroPagingReturnType(
|
|
818
|
+
context: SdkContext,
|
|
819
|
+
operation: SdkLroPagingServiceMethod<SdkHttpOperation>
|
|
820
|
+
) {
|
|
821
|
+
if (operation.response.type?.kind === "array") {
|
|
822
|
+
return {
|
|
823
|
+
name: (operation.response.type.valueType as any).name ?? "",
|
|
824
|
+
type: getTypeExpression(context, operation.response.type.valueType)
|
|
825
|
+
};
|
|
826
|
+
}
|
|
827
|
+
return { name: "", type: "void" };
|
|
828
|
+
}
|
|
829
|
+
|
|
612
830
|
function getPagingOnlyOperationFunction(
|
|
613
831
|
context: SdkContext,
|
|
614
832
|
method: [string[], SdkPagingServiceMethod<SdkHttpOperation>],
|
|
@@ -824,14 +1042,31 @@ function buildBodyParameter(
|
|
|
824
1042
|
if (!bodyParameter || !bodyParameter.type) {
|
|
825
1043
|
return "";
|
|
826
1044
|
}
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
1045
|
+
|
|
1046
|
+
const contentTypes = bodyParameter.contentTypes;
|
|
1047
|
+
const isXml = isXmlPayload(contentTypes);
|
|
1048
|
+
const isDualFormat = hasDualFormatSupport(contentTypes);
|
|
1049
|
+
const bodyType = getNullableValidType(bodyParameter.type);
|
|
1050
|
+
|
|
1051
|
+
// Check if XML serialization is needed and available
|
|
1052
|
+
const useXmlSerialization =
|
|
1053
|
+
isXml && bodyType.kind === "model" && hasXmlSerialization(bodyType);
|
|
1054
|
+
|
|
1055
|
+
let serializerFunctionName: string | undefined;
|
|
1056
|
+
|
|
1057
|
+
if (useXmlSerialization) {
|
|
1058
|
+
// Use XML serializer
|
|
1059
|
+
serializerFunctionName = buildXmlModelSerializer(context, bodyType, {
|
|
831
1060
|
nameOnly: true,
|
|
832
1061
|
skipDiscriminatedUnionSuffix: false
|
|
833
|
-
}
|
|
834
|
-
|
|
1062
|
+
}) as string | undefined;
|
|
1063
|
+
} else {
|
|
1064
|
+
// Use JSON serializer (default)
|
|
1065
|
+
serializerFunctionName = buildModelSerializer(context, bodyType, {
|
|
1066
|
+
nameOnly: true,
|
|
1067
|
+
skipDiscriminatedUnionSuffix: false
|
|
1068
|
+
}) as string | undefined;
|
|
1069
|
+
}
|
|
835
1070
|
|
|
836
1071
|
const bodyParamName = normalizeName(
|
|
837
1072
|
bodyParameter.name,
|
|
@@ -846,6 +1081,28 @@ function buildBodyParameter(
|
|
|
846
1081
|
bodyParameter,
|
|
847
1082
|
bodyParameter.optional ? optionalParamName : undefined
|
|
848
1083
|
);
|
|
1084
|
+
|
|
1085
|
+
// For dual-format operations, check the contentType option at runtime
|
|
1086
|
+
if (
|
|
1087
|
+
isDualFormat &&
|
|
1088
|
+
bodyType.kind === "model" &&
|
|
1089
|
+
hasXmlSerialization(bodyType)
|
|
1090
|
+
) {
|
|
1091
|
+
const xmlSerializerName = buildXmlModelSerializer(context, bodyType, {
|
|
1092
|
+
nameOnly: true,
|
|
1093
|
+
skipDiscriminatedUnionSuffix: false
|
|
1094
|
+
}) as string | undefined;
|
|
1095
|
+
const jsonSerializerName = buildModelSerializer(context, bodyType, {
|
|
1096
|
+
nameOnly: true,
|
|
1097
|
+
skipDiscriminatedUnionSuffix: false
|
|
1098
|
+
}) as string | undefined;
|
|
1099
|
+
|
|
1100
|
+
if (xmlSerializerName && jsonSerializerName) {
|
|
1101
|
+
const isXmlContentTypeRef = resolveReference(XmlHelpers.isXmlContentType);
|
|
1102
|
+
return `\nbody: ${nullOrUndefinedPrefix}(${isXmlContentTypeRef}(${optionalParamName}?.contentType ?? "application/json") ? ${xmlSerializerName}(${bodyNameExpression}) : ${jsonSerializerName}(${bodyNameExpression})),`;
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
|
|
849
1106
|
// if a model being used in both spread and non spread operation, we should only leverage the deserializer in non spread operation
|
|
850
1107
|
if (serializerFunctionName && !isSpreadBodyParameter(bodyParameter)) {
|
|
851
1108
|
return `\nbody: ${nullOrUndefinedPrefix}${serializerFunctionName}(${bodyNameExpression}),`;
|
|
@@ -884,21 +1141,32 @@ export function getParameterMap(
|
|
|
884
1141
|
param: SdkHttpParameter,
|
|
885
1142
|
optionalParamName: string = "options"
|
|
886
1143
|
): string {
|
|
1144
|
+
// Use lowercase for header names since HTTP headers are case-insensitive
|
|
1145
|
+
const serializedName =
|
|
1146
|
+
param.kind === "header"
|
|
1147
|
+
? getHeaderSerializedName(param)
|
|
1148
|
+
: getPropertySerializedName(param);
|
|
1149
|
+
|
|
887
1150
|
if (isConstant(param.type)) {
|
|
888
|
-
return `"${
|
|
1151
|
+
return `"${serializedName}": ${getConstantValue(param.type)}`;
|
|
889
1152
|
}
|
|
890
1153
|
|
|
891
1154
|
if (hasCollectionFormatInfo(param.kind, (param as any).collectionFormat)) {
|
|
892
|
-
return getCollectionFormatForParam(
|
|
1155
|
+
return getCollectionFormatForParam(
|
|
1156
|
+
context,
|
|
1157
|
+
param,
|
|
1158
|
+
optionalParamName,
|
|
1159
|
+
serializedName
|
|
1160
|
+
);
|
|
893
1161
|
}
|
|
894
1162
|
|
|
895
1163
|
// if the parameter or property is optional, we don't need to handle the default value
|
|
896
1164
|
if (isOptional(param)) {
|
|
897
|
-
return getOptional(context, param, optionalParamName);
|
|
1165
|
+
return getOptional(context, param, optionalParamName, serializedName);
|
|
898
1166
|
}
|
|
899
1167
|
|
|
900
1168
|
if (isRequired(param)) {
|
|
901
|
-
return getRequired(context, param);
|
|
1169
|
+
return getRequired(context, param, serializedName);
|
|
902
1170
|
}
|
|
903
1171
|
|
|
904
1172
|
reportDiagnostic(context.program, {
|
|
@@ -917,9 +1185,9 @@ export function getParameterMap(
|
|
|
917
1185
|
function getCollectionFormatForParam(
|
|
918
1186
|
context: SdkContext,
|
|
919
1187
|
param: SdkHttpParameter,
|
|
920
|
-
optionalParamName: string = "options"
|
|
1188
|
+
optionalParamName: string = "options",
|
|
1189
|
+
serializedName: string
|
|
921
1190
|
) {
|
|
922
|
-
const serializedName = getPropertySerializedName(param);
|
|
923
1191
|
const format = (param as any).collectionFormat;
|
|
924
1192
|
return `"${serializedName}": ${serializeRequestValue(
|
|
925
1193
|
context,
|
|
@@ -963,8 +1231,11 @@ function isRequired(param: SdkHttpParameter) {
|
|
|
963
1231
|
return !param.optional;
|
|
964
1232
|
}
|
|
965
1233
|
|
|
966
|
-
function getRequired(
|
|
967
|
-
|
|
1234
|
+
function getRequired(
|
|
1235
|
+
context: SdkContext,
|
|
1236
|
+
param: SdkHttpParameter,
|
|
1237
|
+
serializedName: string
|
|
1238
|
+
) {
|
|
968
1239
|
const clientValue = `${param.onClient ? "context." : ""}${param.name}`;
|
|
969
1240
|
if (param.type.kind === "model") {
|
|
970
1241
|
const propertiesStr = getRequestModelMapping(
|
|
@@ -1003,9 +1274,9 @@ function isOptional(param: SdkHttpParameter) {
|
|
|
1003
1274
|
function getOptional(
|
|
1004
1275
|
context: SdkContext,
|
|
1005
1276
|
param: SdkHttpParameter,
|
|
1006
|
-
optionalParamName: string
|
|
1277
|
+
optionalParamName: string,
|
|
1278
|
+
serializedName: string
|
|
1007
1279
|
) {
|
|
1008
|
-
const serializedName = getPropertySerializedName(param);
|
|
1009
1280
|
const paramName = `${param.onClient ? "context." : `${optionalParamName}?.`}${param.name}`;
|
|
1010
1281
|
if (param.type.kind === "model") {
|
|
1011
1282
|
const propertiesStr = getRequestModelMapping(
|
|
@@ -1171,8 +1442,8 @@ function getEncodeForModelProperty(
|
|
|
1171
1442
|
property: SdkModelPropertyType
|
|
1172
1443
|
): string | undefined {
|
|
1173
1444
|
if (property.encode && property.type.kind === "array") {
|
|
1174
|
-
// Only arrays of string type can have collectionFormat encoding
|
|
1175
|
-
if (property.type.valueType
|
|
1445
|
+
// Only arrays of string type or string-based enum type can have collectionFormat encoding
|
|
1446
|
+
if (!isStringEncodableArrayValueType(property.type.valueType)) {
|
|
1176
1447
|
reportDiagnostic(context.program, {
|
|
1177
1448
|
code: "un-supported-array-encoding",
|
|
1178
1449
|
format: {
|
|
@@ -1197,6 +1468,25 @@ function getEncodeForModelProperty(
|
|
|
1197
1468
|
return getEncodeForType(property.type);
|
|
1198
1469
|
}
|
|
1199
1470
|
|
|
1471
|
+
/**
|
|
1472
|
+
* Checks if an array value type is string-encodable for collection format encoding.
|
|
1473
|
+
* This includes both string type and string-based enum types.
|
|
1474
|
+
*/
|
|
1475
|
+
function isStringEncodableArrayValueType(valueType: SdkType): boolean {
|
|
1476
|
+
// Direct string type
|
|
1477
|
+
if (valueType.kind === "string") {
|
|
1478
|
+
return true;
|
|
1479
|
+
}
|
|
1480
|
+
// String-based enum type
|
|
1481
|
+
if (
|
|
1482
|
+
valueType.kind === "enum" &&
|
|
1483
|
+
(valueType as SdkEnumType).valueType.kind === "string"
|
|
1484
|
+
) {
|
|
1485
|
+
return true;
|
|
1486
|
+
}
|
|
1487
|
+
return false;
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1200
1490
|
function getSerializationExpressionForFlatten(
|
|
1201
1491
|
context: SdkContext,
|
|
1202
1492
|
property: SdkModelPropertyType,
|
|
@@ -1336,6 +1626,14 @@ function getPropertySerializedName(
|
|
|
1336
1626
|
);
|
|
1337
1627
|
}
|
|
1338
1628
|
|
|
1629
|
+
/**
|
|
1630
|
+
* Get the serialized name for a header parameter, normalized to lowercase.
|
|
1631
|
+
* HTTP headers are case-insensitive, so we normalize to lowercase for consistency.
|
|
1632
|
+
*/
|
|
1633
|
+
function getHeaderSerializedName(param: SdkHttpParameter) {
|
|
1634
|
+
return getPropertySerializedName(param).toLowerCase();
|
|
1635
|
+
}
|
|
1636
|
+
|
|
1339
1637
|
/**
|
|
1340
1638
|
* This function helps translating an RLC response to an HLC response,
|
|
1341
1639
|
* extracting properties from body and headers and building the HLC response object
|
|
@@ -1589,7 +1887,15 @@ export function deserializeResponseValue(
|
|
|
1589
1887
|
isTypeNullable(type) || getOptionalForType(type) || !required
|
|
1590
1888
|
? `${restValue} === null || ${restValue} === undefined ? ${restValue}: `
|
|
1591
1889
|
: "";
|
|
1592
|
-
|
|
1890
|
+
if (
|
|
1891
|
+
type.valueType.kind === "enum" &&
|
|
1892
|
+
!isExtensibleEnum(context, type.valueType)
|
|
1893
|
+
) {
|
|
1894
|
+
// Special handling for non-extensible enums to cast the result to the correct type
|
|
1895
|
+
return `${optionalPrefixForString}${parseHelper}(${restValue}) as ${getTypeExpression(context, type)}`;
|
|
1896
|
+
} else {
|
|
1897
|
+
return `${optionalPrefixForString}${parseHelper}(${restValue})`;
|
|
1898
|
+
}
|
|
1593
1899
|
}
|
|
1594
1900
|
}
|
|
1595
1901
|
return `${prefix}.map((${varName}: any) => { return ${elementNullOrUndefinedPrefix}${deserializeResponseValue(context, type.valueType, varName, true, getEncodeForType(type.valueType), recursionDepth + 1)}})`;
|
|
@@ -1743,9 +2049,13 @@ export function getPropertyFullName(
|
|
|
1743
2049
|
property: SdkHttpParameter | SdkModelPropertyType,
|
|
1744
2050
|
propertyPath?: string
|
|
1745
2051
|
) {
|
|
1746
|
-
const normalizedPropertyName =
|
|
1747
|
-
|
|
1748
|
-
|
|
2052
|
+
const normalizedPropertyName =
|
|
2053
|
+
propertyPath === ""
|
|
2054
|
+
? normalizeName(property.name, NameType.Parameter, true)
|
|
2055
|
+
: normalizeModelPropertyName(context, property)
|
|
2056
|
+
.replace(/^"/g, "")
|
|
2057
|
+
.replace(/"$/g, "");
|
|
2058
|
+
|
|
1749
2059
|
let fullName = normalizedPropertyName;
|
|
1750
2060
|
if (propertyPath === "" && property.optional) {
|
|
1751
2061
|
fullName = `options?.${normalizedPropertyName}`;
|
|
@@ -1762,8 +2072,18 @@ export function getPropertyFullName(
|
|
|
1762
2072
|
export function getExpectedStatuses(operation: ServiceOperation): string {
|
|
1763
2073
|
let statusCodes = operation.operation.responses.map((x) => x.statusCodes);
|
|
1764
2074
|
// LROs may call the same path but with GET to get the operation status.
|
|
1765
|
-
if (
|
|
1766
|
-
|
|
2075
|
+
if (
|
|
2076
|
+
(isLroOnlyOperation(operation) || isLroAndPagingOperation(operation)) &&
|
|
2077
|
+
operation.operation.verb !== "get"
|
|
2078
|
+
) {
|
|
2079
|
+
// DELETE: Add 200, 202 for polling
|
|
2080
|
+
// POST/PUT/PATCH: Add 200, 201, 202 for polling
|
|
2081
|
+
const verb = operation.operation.verb.toLowerCase();
|
|
2082
|
+
if (verb === "delete") {
|
|
2083
|
+
statusCodes = Array.from(new Set([...statusCodes, 200, 202]));
|
|
2084
|
+
} else {
|
|
2085
|
+
statusCodes = Array.from(new Set([...statusCodes, 200, 201, 202]));
|
|
2086
|
+
}
|
|
1767
2087
|
}
|
|
1768
2088
|
|
|
1769
2089
|
return `[${statusCodes.map((x) => `"${x}"`).join(", ")}]`;
|