@azure-tools/typespec-ts 0.48.1 → 0.49.0-alpha.20260202.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 (59) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/src/modular/buildClientContext.d.ts.map +1 -1
  3. package/dist/src/modular/buildClientContext.js +6 -25
  4. package/dist/src/modular/buildClientContext.js.map +1 -1
  5. package/dist/src/modular/buildOperations.d.ts.map +1 -1
  6. package/dist/src/modular/buildOperations.js +1 -1
  7. package/dist/src/modular/buildOperations.js.map +1 -1
  8. package/dist/src/modular/buildRestorePoller.d.ts.map +1 -1
  9. package/dist/src/modular/buildRestorePoller.js +9 -2
  10. package/dist/src/modular/buildRestorePoller.js.map +1 -1
  11. package/dist/src/modular/emitSamples.d.ts.map +1 -1
  12. package/dist/src/modular/emitSamples.js +19 -1
  13. package/dist/src/modular/emitSamples.js.map +1 -1
  14. package/dist/src/modular/helpers/clientHelpers.d.ts +1 -0
  15. package/dist/src/modular/helpers/clientHelpers.d.ts.map +1 -1
  16. package/dist/src/modular/helpers/clientHelpers.js +24 -7
  17. package/dist/src/modular/helpers/clientHelpers.js.map +1 -1
  18. package/dist/src/modular/helpers/operationHelpers.d.ts +2 -2
  19. package/dist/src/modular/helpers/operationHelpers.d.ts.map +1 -1
  20. package/dist/src/modular/helpers/operationHelpers.js +40 -9
  21. package/dist/src/modular/helpers/operationHelpers.js.map +1 -1
  22. package/dist/src/modular/helpers/typeHelpers.js +1 -1
  23. package/dist/src/modular/helpers/typeHelpers.js.map +1 -1
  24. package/dist/src/modular/serialization/buildDeserializerFunction.js +5 -1
  25. package/dist/src/modular/serialization/buildDeserializerFunction.js.map +1 -1
  26. package/dist/src/modular/serialization/buildSerializerFunction.js +5 -1
  27. package/dist/src/modular/serialization/buildSerializerFunction.js.map +1 -1
  28. package/dist/src/modular/serialization/serializeUtils.d.ts.map +1 -1
  29. package/dist/src/modular/serialization/serializeUtils.js +1 -0
  30. package/dist/src/modular/serialization/serializeUtils.js.map +1 -1
  31. package/dist/src/modular/type-expressions/get-type-expression.js +1 -1
  32. package/dist/src/modular/type-expressions/get-type-expression.js.map +1 -1
  33. package/dist/src/transform/transformPaths.js +1 -1
  34. package/dist/src/transform/transformPaths.js.map +1 -1
  35. package/dist/src/utils/modelUtils.d.ts.map +1 -1
  36. package/dist/src/utils/modelUtils.js +6 -2
  37. package/dist/src/utils/modelUtils.js.map +1 -1
  38. package/dist/src/utils/operationUtil.d.ts +1 -1
  39. package/dist/src/utils/operationUtil.d.ts.map +1 -1
  40. package/dist/src/utils/operationUtil.js +7 -4
  41. package/dist/src/utils/operationUtil.js.map +1 -1
  42. package/dist/tsconfig.tsbuildinfo +1 -1
  43. package/package.json +7 -7
  44. package/src/modular/buildClientContext.ts +6 -26
  45. package/src/modular/buildOperations.ts +0 -1
  46. package/src/modular/buildRestorePoller.ts +9 -2
  47. package/src/modular/emitSamples.ts +29 -1
  48. package/src/modular/helpers/clientHelpers.ts +28 -10
  49. package/src/modular/helpers/operationHelpers.ts +48 -16
  50. package/src/modular/helpers/typeHelpers.ts +1 -1
  51. package/src/modular/serialization/buildDeserializerFunction.ts +5 -1
  52. package/src/modular/serialization/buildSerializerFunction.ts +5 -1
  53. package/src/modular/serialization/serializeUtils.ts +1 -0
  54. package/src/modular/type-expressions/get-type-expression.ts +1 -1
  55. package/src/transform/transformPaths.ts +1 -1
  56. package/src/utils/modelUtils.ts +5 -1
  57. package/src/utils/operationUtil.ts +11 -3
  58. package/static/static-helpers/pagingHelpers.ts +32 -6
  59. package/static/static-helpers/pollingHelpers.ts +27 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@azure-tools/typespec-ts",
