@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
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { StructureKind } from "ts-morph";
|
|
2
2
|
import { NoTarget } from "@typespec/compiler";
|
|
3
|
-
import { PagingHelpers, PollingHelpers, SerializationHelpers, UrlTemplateHelpers } from "../static-helpers-metadata.js";
|
|
3
|
+
import { PagingHelpers, PollingHelpers, SerializationHelpers, UrlTemplateHelpers, XmlHelpers } from "../static-helpers-metadata.js";
|
|
4
4
|
import { getNullableValidType, isSpreadBodyParameter, isTypeNullable } from "./typeHelpers.js";
|
|
5
5
|
import { getClassicalLayerPrefix, getOperationName } from "./namingHelpers.js";
|
|
6
|
-
import { getCollectionFormatHelper, hasCollectionFormatInfo, isBinaryPayload, getCollectionFormatParseHelper, getCollectionFormatFromArrayEncoding, KnownCollectionFormat } from "../../utils/operationUtil.js";
|
|
6
|
+
import { getCollectionFormatHelper, hasCollectionFormatInfo, isBinaryPayload, isXmlPayload, isMultipartPayload, hasDualFormatSupport, getCollectionFormatParseHelper, getCollectionFormatFromArrayEncoding, KnownCollectionFormat } from "../../utils/operationUtil.js";
|
|
7
7
|
import { getPropertyWithOverrides, isNormalUnion, isSpecialHandledUnion } from "../serialization/serializeUtils.js";
|
|
8
8
|
import { getDocsFromDescription, getFixmeForMultilineDocs } from "./docsHelpers.js";
|
|
9
9
|
import { AzurePollingDependencies } from "../external-dependencies.js";
|
|
10
10
|
import { NameType, normalizeName } from "@azure-tools/rlc-common";
|
|
11
11
|
import { buildModelDeserializer, buildPropertyDeserializer } from "../serialization/buildDeserializerFunction.js";
|
|
12
12
|
import { buildModelSerializer, buildPropertySerializer } from "../serialization/buildSerializerFunction.js";
|
|
13
|
+
import { buildXmlModelSerializer, buildXmlModelDeserializer, hasXmlSerialization } from "../serialization/buildXmlSerializerFunction.js";
|
|
13
14
|
import { refkey } from "../../framework/refkey.js";
|
|
14
15
|
import { reportDiagnostic } from "../../lib.js";
|
|
15
16
|
import { resolveReference } from "../../framework/reference.js";
|
|
@@ -20,6 +21,7 @@ import { getTypeExpression, normalizeModelPropertyName } from "../type-expressio
|
|
|
20
21
|
import { isHttpMetadata, isReadOnly } from "@azure-tools/typespec-client-generator-core";
|
|
21
22
|
import { isMetadata } from "@typespec/http";
|
|
22
23
|
import { useContext } from "../../contextManager.js";
|
|
24
|
+
import { isExtensibleEnum } from "../type-expressions/get-enum-expression.js";
|
|
23
25
|
export function getSendPrivateFunction(dpgContext, client, method, clientType) {
|
|
24
26
|
const operation = method[1];
|
|
25
27
|
const parameters = getOperationSignatureParameters(dpgContext, method, clientType);
|
|
@@ -61,7 +63,7 @@ export function getSendPrivateFunction(dpgContext, client, method, clientType) {
|
|
|
61
63
|
};
|
|
62
64
|
}
|
|
63
65
|
export function getDeserializePrivateFunction(context, operation) {
|
|
64
|
-
var _a, _b, _c, _d, _e, _f;
|
|
66
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
65
67
|
const { name } = getOperationName(operation);
|
|
66
68
|
const dependencies = useDependencies();
|
|
67
69
|
const PathUncheckedResponseReference = resolveReference(dependencies.PathUncheckedResponse);
|
|
@@ -71,15 +73,14 @@ export function getDeserializePrivateFunction(context, operation) {
|
|
|
71
73
|
type: PathUncheckedResponseReference
|
|
72
74
|
}
|
|
73
75
|
];
|
|
74
|
-
// TODO: Support LRO + paging operation
|
|
75
|
-
// https://github.com/Azure/autorest.typescript/issues/2313
|
|
76
76
|
const isLroOnly = isLroOnlyOperation(operation);
|
|
77
|
+
const isLroAndPaging = isLroAndPagingOperation(operation);
|
|
77
78
|
// TODO: Support operation overloads
|
|
78
79
|
// TODO: Support multiple responses
|
|
79
80
|
const response = operation.response;
|
|
80
81
|
const restResponse = operation.operation.responses[0];
|
|
81
82
|
let returnType;
|
|
82
|
-
if (isLroOnly) {
|
|
83
|
+
if (isLroOnly || isLroAndPaging) {
|
|
83
84
|
returnType = buildLroReturnType(context, operation);
|
|
84
85
|
}
|
|
85
86
|
else if (response.type && restResponse) {
|
|
@@ -102,7 +103,7 @@ export function getDeserializePrivateFunction(context, operation) {
|
|
|
102
103
|
const createRestErrorReference = resolveReference(dependencies.createRestError);
|
|
103
104
|
statements.push(`const expectedStatuses = ${getExpectedStatuses(operation)};`);
|
|
104
105
|
statements.push(`if(!expectedStatuses.includes(result.status)){`, `${getExceptionThrowStatement(context, operation)}`, "}");
|
|
105
|
-
const deserializedType = isLroOnly
|
|
106
|
+
const deserializedType = isLroOnly || isLroAndPaging
|
|
106
107
|
? (_c = (_b = operation === null || operation === void 0 ? void 0 : operation.lroMetadata) === null || _b === void 0 ? void 0 : _b.finalResponse) === null || _c === void 0 ? void 0 : _c.result
|
|
107
108
|
: restResponse
|
|
108
109
|
? restResponse.type
|
|
@@ -127,21 +128,86 @@ export function getDeserializePrivateFunction(context, operation) {
|
|
|
127
128
|
`);
|
|
128
129
|
}
|
|
129
130
|
if (deserializedType) {
|
|
130
|
-
const contentTypes = (_f = operation.operation.responses[0]) === null || _f === void 0 ? void 0 : _f.contentTypes;
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
131
|
+
const contentTypes = (_g = (_f = operation.operation.responses[0]) === null || _f === void 0 ? void 0 : _f.contentTypes) !== null && _g !== void 0 ? _g : [];
|
|
132
|
+
const isXml = isXmlPayload(contentTypes);
|
|
133
|
+
const isDualFormat = hasDualFormatSupport(contentTypes);
|
|
134
|
+
const isMultipart = isMultipartPayload(contentTypes);
|
|
135
|
+
const useXmlDeserialization = isXml &&
|
|
136
|
+
deserializedType.kind === "model" &&
|
|
137
|
+
hasXmlSerialization(deserializedType);
|
|
138
|
+
// Workaround for multipart response: cast return value as any due to lack of multipart response handling in core
|
|
139
|
+
const multipartCastSuffix = isMultipart ? " as any" : "";
|
|
140
|
+
// For dual-format responses, check content-type header at runtime
|
|
141
|
+
if (isDualFormat &&
|
|
142
|
+
deserializedType.kind === "model" &&
|
|
143
|
+
hasXmlSerialization(deserializedType)) {
|
|
144
|
+
const xmlDeserializerName = buildXmlModelDeserializer(context, deserializedType, {
|
|
145
|
+
nameOnly: true,
|
|
146
|
+
skipDiscriminatedUnionSuffix: false
|
|
147
|
+
});
|
|
148
|
+
const jsonDeserializerName = buildModelDeserializer(context, deserializedType, {
|
|
149
|
+
nameOnly: true,
|
|
150
|
+
skipDiscriminatedUnionSuffix: false
|
|
151
|
+
});
|
|
152
|
+
if (xmlDeserializerName && jsonDeserializerName) {
|
|
153
|
+
const isXmlContentTypeRef = resolveReference(XmlHelpers.isXmlContentType);
|
|
154
|
+
statements.push(`const responseContentType = result.headers?.["content-type"] ?? "";
|
|
155
|
+
if (${isXmlContentTypeRef}(responseContentType)) {
|
|
156
|
+
return ${xmlDeserializerName}(${deserializedRoot});
|
|
157
|
+
}
|
|
158
|
+
return ${jsonDeserializerName}(${deserializedRoot});`);
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
// Fall back to JSON deserializer
|
|
162
|
+
const deserializeFunctionName = buildModelDeserializer(context, deserializedType, {
|
|
163
|
+
nameOnly: true,
|
|
164
|
+
skipDiscriminatedUnionSuffix: false
|
|
165
|
+
});
|
|
166
|
+
if (deserializeFunctionName) {
|
|
167
|
+
statements.push(`return ${deserializeFunctionName}(${deserializedRoot})`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
137
170
|
}
|
|
138
|
-
else if (
|
|
139
|
-
|
|
171
|
+
else if (useXmlDeserialization) {
|
|
172
|
+
// XML-only response
|
|
173
|
+
const xmlDeserializerName = buildXmlModelDeserializer(context, deserializedType, {
|
|
174
|
+
nameOnly: true,
|
|
175
|
+
skipDiscriminatedUnionSuffix: false
|
|
176
|
+
});
|
|
177
|
+
if (xmlDeserializerName) {
|
|
178
|
+
statements.push(`return ${xmlDeserializerName}(${deserializedRoot})`);
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
// Fall back to JSON deserializer if XML deserializer is not available
|
|
182
|
+
const deserializeFunctionName = buildModelDeserializer(context, deserializedType, {
|
|
183
|
+
nameOnly: true,
|
|
184
|
+
skipDiscriminatedUnionSuffix: false
|
|
185
|
+
});
|
|
186
|
+
if (deserializeFunctionName) {
|
|
187
|
+
statements.push(`return ${deserializeFunctionName}(${deserializedRoot})`);
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
statements.push(`return ${deserializedRoot}`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
140
193
|
}
|
|
141
194
|
else {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
:
|
|
195
|
+
// JSON response (default) - also handles multipart responses
|
|
196
|
+
const deserializeFunctionName = buildModelDeserializer(context, deserializedType, {
|
|
197
|
+
nameOnly: true,
|
|
198
|
+
skipDiscriminatedUnionSuffix: false
|
|
199
|
+
});
|
|
200
|
+
if (deserializeFunctionName) {
|
|
201
|
+
statements.push(`return ${deserializeFunctionName}(${deserializedRoot})${multipartCastSuffix}`);
|
|
202
|
+
}
|
|
203
|
+
else if (isAzureCoreErrorType(context.program, deserializedType.__raw)) {
|
|
204
|
+
statements.push(`return ${deserializedRoot}${multipartCastSuffix}`);
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
statements.push(`return ${deserializeResponseValue(context, deserializedType, deserializedRoot, true, isBinaryPayload(context, response.type.__raw, contentTypes)
|
|
208
|
+
? "binary"
|
|
209
|
+
: getEncodeForType(deserializedType))}${multipartCastSuffix}`);
|
|
210
|
+
}
|
|
145
211
|
}
|
|
146
212
|
}
|
|
147
213
|
else if (returnType.type === "void") {
|
|
@@ -292,8 +358,8 @@ export function getOperationFunction(context, method, clientType) {
|
|
|
292
358
|
return getLroOnlyOperationFunction(context, [method[0], operation], clientType, optionalParamName);
|
|
293
359
|
}
|
|
294
360
|
else if (isLroAndPagingOperation(operation)) {
|
|
295
|
-
// Case 3: both paging + lro operation
|
|
296
|
-
|
|
361
|
+
// Case 3: both paging + lro operation
|
|
362
|
+
return getLroAndPagingOperationFunction(context, [method[0], operation], clientType, optionalParamName);
|
|
297
363
|
}
|
|
298
364
|
// TODO: Support operation overloads
|
|
299
365
|
const response = operation.response;
|
|
@@ -390,6 +456,77 @@ function getLroOnlyOperationFunction(context, method, clientType, optionalParamN
|
|
|
390
456
|
statements
|
|
391
457
|
};
|
|
392
458
|
}
|
|
459
|
+
function getLroAndPagingOperationFunction(context, method, clientType, optionalParamName = "options") {
|
|
460
|
+
var _a;
|
|
461
|
+
const operation = method[1];
|
|
462
|
+
const parameters = getOperationSignatureParameters(context, method, clientType);
|
|
463
|
+
const { name, fixme = [] } = getOperationName(operation);
|
|
464
|
+
const returnType = buildLroPagingReturnType(context, operation);
|
|
465
|
+
// Build paging options from metadata
|
|
466
|
+
const pagingOptions = [
|
|
467
|
+
operation.response.resultSegments &&
|
|
468
|
+
`itemName: "${operation.response.resultSegments.map((p) => p.name).join(".")}"`,
|
|
469
|
+
operation.pagingMetadata.nextLinkSegments &&
|
|
470
|
+
`nextLinkName: "${operation.pagingMetadata.nextLinkSegments.map((p) => p.name).join(".")}"`,
|
|
471
|
+
operation.pagingMetadata.nextLinkVerb !== "GET" &&
|
|
472
|
+
`nextLinkMethod: "${operation.pagingMetadata.nextLinkVerb}"`
|
|
473
|
+
].filter(Boolean);
|
|
474
|
+
// Build LRO resource location config
|
|
475
|
+
const allowedLocations = [
|
|
476
|
+
"azure-async-operation",
|
|
477
|
+
"location",
|
|
478
|
+
"original-uri",
|
|
479
|
+
"operation-location"
|
|
480
|
+
];
|
|
481
|
+
const resourceLocationConfig = ((_a = operation.lroMetadata) === null || _a === void 0 ? void 0 : _a.finalStateVia) &&
|
|
482
|
+
allowedLocations.includes(operation.lroMetadata.finalStateVia)
|
|
483
|
+
? `resourceLocationConfig: "${operation.lroMetadata.finalStateVia}"`
|
|
484
|
+
: "";
|
|
485
|
+
// Resolve references
|
|
486
|
+
const refs = {
|
|
487
|
+
pagedIterator: resolveReference(PagingHelpers.PagedAsyncIterableIterator),
|
|
488
|
+
buildPaging: resolveReference(PagingHelpers.BuildPagedAsyncIterator),
|
|
489
|
+
getLroPoller: resolveReference(PollingHelpers.GetLongRunningPoller),
|
|
490
|
+
pollerLike: resolveReference(AzurePollingDependencies.PollerLike),
|
|
491
|
+
operationState: resolveReference(AzurePollingDependencies.OperationState),
|
|
492
|
+
pathResponse: resolveReference(useDependencies().PathUncheckedResponse)
|
|
493
|
+
};
|
|
494
|
+
const expectedStatuses = getExpectedStatuses(operation);
|
|
495
|
+
const paramList = parameters.map((p) => p.name).join(", ");
|
|
496
|
+
const pagingOptionsStr = pagingOptions.length > 0 ? `,\n {${pagingOptions.join(", ")}}` : "";
|
|
497
|
+
return {
|
|
498
|
+
kind: StructureKind.Function,
|
|
499
|
+
docs: [
|
|
500
|
+
...getDocsFromDescription(operation.doc),
|
|
501
|
+
...getFixmeForMultilineDocs(fixme)
|
|
502
|
+
],
|
|
503
|
+
isAsync: false,
|
|
504
|
+
isExported: true,
|
|
505
|
+
name,
|
|
506
|
+
propertyName: normalizeName(operation.name, NameType.Property),
|
|
507
|
+
parameters,
|
|
508
|
+
returnType: `${refs.pagedIterator}<${returnType.type}>`,
|
|
509
|
+
statements: [
|
|
510
|
+
`
|
|
511
|
+
const initialPagingPoller = ${refs.getLroPoller}(context,
|
|
512
|
+
async (result: ${refs.pathResponse}) => result,
|
|
513
|
+
${expectedStatuses}, {
|
|
514
|
+
updateIntervalInMs: ${optionalParamName}?.updateIntervalInMs,
|
|
515
|
+
abortSignal: ${optionalParamName}?.abortSignal,
|
|
516
|
+
getInitialResponse: () => _${name}Send(${paramList}),
|
|
517
|
+
${resourceLocationConfig}
|
|
518
|
+
}) as ${refs.pollerLike}<${refs.operationState}<${refs.pathResponse}>, ${refs.pathResponse}>;
|
|
519
|
+
|
|
520
|
+
return ${refs.buildPaging}(
|
|
521
|
+
context,
|
|
522
|
+
async () => await initialPagingPoller,
|
|
523
|
+
_${name}Deserialize,
|
|
524
|
+
${expectedStatuses}${pagingOptionsStr}
|
|
525
|
+
);
|
|
526
|
+
`
|
|
527
|
+
]
|
|
528
|
+
};
|
|
529
|
+
}
|
|
393
530
|
function buildLroReturnType(context, operation) {
|
|
394
531
|
const metadata = operation.lroMetadata;
|
|
395
532
|
if (metadata !== undefined && metadata.finalResponse !== undefined) {
|
|
@@ -401,6 +538,16 @@ function buildLroReturnType(context, operation) {
|
|
|
401
538
|
}
|
|
402
539
|
return { name: "", type: "void" };
|
|
403
540
|
}
|
|
541
|
+
function buildLroPagingReturnType(context, operation) {
|
|
542
|
+
var _a, _b;
|
|
543
|
+
if (((_a = operation.response.type) === null || _a === void 0 ? void 0 : _a.kind) === "array") {
|
|
544
|
+
return {
|
|
545
|
+
name: (_b = operation.response.type.valueType.name) !== null && _b !== void 0 ? _b : "",
|
|
546
|
+
type: getTypeExpression(context, operation.response.type.valueType)
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
return { name: "", type: "void" };
|
|
550
|
+
}
|
|
404
551
|
function getPagingOnlyOperationFunction(context, method, clientType) {
|
|
405
552
|
var _a;
|
|
406
553
|
const operation = method[1];
|
|
@@ -552,15 +699,49 @@ function buildBodyParameter(context, bodyParameter, optionalParamName = "options
|
|
|
552
699
|
if (!bodyParameter || !bodyParameter.type) {
|
|
553
700
|
return "";
|
|
554
701
|
}
|
|
555
|
-
const
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
702
|
+
const contentTypes = bodyParameter.contentTypes;
|
|
703
|
+
const isXml = isXmlPayload(contentTypes);
|
|
704
|
+
const isDualFormat = hasDualFormatSupport(contentTypes);
|
|
705
|
+
const bodyType = getNullableValidType(bodyParameter.type);
|
|
706
|
+
// Check if XML serialization is needed and available
|
|
707
|
+
const useXmlSerialization = isXml && bodyType.kind === "model" && hasXmlSerialization(bodyType);
|
|
708
|
+
let serializerFunctionName;
|
|
709
|
+
if (useXmlSerialization) {
|
|
710
|
+
// Use XML serializer
|
|
711
|
+
serializerFunctionName = buildXmlModelSerializer(context, bodyType, {
|
|
712
|
+
nameOnly: true,
|
|
713
|
+
skipDiscriminatedUnionSuffix: false
|
|
714
|
+
});
|
|
715
|
+
}
|
|
716
|
+
else {
|
|
717
|
+
// Use JSON serializer (default)
|
|
718
|
+
serializerFunctionName = buildModelSerializer(context, bodyType, {
|
|
719
|
+
nameOnly: true,
|
|
720
|
+
skipDiscriminatedUnionSuffix: false
|
|
721
|
+
});
|
|
722
|
+
}
|
|
559
723
|
const bodyParamName = normalizeName(bodyParameter.name, NameType.Parameter, true);
|
|
560
724
|
const bodyNameExpression = bodyParameter.optional
|
|
561
725
|
? `${optionalParamName}["${bodyParamName}"]`
|
|
562
726
|
: bodyParamName;
|
|
563
727
|
const nullOrUndefinedPrefix = getPropertySerializationPrefix(context, bodyParameter, bodyParameter.optional ? optionalParamName : undefined);
|
|
728
|
+
// For dual-format operations, check the contentType option at runtime
|
|
729
|
+
if (isDualFormat &&
|
|
730
|
+
bodyType.kind === "model" &&
|
|
731
|
+
hasXmlSerialization(bodyType)) {
|
|
732
|
+
const xmlSerializerName = buildXmlModelSerializer(context, bodyType, {
|
|
733
|
+
nameOnly: true,
|
|
734
|
+
skipDiscriminatedUnionSuffix: false
|
|
735
|
+
});
|
|
736
|
+
const jsonSerializerName = buildModelSerializer(context, bodyType, {
|
|
737
|
+
nameOnly: true,
|
|
738
|
+
skipDiscriminatedUnionSuffix: false
|
|
739
|
+
});
|
|
740
|
+
if (xmlSerializerName && jsonSerializerName) {
|
|
741
|
+
const isXmlContentTypeRef = resolveReference(XmlHelpers.isXmlContentType);
|
|
742
|
+
return `\nbody: ${nullOrUndefinedPrefix}(${isXmlContentTypeRef}(${optionalParamName}?.contentType ?? "application/json") ? ${xmlSerializerName}(${bodyNameExpression}) : ${jsonSerializerName}(${bodyNameExpression})),`;
|
|
743
|
+
}
|
|
744
|
+
}
|
|
564
745
|
// if a model being used in both spread and non spread operation, we should only leverage the deserializer in non spread operation
|
|
565
746
|
if (serializerFunctionName && !isSpreadBodyParameter(bodyParameter)) {
|
|
566
747
|
return `\nbody: ${nullOrUndefinedPrefix}${serializerFunctionName}(${bodyNameExpression}),`;
|
|
@@ -585,18 +766,22 @@ function getEncodingFormat(type) {
|
|
|
585
766
|
* This function helps with renames, translating client names to rest api names
|
|
586
767
|
*/
|
|
587
768
|
export function getParameterMap(context, param, optionalParamName = "options") {
|
|
769
|
+
// Use lowercase for header names since HTTP headers are case-insensitive
|
|
770
|
+
const serializedName = param.kind === "header"
|
|
771
|
+
? getHeaderSerializedName(param)
|
|
772
|
+
: getPropertySerializedName(param);
|
|
588
773
|
if (isConstant(param.type)) {
|
|
589
|
-
return `"${
|
|
774
|
+
return `"${serializedName}": ${getConstantValue(param.type)}`;
|
|
590
775
|
}
|
|
591
776
|
if (hasCollectionFormatInfo(param.kind, param.collectionFormat)) {
|
|
592
|
-
return getCollectionFormatForParam(context, param, optionalParamName);
|
|
777
|
+
return getCollectionFormatForParam(context, param, optionalParamName, serializedName);
|
|
593
778
|
}
|
|
594
779
|
// if the parameter or property is optional, we don't need to handle the default value
|
|
595
780
|
if (isOptional(param)) {
|
|
596
|
-
return getOptional(context, param, optionalParamName);
|
|
781
|
+
return getOptional(context, param, optionalParamName, serializedName);
|
|
597
782
|
}
|
|
598
783
|
if (isRequired(param)) {
|
|
599
|
-
return getRequired(context, param);
|
|
784
|
+
return getRequired(context, param, serializedName);
|
|
600
785
|
}
|
|
601
786
|
reportDiagnostic(context.program, {
|
|
602
787
|
code: "unsupported-parameter-type",
|
|
@@ -609,8 +794,7 @@ export function getParameterMap(context, param, optionalParamName = "options") {
|
|
|
609
794
|
// Return a fallback value to allow the emitter to continue
|
|
610
795
|
return `"${param.name}": undefined`;
|
|
611
796
|
}
|
|
612
|
-
function getCollectionFormatForParam(context, param, optionalParamName = "options") {
|
|
613
|
-
const serializedName = getPropertySerializedName(param);
|
|
797
|
+
function getCollectionFormatForParam(context, param, optionalParamName = "options", serializedName) {
|
|
614
798
|
const format = param.collectionFormat;
|
|
615
799
|
return `"${serializedName}": ${serializeRequestValue(context, param.type, param.optional ? `${optionalParamName}?.${param.name}` : param.name, !param.optional, format, serializedName, true)}`;
|
|
616
800
|
}
|
|
@@ -636,8 +820,7 @@ function getContentTypeValue(param, optionalParamName = "options") {
|
|
|
636
820
|
function isRequired(param) {
|
|
637
821
|
return !param.optional;
|
|
638
822
|
}
|
|
639
|
-
function getRequired(context, param) {
|
|
640
|
-
const serializedName = getPropertySerializedName(param);
|
|
823
|
+
function getRequired(context, param, serializedName) {
|
|
641
824
|
const clientValue = `${param.onClient ? "context." : ""}${param.name}`;
|
|
642
825
|
if (param.type.kind === "model") {
|
|
643
826
|
const propertiesStr = getRequestModelMapping(context, { ...param.type, optional: param.optional }, clientValue);
|
|
@@ -657,8 +840,7 @@ function isConstant(param) {
|
|
|
657
840
|
function isOptional(param) {
|
|
658
841
|
return Boolean(param.optional);
|
|
659
842
|
}
|
|
660
|
-
function getOptional(context, param, optionalParamName) {
|
|
661
|
-
const serializedName = getPropertySerializedName(param);
|
|
843
|
+
function getOptional(context, param, optionalParamName, serializedName) {
|
|
662
844
|
const paramName = `${param.onClient ? "context." : `${optionalParamName}?.`}${param.name}`;
|
|
663
845
|
if (param.type.kind === "model") {
|
|
664
846
|
const propertiesStr = getRequestModelMapping(context, { ...param.type, optional: param.optional }, paramName + "?.");
|
|
@@ -770,8 +952,8 @@ function getNullableCheck(name, type) {
|
|
|
770
952
|
*/
|
|
771
953
|
function getEncodeForModelProperty(context, property) {
|
|
772
954
|
if (property.encode && property.type.kind === "array") {
|
|
773
|
-
// Only arrays of string type can have collectionFormat encoding
|
|
774
|
-
if (property.type.valueType
|
|
955
|
+
// Only arrays of string type or string-based enum type can have collectionFormat encoding
|
|
956
|
+
if (!isStringEncodableArrayValueType(property.type.valueType)) {
|
|
775
957
|
reportDiagnostic(context.program, {
|
|
776
958
|
code: "un-supported-array-encoding",
|
|
777
959
|
format: {
|
|
@@ -790,6 +972,22 @@ function getEncodeForModelProperty(context, property) {
|
|
|
790
972
|
}
|
|
791
973
|
return getEncodeForType(property.type);
|
|
792
974
|
}
|
|
975
|
+
/**
|
|
976
|
+
* Checks if an array value type is string-encodable for collection format encoding.
|
|
977
|
+
* This includes both string type and string-based enum types.
|
|
978
|
+
*/
|
|
979
|
+
function isStringEncodableArrayValueType(valueType) {
|
|
980
|
+
// Direct string type
|
|
981
|
+
if (valueType.kind === "string") {
|
|
982
|
+
return true;
|
|
983
|
+
}
|
|
984
|
+
// String-based enum type
|
|
985
|
+
if (valueType.kind === "enum" &&
|
|
986
|
+
valueType.valueType.kind === "string") {
|
|
987
|
+
return true;
|
|
988
|
+
}
|
|
989
|
+
return false;
|
|
990
|
+
}
|
|
793
991
|
function getSerializationExpressionForFlatten(context, property, propertyPath) {
|
|
794
992
|
const serializeFunctionName = buildPropertySerializer(context, property, {
|
|
795
993
|
nameOnly: true,
|
|
@@ -867,6 +1065,13 @@ function getPropertySerializedName(property) {
|
|
|
867
1065
|
? (_a = property.serializationOptions.json) === null || _a === void 0 ? void 0 : _a.name
|
|
868
1066
|
: property.serializedName)) !== null && _b !== void 0 ? _b : property.name);
|
|
869
1067
|
}
|
|
1068
|
+
/**
|
|
1069
|
+
* Get the serialized name for a header parameter, normalized to lowercase.
|
|
1070
|
+
* HTTP headers are case-insensitive, so we normalize to lowercase for consistency.
|
|
1071
|
+
*/
|
|
1072
|
+
function getHeaderSerializedName(param) {
|
|
1073
|
+
return getPropertySerializedName(param).toLowerCase();
|
|
1074
|
+
}
|
|
870
1075
|
/**
|
|
871
1076
|
* This function helps translating an RLC response to an HLC response,
|
|
872
1077
|
* extracting properties from body and headers and building the HLC response object
|
|
@@ -1053,7 +1258,14 @@ export function deserializeResponseValue(context, type, restValue, required, for
|
|
|
1053
1258
|
const optionalPrefixForString = isTypeNullable(type) || getOptionalForType(type) || !required
|
|
1054
1259
|
? `${restValue} === null || ${restValue} === undefined ? ${restValue}: `
|
|
1055
1260
|
: "";
|
|
1056
|
-
|
|
1261
|
+
if (type.valueType.kind === "enum" &&
|
|
1262
|
+
!isExtensibleEnum(context, type.valueType)) {
|
|
1263
|
+
// Special handling for non-extensible enums to cast the result to the correct type
|
|
1264
|
+
return `${optionalPrefixForString}${parseHelper}(${restValue}) as ${getTypeExpression(context, type)}`;
|
|
1265
|
+
}
|
|
1266
|
+
else {
|
|
1267
|
+
return `${optionalPrefixForString}${parseHelper}(${restValue})`;
|
|
1268
|
+
}
|
|
1057
1269
|
}
|
|
1058
1270
|
}
|
|
1059
1271
|
return `${prefix}.map((${varName}: any) => { return ${elementNullOrUndefinedPrefix}${deserializeResponseValue(context, type.valueType, varName, true, getEncodeForType(type.valueType), recursionDepth + 1)}})`;
|
|
@@ -1172,9 +1384,11 @@ export function getPropertySerializationPrefix(context, property, propertyPath)
|
|
|
1172
1384
|
return "";
|
|
1173
1385
|
}
|
|
1174
1386
|
export function getPropertyFullName(context, property, propertyPath) {
|
|
1175
|
-
const normalizedPropertyName =
|
|
1176
|
-
.
|
|
1177
|
-
|
|
1387
|
+
const normalizedPropertyName = propertyPath === ""
|
|
1388
|
+
? normalizeName(property.name, NameType.Parameter, true)
|
|
1389
|
+
: normalizeModelPropertyName(context, property)
|
|
1390
|
+
.replace(/^"/g, "")
|
|
1391
|
+
.replace(/"$/g, "");
|
|
1178
1392
|
let fullName = normalizedPropertyName;
|
|
1179
1393
|
if (propertyPath === "" && property.optional) {
|
|
1180
1394
|
fullName = `options?.${normalizedPropertyName}`;
|
|
@@ -1191,8 +1405,17 @@ export function getPropertyFullName(context, property, propertyPath) {
|
|
|
1191
1405
|
export function getExpectedStatuses(operation) {
|
|
1192
1406
|
let statusCodes = operation.operation.responses.map((x) => x.statusCodes);
|
|
1193
1407
|
// LROs may call the same path but with GET to get the operation status.
|
|
1194
|
-
if (isLroOnlyOperation(operation)
|
|
1195
|
-
|
|
1408
|
+
if ((isLroOnlyOperation(operation) || isLroAndPagingOperation(operation)) &&
|
|
1409
|
+
operation.operation.verb !== "get") {
|
|
1410
|
+
// DELETE: Add 200, 202 for polling
|
|
1411
|
+
// POST/PUT/PATCH: Add 200, 201, 202 for polling
|
|
1412
|
+
const verb = operation.operation.verb.toLowerCase();
|
|
1413
|
+
if (verb === "delete") {
|
|
1414
|
+
statusCodes = Array.from(new Set([...statusCodes, 200, 202]));
|
|
1415
|
+
}
|
|
1416
|
+
else {
|
|
1417
|
+
statusCodes = Array.from(new Set([...statusCodes, 200, 201, 202]));
|
|
1418
|
+
}
|
|
1196
1419
|
}
|
|
1197
1420
|
return `[${statusCodes.map((x) => `"${x}"`).join(", ")}]`;
|
|
1198
1421
|
}
|