@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.
Files changed (60) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/src/index.d.ts.map +1 -1
  3. package/dist/src/index.js +20 -5
  4. package/dist/src/index.js.map +1 -1
  5. package/dist/src/modular/buildClientContext.d.ts.map +1 -1
  6. package/dist/src/modular/buildClientContext.js +7 -3
  7. package/dist/src/modular/buildClientContext.js.map +1 -1
  8. package/dist/src/modular/buildOperations.d.ts.map +1 -1
  9. package/dist/src/modular/buildOperations.js +24 -3
  10. package/dist/src/modular/buildOperations.js.map +1 -1
  11. package/dist/src/modular/emitModels.d.ts.map +1 -1
  12. package/dist/src/modular/emitModels.js +19 -0
  13. package/dist/src/modular/emitModels.js.map +1 -1
  14. package/dist/src/modular/emitSamples.js +2 -2
  15. package/dist/src/modular/emitSamples.js.map +1 -1
  16. package/dist/src/modular/helpers/clientHelpers.d.ts +2 -1
  17. package/dist/src/modular/helpers/clientHelpers.d.ts.map +1 -1
  18. package/dist/src/modular/helpers/clientHelpers.js +5 -2
  19. package/dist/src/modular/helpers/clientHelpers.js.map +1 -1
  20. package/dist/src/modular/helpers/operationHelpers.d.ts.map +1 -1
  21. package/dist/src/modular/helpers/operationHelpers.js +266 -43
  22. package/dist/src/modular/helpers/operationHelpers.js.map +1 -1
  23. package/dist/src/modular/serialization/buildXmlSerializerFunction.d.ts +32 -0
  24. package/dist/src/modular/serialization/buildXmlSerializerFunction.d.ts.map +1 -0
  25. package/dist/src/modular/serialization/buildXmlSerializerFunction.js +373 -0
  26. package/dist/src/modular/serialization/buildXmlSerializerFunction.js.map +1 -0
  27. package/dist/src/modular/static-helpers-metadata.d.ts +57 -0
  28. package/dist/src/modular/static-helpers-metadata.d.ts.map +1 -1
  29. package/dist/src/modular/static-helpers-metadata.js +57 -0
  30. package/dist/src/modular/static-helpers-metadata.js.map +1 -1
  31. package/dist/src/utils/clientUtils.d.ts.map +1 -1
  32. package/dist/src/utils/clientUtils.js +1 -0
  33. package/dist/src/utils/clientUtils.js.map +1 -1
  34. package/dist/src/utils/mediaTypes.d.ts +4 -0
  35. package/dist/src/utils/mediaTypes.d.ts.map +1 -1
  36. package/dist/src/utils/mediaTypes.js +10 -0
  37. package/dist/src/utils/mediaTypes.js.map +1 -1
  38. package/dist/src/utils/modelUtils.d.ts.map +1 -1
  39. package/dist/src/utils/modelUtils.js +3 -0
  40. package/dist/src/utils/modelUtils.js.map +1 -1
  41. package/dist/src/utils/operationUtil.d.ts +12 -0
  42. package/dist/src/utils/operationUtil.d.ts.map +1 -1
  43. package/dist/src/utils/operationUtil.js +22 -1
  44. package/dist/src/utils/operationUtil.js.map +1 -1
  45. package/dist/tsconfig.tsbuildinfo +1 -1
  46. package/package.json +8 -7
  47. package/src/index.ts +20 -5
  48. package/src/modular/buildClientContext.ts +12 -5
  49. package/src/modular/buildOperations.ts +34 -3
  50. package/src/modular/emitModels.ts +43 -0
  51. package/src/modular/emitSamples.ts +2 -2
  52. package/src/modular/helpers/clientHelpers.ts +6 -2
  53. package/src/modular/helpers/operationHelpers.ts +377 -57
  54. package/src/modular/serialization/buildXmlSerializerFunction.ts +511 -0
  55. package/src/modular/static-helpers-metadata.ts +58 -0
  56. package/src/utils/clientUtils.ts +1 -0
  57. package/src/utils/mediaTypes.ts +12 -0
  58. package/src/utils/modelUtils.ts +3 -0
  59. package/src/utils/operationUtil.ts +34 -1
  60. 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 deserializeFunctionName = buildModelDeserializer(context, deserializedType, {
132
- nameOnly: true,
133
- skipDiscriminatedUnionSuffix: false
134
- });
135
- if (deserializeFunctionName) {
136
- statements.push(`return ${deserializeFunctionName}(${deserializedRoot})`);
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 (isAzureCoreErrorType(context.program, deserializedType.__raw)) {
139
- statements.push(`return ${deserializedRoot}`);
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
- statements.push(`return ${deserializeResponseValue(context, deserializedType, deserializedRoot, true, isBinaryPayload(context, response.type.__raw, contentTypes)
143
- ? "binary"
144
- : getEncodeForType(deserializedType))}`);
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 is not supported yet so handle them as normal operation and customization may be needed
296
- // https://github.com/Azure/autorest.typescript/issues/2313
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 serializerFunctionName = buildModelSerializer(context, getNullableValidType(bodyParameter.type), {
556
- nameOnly: true,
557
- skipDiscriminatedUnionSuffix: false
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 `"${param.name}": ${getConstantValue(param.type)}`;
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.kind !== "string") {
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
- return `${optionalPrefixForString}${parseHelper}(${restValue})`;
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 = normalizeModelPropertyName(context, property)
1176
- .replace(/^"/g, "")
1177
- .replace(/"$/g, "");
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) && operation.operation.verb !== "get") {
1195
- statusCodes = Array.from(new Set([...statusCodes, 200, 201, 202]));
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
  }