@azure-tools/typespec-ts 0.29.0-alpha.20240626.1 → 0.30.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 -0
- package/dist/src/contextManager.d.ts +70 -0
- package/dist/src/contextManager.d.ts.map +1 -0
- package/dist/src/contextManager.js +59 -0
- package/dist/src/contextManager.js.map +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +13 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/metaTree.d.ts +12 -0
- package/dist/src/metaTree.d.ts.map +1 -0
- package/dist/src/metaTree.js +2 -0
- package/dist/src/metaTree.js.map +1 -0
- package/dist/src/modular/buildClassicalClient.js +3 -1
- 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 +17 -7
- package/dist/src/modular/buildCodeModel.js.map +1 -1
- package/dist/src/modular/buildHelperSerializers.d.ts +3 -0
- package/dist/src/modular/buildHelperSerializers.d.ts.map +1 -0
- package/dist/src/modular/buildHelperSerializers.js +60 -0
- package/dist/src/modular/buildHelperSerializers.js.map +1 -0
- package/dist/src/modular/buildOperations.d.ts.map +1 -1
- package/dist/src/modular/buildOperations.js +5 -0
- package/dist/src/modular/buildOperations.js.map +1 -1
- package/dist/src/modular/buildSerializeUtils.d.ts.map +1 -1
- package/dist/src/modular/buildSerializeUtils.js +11 -4
- package/dist/src/modular/buildSerializeUtils.js.map +1 -1
- package/dist/src/modular/buildSubpathIndex.d.ts.map +1 -1
- package/dist/src/modular/buildSubpathIndex.js +6 -0
- package/dist/src/modular/buildSubpathIndex.js.map +1 -1
- package/dist/src/modular/emitModels.d.ts +5 -5
- package/dist/src/modular/emitModels.d.ts.map +1 -1
- package/dist/src/modular/emitModels.js +32 -4
- package/dist/src/modular/emitModels.js.map +1 -1
- package/dist/src/modular/helpers/operationHelpers.d.ts +10 -2
- package/dist/src/modular/helpers/operationHelpers.d.ts.map +1 -1
- package/dist/src/modular/helpers/operationHelpers.js +135 -56
- package/dist/src/modular/helpers/operationHelpers.js.map +1 -1
- package/dist/src/modular/helpers/typeHelpers.d.ts +1 -0
- package/dist/src/modular/helpers/typeHelpers.d.ts.map +1 -1
- package/dist/src/modular/helpers/typeHelpers.js +24 -19
- package/dist/src/modular/helpers/typeHelpers.js.map +1 -1
- package/dist/src/modular/modularCodeModel.d.ts +2 -2
- package/dist/src/modular/modularCodeModel.d.ts.map +1 -1
- package/dist/src/modular/serialization/buildSerializerFunction.d.ts +4 -0
- package/dist/src/modular/serialization/buildSerializerFunction.d.ts.map +1 -0
- package/dist/src/modular/serialization/buildSerializerFunction.js +160 -0
- package/dist/src/modular/serialization/buildSerializerFunction.js.map +1 -0
- package/dist/src/transform/transformSchemas.d.ts.map +1 -1
- package/dist/src/transform/transformSchemas.js +3 -0
- package/dist/src/transform/transformSchemas.js.map +1 -1
- package/dist/src/utils/importHelper.d.ts +10 -0
- package/dist/src/utils/importHelper.d.ts.map +1 -0
- package/dist/src/utils/importHelper.js +54 -0
- package/dist/src/utils/importHelper.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/src/contextManager.ts +99 -0
- package/src/index.ts +14 -2
- package/src/metaTree.ts +14 -0
- package/src/modular/buildClassicalClient.ts +5 -1
- package/src/modular/buildCodeModel.ts +22 -6
- package/src/modular/buildHelperSerializers.ts +71 -0
- package/src/modular/buildOperations.ts +7 -1
- package/src/modular/buildSerializeUtils.ts +19 -11
- package/src/modular/buildSubpathIndex.ts +10 -0
- package/src/modular/emitModels.ts +66 -16
- package/src/modular/helpers/operationHelpers.ts +198 -84
- package/src/modular/helpers/typeHelpers.ts +24 -17
- package/src/modular/modularCodeModel.ts +2 -2
- package/src/modular/serialization/buildSerializerFunction.ts +224 -0
- package/src/transform/transformSchemas.ts +3 -0
- package/src/utils/importHelper.ts +64 -0
|
@@ -6,7 +6,11 @@ import {
|
|
|
6
6
|
NameType,
|
|
7
7
|
OperationResponse
|
|
8
8
|
} from "@azure-tools/rlc-common";
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
SdkContext,
|
|
11
|
+
SdkModelType,
|
|
12
|
+
SdkType
|
|
13
|
+
} from "@azure-tools/typespec-client-generator-core";
|
|
10
14
|
import { NoTarget, Program } from "@typespec/compiler";
|
|
11
15
|
import {
|
|
12
16
|
FunctionDeclarationStructure,
|
|
@@ -14,7 +18,7 @@ import {
|
|
|
14
18
|
ParameterDeclarationStructure
|
|
15
19
|
} from "ts-morph";
|
|
16
20
|
import { reportDiagnostic } from "../../lib.js";
|
|
17
|
-
import { toPascalCase } from "../../utils/casingUtils.js";
|
|
21
|
+
import { toCamelCase, toPascalCase } from "../../utils/casingUtils.js";
|
|
18
22
|
import {
|
|
19
23
|
getCollectionFormatHelper,
|
|
20
24
|
hasCollectionFormatInfo
|
|
@@ -40,7 +44,7 @@ import {
|
|
|
40
44
|
getFixmeForMultilineDocs
|
|
41
45
|
} from "./docsHelpers.js";
|
|
42
46
|
import { getClassicalLayerPrefix, getOperationName } from "./namingHelpers.js";
|
|
43
|
-
import { buildType } from "./typeHelpers.js";
|
|
47
|
+
import { buildType, isTypeNullable } from "./typeHelpers.js";
|
|
44
48
|
|
|
45
49
|
function getRLCResponseType(rlcResponse?: OperationResponse) {
|
|
46
50
|
if (!rlcResponse?.responses) {
|
|
@@ -217,7 +221,8 @@ export function getDeserializePrivateFunction(
|
|
|
217
221
|
allParents.some((p) => p.type === "dict")) ||
|
|
218
222
|
response.isBinaryPayload
|
|
219
223
|
) {
|
|
220
|
-
|
|
224
|
+
// TODO: Fix this any cast when implementing handling dict.
|
|
225
|
+
statements.push(`return result.body as any`);
|
|
221
226
|
} else if (
|
|
222
227
|
deserializedType &&
|
|
223
228
|
properties.length > 0 &&
|
|
@@ -240,9 +245,7 @@ export function getDeserializePrivateFunction(
|
|
|
240
245
|
deserializedType,
|
|
241
246
|
deserializedRoot,
|
|
242
247
|
runtimeImports,
|
|
243
|
-
|
|
244
|
-
? !deserializedType.nullable
|
|
245
|
-
: false,
|
|
248
|
+
false, // TODO: Calculate if required
|
|
246
249
|
[deserializedType],
|
|
247
250
|
deserializedType.format
|
|
248
251
|
)}`
|
|
@@ -563,7 +566,7 @@ function buildHeaderParameter(
|
|
|
563
566
|
paramMap: string,
|
|
564
567
|
param: Parameter
|
|
565
568
|
): string {
|
|
566
|
-
if (!param.optional && param.type
|
|
569
|
+
if (!param.optional && isTypeNullable(param.type) === true) {
|
|
567
570
|
reportDiagnostic(program, {
|
|
568
571
|
code: "nullable-required-header",
|
|
569
572
|
target: NoTarget
|
|
@@ -574,7 +577,7 @@ function buildHeaderParameter(
|
|
|
574
577
|
if (param.optional) {
|
|
575
578
|
conditions.push(`options?.${param.clientName} !== undefined`);
|
|
576
579
|
}
|
|
577
|
-
if (param.type
|
|
580
|
+
if (isTypeNullable(param.type) === true) {
|
|
578
581
|
conditions.push(`options?.${param.clientName} !== null`);
|
|
579
582
|
}
|
|
580
583
|
return conditions.length > 0
|
|
@@ -596,7 +599,7 @@ function buildBodyParameter(
|
|
|
596
599
|
!bodyParameter.type.aliasType &&
|
|
597
600
|
!allParents.some((p) => p.type === "dict")
|
|
598
601
|
) {
|
|
599
|
-
const
|
|
602
|
+
const { propertiesStr: bodyParts } = getRequestModelMapping(
|
|
600
603
|
bodyParameter.type,
|
|
601
604
|
bodyParameter.clientName,
|
|
602
605
|
runtimeImports,
|
|
@@ -611,13 +614,32 @@ function buildBodyParameter(
|
|
|
611
614
|
} else if (bodyParameter && bodyParts.length === 0) {
|
|
612
615
|
return `\nbody: ${bodyParameter.clientName},`;
|
|
613
616
|
}
|
|
617
|
+
} else if (isDiscriminatedUnion(bodyParameter.type.tcgcType)) {
|
|
618
|
+
const serializerName = toCamelCase(`${bodyParameter.type.name}Serializer`);
|
|
619
|
+
addImportToSpecifier("modularModel", runtimeImports, serializerName);
|
|
620
|
+
return `\nbody: ${serializerName}(${bodyParameter.clientName}),`;
|
|
614
621
|
} else if (
|
|
615
622
|
(bodyParameter.type.type === "model" &&
|
|
616
623
|
(bodyParameter.type.aliasType ||
|
|
617
624
|
allParents.some((p) => p.type === "dict"))) ||
|
|
618
625
|
bodyParameter.type.type === "dict"
|
|
619
626
|
) {
|
|
620
|
-
|
|
627
|
+
const elementSerializerName =
|
|
628
|
+
bodyParameter.type.elementType?.type === "model"
|
|
629
|
+
? toCamelCase(`${bodyParameter.type.elementType.name}Serializer`)
|
|
630
|
+
: "";
|
|
631
|
+
let modelSerializerName = "";
|
|
632
|
+
|
|
633
|
+
if (bodyParameter.type.type !== "dict") {
|
|
634
|
+
modelSerializerName = toCamelCase(`${bodyParameter.type.name}Serializer`);
|
|
635
|
+
}
|
|
636
|
+
if (modelSerializerName) {
|
|
637
|
+
return `\nbody: ${modelSerializerName}(${bodyParameter.clientName}),`;
|
|
638
|
+
} else {
|
|
639
|
+
// Need to do this so that Records are compatible with additional properties of other types
|
|
640
|
+
// this should check for compatibility mode once we support the additionalProperties property
|
|
641
|
+
return `\nbody: serializeRecord(${bodyParameter.clientName} as any, ${elementSerializerName}) as any,`;
|
|
642
|
+
}
|
|
621
643
|
}
|
|
622
644
|
|
|
623
645
|
if (bodyParameter.type.type === "list") {
|
|
@@ -625,15 +647,20 @@ function buildBodyParameter(
|
|
|
625
647
|
bodyParameter.type.elementType?.type === "model" &&
|
|
626
648
|
!bodyParameter.type.elementType.aliasType
|
|
627
649
|
) {
|
|
628
|
-
const bodyParts =
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
650
|
+
const { propertiesStr: bodyParts, directAssignment } =
|
|
651
|
+
getRequestModelMapping(
|
|
652
|
+
bodyParameter.type.elementType,
|
|
653
|
+
"p",
|
|
654
|
+
runtimeImports,
|
|
655
|
+
[bodyParameter.type.elementType]
|
|
656
|
+
);
|
|
657
|
+
const mapBody =
|
|
658
|
+
directAssignment === true
|
|
659
|
+
? bodyParts.join(", ")
|
|
660
|
+
: `{ ${bodyParts.join(", ")} }`;
|
|
661
|
+
return `\nbody: (${bodyParameter.clientName} ?? []).map((p) => {
|
|
662
|
+
return ${mapBody};
|
|
663
|
+
}),`;
|
|
637
664
|
}
|
|
638
665
|
return `\nbody: ${bodyParameter.clientName},`;
|
|
639
666
|
}
|
|
@@ -764,12 +791,13 @@ function isRequired(param: Parameter | Property): param is RequiredType {
|
|
|
764
791
|
|
|
765
792
|
function getRequired(param: RequiredType, runtimeImports: RuntimeImports) {
|
|
766
793
|
if (param.type.type === "model") {
|
|
767
|
-
|
|
794
|
+
const { propertiesStr } = getRequestModelMapping(
|
|
768
795
|
param.type,
|
|
769
796
|
param.clientName,
|
|
770
797
|
runtimeImports,
|
|
771
798
|
[param.type]
|
|
772
|
-
)
|
|
799
|
+
);
|
|
800
|
+
return `"${param.restApiName}": { ${propertiesStr.join(",")} }`;
|
|
773
801
|
}
|
|
774
802
|
return `"${param.restApiName}": ${serializeRequestValue(
|
|
775
803
|
param.type,
|
|
@@ -818,12 +846,13 @@ function isOptional(param: Parameter | Property): param is OptionalType {
|
|
|
818
846
|
|
|
819
847
|
function getOptional(param: OptionalType, runtimeImports: RuntimeImports) {
|
|
820
848
|
if (param.type.type === "model") {
|
|
821
|
-
|
|
849
|
+
const { propertiesStr } = getRequestModelMapping(
|
|
822
850
|
param.type,
|
|
823
851
|
"options?." + param.clientName + "?",
|
|
824
852
|
runtimeImports,
|
|
825
853
|
[param.type]
|
|
826
|
-
)
|
|
854
|
+
);
|
|
855
|
+
return `"${param.restApiName}": { ${propertiesStr.join(", ")} }`;
|
|
827
856
|
}
|
|
828
857
|
if (
|
|
829
858
|
param.restApiName === "api-version" &&
|
|
@@ -893,7 +922,7 @@ function getPathParameters(operation: Operation) {
|
|
|
893
922
|
}
|
|
894
923
|
|
|
895
924
|
function getNullableCheck(name: string, type: Type) {
|
|
896
|
-
if (!type
|
|
925
|
+
if (!isTypeNullable(type)) {
|
|
897
926
|
return "";
|
|
898
927
|
}
|
|
899
928
|
|
|
@@ -905,33 +934,47 @@ function getNullableCheck(name: string, type: Type) {
|
|
|
905
934
|
* This function helps translating an HLC request to RLC request,
|
|
906
935
|
* extracting properties from body and headers and building the RLC response object
|
|
907
936
|
*/
|
|
937
|
+
interface RequestModelMappingResult {
|
|
938
|
+
propertiesStr: string[];
|
|
939
|
+
directAssignment?: boolean;
|
|
940
|
+
}
|
|
908
941
|
export function getRequestModelMapping(
|
|
909
942
|
modelPropertyType: Type,
|
|
910
943
|
propertyPath: string = "body",
|
|
911
944
|
runtimeImports: RuntimeImports,
|
|
912
945
|
typeStack: Type[] = []
|
|
913
|
-
) {
|
|
946
|
+
): RequestModelMappingResult {
|
|
914
947
|
const props: string[] = [];
|
|
915
948
|
const allParents = getAllAncestors(modelPropertyType);
|
|
916
949
|
const properties: Property[] =
|
|
917
950
|
getAllProperties(modelPropertyType, allParents) ?? [];
|
|
918
951
|
if (properties.length <= 0) {
|
|
919
|
-
return [];
|
|
952
|
+
return { propertiesStr: [] };
|
|
920
953
|
}
|
|
954
|
+
|
|
955
|
+
let serializerName =
|
|
956
|
+
"name" in modelPropertyType && modelPropertyType.name
|
|
957
|
+
? `${toCamelCase(modelPropertyType.name)}Serializer`
|
|
958
|
+
: undefined;
|
|
959
|
+
|
|
921
960
|
if (isSpecialHandledUnion(modelPropertyType)) {
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
"serialize"
|
|
925
|
-
)
|
|
926
|
-
const definition = `${deserializeFunctionName}(${propertyPath})`;
|
|
961
|
+
serializerName =
|
|
962
|
+
serializerName ??
|
|
963
|
+
getDeserializeFunctionName(modelPropertyType, "serialize");
|
|
964
|
+
const definition = `${serializerName}(${propertyPath})`;
|
|
927
965
|
props.push(definition);
|
|
928
|
-
return props;
|
|
966
|
+
return { propertiesStr: props, directAssignment: true };
|
|
929
967
|
}
|
|
930
968
|
for (const property of properties) {
|
|
931
969
|
if (property.readonly) {
|
|
932
970
|
continue;
|
|
933
971
|
}
|
|
934
|
-
const
|
|
972
|
+
const nullOrUndefinedPrefix = getPropertySerializationPrefix(
|
|
973
|
+
property,
|
|
974
|
+
propertyPath
|
|
975
|
+
);
|
|
976
|
+
|
|
977
|
+
const propertyFullName = getPropertyFullName(property, propertyPath);
|
|
935
978
|
if (property.type.type === "model") {
|
|
936
979
|
let definition;
|
|
937
980
|
if (property.type.coreTypeInfo === "ErrorType") {
|
|
@@ -951,29 +994,35 @@ export function getRequestModelMapping(
|
|
|
951
994
|
}`
|
|
952
995
|
}`;
|
|
953
996
|
} else if (isPolymorphicUnion(property.type)) {
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
}
|
|
958
|
-
const deserializeFunctionName = getDeserializeFunctionName(
|
|
959
|
-
property.type,
|
|
960
|
-
"serialize"
|
|
961
|
-
);
|
|
997
|
+
const deserializeFunctionName = property.type.name
|
|
998
|
+
? `${toCamelCase(property.type.name)}Serializer`
|
|
999
|
+
: getDeserializeFunctionName(property.type, "serialize");
|
|
962
1000
|
definition = `"${property.restApiName}": ${nullOrUndefinedPrefix}${deserializeFunctionName}(${propertyFullName})`;
|
|
963
1001
|
} else {
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
property.
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
1002
|
+
if (property.type.name) {
|
|
1003
|
+
serializerName = `${toCamelCase(property.type.name)}Serializer`;
|
|
1004
|
+
definition = `"${property.restApiName}": ${nullOrUndefinedPrefix}${serializerName}(${propertyPath}.${property.clientName})`;
|
|
1005
|
+
} else {
|
|
1006
|
+
const { propertiesStr, directAssignment } = getRequestModelMapping(
|
|
1007
|
+
property.type,
|
|
1008
|
+
`${propertyPath}.${property.clientName}${
|
|
1009
|
+
property.optional ? "?" : ""
|
|
1010
|
+
}`,
|
|
1011
|
+
runtimeImports,
|
|
1012
|
+
[...typeStack, property.type]
|
|
1013
|
+
);
|
|
1014
|
+
|
|
1015
|
+
const serializeContent =
|
|
1016
|
+
directAssignment === true
|
|
1017
|
+
? propertiesStr.join(",")
|
|
1018
|
+
: `{${propertiesStr.join(",")}}`;
|
|
1019
|
+
definition = `"${property.restApiName}": ${getNullableCheck(
|
|
1020
|
+
propertyFullName,
|
|
1021
|
+
property.type
|
|
1022
|
+
)} ${
|
|
1023
|
+
!property.optional ? "" : `!${propertyFullName} ? undefined :`
|
|
1024
|
+
} ${serializeContent}`;
|
|
1025
|
+
}
|
|
977
1026
|
}
|
|
978
1027
|
|
|
979
1028
|
props.push(definition);
|
|
@@ -987,6 +1036,23 @@ export function getRequestModelMapping(
|
|
|
987
1036
|
}`
|
|
988
1037
|
}`;
|
|
989
1038
|
props.push(definition);
|
|
1039
|
+
} else if (property.type.type === "dict") {
|
|
1040
|
+
const modelName = property.type.elementType?.name;
|
|
1041
|
+
serializerName = modelName ? `${toCamelCase(modelName)}Serializer` : "";
|
|
1042
|
+
// definition = `"${property.restApiName}": ${nullOrUndefinedPrefix}${serializerName}(${propertyPath}.${property.clientName})`;
|
|
1043
|
+
const statement = `"${property.restApiName}": ${nullOrUndefinedPrefix} serializeRecord(${propertyFullName} as any, ${serializerName}) as any`;
|
|
1044
|
+
// addImportToSpecifier(
|
|
1045
|
+
// "serializerHelpers",
|
|
1046
|
+
// runtimeImports,
|
|
1047
|
+
// "serializeRecord"
|
|
1048
|
+
// );
|
|
1049
|
+
|
|
1050
|
+
addImportToSpecifier("modularModel", runtimeImports, serializerName);
|
|
1051
|
+
props.push(statement);
|
|
1052
|
+
} else if (modelPropertyType.type === "enum") {
|
|
1053
|
+
props.push(
|
|
1054
|
+
`"${property.restApiName}": ${nullOrUndefinedPrefix}${propertyPath}.${property.clientName}`
|
|
1055
|
+
);
|
|
990
1056
|
} else {
|
|
991
1057
|
const dot = propertyPath.endsWith("?") ? "." : "";
|
|
992
1058
|
const clientValue = `${
|
|
@@ -1005,7 +1071,7 @@ export function getRequestModelMapping(
|
|
|
1005
1071
|
}
|
|
1006
1072
|
}
|
|
1007
1073
|
|
|
1008
|
-
return props;
|
|
1074
|
+
return { propertiesStr: props };
|
|
1009
1075
|
}
|
|
1010
1076
|
|
|
1011
1077
|
/**
|
|
@@ -1046,10 +1112,10 @@ export function getResponseMapping(
|
|
|
1046
1112
|
}`
|
|
1047
1113
|
}`;
|
|
1048
1114
|
} else if (isSpecialHandledUnion(property.type)) {
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1115
|
+
const nullOrUndefinedPrefix = getPropertySerializationPrefix(
|
|
1116
|
+
property,
|
|
1117
|
+
propertyPath
|
|
1118
|
+
);
|
|
1053
1119
|
const deserializeFunctionName = getDeserializeFunctionName(
|
|
1054
1120
|
property.type,
|
|
1055
1121
|
"deserialize"
|
|
@@ -1121,7 +1187,7 @@ export function deserializeResponseValue(
|
|
|
1121
1187
|
format?: string
|
|
1122
1188
|
): string {
|
|
1123
1189
|
const requiredPrefix = required === false ? `${restValue} === undefined` : "";
|
|
1124
|
-
const nullablePrefix = type
|
|
1190
|
+
const nullablePrefix = isTypeNullable(type) ? `${restValue} === null` : "";
|
|
1125
1191
|
const requiredOrNullablePrefix =
|
|
1126
1192
|
requiredPrefix !== "" && nullablePrefix !== ""
|
|
1127
1193
|
? `(${requiredPrefix} || ${nullablePrefix})`
|
|
@@ -1129,13 +1195,13 @@ export function deserializeResponseValue(
|
|
|
1129
1195
|
switch (type.type) {
|
|
1130
1196
|
case "datetime":
|
|
1131
1197
|
return required
|
|
1132
|
-
? type
|
|
1198
|
+
? isTypeNullable(type)
|
|
1133
1199
|
? `${restValue} === null ? null : new Date(${restValue})`
|
|
1134
1200
|
: `new Date(${restValue})`
|
|
1135
1201
|
: `${restValue} !== undefined? new Date(${restValue}): undefined`;
|
|
1136
1202
|
case "list": {
|
|
1137
1203
|
const prefix =
|
|
1138
|
-
required && !type
|
|
1204
|
+
required && !isTypeNullable(type)
|
|
1139
1205
|
? `${restValue}`
|
|
1140
1206
|
: `${requiredOrNullablePrefix} ? ${restValue} : ${restValue}`;
|
|
1141
1207
|
if (type.elementType?.type === "model") {
|
|
@@ -1148,7 +1214,7 @@ export function deserializeResponseValue(
|
|
|
1148
1214
|
)}}))`;
|
|
1149
1215
|
} else if (isPolymorphicUnion(type.elementType)) {
|
|
1150
1216
|
let nullOrUndefinedPrefix = "";
|
|
1151
|
-
if (type.elementType
|
|
1217
|
+
if (isTypeNullable(type.elementType)) {
|
|
1152
1218
|
nullOrUndefinedPrefix = `!p ? p :`;
|
|
1153
1219
|
}
|
|
1154
1220
|
const deserializeFunctionName = getDeserializeFunctionName(
|
|
@@ -1233,7 +1299,7 @@ export function serializeRequestValue(
|
|
|
1233
1299
|
): string {
|
|
1234
1300
|
const requiredPrefix =
|
|
1235
1301
|
required === false ? `${clientValue} === undefined` : "";
|
|
1236
|
-
const nullablePrefix = type
|
|
1302
|
+
const nullablePrefix = isTypeNullable(type) ? `${clientValue} === null` : "";
|
|
1237
1303
|
const requiredOrNullablePrefix =
|
|
1238
1304
|
requiredPrefix !== "" && nullablePrefix !== ""
|
|
1239
1305
|
? `(${requiredPrefix} || ${nullablePrefix})`
|
|
@@ -1252,20 +1318,32 @@ export function serializeRequestValue(
|
|
|
1252
1318
|
return `${clientValue}${required ? "" : "?"}.getTime()`;
|
|
1253
1319
|
case "rfc3339":
|
|
1254
1320
|
default:
|
|
1255
|
-
return `${clientValue}${
|
|
1321
|
+
return `${getNullableCheck(clientValue, type)} ${clientValue}${
|
|
1322
|
+
required ? "" : "?"
|
|
1323
|
+
}.toISOString()`;
|
|
1256
1324
|
}
|
|
1257
1325
|
case "list": {
|
|
1258
1326
|
const prefix =
|
|
1259
|
-
required && !type
|
|
1327
|
+
required && !isTypeNullable(type)
|
|
1260
1328
|
? `${clientValue}`
|
|
1261
1329
|
: `${requiredOrNullablePrefix}? ${clientValue}: ${clientValue}`;
|
|
1262
1330
|
if (type.elementType?.type === "model" && !type.elementType.aliasType) {
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1331
|
+
if (!type.elementType.name) {
|
|
1332
|
+
// If it is an anonymous model we need to serialize inline
|
|
1333
|
+
const { propertiesStr } = getRequestModelMapping(
|
|
1334
|
+
type.elementType,
|
|
1335
|
+
"p",
|
|
1336
|
+
runtimeImports,
|
|
1337
|
+
[...typeStack, type.elementType]
|
|
1338
|
+
);
|
|
1339
|
+
|
|
1340
|
+
return `${prefix}.map(p => ({${propertiesStr}}))`;
|
|
1341
|
+
} else {
|
|
1342
|
+
// When it is not anonymous we can hand it off to the serializer function
|
|
1343
|
+
return `${prefix}.map(${toCamelCase(
|
|
1344
|
+
type.elementType.name + "Serializer"
|
|
1345
|
+
)})`;
|
|
1346
|
+
}
|
|
1269
1347
|
} else if (
|
|
1270
1348
|
needsDeserialize(type.elementType) &&
|
|
1271
1349
|
!type.elementType?.aliasType
|
|
@@ -1274,7 +1352,7 @@ export function serializeRequestValue(
|
|
|
1274
1352
|
type.elementType!,
|
|
1275
1353
|
"p",
|
|
1276
1354
|
runtimeImports,
|
|
1277
|
-
|
|
1355
|
+
true,
|
|
1278
1356
|
[...typeStack, type.elementType!],
|
|
1279
1357
|
type.elementType?.format
|
|
1280
1358
|
)})`;
|
|
@@ -1283,13 +1361,12 @@ export function serializeRequestValue(
|
|
|
1283
1361
|
isPolymorphicUnion(type.elementType)
|
|
1284
1362
|
) {
|
|
1285
1363
|
let nullOrUndefinedPrefix = "";
|
|
1286
|
-
if (type.elementType
|
|
1364
|
+
if (isTypeNullable(type.elementType)) {
|
|
1287
1365
|
nullOrUndefinedPrefix = `!p ? p :`;
|
|
1288
1366
|
}
|
|
1289
|
-
const serializeFunctionName =
|
|
1290
|
-
type.elementType
|
|
1291
|
-
"serialize"
|
|
1292
|
-
);
|
|
1367
|
+
const serializeFunctionName = type.elementType?.name
|
|
1368
|
+
? `${toCamelCase(type.elementType.name)}Serializer`
|
|
1369
|
+
: getDeserializeFunctionName(type.elementType, "serialize");
|
|
1293
1370
|
return `${prefix}.map(p => ${nullOrUndefinedPrefix}${serializeFunctionName}(p))`;
|
|
1294
1371
|
} else {
|
|
1295
1372
|
return clientValue;
|
|
@@ -1299,7 +1376,10 @@ export function serializeRequestValue(
|
|
|
1299
1376
|
if (format !== "binary") {
|
|
1300
1377
|
addImportToSpecifier("coreUtil", runtimeImports, "uint8ArrayToString");
|
|
1301
1378
|
return required
|
|
1302
|
-
?
|
|
1379
|
+
? `${getNullableCheck(
|
|
1380
|
+
clientValue,
|
|
1381
|
+
type
|
|
1382
|
+
)} uint8ArrayToString(${clientValue}, "${
|
|
1303
1383
|
getEncodingFormat({ format }) ?? "base64"
|
|
1304
1384
|
}")`
|
|
1305
1385
|
: `${clientValue} !== undefined ? uint8ArrayToString(${clientValue}, "${
|
|
@@ -1311,10 +1391,9 @@ export function serializeRequestValue(
|
|
|
1311
1391
|
if (isNormalUnion(type)) {
|
|
1312
1392
|
return `${clientValue}`;
|
|
1313
1393
|
} else if (isSpecialHandledUnion(type)) {
|
|
1314
|
-
const serializeFunctionName =
|
|
1315
|
-
type
|
|
1316
|
-
"serialize"
|
|
1317
|
-
);
|
|
1394
|
+
const serializeFunctionName = type.name
|
|
1395
|
+
? `${toCamelCase(type.name)}Serializer`
|
|
1396
|
+
: getDeserializeFunctionName(type, "serialize");
|
|
1318
1397
|
return `${serializeFunctionName}(${clientValue})`;
|
|
1319
1398
|
} else {
|
|
1320
1399
|
return `${clientValue} as any`;
|
|
@@ -1399,3 +1478,38 @@ export function getAllAncestors(type: Type): Type[] {
|
|
|
1399
1478
|
});
|
|
1400
1479
|
return ancestors;
|
|
1401
1480
|
}
|
|
1481
|
+
|
|
1482
|
+
export function getPropertySerializationPrefix(
|
|
1483
|
+
modularType: Property | Parameter,
|
|
1484
|
+
propertyPath?: string
|
|
1485
|
+
) {
|
|
1486
|
+
const propertyFullName = getPropertyFullName(modularType, propertyPath);
|
|
1487
|
+
if (modularType.optional || isTypeNullable(modularType.type)) {
|
|
1488
|
+
return `!${propertyFullName} ? ${propertyFullName} :`;
|
|
1489
|
+
}
|
|
1490
|
+
|
|
1491
|
+
return "";
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
export function getPropertyFullName(
|
|
1495
|
+
modularType: Property | Parameter,
|
|
1496
|
+
propertyPath?: string
|
|
1497
|
+
) {
|
|
1498
|
+
let fullName = `${modularType.clientName}`;
|
|
1499
|
+
if (propertyPath) {
|
|
1500
|
+
fullName = `${propertyPath}.${modularType.clientName}`;
|
|
1501
|
+
}
|
|
1502
|
+
return fullName;
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1505
|
+
export function isDiscriminatedUnion(type?: SdkType): type is SdkModelType {
|
|
1506
|
+
if (!type) {
|
|
1507
|
+
return false;
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
return Boolean(
|
|
1511
|
+
type.kind === "model" &&
|
|
1512
|
+
type.discriminatorProperty &&
|
|
1513
|
+
type.discriminatedSubtypes
|
|
1514
|
+
);
|
|
1515
|
+
}
|
|
@@ -72,7 +72,7 @@ export function getType(type: Type, format?: string): TypeMetadata {
|
|
|
72
72
|
const simpleType = simpleTypeMap[type.type];
|
|
73
73
|
if (simpleType) {
|
|
74
74
|
const typeMetadata: TypeMetadata = { ...simpleType };
|
|
75
|
-
if (type
|
|
75
|
+
if (isTypeNullable(type)) {
|
|
76
76
|
typeMetadata.nullable = true;
|
|
77
77
|
typeMetadata.name = handleNullableTypeName(typeMetadata);
|
|
78
78
|
}
|
|
@@ -102,7 +102,7 @@ export function getType(type: Type, format?: string): TypeMetadata {
|
|
|
102
102
|
return handleDictType(type);
|
|
103
103
|
|
|
104
104
|
case "never":
|
|
105
|
-
return { name: "never", nullable: type
|
|
105
|
+
return { name: "never", nullable: isTypeNullable(type) };
|
|
106
106
|
default:
|
|
107
107
|
throw new Error(`Unsupported type ${type.type}`);
|
|
108
108
|
}
|
|
@@ -118,9 +118,9 @@ function handleConstantType(type: Type): TypeMetadata {
|
|
|
118
118
|
}
|
|
119
119
|
const name = handleNullableTypeName({
|
|
120
120
|
name: typeName,
|
|
121
|
-
nullable: type
|
|
121
|
+
nullable: isTypeNullable(type)
|
|
122
122
|
});
|
|
123
|
-
return { name, nullable: type
|
|
123
|
+
return { name, nullable: isTypeNullable(type) };
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
/**
|
|
@@ -137,20 +137,24 @@ function handleEnumType(type: Type): TypeMetadata {
|
|
|
137
137
|
return getType(e as Type).name;
|
|
138
138
|
})
|
|
139
139
|
.join(" | ")}`,
|
|
140
|
-
nullable: type
|
|
140
|
+
nullable: isTypeNullable(type)
|
|
141
141
|
};
|
|
142
142
|
}
|
|
143
143
|
const name = handleNullableTypeName({
|
|
144
144
|
name: type.name,
|
|
145
|
-
nullable: type
|
|
145
|
+
nullable: isTypeNullable(type)
|
|
146
146
|
});
|
|
147
147
|
return {
|
|
148
148
|
name,
|
|
149
|
-
nullable: type
|
|
149
|
+
nullable: isTypeNullable(type),
|
|
150
150
|
originModule: "models.js"
|
|
151
151
|
};
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
+
export function isTypeNullable(type: Type) {
|
|
155
|
+
return Boolean(type.tcgcType?.kind === "nullable");
|
|
156
|
+
}
|
|
157
|
+
|
|
154
158
|
/**
|
|
155
159
|
* Handles the conversion of list types to TypeScript representation metadata.
|
|
156
160
|
*/
|
|
@@ -164,14 +168,17 @@ function handleListType(type: Type): TypeMetadata {
|
|
|
164
168
|
type.elementType.format
|
|
165
169
|
);
|
|
166
170
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
+
let name = `${elementTypeMetadata.name}[]`;
|
|
172
|
+
|
|
173
|
+
const isTypeNullable = type.tcgcType?.kind === "nullable";
|
|
174
|
+
|
|
175
|
+
if (isTypeNullable) {
|
|
176
|
+
name = `(${name} | null)`;
|
|
177
|
+
}
|
|
171
178
|
|
|
172
179
|
const listTypeMetadata: TypeMetadata = {
|
|
173
180
|
name: name,
|
|
174
|
-
nullable:
|
|
181
|
+
nullable: isTypeNullable,
|
|
175
182
|
originModule: type.elementType?.type === "model" ? "models.js" : undefined
|
|
176
183
|
};
|
|
177
184
|
|
|
@@ -185,11 +192,11 @@ function handleModelType(type: Type): TypeMetadata {
|
|
|
185
192
|
let name = !type.name ? handleAnomymousModelName(type) : type.name;
|
|
186
193
|
name = handleNullableTypeName({
|
|
187
194
|
name,
|
|
188
|
-
nullable: type
|
|
195
|
+
nullable: isTypeNullable(type)
|
|
189
196
|
});
|
|
190
197
|
return {
|
|
191
198
|
name,
|
|
192
|
-
nullable: type
|
|
199
|
+
nullable: isTypeNullable(type),
|
|
193
200
|
originModule: "models.js"
|
|
194
201
|
};
|
|
195
202
|
}
|
|
@@ -200,10 +207,10 @@ function handleModelType(type: Type): TypeMetadata {
|
|
|
200
207
|
function handleDurationType(type: Type, format?: string): TypeMetadata {
|
|
201
208
|
const isFormatSeconds = format === "seconds";
|
|
202
209
|
let name = isFormatSeconds ? "number" : "string";
|
|
203
|
-
name = handleNullableTypeName({ name, nullable: type
|
|
210
|
+
name = handleNullableTypeName({ name, nullable: isTypeNullable(type) });
|
|
204
211
|
return {
|
|
205
212
|
name,
|
|
206
|
-
nullable: type
|
|
213
|
+
nullable: isTypeNullable(type)
|
|
207
214
|
};
|
|
208
215
|
}
|
|
209
216
|
|
|
@@ -222,7 +229,7 @@ function handleCombinedType(type: Type): TypeMetadata {
|
|
|
222
229
|
return `${sdkType}`;
|
|
223
230
|
})
|
|
224
231
|
.join(" | ");
|
|
225
|
-
return { name: `(${name})`, nullable: type
|
|
232
|
+
return { name: `(${name})`, nullable: isTypeNullable(type) };
|
|
226
233
|
}
|
|
227
234
|
|
|
228
235
|
/**
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
SdkBodyParameter,
|
|
9
9
|
SdkType
|
|
10
10
|
} from "@azure-tools/typespec-client-generator-core";
|
|
11
|
-
import { UsageFlags } from "@typespec/compiler";
|
|
11
|
+
import { UsageFlags, Type as TypespecType } from "@typespec/compiler";
|
|
12
12
|
import { Project } from "ts-morph";
|
|
13
13
|
|
|
14
14
|
export interface ModularOptions {
|
|
@@ -75,7 +75,6 @@ export interface EnumValue {
|
|
|
75
75
|
description: string;
|
|
76
76
|
}
|
|
77
77
|
export interface Type {
|
|
78
|
-
nullable?: boolean;
|
|
79
78
|
name?: string;
|
|
80
79
|
description?: string;
|
|
81
80
|
type:
|
|
@@ -120,6 +119,7 @@ export interface Type {
|
|
|
120
119
|
discriminatorValue?: string;
|
|
121
120
|
isPolymorphicBaseModel?: boolean;
|
|
122
121
|
tcgcType?: SdkType;
|
|
122
|
+
__raw?: TypespecType;
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
export interface Client {
|