@azure-tools/typespec-ts 0.37.0 → 0.38.0
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 +16 -0
- package/README.md +12 -2
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +23 -19
- package/dist/src/index.js.map +1 -1
- package/dist/src/lib.d.ts.map +1 -1
- package/dist/src/lib.js +10 -2
- 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/buildClientContext.d.ts.map +1 -1
- package/dist/src/modular/buildClientContext.js +2 -2
- 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 +0 -2
- package/dist/src/modular/buildOperations.js.map +1 -1
- package/dist/src/modular/buildProjectFiles.d.ts.map +1 -1
- package/dist/src/modular/buildProjectFiles.js +21 -3
- package/dist/src/modular/buildProjectFiles.js.map +1 -1
- package/dist/src/modular/buildRestorePoller.js +2 -2
- package/dist/src/modular/buildRestorePoller.js.map +1 -1
- package/dist/src/modular/buildRootIndex.d.ts +1 -0
- package/dist/src/modular/buildRootIndex.d.ts.map +1 -1
- package/dist/src/modular/buildRootIndex.js +80 -39
- package/dist/src/modular/buildRootIndex.js.map +1 -1
- package/dist/src/modular/buildSubpathIndex.d.ts +1 -0
- package/dist/src/modular/buildSubpathIndex.d.ts.map +1 -1
- package/dist/src/modular/buildSubpathIndex.js +67 -49
- package/dist/src/modular/buildSubpathIndex.js.map +1 -1
- package/dist/src/modular/emitModels.d.ts +4 -3
- package/dist/src/modular/emitModels.d.ts.map +1 -1
- package/dist/src/modular/emitModels.js +91 -26
- package/dist/src/modular/emitModels.js.map +1 -1
- package/dist/src/modular/helpers/classicalOperationHelpers.d.ts.map +1 -1
- package/dist/src/modular/helpers/classicalOperationHelpers.js +30 -18
- package/dist/src/modular/helpers/classicalOperationHelpers.js.map +1 -1
- package/dist/src/modular/helpers/clientHelpers.js +3 -3
- package/dist/src/modular/helpers/clientHelpers.js.map +1 -1
- package/dist/src/modular/helpers/operationHelpers.d.ts +5 -6
- package/dist/src/modular/helpers/operationHelpers.d.ts.map +1 -1
- package/dist/src/modular/helpers/operationHelpers.js +108 -27
- package/dist/src/modular/helpers/operationHelpers.js.map +1 -1
- package/dist/src/modular/serialization/buildDeserializerFunction.d.ts.map +1 -1
- package/dist/src/modular/serialization/buildDeserializerFunction.js +2 -1
- package/dist/src/modular/serialization/buildDeserializerFunction.js.map +1 -1
- package/dist/src/modular/serialization/buildSerializerFunction.d.ts.map +1 -1
- package/dist/src/modular/serialization/buildSerializerFunction.js +72 -20
- package/dist/src/modular/serialization/buildSerializerFunction.js.map +1 -1
- package/dist/src/modular/static-helpers-metadata.d.ts +12 -0
- package/dist/src/modular/static-helpers-metadata.d.ts.map +1 -1
- package/dist/src/modular/static-helpers-metadata.js +12 -0
- package/dist/src/modular/static-helpers-metadata.js.map +1 -1
- package/dist/src/transform/transfromRLCOptions.d.ts.map +1 -1
- package/dist/src/transform/transfromRLCOptions.js +8 -1
- package/dist/src/transform/transfromRLCOptions.js.map +1 -1
- package/dist/src/utils/modelUtils.d.ts.map +1 -1
- package/dist/src/utils/modelUtils.js +67 -44
- package/dist/src/utils/modelUtils.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +45 -42
- package/src/index.ts +40 -21
- package/src/lib.ts +10 -2
- package/src/modular/buildClassicalClient.ts +2 -2
- package/src/modular/buildClientContext.ts +5 -2
- package/src/modular/buildOperations.ts +0 -2
- package/src/modular/buildProjectFiles.ts +27 -3
- package/src/modular/buildRestorePoller.ts +2 -2
- package/src/modular/buildRootIndex.ts +97 -52
- package/src/modular/buildSubpathIndex.ts +79 -57
- package/src/modular/emitModels.ts +118 -29
- package/src/modular/helpers/classicalOperationHelpers.ts +53 -34
- package/src/modular/helpers/clientHelpers.ts +3 -3
- package/src/modular/helpers/operationHelpers.ts +167 -59
- package/src/modular/serialization/buildDeserializerFunction.ts +2 -1
- package/src/modular/serialization/buildSerializerFunction.ts +90 -25
- package/src/modular/static-helpers-metadata.ts +13 -0
- package/src/transform/transfromRLCOptions.ts +11 -1
- package/src/utils/modelUtils.ts +67 -43
- package/static/static-helpers/multipartHelpers.ts +22 -0
- package/dist/src/modular/buildHelperSerializers.d.ts +0 -3
- package/dist/src/modular/buildHelperSerializers.d.ts.map +0 -1
- package/dist/src/modular/buildHelperSerializers.js +0 -60
- package/dist/src/modular/buildHelperSerializers.js.map +0 -1
- package/src/modular/buildHelperSerializers.ts +0 -72
|
@@ -74,21 +74,26 @@ export function getClassicalOperation(
|
|
|
74
74
|
.filter((i) => i.getName() === interfaceName)[0];
|
|
75
75
|
const properties: OptionalKind<PropertySignatureStructure>[] = [];
|
|
76
76
|
if (layer !== prefixes.length - 1) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
name: normalizeName(
|
|
80
|
-
(layer === prefixes.length - 1
|
|
81
|
-
? prefixes[layer]
|
|
82
|
-
: prefixes[layer + 1]) ?? "",
|
|
83
|
-
NameType.Property
|
|
84
|
-
),
|
|
85
|
-
type: `${getClassicalLayerPrefix(
|
|
86
|
-
prefixes,
|
|
87
|
-
NameType.Interface,
|
|
77
|
+
const name = normalizeName(
|
|
78
|
+
(layer === prefixes.length - 1 ? prefixes[layer] : prefixes[layer + 1]) ??
|
|
88
79
|
"",
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
80
|
+
NameType.Property
|
|
81
|
+
);
|
|
82
|
+
if (
|
|
83
|
+
!properties.some((x) => x.name === name) &&
|
|
84
|
+
!(existInterface && existInterface.getProperty(name))
|
|
85
|
+
) {
|
|
86
|
+
properties.push({
|
|
87
|
+
kind: StructureKind.PropertySignature,
|
|
88
|
+
name,
|
|
89
|
+
type: `${getClassicalLayerPrefix(
|
|
90
|
+
prefixes,
|
|
91
|
+
NameType.Interface,
|
|
92
|
+
"",
|
|
93
|
+
layer + 1
|
|
94
|
+
)}Operations`
|
|
95
|
+
});
|
|
96
|
+
}
|
|
92
97
|
} else {
|
|
93
98
|
operationDeclarations.forEach((d) => {
|
|
94
99
|
properties.push({
|
|
@@ -124,13 +129,13 @@ export function getClassicalOperation(
|
|
|
124
129
|
|
|
125
130
|
if (layer === prefixes.length - 1) {
|
|
126
131
|
classicFile.addFunction({
|
|
127
|
-
name: `
|
|
132
|
+
name: `_get${getClassicalLayerPrefix(
|
|
128
133
|
prefixes,
|
|
129
134
|
NameType.Interface,
|
|
130
135
|
"",
|
|
131
136
|
layer
|
|
132
137
|
)}`,
|
|
133
|
-
isExported:
|
|
138
|
+
isExported: false,
|
|
134
139
|
parameters: [
|
|
135
140
|
{
|
|
136
141
|
name: "context",
|
|
@@ -164,7 +169,7 @@ export function getClassicalOperation(
|
|
|
164
169
|
});
|
|
165
170
|
}
|
|
166
171
|
|
|
167
|
-
const operationFunctionName = `
|
|
172
|
+
const operationFunctionName = `_get${getClassicalLayerPrefix(
|
|
168
173
|
prefixes,
|
|
169
174
|
NameType.Interface,
|
|
170
175
|
"",
|
|
@@ -176,27 +181,41 @@ export function getClassicalOperation(
|
|
|
176
181
|
if (existFunction) {
|
|
177
182
|
const returnStatement = existFunction.getBodyText();
|
|
178
183
|
if (returnStatement) {
|
|
179
|
-
let statement =
|
|
180
|
-
|
|
184
|
+
let statement: string | undefined = undefined;
|
|
185
|
+
if (layer !== prefixes.length - 1) {
|
|
186
|
+
const name = normalizeName(
|
|
187
|
+
prefixes[layer + 1] ?? "FIXME",
|
|
188
|
+
NameType.Property
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
// HACK: check if the statement includes a group of this name already to prevent an operation group appearing multiple times
|
|
192
|
+
// TODO: would be good to refactor so that we have an intermediate data structure before generating the return statement
|
|
193
|
+
if (!returnStatement.includes(`${name}:`)) {
|
|
194
|
+
statement = `,
|
|
195
|
+
${normalizeName(
|
|
196
|
+
prefixes[layer + 1] ?? "FIXME",
|
|
197
|
+
NameType.Property
|
|
198
|
+
)}: _get${getClassicalLayerPrefix(
|
|
199
|
+
prefixes,
|
|
200
|
+
NameType.Interface,
|
|
201
|
+
"",
|
|
202
|
+
layer + 1
|
|
203
|
+
)}Operations(context)}`;
|
|
204
|
+
}
|
|
205
|
+
} else {
|
|
206
|
+
statement = `,
|
|
207
|
+
..._get${getClassicalLayerPrefix(
|
|
181
208
|
prefixes,
|
|
182
209
|
NameType.Interface,
|
|
183
210
|
"",
|
|
184
211
|
layer + 1
|
|
185
212
|
)}Operations(context)}`;
|
|
186
|
-
if (layer !== prefixes.length - 1) {
|
|
187
|
-
statement = `,
|
|
188
|
-
${normalizeName(
|
|
189
|
-
prefixes[layer + 1] ?? "FIXME",
|
|
190
|
-
NameType.Property
|
|
191
|
-
)}: get${getClassicalLayerPrefix(
|
|
192
|
-
prefixes,
|
|
193
|
-
NameType.Interface,
|
|
194
|
-
"",
|
|
195
|
-
layer + 1
|
|
196
|
-
)}Operations(context)}`;
|
|
197
213
|
}
|
|
198
|
-
|
|
199
|
-
|
|
214
|
+
|
|
215
|
+
if (statement) {
|
|
216
|
+
const newReturnStatement = returnStatement.replace(/}$/, statement);
|
|
217
|
+
existFunction.setBodyText(newReturnStatement);
|
|
218
|
+
}
|
|
200
219
|
}
|
|
201
220
|
} else {
|
|
202
221
|
const functions = {
|
|
@@ -220,7 +239,7 @@ export function getClassicalOperation(
|
|
|
220
239
|
${normalizeName(
|
|
221
240
|
prefixes[layer + 1] ?? "FIXME",
|
|
222
241
|
NameType.Property
|
|
223
|
-
)}:
|
|
242
|
+
)}: _get${getClassicalLayerPrefix(
|
|
224
243
|
prefixes,
|
|
225
244
|
NameType.Interface,
|
|
226
245
|
"",
|
|
@@ -228,7 +247,7 @@ export function getClassicalOperation(
|
|
|
228
247
|
)}Operations(context)
|
|
229
248
|
}`
|
|
230
249
|
: `return {
|
|
231
|
-
...
|
|
250
|
+
..._get${getClassicalLayerPrefix(
|
|
232
251
|
prefixes,
|
|
233
252
|
NameType.Interface,
|
|
234
253
|
"",
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
PackageFlavor
|
|
18
18
|
} from "@azure-tools/rlc-common";
|
|
19
19
|
import { SdkContext } from "../../utils/interfaces.js";
|
|
20
|
-
import {
|
|
20
|
+
import { getClassicalClientName } from "./namingHelpers.js";
|
|
21
21
|
import { getTypeExpression } from "../type-expressions/get-type-expression.js";
|
|
22
22
|
import { isCredentialType } from "./typeHelpers.js";
|
|
23
23
|
|
|
@@ -106,10 +106,10 @@ export function getClientParametersDeclaration(
|
|
|
106
106
|
apiVersionAsRequired: false
|
|
107
107
|
}
|
|
108
108
|
): OptionalKind<ParameterDeclarationStructure>[] {
|
|
109
|
-
const name =
|
|
109
|
+
const name = getClassicalClientName(client);
|
|
110
110
|
const optionsParam = {
|
|
111
111
|
name: "options",
|
|
112
|
-
type: `${name}
|
|
112
|
+
type: `${name}OptionalParams`,
|
|
113
113
|
initializer: "{}"
|
|
114
114
|
};
|
|
115
115
|
|
|
@@ -168,7 +168,7 @@ export function getDeserializePrivateFunction(
|
|
|
168
168
|
);
|
|
169
169
|
statements.push(
|
|
170
170
|
`if(!expectedStatuses.includes(result.status)){`,
|
|
171
|
-
|
|
171
|
+
`${getExceptionThrowStatement(context, operation)}`,
|
|
172
172
|
"}"
|
|
173
173
|
);
|
|
174
174
|
const deserializedType = isLroOnly
|
|
@@ -186,7 +186,7 @@ export function getDeserializePrivateFunction(
|
|
|
186
186
|
if (isLroOnly && lroSubPath) {
|
|
187
187
|
statements.push(
|
|
188
188
|
`if(${deserializedRoot.split(".").join("?.")} === undefined) {
|
|
189
|
-
throw
|
|
189
|
+
throw ${createRestErrorReference}(\`Expected a result in the response at position "${deserializedRoot}"\`, result);
|
|
190
190
|
}
|
|
191
191
|
`
|
|
192
192
|
);
|
|
@@ -228,6 +228,103 @@ export function getDeserializePrivateFunction(
|
|
|
228
228
|
};
|
|
229
229
|
}
|
|
230
230
|
|
|
231
|
+
interface ExceptionThrowDetail {
|
|
232
|
+
start: number;
|
|
233
|
+
end?: number;
|
|
234
|
+
deserializer: string;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
interface OperationExceptionDetails {
|
|
238
|
+
customized: ExceptionThrowDetail[];
|
|
239
|
+
defaultDeserializer?: string;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function getExceptionDetails(
|
|
243
|
+
context: SdkContext,
|
|
244
|
+
operation: ServiceOperation
|
|
245
|
+
): OperationExceptionDetails {
|
|
246
|
+
const customized: ExceptionThrowDetail[] = [];
|
|
247
|
+
let defaultDeserializer: string | undefined;
|
|
248
|
+
for (const exception of operation.operation.exceptions) {
|
|
249
|
+
if (!exception.type) {
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
const statusCode = exception.statusCodes;
|
|
253
|
+
const deserializeFunctionName = buildModelDeserializer(
|
|
254
|
+
context,
|
|
255
|
+
exception.type,
|
|
256
|
+
false,
|
|
257
|
+
true
|
|
258
|
+
);
|
|
259
|
+
if (
|
|
260
|
+
!deserializeFunctionName ||
|
|
261
|
+
typeof deserializeFunctionName !== "string"
|
|
262
|
+
) {
|
|
263
|
+
continue;
|
|
264
|
+
}
|
|
265
|
+
if (statusCode === "*") {
|
|
266
|
+
defaultDeserializer = deserializeFunctionName;
|
|
267
|
+
} else if (typeof statusCode === "number") {
|
|
268
|
+
customized.push({
|
|
269
|
+
start: statusCode,
|
|
270
|
+
deserializer: deserializeFunctionName
|
|
271
|
+
});
|
|
272
|
+
} else {
|
|
273
|
+
customized.push({
|
|
274
|
+
start: statusCode.start,
|
|
275
|
+
end: statusCode.end,
|
|
276
|
+
deserializer: deserializeFunctionName
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return { customized, defaultDeserializer };
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function getExceptionThrowStatement(
|
|
284
|
+
context: SdkContext,
|
|
285
|
+
operation: ServiceOperation
|
|
286
|
+
) {
|
|
287
|
+
const statements = [];
|
|
288
|
+
const createRestErrorReference = resolveReference(
|
|
289
|
+
useDependencies().createRestError
|
|
290
|
+
);
|
|
291
|
+
const { customized, defaultDeserializer } = getExceptionDetails(
|
|
292
|
+
context,
|
|
293
|
+
operation
|
|
294
|
+
);
|
|
295
|
+
if (customized.length > 0) {
|
|
296
|
+
statements.push(`const error = ${createRestErrorReference}(result);`);
|
|
297
|
+
statements.push(`const statusCode = Number.parseInt(result.status);`);
|
|
298
|
+
const stats: string[] = customized.map((exception) => {
|
|
299
|
+
if (exception.end) {
|
|
300
|
+
return `if(statusCode >= ${exception.start} && statusCode <= ${exception.end}) {
|
|
301
|
+
error.details = ${exception.deserializer}(result.body);
|
|
302
|
+
}`;
|
|
303
|
+
} else {
|
|
304
|
+
return `if(statusCode === ${exception.start}) {
|
|
305
|
+
error.details = ${exception.deserializer}(result.body);
|
|
306
|
+
}`;
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
statements.push(stats.join("\nelse "));
|
|
310
|
+
if (defaultDeserializer) {
|
|
311
|
+
statements.push(`else {
|
|
312
|
+
error.details = ${defaultDeserializer}(result.body);
|
|
313
|
+
}`);
|
|
314
|
+
}
|
|
315
|
+
statements.push("throw error;");
|
|
316
|
+
} else {
|
|
317
|
+
if (defaultDeserializer) {
|
|
318
|
+
statements.push(`const error = ${createRestErrorReference}(result);
|
|
319
|
+
error.details = ${defaultDeserializer}(result.body);`);
|
|
320
|
+
statements.push("throw error;");
|
|
321
|
+
} else {
|
|
322
|
+
statements.push(`throw ${createRestErrorReference}(result);`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
return statements.join("\n");
|
|
326
|
+
}
|
|
327
|
+
|
|
231
328
|
function getOptionalParamsName(
|
|
232
329
|
parameters: OptionalKind<ParameterDeclarationStructure>[]
|
|
233
330
|
) {
|
|
@@ -795,7 +892,7 @@ function getRequired(context: SdkContext, param: SdkModelPropertyType) {
|
|
|
795
892
|
const serializedName = getPropertySerializedName(param);
|
|
796
893
|
const clientValue = `${param.onClient ? "context." : ""}${param.name}`;
|
|
797
894
|
if (param.type.kind === "model") {
|
|
798
|
-
const
|
|
895
|
+
const propertiesStr = getRequestModelMapping(
|
|
799
896
|
context,
|
|
800
897
|
{ ...param.type, optional: param.optional },
|
|
801
898
|
clientValue
|
|
@@ -834,15 +931,12 @@ function getOptional(
|
|
|
834
931
|
const serializedName = getPropertySerializedName(param);
|
|
835
932
|
const paramName = `${param.onClient ? "context." : `${optionalParamName}?.`}${param.name}`;
|
|
836
933
|
if (param.type.kind === "model") {
|
|
837
|
-
const
|
|
934
|
+
const propertiesStr = getRequestModelMapping(
|
|
838
935
|
context,
|
|
839
936
|
{ ...param.type, optional: param.optional },
|
|
840
937
|
paramName + "?."
|
|
841
938
|
);
|
|
842
|
-
const serializeContent =
|
|
843
|
-
directAssignment === true
|
|
844
|
-
? propertiesStr.join(",")
|
|
845
|
-
: `{${propertiesStr.join(",")}}`;
|
|
939
|
+
const serializeContent = `{${propertiesStr.join(",")}}`;
|
|
846
940
|
return `"${serializedName}": ${serializeContent}`;
|
|
847
941
|
}
|
|
848
942
|
return `"${serializedName}": ${serializeRequestValue(
|
|
@@ -948,72 +1042,86 @@ function getNullableCheck(name: string, type: SdkType) {
|
|
|
948
1042
|
return `${name} === null ? null :`;
|
|
949
1043
|
}
|
|
950
1044
|
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
1045
|
+
export function getSerializationExpression(
|
|
1046
|
+
context: SdkContext,
|
|
1047
|
+
property: SdkModelPropertyType,
|
|
1048
|
+
propertyPath: string
|
|
1049
|
+
): string {
|
|
1050
|
+
const dot = propertyPath.endsWith("?") ? "." : "";
|
|
1051
|
+
const propertyPathWithDot = `${propertyPath ? `${propertyPath}${dot}` : `${dot}`}`;
|
|
1052
|
+
const nullOrUndefinedPrefix = getPropertySerializationPrefix(
|
|
1053
|
+
context,
|
|
1054
|
+
property,
|
|
1055
|
+
propertyPath
|
|
1056
|
+
);
|
|
1057
|
+
|
|
1058
|
+
const propertyFullName = getPropertyFullName(
|
|
1059
|
+
context,
|
|
1060
|
+
property,
|
|
1061
|
+
propertyPathWithDot
|
|
1062
|
+
);
|
|
1063
|
+
const serializeFunctionName = buildModelSerializer(
|
|
1064
|
+
context,
|
|
1065
|
+
getNullableValidType(property.type),
|
|
1066
|
+
false,
|
|
1067
|
+
true
|
|
1068
|
+
);
|
|
1069
|
+
if (serializeFunctionName) {
|
|
1070
|
+
return `${nullOrUndefinedPrefix}${serializeFunctionName}(${propertyFullName})`;
|
|
1071
|
+
} else if (isAzureCoreErrorType(context.program, property.type.__raw)) {
|
|
1072
|
+
return `${nullOrUndefinedPrefix}${propertyFullName}`;
|
|
1073
|
+
} else {
|
|
1074
|
+
return serializeRequestValue(
|
|
1075
|
+
context,
|
|
1076
|
+
property.type,
|
|
1077
|
+
propertyFullName,
|
|
1078
|
+
!property.optional,
|
|
1079
|
+
getEncodeForType(property.type)
|
|
1080
|
+
);
|
|
1081
|
+
}
|
|
959
1082
|
}
|
|
960
|
-
|
|
1083
|
+
|
|
1084
|
+
export function getRequestModelProperties(
|
|
961
1085
|
context: SdkContext,
|
|
962
1086
|
modelPropertyType: SdkModelType & { optional?: boolean },
|
|
963
1087
|
propertyPath: string = "body"
|
|
964
|
-
):
|
|
965
|
-
const props: string[] = [];
|
|
1088
|
+
): Array<[string, string]> {
|
|
1089
|
+
const props: [string, string][] = [];
|
|
966
1090
|
const allParents = getAllAncestors(modelPropertyType);
|
|
967
1091
|
const properties: SdkModelPropertyType[] =
|
|
968
1092
|
getAllProperties(modelPropertyType, allParents) ?? [];
|
|
969
1093
|
if (properties.length <= 0) {
|
|
970
|
-
return
|
|
1094
|
+
return [];
|
|
971
1095
|
}
|
|
972
1096
|
for (const property of properties) {
|
|
973
1097
|
if (property.kind === "property" && isReadOnly(property)) {
|
|
974
1098
|
continue;
|
|
975
1099
|
}
|
|
976
|
-
const dot = propertyPath.endsWith("?") ? "." : "";
|
|
977
|
-
const serializedName = getPropertySerializedName(property);
|
|
978
|
-
const propertyPathWithDot = `${propertyPath ? `${propertyPath}${dot}` : `${dot}`}`;
|
|
979
|
-
const nullOrUndefinedPrefix = getPropertySerializationPrefix(
|
|
980
|
-
context,
|
|
981
|
-
property,
|
|
982
|
-
propertyPath
|
|
983
|
-
);
|
|
984
1100
|
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
property,
|
|
988
|
-
|
|
989
|
-
);
|
|
990
|
-
const serializeFunctionName = buildModelSerializer(
|
|
991
|
-
context,
|
|
992
|
-
getNullableValidType(property.type),
|
|
993
|
-
false,
|
|
994
|
-
true
|
|
995
|
-
);
|
|
996
|
-
if (serializeFunctionName) {
|
|
997
|
-
props.push(
|
|
998
|
-
`"${serializedName}": ${nullOrUndefinedPrefix}${serializeFunctionName}(${propertyFullName})`
|
|
999
|
-
);
|
|
1000
|
-
} else if (isAzureCoreErrorType(context.program, property.type.__raw)) {
|
|
1001
|
-
props.push(
|
|
1002
|
-
`"${serializedName}": ${nullOrUndefinedPrefix}${propertyFullName}`
|
|
1003
|
-
);
|
|
1004
|
-
} else {
|
|
1005
|
-
const serializedValue = serializeRequestValue(
|
|
1006
|
-
context,
|
|
1007
|
-
property.type,
|
|
1008
|
-
propertyFullName,
|
|
1009
|
-
!property.optional,
|
|
1010
|
-
getEncodeForType(property.type)
|
|
1011
|
-
);
|
|
1012
|
-
props.push(`"${serializedName}": ${serializedValue}`);
|
|
1013
|
-
}
|
|
1101
|
+
props.push([
|
|
1102
|
+
getPropertySerializedName(property)!,
|
|
1103
|
+
getSerializationExpression(context, property, propertyPath)
|
|
1104
|
+
]);
|
|
1014
1105
|
}
|
|
1015
1106
|
|
|
1016
|
-
return
|
|
1107
|
+
return props;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
/**
|
|
1111
|
+
*
|
|
1112
|
+
* This function helps translating an HLC request to RLC request,
|
|
1113
|
+
* extracting properties from body and headers and building the RLC response object
|
|
1114
|
+
*/
|
|
1115
|
+
export function getRequestModelMapping(
|
|
1116
|
+
context: SdkContext,
|
|
1117
|
+
modelPropertyType: SdkModelType & { optional?: boolean },
|
|
1118
|
+
propertyPath: string = "body"
|
|
1119
|
+
): string[] {
|
|
1120
|
+
return getRequestModelProperties(
|
|
1121
|
+
context,
|
|
1122
|
+
modelPropertyType,
|
|
1123
|
+
propertyPath
|
|
1124
|
+
).map(([name, value]) => `"${name}": ${value}`);
|
|
1017
1125
|
}
|
|
1018
1126
|
|
|
1019
1127
|
function getPropertySerializedName(property: SdkModelPropertyType) {
|
|
@@ -1164,7 +1272,7 @@ export function serializeRequestValue(
|
|
|
1164
1272
|
return `${clientValue} as any`;
|
|
1165
1273
|
}
|
|
1166
1274
|
case "model": // this is to build serialization logic for spread model types
|
|
1167
|
-
return `{${getRequestModelMapping(context, type, "").
|
|
1275
|
+
return `{${getRequestModelMapping(context, type, "").join(",")}}`;
|
|
1168
1276
|
case "nullable":
|
|
1169
1277
|
return serializeRequestValue(
|
|
1170
1278
|
context,
|
|
@@ -34,7 +34,8 @@ export function buildModelDeserializer(
|
|
|
34
34
|
if (
|
|
35
35
|
!type.usage ||
|
|
36
36
|
(type.usage !== undefined &&
|
|
37
|
-
(type.usage & UsageFlags.Output) !== UsageFlags.Output
|
|
37
|
+
(type.usage & UsageFlags.Output) !== UsageFlags.Output &&
|
|
38
|
+
(type.usage & UsageFlags.Exception) !== UsageFlags.Exception)
|
|
38
39
|
) {
|
|
39
40
|
return undefined;
|
|
40
41
|
}
|
|
@@ -10,7 +10,13 @@ import {
|
|
|
10
10
|
import { toCamelCase, toPascalCase } from "../../utils/casingUtils.js";
|
|
11
11
|
|
|
12
12
|
import { SdkContext } from "../../utils/interfaces.js";
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
getAllAncestors,
|
|
15
|
+
getAllProperties,
|
|
16
|
+
getPropertyFullName,
|
|
17
|
+
getRequestModelMapping,
|
|
18
|
+
getSerializationExpression
|
|
19
|
+
} from "../helpers/operationHelpers.js";
|
|
14
20
|
import { normalizeModelName } from "../emitModels.js";
|
|
15
21
|
import { NameType } from "@azure-tools/rlc-common";
|
|
16
22
|
import { isAzureCoreErrorType } from "../../utils/modelUtils.js";
|
|
@@ -19,6 +25,9 @@ import {
|
|
|
19
25
|
isSupportedSerializeType,
|
|
20
26
|
ModelSerializeOptions
|
|
21
27
|
} from "./serializeUtils.js";
|
|
28
|
+
import { MultipartHelpers } from "../static-helpers-metadata.js";
|
|
29
|
+
import { resolveReference } from "../../framework/reference.js";
|
|
30
|
+
import { isOrExtendsHttpFile } from "@typespec/http";
|
|
22
31
|
|
|
23
32
|
export function buildModelSerializer(
|
|
24
33
|
context: SdkContext,
|
|
@@ -43,7 +52,10 @@ export function buildModelSerializer(
|
|
|
43
52
|
// throw new Error(`NYI Serialization of anonymous types`);
|
|
44
53
|
return undefined;
|
|
45
54
|
}
|
|
46
|
-
if (
|
|
55
|
+
if (
|
|
56
|
+
isAzureCoreErrorType(context.program, type.__raw!) ||
|
|
57
|
+
isOrExtendsHttpFile(context.program, type.__raw!)
|
|
58
|
+
) {
|
|
47
59
|
return undefined;
|
|
48
60
|
}
|
|
49
61
|
}
|
|
@@ -331,37 +343,90 @@ function buildModelTypeSerializer(
|
|
|
331
343
|
statements: ["return item;"]
|
|
332
344
|
};
|
|
333
345
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
346
|
+
if (
|
|
347
|
+
(type.usage & UsageFlags.Input) === UsageFlags.Input &&
|
|
348
|
+
(type.usage & UsageFlags.MultipartFormData) === UsageFlags.MultipartFormData
|
|
349
|
+
) {
|
|
350
|
+
// For MFD models, serialize into an array of parts
|
|
351
|
+
// TODO: cleaner abstraction, quite a bit of duplication with the non-MFD stuff here
|
|
352
|
+
const parts: string[] = [];
|
|
338
353
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
354
|
+
const properties = getAllProperties(type, getAllAncestors(type));
|
|
355
|
+
for (const property of properties) {
|
|
356
|
+
if (property.kind !== "property") {
|
|
357
|
+
continue;
|
|
358
|
+
}
|
|
359
|
+
const expr = getSerializationExpression(context, property, "item");
|
|
360
|
+
|
|
361
|
+
let partDefinition: string;
|
|
362
|
+
if (property.isMultipartFileInput) {
|
|
363
|
+
const createFilePartDescriptorDefinition = resolveReference(
|
|
364
|
+
MultipartHelpers.createFilePartDescriptor
|
|
365
|
+
);
|
|
366
|
+
|
|
367
|
+
const itemPath = property.multipartOptions?.isMulti
|
|
368
|
+
? "x"
|
|
369
|
+
: getPropertyFullName(context, property, "item");
|
|
370
|
+
partDefinition = `${createFilePartDescriptorDefinition}("${property.serializedName}", ${itemPath}, )`;
|
|
371
|
+
|
|
372
|
+
// If the TypeSpec doesn't specify a default content type, TCGC will infer a default of "*/*".
|
|
373
|
+
// In this case, we actually want the content type to be left unset so that Core will take care of
|
|
374
|
+
// setting the content type correctly.
|
|
375
|
+
const contentType =
|
|
376
|
+
property.multipartOptions?.defaultContentTypes?.[0] === "*/*"
|
|
377
|
+
? undefined
|
|
378
|
+
: property.multipartOptions?.defaultContentTypes?.[0];
|
|
351
379
|
|
|
352
|
-
|
|
380
|
+
if (property.multipartOptions?.isMulti) {
|
|
381
|
+
partDefinition = `...(item["${property.serializedName}"].map((x: unknown) => ${createFilePartDescriptorDefinition}("${property.serializedName}", x${contentType ? `", ${contentType}"` : ""})))`;
|
|
382
|
+
} else {
|
|
383
|
+
partDefinition = `${createFilePartDescriptorDefinition}("${property.serializedName}", item["${property.serializedName}"]${contentType ? `, "${contentType}"` : ""})`;
|
|
384
|
+
}
|
|
385
|
+
} else if (property.multipartOptions?.isMulti) {
|
|
386
|
+
partDefinition = `...((${expr}).map((x: unknown) => ({ name: "${property.serializedName}", body: x })))`;
|
|
387
|
+
} else {
|
|
388
|
+
partDefinition = `{ name: "${property.serializedName}", body: (${expr}) }`;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
if (property.optional) {
|
|
392
|
+
parts.push(
|
|
393
|
+
`...(${getPropertyFullName(context, property, "item")} === undefined ? [] : [${partDefinition}])`
|
|
394
|
+
);
|
|
395
|
+
} else {
|
|
396
|
+
parts.push(partDefinition);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// TODO: How to handle additionalProperties for MFD?
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
serializerFunction.statements = [`return [${parts.join(",")}]`];
|
|
403
|
+
} else {
|
|
404
|
+
// This is only handling the compatibility mode, will need to update when we handle additionalProperties property.
|
|
405
|
+
const additionalPropertiesSpread = hasAdditionalProperties(type)
|
|
406
|
+
? "...item"
|
|
407
|
+
: "";
|
|
353
408
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
409
|
+
const propertiesStr = getRequestModelMapping(context, type, "item");
|
|
410
|
+
|
|
411
|
+
if (additionalPropertiesSpread) {
|
|
412
|
+
propertiesStr.unshift(additionalPropertiesSpread);
|
|
413
|
+
}
|
|
414
|
+
const serializeContent = `{${propertiesStr.join(",")}}`;
|
|
415
|
+
|
|
416
|
+
const output = [];
|
|
417
|
+
|
|
418
|
+
// don't emit a serializer if there is nothing to serialize
|
|
419
|
+
if (propertiesStr.length) {
|
|
420
|
+
output.push(`
|
|
357
421
|
return ${serializeContent}
|
|
358
422
|
`);
|
|
359
|
-
|
|
360
|
-
|
|
423
|
+
} else {
|
|
424
|
+
output.push(`
|
|
361
425
|
return item;
|
|
362
426
|
`);
|
|
427
|
+
}
|
|
428
|
+
serializerFunction.statements = output;
|
|
363
429
|
}
|
|
364
|
-
serializerFunction.statements = output;
|
|
365
430
|
return serializerFunction;
|
|
366
431
|
}
|
|
367
432
|
|
|
@@ -71,3 +71,16 @@ export const PollingHelpers = {
|
|
|
71
71
|
location: "pollingHelpers.ts"
|
|
72
72
|
}
|
|
73
73
|
} as const;
|
|
74
|
+
|
|
75
|
+
export const MultipartHelpers = {
|
|
76
|
+
FileContents: {
|
|
77
|
+
kind: "typeAlias",
|
|
78
|
+
name: "FileContents",
|
|
79
|
+
location: "multipartHelpers.ts"
|
|
80
|
+
},
|
|
81
|
+
createFilePartDescriptor: {
|
|
82
|
+
kind: "function",
|
|
83
|
+
name: "createFilePartDescriptor",
|
|
84
|
+
location: "multipartHelpers.ts"
|
|
85
|
+
}
|
|
86
|
+
} as const;
|
|
@@ -5,7 +5,8 @@ import {
|
|
|
5
5
|
PackageDetails,
|
|
6
6
|
PackageFlavor,
|
|
7
7
|
RLCOptions,
|
|
8
|
-
ServiceInfo
|
|
8
|
+
ServiceInfo,
|
|
9
|
+
isAzurePackage
|
|
9
10
|
} from "@azure-tools/rlc-common";
|
|
10
11
|
import {
|
|
11
12
|
getHttpOperationWithCache,
|
|
@@ -32,6 +33,15 @@ export function transformRLCOptions(
|
|
|
32
33
|
emitterOptions,
|
|
33
34
|
dpgContext.generationPathDetail?.rootDir ?? ""
|
|
34
35
|
);
|
|
36
|
+
if (
|
|
37
|
+
!isAzurePackage({ options }) &&
|
|
38
|
+
emitterOptions.isModularLibrary !== false
|
|
39
|
+
) {
|
|
40
|
+
options.isModularLibrary = true;
|
|
41
|
+
}
|
|
42
|
+
if (dpgContext.arm && emitterOptions.isModularLibrary !== false) {
|
|
43
|
+
options.isModularLibrary = true;
|
|
44
|
+
}
|
|
35
45
|
const batch = getRLCClients(dpgContext);
|
|
36
46
|
options.batch = batch;
|
|
37
47
|
return options;
|