@azure-tools/typespec-ts 0.34.0 → 0.35.0-alpha.20241203.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/README.md +16 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +22 -19
- package/dist/src/index.js.map +1 -1
- package/dist/src/lib.d.ts +19 -1
- package/dist/src/lib.d.ts.map +1 -1
- package/dist/src/lib.js +14 -1
- package/dist/src/lib.js.map +1 -1
- package/dist/src/modular/buildClassicalClient.js +2 -2
- package/dist/src/modular/buildClassicalClient.js.map +1 -1
- package/dist/src/modular/buildCodeModel.d.ts.map +1 -1
- package/dist/src/modular/buildCodeModel.js +18 -0
- package/dist/src/modular/buildCodeModel.js.map +1 -1
- package/dist/src/modular/helpers/clientHelpers.js +1 -1
- package/dist/src/modular/helpers/clientHelpers.js.map +1 -1
- package/dist/src/modular/helpers/operationHelpers.js +2 -2
- package/dist/src/modular/helpers/operationHelpers.js.map +1 -1
- package/dist/src/transform/transform.d.ts.map +1 -1
- package/dist/src/transform/transform.js +7 -5
- package/dist/src/transform/transform.js.map +1 -1
- package/dist/src/transform/transformApiVersionInfo.js +2 -2
- package/dist/src/transform/transformApiVersionInfo.js.map +1 -1
- package/dist/src/transform/transformHelperFunctionDetails.js +2 -29
- package/dist/src/transform/transformHelperFunctionDetails.js.map +1 -1
- package/dist/src/transform/transformParameters.d.ts +8 -1
- package/dist/src/transform/transformParameters.d.ts.map +1 -1
- package/dist/src/transform/transformParameters.js +63 -38
- package/dist/src/transform/transformParameters.js.map +1 -1
- package/dist/src/transform/transformPaths.d.ts.map +1 -1
- package/dist/src/transform/transformPaths.js +14 -6
- package/dist/src/transform/transformPaths.js.map +1 -1
- package/dist/src/transform/transfromRLCOptions.d.ts.map +1 -1
- package/dist/src/transform/transfromRLCOptions.js +6 -4
- package/dist/src/transform/transfromRLCOptions.js.map +1 -1
- package/dist/src/utils/emitUtil.js +3 -0
- package/dist/src/utils/emitUtil.js.map +1 -1
- package/dist/src/utils/modelUtils.d.ts +2 -1
- package/dist/src/utils/modelUtils.d.ts.map +1 -1
- package/dist/src/utils/modelUtils.js +10 -25
- package/dist/src/utils/modelUtils.js.map +1 -1
- package/dist/src/utils/operationUtil.d.ts +1 -4
- package/dist/src/utils/operationUtil.d.ts.map +1 -1
- package/dist/src/utils/operationUtil.js +8 -22
- package/dist/src/utils/operationUtil.js.map +1 -1
- package/dist/src/utils/parameterUtils.d.ts +9 -0
- package/dist/src/utils/parameterUtils.d.ts.map +1 -0
- package/dist/src/utils/parameterUtils.js +165 -0
- package/dist/src/utils/parameterUtils.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +20 -20
- package/src/index.ts +22 -24
- package/src/lib.ts +14 -1
- package/src/modular/buildClassicalClient.ts +2 -2
- package/src/modular/buildCodeModel.ts +19 -1
- package/src/modular/helpers/clientHelpers.ts +1 -1
- package/src/modular/helpers/operationHelpers.ts +2 -2
- package/src/transform/transform.ts +3 -1
- package/src/transform/transformApiVersionInfo.ts +2 -2
- package/src/transform/transformHelperFunctionDetails.ts +2 -27
- package/src/transform/transformParameters.ts +83 -42
- package/src/transform/transformPaths.ts +23 -5
- package/src/transform/transfromRLCOptions.ts +6 -4
- package/src/utils/emitUtil.ts +3 -0
- package/src/utils/modelUtils.ts +14 -34
- package/src/utils/operationUtil.ts +14 -23
- package/src/utils/parameterUtils.ts +234 -0
- package/static/static-helpers/pagingHelpers.ts +0 -3
- package/static/static-helpers/pollingHelpers.ts +0 -3
- package/static/static-helpers/serialization/build-csv-collection.ts +0 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@azure-tools/typespec-ts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.35.0-alpha.20241203.1",
|
|
4
4
|
"description": "An experimental TypeSpec emitter for TypeScript RLC",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -18,14 +18,14 @@
|
|
|
18
18
|
"license": "MIT",
|
|
19
19
|
"devDependencies": {
|
|
20
20
|
"@azure-rest/core-client": "^2.3.1",
|
|
21
|
-
"@azure-tools/cadl-ranch-expect": "^0.15.
|
|
22
|
-
"@azure-tools/cadl-ranch-specs": "^0.
|
|
23
|
-
"@azure-tools/cadl-ranch": "^0.
|
|
21
|
+
"@azure-tools/cadl-ranch-expect": "^0.15.6",
|
|
22
|
+
"@azure-tools/cadl-ranch-specs": "^0.39.2",
|
|
23
|
+
"@azure-tools/cadl-ranch": "^0.16.1",
|
|
24
24
|
"@azure-tools/cadl-ranch-api": "^0.5.0",
|
|
25
|
-
"@azure-tools/typespec-autorest": ">=0.
|
|
26
|
-
"@azure-tools/typespec-azure-core": ">=0.
|
|
27
|
-
"@azure-tools/typespec-azure-resource-manager": ">=0.
|
|
28
|
-
"@azure-tools/typespec-client-generator-core": ">=0.
|
|
25
|
+
"@azure-tools/typespec-autorest": ">=0.48.0 <1.0.0",
|
|
26
|
+
"@azure-tools/typespec-azure-core": ">=0.48.0 <1.0.0",
|
|
27
|
+
"@azure-tools/typespec-azure-resource-manager": ">=0.48.0 <1.0.0",
|
|
28
|
+
"@azure-tools/typespec-client-generator-core": ">=0.48.0 <1.0.0",
|
|
29
29
|
"@azure/abort-controller": "^2.1.2",
|
|
30
30
|
"@azure/core-auth": "^1.6.0",
|
|
31
31
|
"@azure/core-lro": "^3.1.0",
|
|
@@ -40,12 +40,12 @@
|
|
|
40
40
|
"@types/node": "^18.0.0",
|
|
41
41
|
"@typescript-eslint/eslint-plugin": "^6.8.0",
|
|
42
42
|
"@typescript-eslint/parser": "^6.8.0",
|
|
43
|
-
"@typespec/compiler": ">=0.
|
|
44
|
-
"@typespec/http": ">=0.
|
|
45
|
-
"@typespec/openapi": ">=0.
|
|
46
|
-
"@typespec/rest": ">=0.
|
|
43
|
+
"@typespec/compiler": ">=0.62.0 <1.0.0",
|
|
44
|
+
"@typespec/http": ">=0.62.0 <1.0.0",
|
|
45
|
+
"@typespec/openapi": ">=0.62.0, <1.0.0",
|
|
46
|
+
"@typespec/rest": ">=0.62.0 <1.0.0",
|
|
47
47
|
"@typespec/ts-http-runtime": "1.0.0-alpha.20240314.2",
|
|
48
|
-
"@typespec/versioning": ">=0.
|
|
48
|
+
"@typespec/versioning": ">=0.62.0 <1.0.0",
|
|
49
49
|
"chai": "^4.3.6",
|
|
50
50
|
"chalk": "^4.0.0",
|
|
51
51
|
"cross-env": "^7.0.3",
|
|
@@ -65,15 +65,15 @@
|
|
|
65
65
|
"tsx": "^4.16.5"
|
|
66
66
|
},
|
|
67
67
|
"peerDependencies": {
|
|
68
|
-
"@azure-tools/typespec-azure-core": ">=0.
|
|
69
|
-
"@azure-tools/typespec-client-generator-core": ">=0.
|
|
70
|
-
"@typespec/compiler": ">=0.
|
|
71
|
-
"@typespec/http": ">=0.
|
|
72
|
-
"@typespec/rest": ">=0.
|
|
73
|
-
"@typespec/versioning": ">=0.
|
|
68
|
+
"@azure-tools/typespec-azure-core": ">=0.48.0 <1.0.0",
|
|
69
|
+
"@azure-tools/typespec-client-generator-core": ">=0.48.0 <1.0.0",
|
|
70
|
+
"@typespec/compiler": ">=0.62.0 <1.0.0",
|
|
71
|
+
"@typespec/http": ">=0.62.0 <1.0.0",
|
|
72
|
+
"@typespec/rest": ">=0.62.0 <1.0.0",
|
|
73
|
+
"@typespec/versioning": ">=0.62.0 <1.0.0"
|
|
74
74
|
},
|
|
75
75
|
"dependencies": {
|
|
76
|
-
"@azure-tools/rlc-common": "^0.
|
|
76
|
+
"@azure-tools/rlc-common": "^0.35.0",
|
|
77
77
|
"fs-extra": "^11.1.0",
|
|
78
78
|
"lodash": "^4.17.21",
|
|
79
79
|
"prettier": "^3.3.3",
|
package/src/index.ts
CHANGED
|
@@ -91,10 +91,9 @@ export async function $onEmit(context: EmitContext) {
|
|
|
91
91
|
const program: Program = context.program;
|
|
92
92
|
const emitterOptions: EmitterOptions = context.options;
|
|
93
93
|
const dpgContext = await createContextWithDefaultOptions(context);
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
);
|
|
94
|
+
// Enrich the dpg context with path detail and common options
|
|
95
|
+
await enrichDpgContext();
|
|
96
|
+
const rlcOptions = dpgContext.rlcOptions ?? {};
|
|
98
97
|
|
|
99
98
|
const needUnexpectedHelper: Map<string, boolean> = new Map<string, boolean>();
|
|
100
99
|
const serviceNameToRlcModelsMap: Map<string, RLCModel> = new Map<
|
|
@@ -109,7 +108,6 @@ export async function $onEmit(context: EmitContext) {
|
|
|
109
108
|
compilerContext: context,
|
|
110
109
|
tcgcContext: dpgContext
|
|
111
110
|
});
|
|
112
|
-
const { modularSourcesDir } = await calculateGenerationDir(rlcOptions);
|
|
113
111
|
const staticHelpers = await loadStaticHelpers(
|
|
114
112
|
outputProject,
|
|
115
113
|
{
|
|
@@ -117,7 +115,7 @@ export async function $onEmit(context: EmitContext) {
|
|
|
117
115
|
...PagingHelpers,
|
|
118
116
|
...PollingHelpers
|
|
119
117
|
},
|
|
120
|
-
{ sourcesDir: modularSourcesDir }
|
|
118
|
+
{ sourcesDir: dpgContext.generationPathDetail?.modularSourcesDir }
|
|
121
119
|
);
|
|
122
120
|
const extraDependencies = isAzurePackage({ options: rlcOptions })
|
|
123
121
|
? {
|
|
@@ -136,11 +134,10 @@ export async function $onEmit(context: EmitContext) {
|
|
|
136
134
|
|
|
137
135
|
const rlcCodeModels: RLCModel[] = [];
|
|
138
136
|
let modularCodeModel: ModularCodeModel;
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
// 2. Clear sources folder
|
|
137
|
+
|
|
138
|
+
// 1. Clear sources folder
|
|
142
139
|
await clearSrcFolder();
|
|
143
|
-
//
|
|
140
|
+
// 2. Generate RLC code model
|
|
144
141
|
// TODO: skip this step in modular once modular generator is sufficiently decoupled
|
|
145
142
|
await buildRLCCodeModels();
|
|
146
143
|
|
|
@@ -155,28 +152,26 @@ export async function $onEmit(context: EmitContext) {
|
|
|
155
152
|
await generateMetadataAndTest();
|
|
156
153
|
|
|
157
154
|
async function enrichDpgContext() {
|
|
158
|
-
const options: RLCOptions = transformRLCOptions(emitterOptions, dpgContext);
|
|
159
155
|
const generationPathDetail: GenerationDirDetail =
|
|
160
|
-
await calculateGenerationDir(
|
|
156
|
+
await calculateGenerationDir();
|
|
161
157
|
dpgContext.generationPathDetail = generationPathDetail;
|
|
158
|
+
const options: RLCOptions = transformRLCOptions(emitterOptions, dpgContext);
|
|
159
|
+
// clear output folder if needed
|
|
160
|
+
if (options.clearOutputFolder) {
|
|
161
|
+
await fsextra.emptyDir(context.emitterOutputDir);
|
|
162
|
+
}
|
|
162
163
|
const hasTestFolder = await fsextra.pathExists(
|
|
163
164
|
join(dpgContext.generationPathDetail?.metadataDir ?? "", "test")
|
|
164
165
|
);
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
(
|
|
166
|
+
options.generateTest =
|
|
167
|
+
options.generateTest === true ||
|
|
168
|
+
(options.generateTest === undefined &&
|
|
168
169
|
!hasTestFolder &&
|
|
169
|
-
isAzurePackage({ options:
|
|
170
|
-
dpgContext.rlcOptions =
|
|
170
|
+
isAzurePackage({ options: options }));
|
|
171
|
+
dpgContext.rlcOptions = options;
|
|
171
172
|
}
|
|
172
173
|
|
|
173
|
-
async function calculateGenerationDir(
|
|
174
|
-
options: RLCOptions
|
|
175
|
-
): Promise<GenerationDirDetail> {
|
|
176
|
-
// clear output folder if needed
|
|
177
|
-
if (options.clearOutputFolder) {
|
|
178
|
-
await fsextra.emptyDir(context.emitterOutputDir);
|
|
179
|
-
}
|
|
174
|
+
async function calculateGenerationDir(): Promise<GenerationDirDetail> {
|
|
180
175
|
const projectRoot = context.emitterOutputDir ?? "";
|
|
181
176
|
const customizationFolder = join(projectRoot, "generated");
|
|
182
177
|
// if customization folder exists, use it as sources root
|
|
@@ -304,6 +299,9 @@ export async function $onEmit(context: EmitContext) {
|
|
|
304
299
|
}
|
|
305
300
|
|
|
306
301
|
binder.resolveAllReferences(modularSourcesRoot);
|
|
302
|
+
if (program.compilerOptions.noEmit || program.hasError()) {
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
307
305
|
|
|
308
306
|
for (const file of project.getSourceFiles()) {
|
|
309
307
|
file.fixMissingImports(
|
package/src/lib.ts
CHANGED
|
@@ -92,7 +92,8 @@ export const RLCOptionsSchema: JSONSchemaType<EmitterOptions> = {
|
|
|
92
92
|
compatibilityMode: { type: "boolean", nullable: true },
|
|
93
93
|
experimentalExtensibleEnums: { type: "boolean", nullable: true },
|
|
94
94
|
clearOutputFolder: { type: "boolean", nullable: true },
|
|
95
|
-
ignorePropertyNameNormalize: { type: "boolean", nullable: true }
|
|
95
|
+
ignorePropertyNameNormalize: { type: "boolean", nullable: true },
|
|
96
|
+
compatibilityQueryMultiFormat: { type: "boolean", nullable: true }
|
|
96
97
|
},
|
|
97
98
|
required: []
|
|
98
99
|
};
|
|
@@ -267,6 +268,18 @@ const libDef = {
|
|
|
267
268
|
messages: {
|
|
268
269
|
default: paramMessage`Path parameter '${"paramName"}' cannot be optional.`
|
|
269
270
|
}
|
|
271
|
+
},
|
|
272
|
+
"un-supported-format-cases": {
|
|
273
|
+
severity: "warning",
|
|
274
|
+
messages: {
|
|
275
|
+
default: paramMessage`The parameter ${"paramName"} with explode: ${"explode"} and format: ${"format"} is not supported.`
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
"parameter-type-not-supported": {
|
|
279
|
+
severity: "warning",
|
|
280
|
+
messages: {
|
|
281
|
+
default: paramMessage`Parameter '${"paramName"}' with type '${"paramType"}' is not supported and we would ignore this parameter.`
|
|
282
|
+
}
|
|
270
283
|
}
|
|
271
284
|
},
|
|
272
285
|
emitter: {
|
|
@@ -108,9 +108,9 @@ export function buildClassicalClient(
|
|
|
108
108
|
});
|
|
109
109
|
|
|
110
110
|
constructor.addStatements([
|
|
111
|
-
`this._client = create${modularClientName}(${paramNames.join(",")})
|
|
111
|
+
`this._client = create${modularClientName}(${paramNames.join(",")});`
|
|
112
112
|
]);
|
|
113
|
-
constructor.addStatements(`this.pipeline = this._client.pipeline
|
|
113
|
+
constructor.addStatements(`this.pipeline = this._client.pipeline;`);
|
|
114
114
|
|
|
115
115
|
buildClientOperationGroups(clientFile, _client, dpgContext, clientClass);
|
|
116
116
|
importAllApis(clientFile, srcPath, subfolder);
|
|
@@ -509,7 +509,19 @@ function emitParameter(
|
|
|
509
509
|
context: SdkContext,
|
|
510
510
|
parameter: HttpOperationParameter | HttpServerParameter,
|
|
511
511
|
implementation: string
|
|
512
|
-
): Parameter {
|
|
512
|
+
): Parameter | undefined {
|
|
513
|
+
if (parameter.type === "cookie") {
|
|
514
|
+
// TODO: support cookie parameters, https://github.com/Azure/autorest.typescript/issues/2898
|
|
515
|
+
reportDiagnostic(context.program, {
|
|
516
|
+
code: "parameter-type-not-supported",
|
|
517
|
+
format: {
|
|
518
|
+
paramType: parameter.type,
|
|
519
|
+
paramName: parameter.name
|
|
520
|
+
},
|
|
521
|
+
target: NoTarget
|
|
522
|
+
});
|
|
523
|
+
return undefined;
|
|
524
|
+
}
|
|
513
525
|
const base = emitParamBase(context, parameter.param);
|
|
514
526
|
let type = getType(context, parameter.param.type, {
|
|
515
527
|
usage: UsageFlags.Input
|
|
@@ -857,6 +869,9 @@ function emitBasicOperation(
|
|
|
857
869
|
continue;
|
|
858
870
|
}
|
|
859
871
|
const emittedParam = emitParameter(context, param, "Method");
|
|
872
|
+
if (emittedParam === undefined) {
|
|
873
|
+
continue;
|
|
874
|
+
}
|
|
860
875
|
if (isApiVersion(context, param)) {
|
|
861
876
|
emittedParam.isApiVersion = true;
|
|
862
877
|
methodApiVersionParam = emittedParam;
|
|
@@ -1719,6 +1734,9 @@ function emitServerParams(
|
|
|
1719
1734
|
serverParameter,
|
|
1720
1735
|
"Client"
|
|
1721
1736
|
);
|
|
1737
|
+
if (emittedParameter === undefined) {
|
|
1738
|
+
continue;
|
|
1739
|
+
}
|
|
1722
1740
|
endpointPathParameters.push(emittedParameter);
|
|
1723
1741
|
if (isApiVersion(context, serverParameter as any)) {
|
|
1724
1742
|
emittedParameter.isApiVersion = true;
|
|
@@ -997,7 +997,7 @@ export function serializeRequestValue(
|
|
|
997
997
|
case "headerDefault":
|
|
998
998
|
return `${nullOrUndefinedPrefix}${clientValue}.toUTCString()`;
|
|
999
999
|
case "unixTimestamp":
|
|
1000
|
-
return `${nullOrUndefinedPrefix}${clientValue}.getTime()`;
|
|
1000
|
+
return `${nullOrUndefinedPrefix}((${clientValue}.getTime() / 1000) | 0)`;
|
|
1001
1001
|
case "rfc3339":
|
|
1002
1002
|
default:
|
|
1003
1003
|
return `${getNullableCheck(clientValue, type)} ${clientValue}${
|
|
@@ -1086,7 +1086,7 @@ export function deserializeResponseValue(
|
|
|
1086
1086
|
: "";
|
|
1087
1087
|
switch (type.type) {
|
|
1088
1088
|
case "datetime":
|
|
1089
|
-
return `${nullOrUndefinedPrefix} new Date(${restValue})`;
|
|
1089
|
+
return `${nullOrUndefinedPrefix} new Date(${type.format === "unixTimestamp" ? `${restValue} * 1000` : restValue})`;
|
|
1090
1090
|
case "list": {
|
|
1091
1091
|
const prefix = nullOrUndefinedPrefix + restValue;
|
|
1092
1092
|
let elementNullOrUndefinedPrefix = "";
|
|
@@ -46,6 +46,7 @@ export async function transformRLCModel(
|
|
|
46
46
|
): Promise<RLCModel> {
|
|
47
47
|
const program = dpgContext.program;
|
|
48
48
|
const options: RLCOptions = dpgContext.rlcOptions!;
|
|
49
|
+
const rlcSourceDir = dpgContext.generationPathDetail?.rlcSourcesDir;
|
|
49
50
|
const srcPath = path.join(
|
|
50
51
|
dpgContext.generationPathDetail?.rlcSourcesDir ?? "",
|
|
51
52
|
options.batch && options.batch.length > 1
|
|
@@ -100,7 +101,8 @@ export async function transformRLCModel(
|
|
|
100
101
|
importInfo: {
|
|
101
102
|
internalImports: importSet,
|
|
102
103
|
runtimeImports: buildRuntimeImports(options.flavor)
|
|
103
|
-
}
|
|
104
|
+
},
|
|
105
|
+
rlcSourceDir
|
|
104
106
|
};
|
|
105
107
|
model.sampleGroups = transformSampleGroups(
|
|
106
108
|
model,
|
|
@@ -86,7 +86,7 @@ export function getOperationApiVersion(
|
|
|
86
86
|
relevantProperty: p.param
|
|
87
87
|
});
|
|
88
88
|
required.add(!p.param.optional);
|
|
89
|
-
if (p.type
|
|
89
|
+
if (p.type === "query" || p.type === "path") {
|
|
90
90
|
locations.add(p.type);
|
|
91
91
|
}
|
|
92
92
|
const typeString = JSON.stringify(trimUsage(type));
|
|
@@ -127,7 +127,7 @@ export function getOperationApiVersion(
|
|
|
127
127
|
relevantProperty: p.param
|
|
128
128
|
});
|
|
129
129
|
required.add(!p.param.optional);
|
|
130
|
-
if (p.type
|
|
130
|
+
if (p.type === "query" || p.type === "path") {
|
|
131
131
|
locations.add(p.type);
|
|
132
132
|
}
|
|
133
133
|
const typeString = JSON.stringify(trimUsage(type));
|
|
@@ -177,33 +177,19 @@ function extractSpecialSerializeInfo(
|
|
|
177
177
|
dpgContext: SdkContext
|
|
178
178
|
) {
|
|
179
179
|
let hasMultiCollection = false;
|
|
180
|
-
let hasPipeCollection = false;
|
|
181
|
-
let hasTsvCollection = false;
|
|
182
|
-
let hasSsvCollection = false;
|
|
183
180
|
let hasCsvCollection = false;
|
|
184
181
|
const clientOperations = listOperationsInOperationGroup(dpgContext, client);
|
|
185
182
|
for (const clientOp of clientOperations) {
|
|
186
183
|
const route = getHttpOperationWithCache(dpgContext, clientOp);
|
|
187
184
|
route.parameters.parameters.forEach((parameter) => {
|
|
188
185
|
const serializeInfo = getSpecialSerializeInfo(
|
|
186
|
+
dpgContext,
|
|
189
187
|
parameter.type,
|
|
190
188
|
(parameter as any).format
|
|
191
189
|
);
|
|
192
190
|
hasMultiCollection = hasMultiCollection
|
|
193
191
|
? hasMultiCollection
|
|
194
192
|
: serializeInfo.hasMultiCollection;
|
|
195
|
-
hasPipeCollection = hasPipeCollection
|
|
196
|
-
? hasPipeCollection
|
|
197
|
-
: serializeInfo.hasPipeCollection;
|
|
198
|
-
hasTsvCollection = hasTsvCollection
|
|
199
|
-
? hasTsvCollection
|
|
200
|
-
: serializeInfo.hasTsvCollection;
|
|
201
|
-
hasSsvCollection = hasSsvCollection
|
|
202
|
-
? hasSsvCollection
|
|
203
|
-
: serializeInfo.hasSsvCollection;
|
|
204
|
-
hasCsvCollection = hasCsvCollection
|
|
205
|
-
? hasCsvCollection
|
|
206
|
-
: serializeInfo.hasCsvCollection;
|
|
207
193
|
});
|
|
208
194
|
}
|
|
209
195
|
const operationGroups = listOperationGroups(dpgContext, client, true);
|
|
@@ -216,21 +202,13 @@ function extractSpecialSerializeInfo(
|
|
|
216
202
|
const route = getHttpOperationWithCache(dpgContext, op);
|
|
217
203
|
route.parameters.parameters.forEach((parameter) => {
|
|
218
204
|
const serializeInfo = getSpecialSerializeInfo(
|
|
205
|
+
dpgContext,
|
|
219
206
|
parameter.type,
|
|
220
207
|
(parameter as any).format
|
|
221
208
|
);
|
|
222
209
|
hasMultiCollection = hasMultiCollection
|
|
223
210
|
? hasMultiCollection
|
|
224
211
|
: serializeInfo.hasMultiCollection;
|
|
225
|
-
hasPipeCollection = hasPipeCollection
|
|
226
|
-
? hasPipeCollection
|
|
227
|
-
: serializeInfo.hasPipeCollection;
|
|
228
|
-
hasTsvCollection = hasTsvCollection
|
|
229
|
-
? hasTsvCollection
|
|
230
|
-
: serializeInfo.hasTsvCollection;
|
|
231
|
-
hasSsvCollection = hasSsvCollection
|
|
232
|
-
? hasSsvCollection
|
|
233
|
-
: serializeInfo.hasSsvCollection;
|
|
234
212
|
hasCsvCollection = hasCsvCollection
|
|
235
213
|
? hasCsvCollection
|
|
236
214
|
: serializeInfo.hasCsvCollection;
|
|
@@ -239,9 +217,6 @@ function extractSpecialSerializeInfo(
|
|
|
239
217
|
}
|
|
240
218
|
return {
|
|
241
219
|
hasMultiCollection,
|
|
242
|
-
hasPipeCollection,
|
|
243
|
-
hasTsvCollection,
|
|
244
|
-
hasSsvCollection,
|
|
245
220
|
hasCsvCollection
|
|
246
221
|
};
|
|
247
222
|
}
|
|
@@ -29,14 +29,14 @@ import {
|
|
|
29
29
|
listOperationGroups,
|
|
30
30
|
listOperationsInOperationGroup
|
|
31
31
|
} from "@azure-tools/typespec-client-generator-core";
|
|
32
|
-
import { Type, isVoidType } from "@typespec/compiler";
|
|
32
|
+
import { NoTarget, Type, isVoidType } from "@typespec/compiler";
|
|
33
33
|
import {
|
|
34
34
|
getBodyType,
|
|
35
35
|
getFormattedPropertyDoc,
|
|
36
36
|
getImportedModelName,
|
|
37
37
|
getSchemaForType,
|
|
38
|
-
getSerializeTypeName,
|
|
39
38
|
getTypeName,
|
|
39
|
+
isArrayType,
|
|
40
40
|
isBodyRequired
|
|
41
41
|
} from "../utils/modelUtils.js";
|
|
42
42
|
import {
|
|
@@ -44,8 +44,16 @@ import {
|
|
|
44
44
|
getOperationName,
|
|
45
45
|
getSpecialSerializeInfo
|
|
46
46
|
} from "../utils/operationUtil.js";
|
|
47
|
-
|
|
48
47
|
import { SdkContext } from "../utils/interfaces.js";
|
|
48
|
+
import { getParameterSerializationInfo } from "../utils/parameterUtils.js";
|
|
49
|
+
import { reportDiagnostic } from "../lib.js";
|
|
50
|
+
|
|
51
|
+
interface ParameterTransformationOptions {
|
|
52
|
+
apiVersionInfo?: ApiVersionInfo;
|
|
53
|
+
operationGroupName?: string;
|
|
54
|
+
operationName?: string;
|
|
55
|
+
importModels?: Set<string>;
|
|
56
|
+
}
|
|
49
57
|
|
|
50
58
|
export function transformToParameterTypes(
|
|
51
59
|
client: SdkClient,
|
|
@@ -90,20 +98,27 @@ export function transformToParameterTypes(
|
|
|
90
98
|
operationName: getOperationName(dpgContext, route.operation),
|
|
91
99
|
parameters: []
|
|
92
100
|
};
|
|
101
|
+
const options = {
|
|
102
|
+
apiVersionInfo,
|
|
103
|
+
operationGroupName: rlcParameter.operationGroup,
|
|
104
|
+
operationName: rlcParameter.operationName,
|
|
105
|
+
importModels: outputImportedSet
|
|
106
|
+
};
|
|
93
107
|
// transform query param
|
|
94
108
|
const queryParams = transformQueryParameters(
|
|
95
109
|
dpgContext,
|
|
96
110
|
parameters,
|
|
97
|
-
|
|
98
|
-
outputImportedSet
|
|
111
|
+
options
|
|
99
112
|
);
|
|
100
113
|
// transform path param
|
|
101
|
-
const pathParams = transformPathParameters();
|
|
114
|
+
const pathParams = transformPathParameters(dpgContext, parameters, options);
|
|
115
|
+
// TODO: support cookie parameters, https://github.com/Azure/autorest.typescript/issues/2898
|
|
116
|
+
transformCookieParameters(dpgContext, parameters);
|
|
102
117
|
// transform header param including content-type
|
|
103
118
|
const headerParams = transformHeaderParameters(
|
|
104
119
|
dpgContext,
|
|
105
120
|
parameters,
|
|
106
|
-
|
|
121
|
+
options
|
|
107
122
|
);
|
|
108
123
|
// transform body
|
|
109
124
|
const bodyType = getBodyType(route);
|
|
@@ -130,65 +145,62 @@ function getParameterMetadata(
|
|
|
130
145
|
dpgContext: SdkContext,
|
|
131
146
|
paramType: "query" | "path" | "header",
|
|
132
147
|
parameter: HttpOperationParameter,
|
|
133
|
-
|
|
148
|
+
options: ParameterTransformationOptions
|
|
134
149
|
): ParameterMetadata {
|
|
135
150
|
const program = dpgContext.program;
|
|
151
|
+
const importedModels = options.importModels ?? new Set<string>();
|
|
136
152
|
const schemaContext = [SchemaContext.Exception, SchemaContext.Input];
|
|
137
153
|
const schema = getSchemaForType(dpgContext, parameter.param.type, {
|
|
138
154
|
usage: schemaContext,
|
|
139
155
|
needRef: false,
|
|
140
156
|
relevantProperty: parameter.param
|
|
141
157
|
}) as Schema;
|
|
142
|
-
let type = getTypeName(schema, schemaContext);
|
|
143
158
|
const name = getParameterName(parameter.name);
|
|
144
159
|
let description =
|
|
145
160
|
getFormattedPropertyDoc(program, parameter.param, schema) ?? "";
|
|
146
|
-
if (
|
|
147
|
-
type === "string[]" ||
|
|
148
|
-
type === "Array<string>" ||
|
|
149
|
-
type === "number[]" ||
|
|
150
|
-
type === "Array<number>"
|
|
151
|
-
) {
|
|
161
|
+
if (isArrayType(schema)) {
|
|
152
162
|
const serializeInfo = getSpecialSerializeInfo(
|
|
163
|
+
dpgContext,
|
|
153
164
|
parameter.type,
|
|
154
165
|
(parameter as any).format
|
|
155
166
|
);
|
|
156
|
-
if (
|
|
157
|
-
serializeInfo.
|
|
158
|
-
serializeInfo.hasPipeCollection ||
|
|
159
|
-
serializeInfo.hasSsvCollection ||
|
|
160
|
-
serializeInfo.hasTsvCollection ||
|
|
161
|
-
serializeInfo.hasCsvCollection
|
|
162
|
-
) {
|
|
163
|
-
type = "string";
|
|
164
|
-
description += ` This parameter needs to be formatted as ${serializeInfo.collectionInfo.join(
|
|
167
|
+
if (serializeInfo.hasMultiCollection || serializeInfo.hasCsvCollection) {
|
|
168
|
+
description += `${description ? "\n" : ""}This parameter could be formatted as ${serializeInfo.collectionInfo.join(
|
|
165
169
|
", "
|
|
166
|
-
)} collection, we provide ${serializeInfo.descriptions.join(
|
|
170
|
+
)} collection string, we provide ${serializeInfo.descriptions.join(
|
|
167
171
|
", "
|
|
168
172
|
)} from serializeHelper.ts to help${
|
|
169
173
|
serializeInfo.hasMultiCollection
|
|
170
174
|
? ", you will probably need to set skipUrlEncoding as true when sending the request"
|
|
171
175
|
: ""
|
|
172
|
-
}
|
|
176
|
+
}.`;
|
|
177
|
+
}
|
|
178
|
+
if ((parameter as any).format === "tsv") {
|
|
179
|
+
description += `${description ? "\n" : ""}This parameter could be formatted as tsv collection string.`;
|
|
173
180
|
}
|
|
174
181
|
}
|
|
175
|
-
|
|
176
|
-
paramType !== "query" && type !== "string"
|
|
177
|
-
? getSerializeTypeName(dpgContext.program, schema, schemaContext)
|
|
178
|
-
: type;
|
|
182
|
+
|
|
179
183
|
getImportedModelName(schema, schemaContext)?.forEach(
|
|
180
184
|
importedModels.add,
|
|
181
185
|
importedModels
|
|
182
186
|
);
|
|
187
|
+
const serializationType = getParameterSerializationInfo(
|
|
188
|
+
dpgContext,
|
|
189
|
+
parameter,
|
|
190
|
+
schema,
|
|
191
|
+
options.operationGroupName,
|
|
192
|
+
options.operationName
|
|
193
|
+
);
|
|
183
194
|
return {
|
|
184
195
|
type: paramType,
|
|
185
196
|
name,
|
|
186
197
|
param: {
|
|
187
198
|
name,
|
|
188
|
-
type,
|
|
189
|
-
typeName:
|
|
199
|
+
type: serializationType.typeName,
|
|
200
|
+
typeName: serializationType.typeName,
|
|
190
201
|
required: !parameter.param.optional,
|
|
191
|
-
description
|
|
202
|
+
description,
|
|
203
|
+
wrapperType: serializationType.wrapperType
|
|
192
204
|
}
|
|
193
205
|
};
|
|
194
206
|
}
|
|
@@ -200,11 +212,29 @@ function getParameterName(name: string) {
|
|
|
200
212
|
return `"${name}"`;
|
|
201
213
|
}
|
|
202
214
|
|
|
215
|
+
function transformCookieParameters(
|
|
216
|
+
dpgContext: SdkContext,
|
|
217
|
+
parameters: HttpOperationParameters
|
|
218
|
+
) {
|
|
219
|
+
// TODO: support cookie parameters, https://github.com/Azure/autorest.typescript/issues/2898
|
|
220
|
+
parameters.parameters
|
|
221
|
+
.filter((p) => p.type === "cookie")
|
|
222
|
+
.forEach((p) => {
|
|
223
|
+
reportDiagnostic(dpgContext.program, {
|
|
224
|
+
code: "parameter-type-not-supported",
|
|
225
|
+
format: {
|
|
226
|
+
paramName: p.name,
|
|
227
|
+
paramType: p.type
|
|
228
|
+
},
|
|
229
|
+
target: NoTarget
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
|
|
203
234
|
function transformQueryParameters(
|
|
204
235
|
dpgContext: SdkContext,
|
|
205
236
|
parameters: HttpOperationParameters,
|
|
206
|
-
options:
|
|
207
|
-
importModels: Set<string> = new Set<string>()
|
|
237
|
+
options: ParameterTransformationOptions
|
|
208
238
|
): ParameterMetadata[] {
|
|
209
239
|
const queryParameters = parameters.parameters.filter(
|
|
210
240
|
(p) =>
|
|
@@ -218,7 +248,7 @@ function transformQueryParameters(
|
|
|
218
248
|
return [];
|
|
219
249
|
}
|
|
220
250
|
return queryParameters.map((qp) =>
|
|
221
|
-
getParameterMetadata(dpgContext, "query", qp,
|
|
251
|
+
getParameterMetadata(dpgContext, "query", qp, options)
|
|
222
252
|
);
|
|
223
253
|
}
|
|
224
254
|
|
|
@@ -226,16 +256,27 @@ function transformQueryParameters(
|
|
|
226
256
|
* Only support to take the global path parameter as path parameter
|
|
227
257
|
* @returns
|
|
228
258
|
*/
|
|
229
|
-
function transformPathParameters(
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
259
|
+
function transformPathParameters(
|
|
260
|
+
dpgContext: SdkContext,
|
|
261
|
+
parameters: HttpOperationParameters,
|
|
262
|
+
options: ParameterTransformationOptions
|
|
263
|
+
) {
|
|
264
|
+
// build wrapper path parameters
|
|
265
|
+
const pathParameters = parameters.parameters.filter((p) => p.type === "path");
|
|
266
|
+
if (!pathParameters.length) {
|
|
267
|
+
return [];
|
|
268
|
+
}
|
|
269
|
+
// only need to build path parameters for wrapper type
|
|
270
|
+
const params = pathParameters
|
|
271
|
+
.map((qp) => getParameterMetadata(dpgContext, "path", qp, options))
|
|
272
|
+
.filter((p) => p.param.wrapperType);
|
|
273
|
+
return params;
|
|
233
274
|
}
|
|
234
275
|
|
|
235
276
|
export function transformHeaderParameters(
|
|
236
277
|
dpgContext: SdkContext,
|
|
237
278
|
parameters: HttpOperationParameters,
|
|
238
|
-
|
|
279
|
+
options: ParameterTransformationOptions
|
|
239
280
|
): ParameterMetadata[] {
|
|
240
281
|
const headerParameters = parameters.parameters.filter(
|
|
241
282
|
(p) => p.type === "header"
|
|
@@ -244,7 +285,7 @@ export function transformHeaderParameters(
|
|
|
244
285
|
return [];
|
|
245
286
|
}
|
|
246
287
|
return headerParameters.map((qp) =>
|
|
247
|
-
getParameterMetadata(dpgContext, "header", qp,
|
|
288
|
+
getParameterMetadata(dpgContext, "header", qp, options)
|
|
248
289
|
);
|
|
249
290
|
}
|
|
250
291
|
|
|
@@ -31,12 +31,12 @@ import {
|
|
|
31
31
|
import {
|
|
32
32
|
getImportedModelName,
|
|
33
33
|
getSchemaForType,
|
|
34
|
-
getTypeName,
|
|
35
34
|
isBodyRequired
|
|
36
35
|
} from "../utils/modelUtils.js";
|
|
37
36
|
|
|
38
37
|
import { SdkContext } from "../utils/interfaces.js";
|
|
39
38
|
import { getDoc } from "@typespec/compiler";
|
|
39
|
+
import { getParameterSerializationInfo } from "../utils/parameterUtils.js";
|
|
40
40
|
|
|
41
41
|
export function transformPaths(
|
|
42
42
|
client: SdkClient,
|
|
@@ -133,15 +133,33 @@ function transformOperation(
|
|
|
133
133
|
.filter((p) => p.type === "path")
|
|
134
134
|
.map((p) => {
|
|
135
135
|
const schemaUsage = [SchemaContext.Input, SchemaContext.Exception];
|
|
136
|
+
const options = {
|
|
137
|
+
usage: schemaUsage,
|
|
138
|
+
needRef: false,
|
|
139
|
+
relevantProperty: p.param
|
|
140
|
+
};
|
|
136
141
|
const schema = p.param.sourceProperty
|
|
137
|
-
? getSchemaForType(
|
|
138
|
-
|
|
142
|
+
? getSchemaForType(
|
|
143
|
+
dpgContext,
|
|
144
|
+
p.param.sourceProperty?.type,
|
|
145
|
+
|
|
146
|
+
options
|
|
147
|
+
)
|
|
148
|
+
: getSchemaForType(dpgContext, p.param.type, options);
|
|
139
149
|
const importedNames = getImportedModelName(schema, schemaUsage) ?? [];
|
|
140
150
|
importedNames.forEach(importSet.add, importSet);
|
|
151
|
+
const serializationType = getParameterSerializationInfo(
|
|
152
|
+
dpgContext,
|
|
153
|
+
p,
|
|
154
|
+
schema,
|
|
155
|
+
operationGroupName,
|
|
156
|
+
method.operationName
|
|
157
|
+
);
|
|
141
158
|
return {
|
|
142
159
|
name: p.name,
|
|
143
|
-
type:
|
|
144
|
-
description: getDoc(program, p.param)
|
|
160
|
+
type: serializationType.typeName,
|
|
161
|
+
description: getDoc(program, p.param) ?? "",
|
|
162
|
+
wrapperType: serializationType.wrapperType
|
|
145
163
|
};
|
|
146
164
|
}),
|
|
147
165
|
operationGroupName: getOperationGroupName(dpgContext, route),
|