3
- "version": "0.48.1",
3
+ "version": "0.49.0-alpha.20260202.1",
4
4
  "description": "An experimental TypeSpec emitter for TypeScript RLC",
5
5
  "main": "dist/src/index.js",
6
6
  "type": "module",
@@ -18,15 +18,15 @@
18
18
  "license": "MIT",
19
19
  "devDependencies": {
20
20
  "@azure-rest/core-client": "^2.3.1",
21
- "@typespec/http-specs": "0.1.0-alpha.31-dev.1",
22
- "@typespec/spector": "0.1.0-alpha.23-dev.0",
21
+ "@typespec/http-specs": "0.1.0-alpha.32-dev.1",
22
+ "@typespec/spector": "0.1.0-alpha.23-dev.1",
23
23
  "@typespec/spec-api": "0.1.0-alpha.13-dev.0",
24
24
  "@typespec/tspd": "0.73.3",
25
- "@azure-tools/azure-http-specs": "0.1.0-alpha.37-dev.0",
25
+ "@azure-tools/azure-http-specs": "0.1.0-alpha.37-dev.1",
26
26
  "@azure-tools/typespec-autorest": "^0.64.0",
27
27
  "@azure-tools/typespec-azure-core": "^0.64.0",
28
28
  "@azure-tools/typespec-azure-resource-manager": "^0.64.0",
29
- "@azure-tools/typespec-client-generator-core": "^0.64.1",
29
+ "@azure-tools/typespec-client-generator-core": "^0.64.4",
30
30
  "@azure/abort-controller": "^2.1.2",
31
31
  "@azure/core-auth": "^1.6.0",
32
32
  "@azure/core-lro": "^3.1.0",
@@ -65,7 +65,7 @@
65
65
  },
66
66
  "peerDependencies": {
67
67
  "@azure-tools/typespec-azure-core": "^0.64.0",
68
- "@azure-tools/typespec-client-generator-core": "^0.64.1",
68
+ "@azure-tools/typespec-client-generator-core": "^0.64.4",
69
69
  "@typespec/compiler": "^1.8.0",
70
70
  "@typespec/http": "^1.8.0",
71
71
  "@typespec/rest": "^0.78.0",
@@ -73,7 +73,7 @@
73
73
  "@typespec/xml": "^0.78.0"
74
74
  },
