@azure-tools/typespec-ts 0.46.1-alpha.20251201.1 → 0.47.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 +15 -3
- package/LICENSE +21 -0
- package/dist/src/framework/hooks/sdkTypes.d.ts +7 -1
- package/dist/src/framework/hooks/sdkTypes.d.ts.map +1 -1
- package/dist/src/framework/hooks/sdkTypes.js +59 -1
- package/dist/src/framework/hooks/sdkTypes.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 +12 -0
- package/dist/src/lib.js.map +1 -1
- package/dist/src/modular/buildClassicalClient.d.ts.map +1 -1
- package/dist/src/modular/buildClassicalClient.js +84 -6
- package/dist/src/modular/buildClassicalClient.js.map +1 -1
- package/dist/src/modular/emitModels.d.ts.map +1 -1
- package/dist/src/modular/emitModels.js +57 -14
- package/dist/src/modular/emitModels.js.map +1 -1
- package/dist/src/modular/emitSamples.d.ts.map +1 -1
- package/dist/src/modular/emitSamples.js +52 -25
- package/dist/src/modular/emitSamples.js.map +1 -1
- package/dist/src/modular/helpers/operationHelpers.d.ts +5 -4
- package/dist/src/modular/helpers/operationHelpers.d.ts.map +1 -1
- package/dist/src/modular/helpers/operationHelpers.js +113 -23
- package/dist/src/modular/helpers/operationHelpers.js.map +1 -1
- package/dist/src/modular/helpers/typeHelpers.d.ts +3 -1
- package/dist/src/modular/helpers/typeHelpers.d.ts.map +1 -1
- package/dist/src/modular/helpers/typeHelpers.js +7 -3
- package/dist/src/modular/helpers/typeHelpers.js.map +1 -1
- package/dist/src/modular/serialization/buildDeserializerFunction.d.ts +4 -2
- package/dist/src/modular/serialization/buildDeserializerFunction.d.ts.map +1 -1
- package/dist/src/modular/serialization/buildDeserializerFunction.js +60 -17
- package/dist/src/modular/serialization/buildDeserializerFunction.js.map +1 -1
- package/dist/src/modular/serialization/buildSerializerFunction.d.ts +4 -2
- package/dist/src/modular/serialization/buildSerializerFunction.d.ts.map +1 -1
- package/dist/src/modular/serialization/buildSerializerFunction.js +61 -19
- package/dist/src/modular/serialization/buildSerializerFunction.js.map +1 -1
- package/dist/src/modular/serialization/serializeUtils.d.ts +11 -0
- package/dist/src/modular/serialization/serializeUtils.d.ts.map +1 -1
- package/dist/src/modular/serialization/serializeUtils.js +15 -0
- package/dist/src/modular/serialization/serializeUtils.js.map +1 -1
- package/dist/src/modular/static-helpers-metadata.d.ts +5 -0
- package/dist/src/modular/static-helpers-metadata.d.ts.map +1 -1
- package/dist/src/modular/static-helpers-metadata.js +5 -0
- package/dist/src/modular/static-helpers-metadata.js.map +1 -1
- package/dist/src/utils/namespaceUtils.d.ts.map +1 -1
- package/dist/src/utils/namespaceUtils.js +19 -4
- package/dist/src/utils/namespaceUtils.js.map +1 -1
- package/dist/src/utils/operationUtil.d.ts +1 -0
- package/dist/src/utils/operationUtil.d.ts.map +1 -1
- package/dist/src/utils/operationUtil.js +26 -0
- package/dist/src/utils/operationUtil.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -11
- package/src/framework/hooks/sdkTypes.ts +102 -2
- package/src/lib.ts +12 -0
- package/src/modular/buildClassicalClient.ts +116 -6
- package/src/modular/emitModels.ts +72 -19
- package/src/modular/emitSamples.ts +85 -20
- package/src/modular/helpers/operationHelpers.ts +151 -41
- package/src/modular/helpers/typeHelpers.ts +19 -3
- package/src/modular/serialization/buildDeserializerFunction.ts +87 -35
- package/src/modular/serialization/buildSerializerFunction.ts +86 -36
- package/src/modular/serialization/serializeUtils.ts +37 -0
- package/src/modular/static-helpers-metadata.ts +5 -0
- package/src/utils/namespaceUtils.ts +19 -3
- package/src/utils/operationUtil.ts +35 -0
- package/static/static-helpers/serialization/check-prop-undefined.ts +17 -0
|
@@ -2,6 +2,7 @@ import { FunctionDeclarationStructure, StructureKind } from "ts-morph";
|
|
|
2
2
|
import {
|
|
3
3
|
SdkArrayType,
|
|
4
4
|
SdkDictionaryType,
|
|
5
|
+
SdkModelPropertyType,
|
|
5
6
|
SdkModelType,
|
|
6
7
|
SdkType,
|
|
7
8
|
SdkUnionType,
|
|
@@ -34,17 +35,55 @@ import {
|
|
|
34
35
|
} from "../helpers/typeHelpers.js";
|
|
35
36
|
import { reportDiagnostic } from "../../lib.js";
|
|
36
37
|
import { NoTarget } from "@typespec/compiler";
|
|
38
|
+
import { useContext } from "../../contextManager.js";
|
|
39
|
+
|
|
40
|
+
export function buildPropertyDeserializer(
|
|
41
|
+
context: SdkContext,
|
|
42
|
+
property: SdkModelPropertyType,
|
|
43
|
+
options: ModelSerializeOptions = {
|
|
44
|
+
nameOnly: false,
|
|
45
|
+
skipDiscriminatedUnionSuffix: false
|
|
46
|
+
}
|
|
47
|
+
) {
|
|
48
|
+
const propertyContext =
|
|
49
|
+
useContext("sdkTypes").flattenProperties.get(property);
|
|
50
|
+
// only build de-serializer for flatten property
|
|
51
|
+
if (property.flatten !== true || !propertyContext) {
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const predefinedName = `_${normalizeName(
|
|
56
|
+
`${propertyContext.baseModel.name}_${property.name}`,
|
|
57
|
+
NameType.Method,
|
|
58
|
+
true
|
|
59
|
+
)}Deserializer`;
|
|
60
|
+
return buildModelDeserializer(context, property.type, {
|
|
61
|
+
...options,
|
|
62
|
+
flatten: {
|
|
63
|
+
baseModel: propertyContext.baseModel,
|
|
64
|
+
property
|
|
65
|
+
},
|
|
66
|
+
overrides: {
|
|
67
|
+
allOptional: property.optional,
|
|
68
|
+
propertyRenames: propertyContext.conflictMap
|
|
69
|
+
},
|
|
70
|
+
predefinedName
|
|
71
|
+
});
|
|
72
|
+
}
|
|
37
73
|
|
|
38
74
|
export function buildModelDeserializer(
|
|
39
75
|
context: SdkContext,
|
|
40
76
|
type: SdkType,
|
|
41
|
-
|
|
42
|
-
|
|
77
|
+
options: ModelSerializeOptions = {
|
|
78
|
+
nameOnly: false,
|
|
79
|
+
skipDiscriminatedUnionSuffix: false
|
|
80
|
+
}
|
|
43
81
|
): FunctionDeclarationStructure | undefined | string {
|
|
44
82
|
// const modelTcgcType = getTcgcType(type) as SdkModelType;
|
|
45
83
|
if (!isSupportedSerializeType(type)) {
|
|
46
84
|
return undefined;
|
|
47
85
|
}
|
|
86
|
+
const { nameOnly, skipDiscriminatedUnionSuffix } = options;
|
|
48
87
|
if (type.kind === "model" || type.kind === "union" || type.kind === "enum") {
|
|
49
88
|
if (
|
|
50
89
|
!type.usage ||
|
|
@@ -72,16 +111,13 @@ export function buildModelDeserializer(
|
|
|
72
111
|
return buildPolymorphicDeserializer(context, type, nameOnly);
|
|
73
112
|
}
|
|
74
113
|
|
|
75
|
-
if (isDiscriminatedUnion(type) && !
|
|
114
|
+
if (isDiscriminatedUnion(type) && !skipDiscriminatedUnionSuffix) {
|
|
76
115
|
return buildDiscriminatedUnionDeserializer(context, type, nameOnly);
|
|
77
116
|
}
|
|
78
117
|
|
|
79
118
|
switch (type.kind) {
|
|
80
119
|
case "model":
|
|
81
|
-
return buildModelTypeDeserializer(context, type,
|
|
82
|
-
nameOnly,
|
|
83
|
-
skipDiscriminatedUnionSuffix: skipDiscriminatedUnion
|
|
84
|
-
});
|
|
120
|
+
return buildModelTypeDeserializer(context, type, options);
|
|
85
121
|
case "union": // for non-discriminated union, we just return whatever we get
|
|
86
122
|
return buildUnionDeserializer(context, type, nameOnly);
|
|
87
123
|
case "dict":
|
|
@@ -220,6 +256,7 @@ function buildDiscriminatedUnionDeserializer(
|
|
|
220
256
|
if (nameOnly) {
|
|
221
257
|
return resolveReference(refkey(type, "deserializer"));
|
|
222
258
|
}
|
|
259
|
+
// Get the base deserializer name and ensure reference tracking
|
|
223
260
|
const baseDeserializerName = `${normalizeModelName(
|
|
224
261
|
context,
|
|
225
262
|
type,
|
|
@@ -241,12 +278,17 @@ function buildDiscriminatedUnionDeserializer(
|
|
|
241
278
|
type.discriminatorProperty
|
|
242
279
|
);
|
|
243
280
|
const union = subType.discriminatedSubtypes ? "Union" : "";
|
|
244
|
-
const subTypeName =
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
NameType.
|
|
248
|
-
|
|
281
|
+
const subTypeName = normalizeModelName(
|
|
282
|
+
context,
|
|
283
|
+
subType,
|
|
284
|
+
NameType.Interface,
|
|
285
|
+
!union
|
|
249
286
|
);
|
|
287
|
+
// Get the deserializer name and ensure reference tracking
|
|
288
|
+
const subtypeDeserializerName = buildModelDeserializer(context, subType, {
|
|
289
|
+
nameOnly: true,
|
|
290
|
+
skipDiscriminatedUnionSuffix: false
|
|
291
|
+
}) as string;
|
|
250
292
|
|
|
251
293
|
const caseLabels = discriminatedValues.map((value) => `case "${value}":`);
|
|
252
294
|
cases.push(`
|
|
@@ -338,14 +380,18 @@ function buildModelTypeDeserializer(
|
|
|
338
380
|
});
|
|
339
381
|
return ""; // Return empty string to continue processing
|
|
340
382
|
}
|
|
341
|
-
const deserializerFunctionName =
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
383
|
+
const deserializerFunctionName =
|
|
384
|
+
options.predefinedName ??
|
|
385
|
+
`${normalizeModelName(
|
|
386
|
+
context,
|
|
387
|
+
type,
|
|
388
|
+
NameType.Operation,
|
|
389
|
+
options.skipDiscriminatedUnionSuffix
|
|
390
|
+
)}Deserializer`;
|
|
347
391
|
if (options.nameOnly) {
|
|
348
|
-
return
|
|
392
|
+
return options.flatten
|
|
393
|
+
? resolveReference(refkey(options.flatten.property, "deserializer"))
|
|
394
|
+
: resolveReference(refkey(type, "deserializer"));
|
|
349
395
|
}
|
|
350
396
|
const deserializerFunction: FunctionDeclarationStructure = {
|
|
351
397
|
kind: StructureKind.Function,
|
|
@@ -357,7 +403,9 @@ function buildModelTypeDeserializer(
|
|
|
357
403
|
type: "any"
|
|
358
404
|
}
|
|
359
405
|
],
|
|
360
|
-
returnType:
|
|
406
|
+
returnType: options.flatten
|
|
407
|
+
? undefined // not set return type for flattened property deserializer and type system will infer correct one
|
|
408
|
+
: resolveReference(refkey(type)),
|
|
361
409
|
statements: ["return item;"]
|
|
362
410
|
};
|
|
363
411
|
const nullabilityPrefix = "";
|
|
@@ -365,7 +413,13 @@ function buildModelTypeDeserializer(
|
|
|
365
413
|
const additionalPropertiesSpread =
|
|
366
414
|
getAdditionalPropertiesStatement(context, type) ?? "";
|
|
367
415
|
|
|
368
|
-
const propertiesStr = getResponseMapping(
|
|
416
|
+
const propertiesStr = getResponseMapping(
|
|
417
|
+
context,
|
|
418
|
+
type,
|
|
419
|
+
"item",
|
|
420
|
+
options.overrides,
|
|
421
|
+
!options.flatten
|
|
422
|
+
);
|
|
369
423
|
const propertiesDeserialization = propertiesStr.filter((p) => p.trim());
|
|
370
424
|
|
|
371
425
|
const output = [];
|
|
@@ -406,8 +460,10 @@ function getAdditionalPropertiesStatement(
|
|
|
406
460
|
const deserializerFunction = buildModelDeserializer(
|
|
407
461
|
context,
|
|
408
462
|
additionalPropertyType,
|
|
409
|
-
|
|
410
|
-
|
|
463
|
+
{
|
|
464
|
+
nameOnly: true,
|
|
465
|
+
skipDiscriminatedUnionSuffix: false
|
|
466
|
+
}
|
|
411
467
|
);
|
|
412
468
|
if (typeof deserializerFunction === "string") {
|
|
413
469
|
params.push(deserializerFunction);
|
|
@@ -431,12 +487,10 @@ function buildDictTypeDeserializer(
|
|
|
431
487
|
type: SdkDictionaryType,
|
|
432
488
|
nameOnly = false
|
|
433
489
|
): FunctionDeclarationStructure | undefined | string {
|
|
434
|
-
const valueDeserializer = buildModelDeserializer(
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
true
|
|
439
|
-
);
|
|
490
|
+
const valueDeserializer = buildModelDeserializer(context, type.valueType, {
|
|
491
|
+
nameOnly: true,
|
|
492
|
+
skipDiscriminatedUnionSuffix: false
|
|
493
|
+
});
|
|
440
494
|
if (!valueDeserializer) {
|
|
441
495
|
return undefined;
|
|
442
496
|
}
|
|
@@ -490,12 +544,10 @@ function buildArrayTypeDeserializer(
|
|
|
490
544
|
type: SdkArrayType,
|
|
491
545
|
nameOnly = false
|
|
492
546
|
): FunctionDeclarationStructure | undefined | string {
|
|
493
|
-
const valueDeserializer = buildModelDeserializer(
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
true
|
|
498
|
-
);
|
|
547
|
+
const valueDeserializer = buildModelDeserializer(context, type.valueType, {
|
|
548
|
+
nameOnly: true,
|
|
549
|
+
skipDiscriminatedUnionSuffix: false
|
|
550
|
+
});
|
|
499
551
|
if (!valueDeserializer) {
|
|
500
552
|
return undefined;
|
|
501
553
|
}
|
|
@@ -2,6 +2,7 @@ import { FunctionDeclarationStructure, StructureKind } from "ts-morph";
|
|
|
2
2
|
import {
|
|
3
3
|
SdkArrayType,
|
|
4
4
|
SdkDictionaryType,
|
|
5
|
+
SdkModelPropertyType,
|
|
5
6
|
SdkModelType,
|
|
6
7
|
SdkType,
|
|
7
8
|
SdkUnionType,
|
|
@@ -40,17 +41,53 @@ import {
|
|
|
40
41
|
} from "../helpers/typeHelpers.js";
|
|
41
42
|
import { reportDiagnostic } from "../../lib.js";
|
|
42
43
|
import { NoTarget } from "@typespec/compiler";
|
|
44
|
+
import { useContext } from "../../contextManager.js";
|
|
45
|
+
|
|
46
|
+
export function buildPropertySerializer(
|
|
47
|
+
context: SdkContext,
|
|
48
|
+
property: SdkModelPropertyType,
|
|
49
|
+
options: ModelSerializeOptions = {
|
|
50
|
+
nameOnly: false,
|
|
51
|
+
skipDiscriminatedUnionSuffix: false
|
|
52
|
+
}
|
|
53
|
+
) {
|
|
54
|
+
const propertyContext =
|
|
55
|
+
useContext("sdkTypes").flattenProperties.get(property);
|
|
56
|
+
// only build de-serializer for flatten property
|
|
57
|
+
if (property.flatten !== true || !propertyContext) {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
const predefinedName = `_${normalizeName(
|
|
61
|
+
`${propertyContext.baseModel.name}_${property.name}`,
|
|
62
|
+
NameType.Method,
|
|
63
|
+
true
|
|
64
|
+
)}Serializer`;
|
|
65
|
+
return buildModelSerializer(context, property.type, {
|
|
66
|
+
...options,
|
|
67
|
+
flatten: {
|
|
68
|
+
baseModel: propertyContext.baseModel,
|
|
69
|
+
property
|
|
70
|
+
},
|
|
71
|
+
overrides: {
|
|
72
|
+
allOptional: property.optional,
|
|
73
|
+
propertyRenames: propertyContext.conflictMap
|
|
74
|
+
},
|
|
75
|
+
predefinedName
|
|
76
|
+
});
|
|
77
|
+
}
|
|
43
78
|
|
|
44
79
|
export function buildModelSerializer(
|
|
45
80
|
context: SdkContext,
|
|
46
81
|
type: SdkType,
|
|
47
|
-
|
|
48
|
-
|
|
82
|
+
options: ModelSerializeOptions = {
|
|
83
|
+
nameOnly: false,
|
|
84
|
+
skipDiscriminatedUnionSuffix: false
|
|
85
|
+
}
|
|
49
86
|
): FunctionDeclarationStructure | undefined | string {
|
|
50
|
-
// const modelTcgcType = getTcgcType(type) as SdkModelType;
|
|
51
87
|
if (!isSupportedSerializeType(type)) {
|
|
52
88
|
return undefined;
|
|
53
89
|
}
|
|
90
|
+
const { nameOnly } = options;
|
|
54
91
|
if (type.kind === "model" || type.kind === "union" || type.kind === "enum") {
|
|
55
92
|
if (
|
|
56
93
|
!type.usage ||
|
|
@@ -80,16 +117,13 @@ export function buildModelSerializer(
|
|
|
80
117
|
return buildPolymorphicSerializer(context, type, nameOnly);
|
|
81
118
|
}
|
|
82
119
|
|
|
83
|
-
if (isDiscriminatedUnion(type) && !
|
|
120
|
+
if (isDiscriminatedUnion(type) && !options.skipDiscriminatedUnionSuffix) {
|
|
84
121
|
return buildDiscriminatedUnionSerializer(context, type, nameOnly);
|
|
85
122
|
}
|
|
86
123
|
|
|
87
124
|
switch (type.kind) {
|
|
88
125
|
case "model":
|
|
89
|
-
return buildModelTypeSerializer(context, type,
|
|
90
|
-
nameOnly,
|
|
91
|
-
skipDiscriminatedUnionSuffix: skipDiscriminatedUnion
|
|
92
|
-
});
|
|
126
|
+
return buildModelTypeSerializer(context, type, options);
|
|
93
127
|
case "union": // for non-discriminated union, we just return whatever we get
|
|
94
128
|
return buildUnionSerializer(context, type, nameOnly);
|
|
95
129
|
case "dict":
|
|
@@ -227,6 +261,7 @@ function buildDiscriminatedUnionSerializer(
|
|
|
227
261
|
if (nameOnly) {
|
|
228
262
|
return resolveReference(refkey(type, "serializer"));
|
|
229
263
|
}
|
|
264
|
+
// Get the base serializer name and ensure reference tracking
|
|
230
265
|
const baseSerializerName = `${normalizeModelName(
|
|
231
266
|
context,
|
|
232
267
|
type,
|
|
@@ -248,12 +283,17 @@ function buildDiscriminatedUnionSerializer(
|
|
|
248
283
|
type.discriminatorProperty
|
|
249
284
|
);
|
|
250
285
|
const union = subType.discriminatedSubtypes ? "Union" : "";
|
|
251
|
-
const subTypeName =
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
NameType.
|
|
255
|
-
|
|
286
|
+
const subTypeName = normalizeModelName(
|
|
287
|
+
context,
|
|
288
|
+
subType,
|
|
289
|
+
NameType.Interface,
|
|
290
|
+
!union
|
|
256
291
|
);
|
|
292
|
+
// Get the serializer name and ensure reference tracking
|
|
293
|
+
const subtypeSerializerName = buildModelSerializer(context, subType, {
|
|
294
|
+
nameOnly: true,
|
|
295
|
+
skipDiscriminatedUnionSuffix: false
|
|
296
|
+
}) as string;
|
|
257
297
|
|
|
258
298
|
const caseLabels = discriminatedValues.map((value) => `case "${value}":`);
|
|
259
299
|
cases.push(`
|
|
@@ -345,14 +385,18 @@ function buildModelTypeSerializer(
|
|
|
345
385
|
});
|
|
346
386
|
return ""; // Return empty string to continue processing
|
|
347
387
|
}
|
|
348
|
-
const serializerFunctionName =
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
388
|
+
const serializerFunctionName =
|
|
389
|
+
options.predefinedName ??
|
|
390
|
+
`${normalizeModelName(
|
|
391
|
+
context,
|
|
392
|
+
type,
|
|
393
|
+
NameType.Operation,
|
|
394
|
+
options.skipDiscriminatedUnionSuffix
|
|
395
|
+
)}Serializer`;
|
|
354
396
|
if (options.nameOnly) {
|
|
355
|
-
return
|
|
397
|
+
return options.flatten
|
|
398
|
+
? resolveReference(refkey(options.flatten.property, "serializer"))
|
|
399
|
+
: resolveReference(refkey(type, "serializer"));
|
|
356
400
|
}
|
|
357
401
|
const serializerFunction: FunctionDeclarationStructure = {
|
|
358
402
|
kind: StructureKind.Function,
|
|
@@ -361,7 +405,9 @@ function buildModelTypeSerializer(
|
|
|
361
405
|
parameters: [
|
|
362
406
|
{
|
|
363
407
|
name: "item",
|
|
364
|
-
type:
|
|
408
|
+
type: options.flatten
|
|
409
|
+
? resolveReference(refkey(options.flatten.baseModel))
|
|
410
|
+
: resolveReference(refkey(type))
|
|
365
411
|
}
|
|
366
412
|
],
|
|
367
413
|
returnType: "any",
|
|
@@ -435,7 +481,13 @@ function buildModelTypeSerializer(
|
|
|
435
481
|
type
|
|
436
482
|
);
|
|
437
483
|
|
|
438
|
-
const propertiesStr = getRequestModelMapping(
|
|
484
|
+
const propertiesStr = getRequestModelMapping(
|
|
485
|
+
context,
|
|
486
|
+
type,
|
|
487
|
+
"item",
|
|
488
|
+
options.overrides,
|
|
489
|
+
!options.flatten
|
|
490
|
+
);
|
|
439
491
|
|
|
440
492
|
if (additionalPropertiesSpread) {
|
|
441
493
|
propertiesStr.unshift(additionalPropertiesSpread);
|
|
@@ -470,8 +522,10 @@ function getAdditionalPropertiesStatement(
|
|
|
470
522
|
const deserializerFunction = buildModelSerializer(
|
|
471
523
|
context,
|
|
472
524
|
additionalPropertyType,
|
|
473
|
-
|
|
474
|
-
|
|
525
|
+
{
|
|
526
|
+
nameOnly: true,
|
|
527
|
+
skipDiscriminatedUnionSuffix: false
|
|
528
|
+
}
|
|
475
529
|
);
|
|
476
530
|
const params = [`item.${getAdditionalPropertiesName(context, type)} ?? {}`];
|
|
477
531
|
if (typeof deserializerFunction === "string") {
|
|
@@ -497,12 +551,10 @@ function buildDictTypeSerializer(
|
|
|
497
551
|
type: SdkDictionaryType,
|
|
498
552
|
nameOnly = false
|
|
499
553
|
): FunctionDeclarationStructure | undefined | string {
|
|
500
|
-
const valueSerializer = buildModelSerializer(
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
true
|
|
505
|
-
);
|
|
554
|
+
const valueSerializer = buildModelSerializer(context, type.valueType, {
|
|
555
|
+
nameOnly: true,
|
|
556
|
+
skipDiscriminatedUnionSuffix: false
|
|
557
|
+
});
|
|
506
558
|
if (!valueSerializer) {
|
|
507
559
|
return undefined;
|
|
508
560
|
}
|
|
@@ -555,12 +607,10 @@ function buildArrayTypeSerializer(
|
|
|
555
607
|
type: SdkArrayType,
|
|
556
608
|
nameOnly = false
|
|
557
609
|
): FunctionDeclarationStructure | undefined | string {
|
|
558
|
-
const valueSerializer = buildModelSerializer(
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
true
|
|
563
|
-
);
|
|
610
|
+
const valueSerializer = buildModelSerializer(context, type.valueType, {
|
|
611
|
+
nameOnly: true,
|
|
612
|
+
skipDiscriminatedUnionSuffix: false
|
|
613
|
+
});
|
|
564
614
|
if (!valueSerializer) {
|
|
565
615
|
return undefined;
|
|
566
616
|
}
|
|
@@ -182,4 +182,41 @@ export function isPolymorphicUnion(t: SdkType): boolean {
|
|
|
182
182
|
export interface ModelSerializeOptions {
|
|
183
183
|
nameOnly: boolean;
|
|
184
184
|
skipDiscriminatedUnionSuffix: boolean;
|
|
185
|
+
// Indicates if the serializer is being built for a property that is flattened.
|
|
186
|
+
flatten?: {
|
|
187
|
+
baseModel: SdkModelType;
|
|
188
|
+
property: SdkModelPropertyType;
|
|
189
|
+
};
|
|
190
|
+
// Indicates if any overrides should be applied when building the serializer/deserializer.
|
|
191
|
+
overrides?: ModelOverrideOptions;
|
|
192
|
+
// Predefined name to use for the serializer/deserializer instead of generating one.
|
|
193
|
+
predefinedName?: string;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Options for overriding model information during serialization/deserialization.
|
|
197
|
+
export interface ModelOverrideOptions {
|
|
198
|
+
// If true, all properties will be treated as optional during serialization/deserialization.
|
|
199
|
+
allOptional?: boolean;
|
|
200
|
+
|
|
201
|
+
// The <Property, Client_Name> map for any renamed properties.
|
|
202
|
+
// Mainly because the original client name has collision with other property names during flattening.
|
|
203
|
+
propertyRenames?: Map<SdkModelPropertyType, string>;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export function getPropertyWithOverrides(
|
|
207
|
+
property: SdkModelPropertyType,
|
|
208
|
+
overrides?: ModelOverrideOptions
|
|
209
|
+
): SdkModelPropertyType {
|
|
210
|
+
if (!overrides) {
|
|
211
|
+
return property;
|
|
212
|
+
}
|
|
213
|
+
let updatedProperty = property;
|
|
214
|
+
if (overrides.allOptional) {
|
|
215
|
+
updatedProperty = { ...updatedProperty, optional: true };
|
|
216
|
+
}
|
|
217
|
+
const renamedClientName = overrides.propertyRenames?.get(property);
|
|
218
|
+
if (renamedClientName) {
|
|
219
|
+
updatedProperty = { ...updatedProperty, name: renamedClientName };
|
|
220
|
+
}
|
|
221
|
+
return updatedProperty;
|
|
185
222
|
}
|
|
@@ -33,6 +33,11 @@ export const SerializationHelpers = {
|
|
|
33
33
|
kind: "function",
|
|
34
34
|
name: "getBinaryResponse",
|
|
35
35
|
location: "serialization/get-binary-response.ts"
|
|
36
|
+
},
|
|
37
|
+
areAllPropsUndefined: {
|
|
38
|
+
kind: "function",
|
|
39
|
+
name: "areAllPropsUndefined",
|
|
40
|
+
location: "serialization/check-prop-undefined.ts"
|
|
36
41
|
}
|
|
37
42
|
} as const;
|
|
38
43
|
|
|
@@ -3,8 +3,10 @@ import {
|
|
|
3
3
|
isGlobalNamespace,
|
|
4
4
|
isService,
|
|
5
5
|
Namespace,
|
|
6
|
+
NoTarget,
|
|
6
7
|
Operation
|
|
7
8
|
} from "@typespec/compiler";
|
|
9
|
+
import { reportDiagnostic } from "../lib.js";
|
|
8
10
|
import { SdkContext } from "./interfaces.js";
|
|
9
11
|
|
|
10
12
|
export function getModelNamespaceName(
|
|
@@ -68,14 +70,28 @@ export function getOperationNamespaceInterfaceName(
|
|
|
68
70
|
export function detectModelConflicts(dpgContext: SdkContext) {
|
|
69
71
|
const allModels = getAllModels(dpgContext);
|
|
70
72
|
const nameSet = new Set<string>();
|
|
73
|
+
const reported = new Set<string>();
|
|
74
|
+
let hasConflict = false;
|
|
71
75
|
for (const model of allModels) {
|
|
72
76
|
if (model.name === "") {
|
|
73
77
|
continue;
|
|
74
78
|
}
|
|
75
|
-
if (nameSet.has(model.name)) {
|
|
76
|
-
|
|
79
|
+
if (nameSet.has(model.name) && !reported.has(model.name)) {
|
|
80
|
+
reportDiagnostic(dpgContext.program, {
|
|
81
|
+
code: "detected-model-name-conflict",
|
|
82
|
+
format: {
|
|
83
|
+
modelName: model.name,
|
|
84
|
+
namespaces: allModels
|
|
85
|
+
.filter((m) => m.name === model.name)
|
|
86
|
+
.map((m) => m.namespace)
|
|
87
|
+
.join(" and ")
|
|
88
|
+
},
|
|
89
|
+
target: NoTarget
|
|
90
|
+
});
|
|
91
|
+
reported.add(model.name);
|
|
92
|
+
hasConflict = true;
|
|
77
93
|
}
|
|
78
94
|
nameSet.add(model.name);
|
|
79
95
|
}
|
|
80
|
-
return
|
|
96
|
+
return hasConflict;
|
|
81
97
|
}
|
|
@@ -679,6 +679,41 @@ export function getMethodHierarchiesMap(
|
|
|
679
679
|
return operationHierarchiesMap;
|
|
680
680
|
}
|
|
681
681
|
|
|
682
|
+
export function isTenantLevelOperation(
|
|
683
|
+
operation: ServiceOperation,
|
|
684
|
+
client: SdkClientType<SdkServiceOperation>
|
|
685
|
+
): boolean {
|
|
686
|
+
// Check if this operation has a subscriptionId path parameter
|
|
687
|
+
const subscriptionIdParam = operation.operation.parameters?.find(
|
|
688
|
+
(param) =>
|
|
689
|
+
param.name.toLowerCase() === "subscriptionid" && param.kind === "path"
|
|
690
|
+
);
|
|
691
|
+
|
|
692
|
+
if (subscriptionIdParam) {
|
|
693
|
+
// The operation has a client-level subscriptionId parameter, then it's not tenant-level
|
|
694
|
+
if (subscriptionIdParam.onClient) {
|
|
695
|
+
return false;
|
|
696
|
+
}
|
|
697
|
+
} else {
|
|
698
|
+
// Skip tenant-level internal ARM APIs
|
|
699
|
+
// Ref: https://armwiki.azurewebsites.net/rpaas/operations_auto_gen.html#special-cases
|
|
700
|
+
const pathLC = operation.operation.path.toLowerCase();
|
|
701
|
+
// Get the provider namespace from the client
|
|
702
|
+
const clientNamespaceLC = client.namespace.toLowerCase();
|
|
703
|
+
if (
|
|
704
|
+
operation.crossLanguageDefinitionId?.toLowerCase() ===
|
|
705
|
+
"azure.resourcemanager.operations.list" ||
|
|
706
|
+
pathLC.includes(`${clientNamespaceLC}/checknameavailability`)
|
|
707
|
+
) {
|
|
708
|
+
return false;
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
// The operation has no subscriptionId parameter or has method-level subscriptionId parameter
|
|
713
|
+
// Considered as tenant-level
|
|
714
|
+
return true;
|
|
715
|
+
}
|
|
716
|
+
|
|
682
717
|
function resolveParameterNameConflict(
|
|
683
718
|
operationOrGroup: SdkServiceMethod<SdkHttpOperation>,
|
|
684
719
|
p: SdkMethodParameter | SdkHttpParameter | SdkBodyParameter
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns true if all specified properties of the item are undefined.
|
|
3
|
+
* @param item The object to check.
|
|
4
|
+
* @param properties The list of property names to check on the item.
|
|
5
|
+
* @returns True if all specified properties are undefined, otherwise false.
|
|
6
|
+
*/
|
|
7
|
+
export function areAllPropsUndefined(
|
|
8
|
+
item: Record<string, any>,
|
|
9
|
+
properties: string[]
|
|
10
|
+
): boolean {
|
|
11
|
+
for (const property of properties) {
|
|
12
|
+
if (item[property] !== undefined) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return true;
|
|
17
|
+
}
|