@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.
- package/CHANGELOG.md +11 -0
- package/dist/src/modular/buildClientContext.d.ts.map +1 -1
- package/dist/src/modular/buildClientContext.js +6 -25
- 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 +1 -1
- package/dist/src/modular/buildOperations.js.map +1 -1
- package/dist/src/modular/buildRestorePoller.d.ts.map +1 -1
- package/dist/src/modular/buildRestorePoller.js +9 -2
- package/dist/src/modular/buildRestorePoller.js.map +1 -1
- package/dist/src/modular/emitSamples.d.ts.map +1 -1
- package/dist/src/modular/emitSamples.js +19 -1
- package/dist/src/modular/emitSamples.js.map +1 -1
- package/dist/src/modular/helpers/clientHelpers.d.ts +1 -0
- package/dist/src/modular/helpers/clientHelpers.d.ts.map +1 -1
- package/dist/src/modular/helpers/clientHelpers.js +24 -7
- package/dist/src/modular/helpers/clientHelpers.js.map +1 -1
- package/dist/src/modular/helpers/operationHelpers.d.ts +2 -2
- package/dist/src/modular/helpers/operationHelpers.d.ts.map +1 -1
- package/dist/src/modular/helpers/operationHelpers.js +40 -9
- package/dist/src/modular/helpers/operationHelpers.js.map +1 -1
- package/dist/src/modular/helpers/typeHelpers.js +1 -1
- package/dist/src/modular/helpers/typeHelpers.js.map +1 -1
- package/dist/src/modular/serialization/buildDeserializerFunction.js +5 -1
- package/dist/src/modular/serialization/buildDeserializerFunction.js.map +1 -1
- package/dist/src/modular/serialization/buildSerializerFunction.js +5 -1
- package/dist/src/modular/serialization/buildSerializerFunction.js.map +1 -1
- package/dist/src/modular/serialization/serializeUtils.d.ts.map +1 -1
- package/dist/src/modular/serialization/serializeUtils.js +1 -0
- package/dist/src/modular/serialization/serializeUtils.js.map +1 -1
- package/dist/src/modular/type-expressions/get-type-expression.js +1 -1
- package/dist/src/modular/type-expressions/get-type-expression.js.map +1 -1
- package/dist/src/transform/transformPaths.js +1 -1
- package/dist/src/transform/transformPaths.js.map +1 -1
- package/dist/src/utils/modelUtils.d.ts.map +1 -1
- package/dist/src/utils/modelUtils.js +6 -2
- package/dist/src/utils/modelUtils.js.map +1 -1
- package/dist/src/utils/operationUtil.d.ts +1 -1
- package/dist/src/utils/operationUtil.d.ts.map +1 -1
- package/dist/src/utils/operationUtil.js +7 -4
- package/dist/src/utils/operationUtil.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -7
- package/src/modular/buildClientContext.ts +6 -26
- package/src/modular/buildOperations.ts +0 -1
- package/src/modular/buildRestorePoller.ts +9 -2
- package/src/modular/emitSamples.ts +29 -1
- package/src/modular/helpers/clientHelpers.ts +28 -10
- package/src/modular/helpers/operationHelpers.ts +48 -16
- package/src/modular/helpers/typeHelpers.ts +1 -1
- package/src/modular/serialization/buildDeserializerFunction.ts +5 -1
- package/src/modular/serialization/buildSerializerFunction.ts +5 -1
- package/src/modular/serialization/serializeUtils.ts +1 -0
- package/src/modular/type-expressions/get-type-expression.ts +1 -1
- package/src/transform/transformPaths.ts +1 -1
- package/src/utils/modelUtils.ts +5 -1
- package/src/utils/operationUtil.ts +11 -3
- package/static/static-helpers/pagingHelpers.ts +32 -6
- 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.
|
|
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.
|
|
22
|
-
"@typespec/spector": "0.1.0-alpha.23-dev.
|
|
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.
|
|
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.
|
|
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.
|
|
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": "
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
270
|
+
factoryFunction.addStatements(apiVersionStatement);
|
|
291
271
|
|
|
292
272
|
const contextRequiredParam = requiredParams.filter(
|
|
293
273
|
(p) =>
|
|
@@ -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 {
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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 = ["
|
|
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
|
-
|
|
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
|
-
|
|
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[] = [];
|
|
@@ -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:
|
package/src/utils/modelUtils.ts
CHANGED
|
@@ -1187,7 +1187,7 @@ function getSchemaForArrayModel(
|
|
|
1187
1187
|
.join(" | ");
|
|
1188
1188
|
}
|
|
1189
1189
|
}
|
|
1190
|
-
} else if (schema.items
|
|
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(
|
|
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(
|
|
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
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
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
|
+
}
|