75
75
  "dependencies": {
76
- "@azure-tools/rlc-common": "^0.48.1",
76
+ "@azure-tools/rlc-common": "0.49.0-alpha.20260202.1",
77
77
  "fast-xml-parser": "^4.5.0",
78
78
  "fs-extra": "^11.1.0",
79
79
  "lodash": "^4.17.21",
@@ -81,8 +81,7 @@ export function buildClientContext(
81
81
  // Get all client parameters (both required and optional) for the interface
82
82
  const requiredInterfaceProperties = getClientParameters(client, dpgContext, {
83
83
  onClientOnly: false,
84
- requiredOnly: true,
85
- apiVersionAsRequired: true
84
+ requiredOnly: true
86
85
  })
87
86
  .filter((p) => {
88
87
  const clientParamName = getClientParameterName(p);
@@ -239,7 +238,7 @@ export function buildClientContext(
239
238
  `);
240
239
  }
241
240
 
242
- let apiVersionPolicyStatement = `clientContext.pipeline.removePolicy({ name: "ApiVersionPolicy" });`;
241
+ let apiVersionStatement = ``;
243
242
  const endpointParameter = getClientParameters(client, dpgContext, {
244
243
  onClientOnly: false,
245
244
  requiredOnly: true,
@@ -255,39 +254,20 @@ export function buildClientContext(
255
254
  const apiVersionInEndpoint =
256
255
  templateArguments && templateArguments.find((p) => p.isApiVersionParam);
257
256
  if (!apiVersionInEndpoint && apiVersionParam.clientDefaultValue) {
258
- apiVersionPolicyStatement += `const ${apiVersionParamName} = options.${apiVersionParamName} ?? "${apiVersionParam.clientDefaultValue}";`;
259
- }
260
-
261
- if (apiVersionParam.kind === "method") {
262
- apiVersionPolicyStatement += `
263
- clientContext.pipeline.addPolicy({
264
- name: 'ClientApiVersionPolicy',
265
- sendRequest: (req, next) => {
266
- // Use the apiVersion defined in request url directly
267
- // Append one if there is no apiVersion and we have one at client options
268
- const url = new URL(req.url);
269
- if (!url.searchParams.get("api-version")) {
270
- req.url = \`\${req.url}\${
271
- Array.from(url.searchParams.keys()).length > 0 ? "&" : "?"
272
- }api-version=\${${getClientParameterName(apiVersionParam)}}\`;
273
- }
274
-
275
- return next(req);
276
- },
277
- });`;
257
+ apiVersionStatement += `const ${apiVersionParamName} = options.${apiVersionParamName};`;
278
258
  }
279
259
  } else if (isAzurePackage(emitterOptions)) {
280
- apiVersionPolicyStatement += `
260
+ apiVersionStatement += `
281
261
  if (options.apiVersion) {
282
262
  logger.warning("This client does not support client api-version, please change it at the operation level");
283
263
  }`;
284
264
  } else {
285
- apiVersionPolicyStatement += `
265
+ apiVersionStatement += `
286
266
  if (options.apiVersion) {
287
267
  console.warn("This client does not support client api-version, please change it at the operation level");
288
268
  }`;
289
269
  }
290
- factoryFunction.addStatements(apiVersionPolicyStatement);
270
+ factoryFunction.addStatements(apiVersionStatement);
291
271
 
292
272
  const contextRequiredParam = requiredParams.filter(
293
273
  (p) =>
@@ -84,7 +84,6 @@ export function buildOperationFiles(
84
84
  );
85
85
  const sendOperationDeclaration = getSendPrivateFunction(
86
86
  dpgContext,
87
- client,
88
87
  [prefixes, op],
89
88
  clientType
90
89
  );
@@ -111,6 +111,7 @@ export function buildRestorePoller(
111
111
  \`Please ensure the operation is in this client! We can't find its deserializeHelper for \${sourceOperation?.name}.\`
112
112
  );
113
113
  }
114
+ const apiVersion = getApiVersionFromUrl(initialRequestUrl);
114
115
  return ${resolveReference(PollingHelpers.GetLongRunningPoller)}(
115
116
  (client as any)["_client"] ?? client,
116
117
  deserializeHelper as (result: TResponse) => Promise<TResult>,
@@ -120,7 +121,8 @@ export function buildRestorePoller(
120
121
  abortSignal: options?.abortSignal,
121
122
  resourceLocationConfig,
122
123
  restoreFrom: serializedState,
123
- initialRequestUrl
124
+ initialRequestUrl,
125
+ apiVersion,
124
126
  }
125
127
  );
126
128
  }
@@ -209,7 +211,12 @@ export function buildRestorePoller(
209
211
  function getPathFromMapKey(mapKey: string): string {
210
212
  const pathStart = mapKey.indexOf("/");
211
213
  return mapKey.slice(pathStart);
212
- }
214
+ }
215
+
216
+ function getApiVersionFromUrl(urlStr: string): string | undefined {
217
+ const url = new URL(urlStr);
218
+ return url.searchParams.get("api-version") ?? undefined;
219
+ }
213
220
  `;
214
221
  restorePollerFile.addStatements(restorePollerHelperContent);
215
222
  }
@@ -38,7 +38,12 @@ import {
38
38
  ServiceOperation
39
39
  } from "../utils/operationUtil.js";
40
40
  import { getSubscriptionId } from "../transform/transfromRLCOptions.js";
41
- import { getClientParametersDeclaration } from "./helpers/clientHelpers.js";
41
+ import {
42
+ getClientParametersDeclaration,
43
+ getClientParameters,
44
+ hasDefaultValue,
45
+ getClientParameterName
46
+ } from "./helpers/clientHelpers.js";
42
47
  import { getOperationFunction } from "./helpers/operationHelpers.js";
43
48
  import { ModelOverrideOptions } from "./serialization/serializeUtils.js";
44
49
 
@@ -298,6 +303,12 @@ function prepareExampleParameters(
298
303
  // TODO: blocked by TCGC issue: https://github.com/Azure/typespec-azure/issues/1419
299
304
  // refine this to support generic client-level parameters once resolved
300
305
  const result: ExampleValue[] = [];
306
+
307
+ // Get the raw SDK parameters to check for default values
308
+ const rawClientParams = getClientParameters(topLevelClient, dpgContext, {
309
+ onClientOnly: true
310
+ });
311
+
301
312
  const clientParams = getClientParametersDeclaration(
302
313
  topLevelClient,
303
314
  dpgContext,
@@ -306,11 +317,27 @@ function prepareExampleParameters(
306
317
  }
307
318
  );
308
319
 
320
+ // Helper to check if a parameter has a default value
321
+ const hasParamDefaultValue = (paramName: string) => {
322
+ const rawParam = rawClientParams.find((p) => {
323
+ return getClientParameterName(p) === paramName;
324
+ });
325
+
326
+ if (!rawParam) return false;
327
+
328
+ return hasDefaultValue(rawParam);
329
+ };
330
+
309
331
  for (const param of clientParams) {
310
332
  if (param.name === "options" || param.name === "credential") {
311
333
  continue;
312
334
  }
313
335
 
336
+ // Skip parameters that have default values - they are truly optional
337
+ if (hasParamDefaultValue(param.name)) {
338
+ continue;
339
+ }
340
+
314
341
  const exampleValue: ExampleValue = {
315
342
  name: param.name === "endpointParam" ? "endpoint" : param.name,
316
343
  value: getEnvironmentVariableName(
@@ -517,6 +544,7 @@ function getParameterValue(
517
544
  switch (value.kind) {
518
545
  case "string": {
519
546
  switch (value.type.kind) {
547
+ case "plainDate":
520
548
  case "utcDateTime":
521
549
  retValue = `new Date("${value.value}")`;
522
550
  break;
@@ -40,6 +40,28 @@ type SdkParameter =
40
40
  | SdkCredentialParameter
41
41
  | SdkHttpParameter;
42
42
 
43
+ export function hasDefaultValue(p: SdkParameter) {
44
+ if (
45
+ p.clientDefaultValue ||
46
+ p.__raw?.defaultValue ||
47
+ p.type.kind === "constant"
48
+ ) {
49
+ return true;
50
+ }
51
+
52
+ // Special case for endpoint parameters with template arguments that have default values
53
+ if (p.type.kind === "endpoint" && p.type.templateArguments[0]) {
54
+ const templateArg = p.type.templateArguments[0];
55
+ return !!(
56
+ templateArg.clientDefaultValue ||
57
+ templateArg.__raw?.defaultValue ||
58
+ templateArg.type?.kind === "constant"
59
+ );
60
+ }
61
+
62
+ return false;
63
+ }
64
+
43
65
  export function getClientParameters(
44
66
  client: SdkClientType<SdkServiceOperation>,
45
67
  dpgContext: SdkContext,
@@ -70,19 +92,15 @@ export function getClientParameters(
70
92
  }
71
93
  }
72
94
 
73
- const hasDefaultValue = (p: SdkParameter) =>
74
- p.clientDefaultValue || p.__raw?.defaultValue || p.type.kind === "constant";
75
95
  const isRequired = (p: SdkParameter) =>
76
96
  // Special case: when apiVersionAsRequired is true, apiVersion should always be considered required
77
97
  (options.apiVersionAsRequired && p.isApiVersionParam) ||
78
- (!p.optional &&
79
- !hasDefaultValue(p) &&
80
- !(
81
- p.type.kind === "endpoint" &&
82
- p.type.templateArguments[0] &&
83
- hasDefaultValue(p.type.templateArguments[0])
84
- ));
85
- const isOptional = (p: SdkParameter) => p.optional || hasDefaultValue(p);
98
+ (!p.optional && !hasDefaultValue(p));
99
+ const isOptional = (p: SdkParameter) =>
100
+ p.optional ||
101
+ p.clientDefaultValue ||
102
+ p.__raw?.defaultValue ||
103
+ p.type.kind === "constant";
86
104
  const skipCredentials = (p: SdkParameter) => p.kind !== "credential";
87
105
  const skipMethodParam = (p: SdkParameter) => p.kind !== "method";
88
106
  const armSpecific = (p: SdkParameter) =>
@@ -70,7 +70,6 @@ import {
70
70
  isHttpMetadata,
71
71
  isReadOnly,
72
72
  SdkBodyParameter,
73
- SdkClientType,
74
73
  SdkConstantType,
75
74
  SdkEnumType,
76
75
  SdkHttpOperation,
@@ -90,7 +89,6 @@ import { isExtensibleEnum } from "../type-expressions/get-enum-expression.js";
90
89
 
91
90
  export function getSendPrivateFunction(
92
91
  dpgContext: SdkContext,
93
- client: SdkClientType<SdkHttpOperation>,
94
92
  method: [string[], ServiceOperation],
95
93
  clientType: string
96
94
  ): OptionalKind<FunctionDeclarationStructure> {
@@ -114,12 +112,6 @@ export function getSendPrivateFunction(
114
112
  const operationPath = operation.operation.path;
115
113
  const operationMethod = operation.operation.verb.toLowerCase();
116
114
  const optionalParamName = getOptionalParamsName(parameters);
117
- const hasQueryApiVersion = operation.operation.parameters.some(
118
- (p) => p.onClient && p.kind === "query" && p.isApiVersionParam
119
- );
120
- const hasClientApiVersion = client.clientInitialization.parameters.some(
121
- (p) => p.isApiVersionParam && p.onClient && p.kind === "method"
122
- );
123
115
  const statements: string[] = [];
124
116
  let pathStr = `"${operationPath}"`;
125
117
  const urlTemplateParams = [
@@ -134,11 +126,6 @@ export function getSendPrivateFunction(
134
126
  });`);
135
127
  pathStr = "path";
136
128
  }
137
- if (hasClientApiVersion && !hasQueryApiVersion) {
138
- statements.push(
139
- `context.pipeline.removePolicy({ name: "ClientApiVersionPolicy"});`
140
- );
141
- }
142
129
 
143
130
  statements.push(
144
131
  `return context.path(${pathStr}).${operationMethod}({...${resolveReference(dependencies.operationOptionsToRequestParameters)}(${optionalParamName}), ${getHeaderAndBodyParameters(
@@ -684,9 +671,11 @@ function getLroOnlyOperationFunction(
684
671
  const resourceLocationConfig =
685
672
  lroMetadata?.finalStateVia &&
686
673
  allowedFinalLocation.includes(lroMetadata?.finalStateVia)
687
- ? `resourceLocationConfig: "${lroMetadata?.finalStateVia}"`
674
+ ? `resourceLocationConfig: "${lroMetadata?.finalStateVia}",`
688
675
  : "";
676
+ const apiVersion = getApiVersionExpression(operation);
689
677
  const statements: string[] = [];
678
+
690
679
  statements.push(`
691
680
 
692
681
  return ${getLongRunningPollerReference}(context, _${name}Deserialize, ${getExpectedStatuses(
@@ -698,6 +687,7 @@ function getLroOnlyOperationFunction(
698
687
  .map((p) => p.name)
699
688
  .join(", ")}),
700
689
  ${resourceLocationConfig}
690
+ ${apiVersion ? `apiVersion: ${apiVersion}` : ""}
701
691
  }) as ${pollerLikeReference}<${operationStateReference}<${
702
692
  returnType.type
703
693
  }>, ${returnType.type}>;
@@ -725,6 +715,9 @@ function getLroAndPagingOperationFunction(
725
715
 
726
716
  const returnType = buildLroPagingReturnType(context, operation);
727
717
 
718
+ // Get apiVersion expression for both LRO poller and paging options
719
+ const apiVersion = getApiVersionExpression(operation);
720
+
728
721
  // Build paging options from metadata
729
722
  const pagingOptions = [
730
723
  operation.response.resultSegments &&
@@ -732,7 +725,8 @@ function getLroAndPagingOperationFunction(
732
725
  operation.pagingMetadata.nextLinkSegments &&
733
726
  `nextLinkName: "${operation.pagingMetadata.nextLinkSegments.map((p) => p.name).join(".")}"`,
734
727
  operation.pagingMetadata.nextLinkVerb !== "GET" &&
735
- `nextLinkMethod: "${operation.pagingMetadata.nextLinkVerb}"`
728
+ `nextLinkMethod: "${operation.pagingMetadata.nextLinkVerb}"`,
729
+ apiVersion && `apiVersion: ${apiVersion}`
736
730
  ].filter(Boolean);
737
731
 
738
732
  // Build LRO resource location config
@@ -745,7 +739,7 @@ function getLroAndPagingOperationFunction(
745
739
  const resourceLocationConfig =
746
740
  operation.lroMetadata?.finalStateVia &&
747
741
  allowedLocations.includes(operation.lroMetadata.finalStateVia)
748
- ? `resourceLocationConfig: "${operation.lroMetadata.finalStateVia}"`
742
+ ? `resourceLocationConfig: "${operation.lroMetadata.finalStateVia}",`
749
743
  : "";
750
744
 
751
745
  // Resolve references
@@ -784,6 +778,7 @@ function getLroAndPagingOperationFunction(
784
778
  abortSignal: ${optionalParamName}?.abortSignal,
785
779
  getInitialResponse: () => _${name}Send(${paramList}),
786
780
  ${resourceLocationConfig}
781
+ ${apiVersion ? `apiVersion: ${apiVersion}` : ""}
787
782
  }) as ${refs.pollerLike}<${refs.operationState}<${refs.pathResponse}>, ${refs.pathResponse}>;
788
783
 
789
784
  return ${refs.buildPaging}(
@@ -887,6 +882,8 @@ function getPagingOnlyOperationFunction(
887
882
  // Check for nextLinkVerb from TCGC pagingMetadata (supports @Legacy.nextLinkVerb decorator)
888
883
  const nextLinkMethod = operation.pagingMetadata.nextLinkVerb;
889
884
 
885
+ const apiVersion = getApiVersionExpression(operation);
886
+
890
887
  if (itemName) {
891
888
  options.push(`itemName: "${itemName}"`);
892
889
  }
@@ -896,6 +893,9 @@ function getPagingOnlyOperationFunction(
896
893
  if (nextLinkMethod && nextLinkMethod !== "GET") {
897
894
  options.push(`nextLinkMethod: "${nextLinkMethod}"`);
898
895
  }
896
+ if (apiVersion) {
897
+ options.push(`apiVersion: ${apiVersion}`);
898
+ }
899
899
  statements.push(
900
900
  `return ${buildPagedAsyncIteratorReference}(
901
901
  context,
@@ -1151,6 +1151,11 @@ export function getParameterMap(
1151
1151
  return `"${serializedName}": ${getConstantValue(param.type)}`;
1152
1152
  }
1153
1153
 
1154
+ // Special case for api-version parameters with default values
1155
+ if (param.isApiVersionParam && param.clientDefaultValue) {
1156
+ return `"${serializedName}": ${param.onClient ? "context." : ""}${param.name} ?? "${param.clientDefaultValue}"`;
1157
+ }
1158
+
1154
1159
  if (hasCollectionFormatInfo(param.kind, (param as any).collectionFormat)) {
1155
1160
  return getCollectionFormatForParam(
1156
1161
  context,
@@ -1722,6 +1727,9 @@ export function serializeRequestValue(
1722
1727
  ? `!${clientValue}? ${clientValue}: `
1723
1728
  : "";
1724
1729
  switch (type.kind) {
1730
+ case "plainDate":
1731
+ // plainDate always uses ISO8601 format (YYYY-MM-DD)
1732
+ return `${nullOrUndefinedPrefix}${clientValue}.toISOString().split('T')[0]`;
1725
1733
  case "utcDateTime":
1726
1734
  switch (type.encode ?? format) {
1727
1735
  case "rfc7231":
@@ -1849,6 +1857,9 @@ export function deserializeResponseValue(
1849
1857
  ? `!${restValue}? ${restValue}: `
1850
1858
  : "";
1851
1859
  switch (type.kind) {
1860
+ case "plainDate":
1861
+ // plainDate deserializes from YYYY-MM-DD string to Date
1862
+ return `${nullOrUndefinedPrefix} new Date(${restValue})`;
1852
1863
  case "utcDateTime":
1853
1864
  return `${nullOrUndefinedPrefix} new Date(${type.encode === "unixTimestamp" ? `${restValue} * 1000` : restValue})`;
1854
1865
  case "array": {
@@ -2088,3 +2099,24 @@ export function getExpectedStatuses(operation: ServiceOperation): string {
2088
2099
 
2089
2100
  return `[${statusCodes.map((x) => `"${x}"`).join(", ")}]`;
2090
2101
  }
2102
+
2103
+ /**
2104
+ * Gets the apiVersion expression with default value fallback for query parameters.
2105
+ * @param operation - The operation to get the apiVersion parameter from
2106
+ * @returns The apiVersion expression string, or undefined if no apiVersion query param exists
2107
+ */
2108
+ function getApiVersionExpression(
2109
+ operation: ServiceOperation
2110
+ ): string | undefined {
2111
+ const queryApiVersionParam = operation.operation.parameters.find(
2112
+ (p) => p.kind === "query" && p.isApiVersionParam
2113
+ );
2114
+ if (!queryApiVersionParam) {
2115
+ return undefined;
2116
+ }
2117
+ const paramAccess = `${queryApiVersionParam.onClient ? "context." : ""}${queryApiVersionParam.name}`;
2118
+ const defaultValueSuffix = queryApiVersionParam.clientDefaultValue
2119
+ ? ` ?? "${queryApiVersionParam.clientDefaultValue}"`
2120
+ : "";
2121
+ return `${paramAccess}${defaultValueSuffix}`;
2122
+ }
@@ -78,7 +78,7 @@ const NumericTypeKinds = [
78
78
  "decimal128"
79
79
  ];
80
80
 
81
- const DateTimeTypeKinds = ["plainDate", "plainTime"];
81
+ const DateTimeTypeKinds = ["plainTime"];
82
82
 
83
83
  // This may be a good candidate to move to TCGC
84
84
  export function isNumericTypeKind(kind: string): boolean {
@@ -178,7 +178,11 @@ function buildPolymorphicDeserializer(
178
178
 
179
179
  const subTypes = type.discriminatedSubtypes;
180
180
  if (!subTypes) {
181
- return;
181
+ // No subtypes - treat as a regular model and generate simple deserializer
182
+ return buildModelTypeDeserializer(context, type, {
183
+ nameOnly,
184
+ skipDiscriminatedUnionSuffix: false
185
+ });
182
186
  }
183
187
 
184
188
  const cases: string[] = [];
@@ -184,7 +184,11 @@ function buildPolymorphicSerializer(
184
184
 
185
185
  const subTypes = type.discriminatedSubtypes;
186
186
  if (!subTypes) {
187
- return;
187
+ // No subtypes - treat as a regular model and generate simple serializer
188
+ return buildModelTypeSerializer(context, type, {
189
+ nameOnly,
190
+ skipDiscriminatedUnionSuffix: false
191
+ });
188
192
  }
189
193
 
190
194
  const cases: string[] = [];
@@ -81,6 +81,7 @@ export function isSpecialUnionVariant(
81
81
 
82
82
  if (
83
83
  t.kind === "utcDateTime" ||
84
+ t.kind === "plainDate" ||
84
85
  t.kind === "bytes" ||
85
86
  (t.kind === "model" &&
86
87
  t.properties
@@ -62,7 +62,6 @@ export function getTypeExpression(
62
62
  }
63
63
  return "number";
64
64
  case "endpoint":
65
- case "plainDate":
66
65
  case "plainTime":
67
66
  case "string":
68
67
  case "url":
@@ -103,6 +102,7 @@ export function getTypeExpression(
103
102
  case "union":
104
103
  return getUnionExpression(context, type, options);
105
104
  case "utcDateTime":
105
+ case "plainDate":
106
106
  return "Date";
107
107
 
108
108
  default:
@@ -96,7 +96,7 @@ function transformOperation(
96
96
  responseTypes,
97
97
  operationGroupName
98
98
  ),
99
- isPaging: isPagingOperation(program, route)
99
+ isPaging: isPagingOperation(dpgContext, route)
100
100
  }
101
101
  };
102
102
  if (
@@ -1187,7 +1187,7 @@ function getSchemaForArrayModel(
1187
1187
  .join(" | ");
1188
1188
  }
1189
1189
  }
1190
- } else if (schema.items.type.includes("|")) {
1190
+ } else if (schema.items?.type?.includes("|")) {
1191
1191
  schema.typeName = `(${schema.items.type})[]`;
1192
1192
  } else {
1193
1193
  schema.typeName = `${schema.items.type}[]`;
@@ -1326,6 +1326,10 @@ function getSchemaForStdScalar(
1326
1326
  type: "number",
1327
1327
  format: "safeint"
1328
1328
  });
1329
+ case "numeric":
1330
+ return applyIntrinsicDecorators(program, type, {
1331
+ type: "number"
1332
+ });
1329
1333
  case "uint8":
1330
1334
  return applyIntrinsicDecorators(program, type, {
1331
1335
  type: "number",
@@ -15,6 +15,7 @@ import {
15
15
  } from "@azure-tools/rlc-common";
16
16
  import { getLroMetadata } from "@azure-tools/typespec-azure-core";
17
17
  import {
18
+ getDisablePageable,
18
19
  getHttpOperationWithCache,
19
20
  getWireName,
20
21
  InitializedByFlags,
@@ -424,7 +425,15 @@ export function extractPageDetails(
424
425
  return undefined;
425
426
  }
426
427
 
427
- export function isPagingOperation(program: Program, operation: HttpOperation) {
428
+ export function isPagingOperation(
429
+ dpgContext: SdkContext,
430
+ operation: HttpOperation
431
+ ) {
432
+ const { program } = dpgContext;
433
+ if (getDisablePageable(dpgContext, operation.operation)) {
434
+ return false;
435
+ }
436
+
428
437
  return extractPageDetails(program, operation) !== undefined;
429
438
  }
430
439
 
@@ -471,14 +480,13 @@ function findRootSourceProperty(property: ModelProperty): ModelProperty {
471
480
  }
472
481
 
473
482
  export function hasPagingOperations(client: SdkClient, dpgContext: SdkContext) {
474
- const program = dpgContext.program;
475
483
  for (const op of listOperationsUnderRLCClient(client)) {
476
484
  const route = getHttpOperationWithCache(dpgContext, op);
477
485
  // ignore overload base operation
478
486
  if (route.overloads && route.overloads?.length > 0) {
479
487
  continue;
480
488
  }
481
- if (isPagingOperation(program, route)) {
489
+ if (isPagingOperation(dpgContext, route)) {
482
490
  return true;
483
491
  }
484
492
  }
@@ -91,6 +91,7 @@ export interface BuildPagedAsyncIteratorOptions {
91
91
  itemName?: string;
92
92
  nextLinkName?: string;
93
93
  nextLinkMethod?: "GET" | "POST";
94
+ apiVersion?: string;
94
95
  }
95
96
 
96
97
  /**
@@ -111,14 +112,21 @@ export function buildPagedAsyncIterator<
111
112
  const itemName = options.itemName ?? "value";
112
113
  const nextLinkName = options.nextLinkName ?? "nextLink";
113
114
  const nextLinkMethod = options.nextLinkMethod ?? "GET";
115
+ const apiVersion = options.apiVersion;
114
116
  const pagedResult: PagedResult<TElement, TPage, TPageSettings> = {
115
117
  getPage: async (pageLink?: string) => {
116
- const result =
117
- pageLink === undefined
118
- ? await getInitialResponse()
119
- : nextLinkMethod === "POST"
120
- ? await client.pathUnchecked(pageLink).post()
121
- : await client.pathUnchecked(pageLink).get();
118
+ let result;
119
+ if (pageLink === undefined) {
120
+ result = await getInitialResponse();
121
+ } else {
122
+ const resolvedPageLink = apiVersion
123
+ ? addApiVersionToUrl(pageLink, apiVersion)
124
+ : pageLink;
125
+ result =
126
+ nextLinkMethod === "POST"
127
+ ? await client.pathUnchecked(resolvedPageLink).post()
128
+ : await client.pathUnchecked(resolvedPageLink).get();
129
+ }
122
130
  checkPagingRequest(result, expectedStatuses);
123
131
  const results = await processResponseBody(result as TResponse);
124
132
  const nextLink = getNextLink(results, nextLinkName);
@@ -273,3 +281,21 @@ function checkPagingRequest(
273
281
  );
274
282
  }
275
283
  }
284
+
285
+ /**
286
+ * Adds the api-version query parameter on a URL if it's not present.
287
+ * @param url - the URL to modify
288
+ * @param apiVersion - the API version to set
289
+ * @returns - the URL with the api-version query parameter set
290
+ */
291
+ function addApiVersionToUrl(url: string, apiVersion: string): string {
292
+ // The base URL is only used for parsing and won't appear in the returned URL
293
+ const urlObj = new URL(url, "https://microsoft.com");
294
+ if (!urlObj.searchParams.get("api-version")) {
295
+ // Append one if there is no apiVersion
296
+ return `${url}${
297
+ Array.from(urlObj.searchParams.keys()).length > 0 ? "&" : "?"
298
+ }api-version=${apiVersion}`;
299
+ }
300
+ return url;
301
+ }