@azure-tools/typespec-ts 0.19.0 → 0.20.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 +11 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +8 -4
- package/dist/src/index.js.map +1 -1
- package/dist/src/lib.d.ts +28 -1
- package/dist/src/lib.d.ts.map +1 -1
- package/dist/src/lib.js +18 -0
- package/dist/src/lib.js.map +1 -1
- package/dist/src/modular/buildClassicalClient.js +9 -0
- package/dist/src/modular/buildClassicalClient.js.map +1 -1
- package/dist/src/modular/buildClassicalOperationGroups.d.ts.map +1 -1
- package/dist/src/modular/buildClassicalOperationGroups.js +5 -1
- package/dist/src/modular/buildClassicalOperationGroups.js.map +1 -1
- package/dist/src/modular/buildCodeModel.d.ts.map +1 -1
- package/dist/src/modular/buildCodeModel.js +81 -65
- package/dist/src/modular/buildCodeModel.js.map +1 -1
- package/dist/src/modular/buildOperations.d.ts +1 -0
- package/dist/src/modular/buildOperations.d.ts.map +1 -1
- package/dist/src/modular/buildOperations.js +30 -13
- package/dist/src/modular/buildOperations.js.map +1 -1
- package/dist/src/modular/buildPagingFiles.d.ts +4 -0
- package/dist/src/modular/buildPagingFiles.d.ts.map +1 -0
- package/dist/src/modular/buildPagingFiles.js +333 -0
- package/dist/src/modular/buildPagingFiles.js.map +1 -0
- package/dist/src/modular/buildProjectFiles.d.ts.map +1 -1
- package/dist/src/modular/buildProjectFiles.js +15 -8
- package/dist/src/modular/buildProjectFiles.js.map +1 -1
- package/dist/src/modular/buildSubpathIndex.d.ts.map +1 -1
- package/dist/src/modular/buildSubpathIndex.js +10 -1
- package/dist/src/modular/buildSubpathIndex.js.map +1 -1
- package/dist/src/modular/emitModels.d.ts +21 -2
- package/dist/src/modular/emitModels.d.ts.map +1 -1
- package/dist/src/modular/emitModels.js +26 -5
- package/dist/src/modular/emitModels.js.map +1 -1
- package/dist/src/modular/helpers/operationHelpers.d.ts +7 -4
- package/dist/src/modular/helpers/operationHelpers.d.ts.map +1 -1
- package/dist/src/modular/helpers/operationHelpers.js +135 -99
- package/dist/src/modular/helpers/operationHelpers.js.map +1 -1
- package/dist/src/modular/helpers/typeHelpers.d.ts.map +1 -1
- package/dist/src/modular/helpers/typeHelpers.js +2 -1
- package/dist/src/modular/helpers/typeHelpers.js.map +1 -1
- package/dist/src/modular/modularCodeModel.d.ts +2 -1
- package/dist/src/modular/modularCodeModel.d.ts.map +1 -1
- package/dist/src/transform/transformApiVersionInfo.d.ts.map +1 -1
- package/dist/src/transform/transformApiVersionInfo.js +16 -10
- package/dist/src/transform/transformApiVersionInfo.js.map +1 -1
- package/dist/src/transform/transformHelperFunctionDetails.d.ts +1 -1
- package/dist/src/transform/transformHelperFunctionDetails.d.ts.map +1 -1
- package/dist/src/transform/transformHelperFunctionDetails.js +11 -16
- package/dist/src/transform/transformHelperFunctionDetails.js.map +1 -1
- package/dist/src/transform/transformParameters.d.ts.map +1 -1
- package/dist/src/transform/transformParameters.js +19 -14
- package/dist/src/transform/transformParameters.js.map +1 -1
- package/dist/src/transform/transformResponses.js +5 -3
- package/dist/src/transform/transformResponses.js.map +1 -1
- package/dist/src/transform/transformSchemas.d.ts.map +1 -1
- package/dist/src/transform/transformSchemas.js +32 -17
- package/dist/src/transform/transformSchemas.js.map +1 -1
- package/dist/src/transform/transfromRLCOptions.js.map +1 -1
- package/dist/src/utils/emitUtil.js +1 -1
- package/dist/src/utils/emitUtil.js.map +1 -1
- package/dist/src/utils/modelUtils.d.ts +1 -0
- package/dist/src/utils/modelUtils.d.ts.map +1 -1
- package/dist/src/utils/modelUtils.js +103 -57
- package/dist/src/utils/modelUtils.js.map +1 -1
- package/dist/src/utils/operationUtil.d.ts +3 -1
- package/dist/src/utils/operationUtil.d.ts.map +1 -1
- package/dist/src/utils/operationUtil.js +21 -7
- package/dist/src/utils/operationUtil.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +18 -19
- package/src/index.ts +20 -4
- package/src/lib.ts +18 -0
- package/src/modular/buildClassicalClient.ts +15 -0
- package/src/modular/buildClassicalOperationGroups.ts +17 -1
- package/src/modular/buildCodeModel.ts +100 -77
- package/src/modular/buildOperations.ts +55 -13
- package/src/modular/buildPagingFiles.ts +356 -0
- package/src/modular/buildProjectFiles.ts +17 -15
- package/src/modular/buildSubpathIndex.ts +12 -1
- package/src/modular/emitModels.ts +29 -5
- package/src/modular/helpers/operationHelpers.ts +130 -119
- package/src/modular/helpers/typeHelpers.ts +8 -6
- package/src/modular/modularCodeModel.ts +2 -1
- package/src/transform/transformApiVersionInfo.ts +25 -15
- package/src/transform/transformHelperFunctionDetails.ts +19 -21
- package/src/transform/transformParameters.ts +33 -14
- package/src/transform/transformResponses.ts +8 -3
- package/src/transform/transformSchemas.ts +33 -17
- package/src/transform/transfromRLCOptions.ts +2 -2
- package/src/utils/emitUtil.ts +1 -1
- package/src/utils/modelUtils.ts +119 -63
- package/src/utils/operationUtil.ts +26 -10
package/src/utils/modelUtils.ts
CHANGED
|
@@ -55,13 +55,14 @@ import {
|
|
|
55
55
|
Schema,
|
|
56
56
|
SchemaContext
|
|
57
57
|
} from "@azure-tools/rlc-common";
|
|
58
|
-
import { getResourceOperation } from "@typespec/rest";
|
|
59
58
|
import {
|
|
60
59
|
getHeaderFieldName,
|
|
61
60
|
getPathParamName,
|
|
62
61
|
getQueryParamName,
|
|
63
62
|
isStatusCode,
|
|
64
|
-
HttpOperation
|
|
63
|
+
HttpOperation,
|
|
64
|
+
createMetadataInfo,
|
|
65
|
+
Visibility
|
|
65
66
|
} from "@typespec/http";
|
|
66
67
|
import { getPagedResult, isFixed } from "@azure-tools/typespec-azure-core";
|
|
67
68
|
import { extractPagedMetadataNested } from "./operationUtil.js";
|
|
@@ -190,7 +191,7 @@ export function getSchemaForType(
|
|
|
190
191
|
} else if (type.kind === "UnionVariant") {
|
|
191
192
|
return getSchemaForUnionVariant(dpgContext, type, usage);
|
|
192
193
|
} else if (type.kind === "Enum") {
|
|
193
|
-
return getSchemaForEnum(
|
|
194
|
+
return getSchemaForEnum(dpgContext, type);
|
|
194
195
|
} else if (type.kind === "Scalar") {
|
|
195
196
|
return getSchemaForScalar(dpgContext, type, relevantProperty);
|
|
196
197
|
} else if (type.kind === "EnumMember") {
|
|
@@ -634,9 +635,9 @@ function getSchemaForModel(
|
|
|
634
635
|
modelSchema.discriminator = {
|
|
635
636
|
name: propertyName,
|
|
636
637
|
type: "string",
|
|
637
|
-
required: true,
|
|
638
638
|
description: `Discriminator property for ${model.name}.`
|
|
639
639
|
};
|
|
640
|
+
modelSchema.discriminatorValue = propertyName;
|
|
640
641
|
|
|
641
642
|
modelSchema.isPolyParent = true;
|
|
642
643
|
}
|
|
@@ -678,15 +679,18 @@ function getSchemaForModel(
|
|
|
678
679
|
propSchema
|
|
679
680
|
);
|
|
680
681
|
propSchema.usage = usage;
|
|
681
|
-
// Use the description from ModelProperty not
|
|
682
|
+
// Use the description from ModelProperty not derived from Model Type
|
|
682
683
|
propSchema.description = propertyDescription;
|
|
683
684
|
modelSchema.properties[name] = propSchema;
|
|
684
685
|
// if this property is a discriminator property, remove it to keep autorest validation happy
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
686
|
+
const { propertyName } = getDiscriminator(program, model) || {};
|
|
687
|
+
if (
|
|
688
|
+
propertyName &&
|
|
689
|
+
name === `"${propertyName}"` &&
|
|
690
|
+
modelSchema.discriminator
|
|
691
|
+
) {
|
|
692
|
+
modelSchema.discriminator.type = propSchema.typeName ?? propSchema.type;
|
|
693
|
+
continue;
|
|
690
694
|
}
|
|
691
695
|
|
|
692
696
|
// Apply decorators on the property to the type's schema
|
|
@@ -815,26 +819,28 @@ function getSchemaForEnumMember(program: Program, e: EnumMember) {
|
|
|
815
819
|
return { type, description: getDoc(program, e), isConstant: true };
|
|
816
820
|
}
|
|
817
821
|
|
|
818
|
-
function getSchemaForEnum(
|
|
822
|
+
function getSchemaForEnum(dpgContext: SdkContext, e: Enum) {
|
|
819
823
|
const values = [];
|
|
820
824
|
const type = enumMemberType(e.members.values().next().value);
|
|
821
825
|
for (const option of e.members.values()) {
|
|
822
826
|
if (type !== enumMemberType(option)) {
|
|
823
|
-
reportDiagnostic(program, {
|
|
827
|
+
reportDiagnostic(dpgContext.program, {
|
|
828
|
+
code: "union-unsupported",
|
|
829
|
+
target: e
|
|
830
|
+
});
|
|
824
831
|
continue;
|
|
825
832
|
}
|
|
826
833
|
|
|
827
|
-
values.push(
|
|
834
|
+
values.push(getSchemaForType(dpgContext, option));
|
|
828
835
|
}
|
|
829
836
|
|
|
830
|
-
const schema: any = { type, description: getDoc(program, e) };
|
|
837
|
+
const schema: any = { type, description: getDoc(dpgContext.program, e) };
|
|
831
838
|
if (values.length > 0) {
|
|
832
839
|
schema.enum = values;
|
|
833
|
-
schema.type =
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
if (!isFixed(program, e)) {
|
|
840
|
+
schema.type = values
|
|
841
|
+
.map((item) => `${getTypeName(item, [SchemaContext.Input]) ?? item}`)
|
|
842
|
+
.join(" | ");
|
|
843
|
+
if (!isFixed(dpgContext.program, e)) {
|
|
838
844
|
schema.name = "string";
|
|
839
845
|
schema.typeName = "string";
|
|
840
846
|
}
|
|
@@ -1048,7 +1054,7 @@ function getSchemaForStdScalar(
|
|
|
1048
1054
|
case "safeint":
|
|
1049
1055
|
return applyIntrinsicDecorators(program, type, {
|
|
1050
1056
|
type: "number",
|
|
1051
|
-
format: "
|
|
1057
|
+
format: "safeint"
|
|
1052
1058
|
});
|
|
1053
1059
|
case "uint8":
|
|
1054
1060
|
return applyIntrinsicDecorators(program, type, {
|
|
@@ -1073,18 +1079,44 @@ function getSchemaForStdScalar(
|
|
|
1073
1079
|
case "float64":
|
|
1074
1080
|
return applyIntrinsicDecorators(program, type, {
|
|
1075
1081
|
type: "number",
|
|
1076
|
-
format: "
|
|
1082
|
+
format: "float64"
|
|
1077
1083
|
});
|
|
1078
1084
|
case "float32":
|
|
1079
1085
|
return applyIntrinsicDecorators(program, type, {
|
|
1080
1086
|
type: "number",
|
|
1081
|
-
format: "
|
|
1087
|
+
format: "float32"
|
|
1082
1088
|
});
|
|
1083
1089
|
case "float":
|
|
1084
1090
|
return applyIntrinsicDecorators(program, type, {
|
|
1085
1091
|
type: "number",
|
|
1086
1092
|
format: "float"
|
|
1087
1093
|
});
|
|
1094
|
+
case "decimal":
|
|
1095
|
+
reportDiagnostic(program, {
|
|
1096
|
+
code: "decimal-to-number",
|
|
1097
|
+
format: {
|
|
1098
|
+
propertyName: relevantProperty?.name ?? ""
|
|
1099
|
+
},
|
|
1100
|
+
target: relevantProperty ?? type
|
|
1101
|
+
});
|
|
1102
|
+
return applyIntrinsicDecorators(program, type, {
|
|
1103
|
+
type: "number",
|
|
1104
|
+
format: "decimal",
|
|
1105
|
+
description: "decimal"
|
|
1106
|
+
});
|
|
1107
|
+
case "decimal128":
|
|
1108
|
+
reportDiagnostic(program, {
|
|
1109
|
+
code: "decimal-to-number",
|
|
1110
|
+
format: {
|
|
1111
|
+
propertyName: relevantProperty?.name ?? ""
|
|
1112
|
+
},
|
|
1113
|
+
target: relevantProperty ?? type
|
|
1114
|
+
});
|
|
1115
|
+
return applyIntrinsicDecorators(program, type, {
|
|
1116
|
+
type: "number",
|
|
1117
|
+
format: "decimal128",
|
|
1118
|
+
description: "decimal128"
|
|
1119
|
+
});
|
|
1088
1120
|
case "string":
|
|
1089
1121
|
if (format === "binary") {
|
|
1090
1122
|
return {
|
|
@@ -1167,6 +1199,37 @@ export function getTypeName(schema: Schema, usage?: SchemaContext[]): string {
|
|
|
1167
1199
|
return getPriorityName(schema, usage) ?? schema.type ?? "any";
|
|
1168
1200
|
}
|
|
1169
1201
|
|
|
1202
|
+
export function getSerializeTypeName(
|
|
1203
|
+
program: Program,
|
|
1204
|
+
schema: Schema,
|
|
1205
|
+
usage?: SchemaContext[]
|
|
1206
|
+
): string {
|
|
1207
|
+
const typeName = getTypeName(schema, usage);
|
|
1208
|
+
const formattedName = (schema.alias ?? typeName).replace(
|
|
1209
|
+
"Date | string",
|
|
1210
|
+
"string"
|
|
1211
|
+
);
|
|
1212
|
+
const canSerialize = schema.enum
|
|
1213
|
+
? schema.enum.every((type) => {
|
|
1214
|
+
return isSerializable(type) || type.type === "null";
|
|
1215
|
+
})
|
|
1216
|
+
: isSerializable(schema);
|
|
1217
|
+
if (canSerialize) {
|
|
1218
|
+
return schema.alias ? typeName : formattedName;
|
|
1219
|
+
}
|
|
1220
|
+
reportDiagnostic(program, {
|
|
1221
|
+
code: "unable-serialized-type",
|
|
1222
|
+
format: { type: typeName },
|
|
1223
|
+
target: NoTarget
|
|
1224
|
+
});
|
|
1225
|
+
return "string";
|
|
1226
|
+
function isSerializable(type: any) {
|
|
1227
|
+
return (
|
|
1228
|
+
["string", "number", "boolean"].includes(type.type) || type.isConstant
|
|
1229
|
+
);
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1170
1233
|
export function getImportedModelName(
|
|
1171
1234
|
schema: Schema,
|
|
1172
1235
|
usage?: SchemaContext[]
|
|
@@ -1234,7 +1297,26 @@ function getPriorityName(schema: Schema, usage?: SchemaContext[]): string {
|
|
|
1234
1297
|
|
|
1235
1298
|
function getEnumStringDescription(type: any) {
|
|
1236
1299
|
if (type.name === "string" && type.enum && type.enum.length > 0) {
|
|
1237
|
-
return `Possible values: ${type.enum
|
|
1300
|
+
return `Possible values: ${type.enum
|
|
1301
|
+
.map((e: Schema) => {
|
|
1302
|
+
return e.type;
|
|
1303
|
+
})
|
|
1304
|
+
.join(", ")}`;
|
|
1305
|
+
}
|
|
1306
|
+
return undefined;
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
function getDecimalDescription(type: any) {
|
|
1310
|
+
if (
|
|
1311
|
+
(type.format === "decimal" || type.format === "decimal128") &&
|
|
1312
|
+
type.type === "number"
|
|
1313
|
+
) {
|
|
1314
|
+
return `NOTE: This property is represented as a 'number' in JavaScript, but it corresponds to a 'decimal' type in other languages.
|
|
1315
|
+
Due to the inherent limitations of floating-point arithmetic in JavaScript, precision issues may arise when performing arithmetic operations.
|
|
1316
|
+
If your application requires high precision for arithmetic operations or when round-tripping data back to other languages, consider using a library like decimal.js, which provides an arbitrary-precision Decimal type.
|
|
1317
|
+
For simpler cases, where you need to control the number of decimal places for display purposes, you can use the 'toFixed()' method. However, be aware that 'toFixed()' returns a string and may not be suitable for all arithmetic precision requirements.
|
|
1318
|
+
Always be cautious with direct arithmetic operations and consider implementing appropriate rounding strategies to maintain accuracy.
|
|
1319
|
+
`;
|
|
1238
1320
|
}
|
|
1239
1321
|
return undefined;
|
|
1240
1322
|
}
|
|
@@ -1246,7 +1328,8 @@ export function getFormattedPropertyDoc(
|
|
|
1246
1328
|
sperator: string = "\n\n"
|
|
1247
1329
|
) {
|
|
1248
1330
|
const propertyDoc = getDoc(program, type);
|
|
1249
|
-
const enhancedDocFromType =
|
|
1331
|
+
const enhancedDocFromType =
|
|
1332
|
+
getEnumStringDescription(schemaType) ?? getDecimalDescription(schemaType);
|
|
1250
1333
|
if (propertyDoc && enhancedDocFromType) {
|
|
1251
1334
|
return `${propertyDoc}${sperator}${enhancedDocFromType}`;
|
|
1252
1335
|
}
|
|
@@ -1257,41 +1340,14 @@ export function getBodyType(
|
|
|
1257
1340
|
program: Program,
|
|
1258
1341
|
route: HttpOperation
|
|
1259
1342
|
): Type | undefined {
|
|
1260
|
-
|
|
1261
|
-
if (bodyModel
|
|
1262
|
-
const
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
if (resp && resp.responses && resp.responses.length > 0) {
|
|
1269
|
-
const responseBody = resp.responses[0]?.body;
|
|
1270
|
-
if (responseBody) {
|
|
1271
|
-
const bodyTypeInResponse = getEffectiveModelFromType(
|
|
1272
|
-
program,
|
|
1273
|
-
|
|
1274
|
-
responseBody.type
|
|
1275
|
-
);
|
|
1276
|
-
// response body type is reosurce type, and request body type (if templated) contains resource type
|
|
1277
|
-
if (
|
|
1278
|
-
bodyTypeInResponse === resourceType &&
|
|
1279
|
-
bodyModel.templateMapper &&
|
|
1280
|
-
bodyModel.templateMapper.args &&
|
|
1281
|
-
bodyModel.templateMapper.args.some((it) => {
|
|
1282
|
-
return it.kind === "Model" || it.kind === "Union"
|
|
1283
|
-
? it === bodyTypeInResponse
|
|
1284
|
-
: false;
|
|
1285
|
-
})
|
|
1286
|
-
) {
|
|
1287
|
-
bodyModel = resourceType;
|
|
1288
|
-
}
|
|
1289
|
-
}
|
|
1290
|
-
}
|
|
1291
|
-
}
|
|
1292
|
-
if (resourceType && bodyModel.name === "") {
|
|
1293
|
-
bodyModel = resourceType;
|
|
1294
|
-
}
|
|
1343
|
+
const bodyModel = route.parameters.body?.type;
|
|
1344
|
+
if (bodyModel) {
|
|
1345
|
+
const metadataInfo = createMetadataInfo(program);
|
|
1346
|
+
const payloadType = metadataInfo.getEffectivePayloadType(
|
|
1347
|
+
bodyModel,
|
|
1348
|
+
Visibility.All
|
|
1349
|
+
);
|
|
1350
|
+
return payloadType;
|
|
1295
1351
|
}
|
|
1296
1352
|
return bodyModel;
|
|
1297
1353
|
}
|
|
@@ -1444,7 +1500,7 @@ export function getModelInlineSigniture(
|
|
|
1444
1500
|
schema: ObjectSchema,
|
|
1445
1501
|
options: { importedModels?: Set<string>; usage?: SchemaContext[] } = {}
|
|
1446
1502
|
) {
|
|
1447
|
-
let
|
|
1503
|
+
let schemaSignature = `{`;
|
|
1448
1504
|
for (const propName in schema.properties) {
|
|
1449
1505
|
const propType = schema.properties[propName]!;
|
|
1450
1506
|
const propTypeName = getTypeName(propType, options.usage);
|
|
@@ -1461,9 +1517,9 @@ export function getModelInlineSigniture(
|
|
|
1461
1517
|
}
|
|
1462
1518
|
}
|
|
1463
1519
|
const isOptional = propType.required ? "" : "?";
|
|
1464
|
-
|
|
1520
|
+
schemaSignature += `${propName}${isOptional}: ${propTypeName};`;
|
|
1465
1521
|
}
|
|
1466
1522
|
|
|
1467
|
-
|
|
1468
|
-
return
|
|
1523
|
+
schemaSignature += `}`;
|
|
1524
|
+
return schemaSignature;
|
|
1469
1525
|
}
|
|
@@ -179,17 +179,22 @@ export function isDefinedStatusCode(statusCodes: HttpStatusCodesEntry) {
|
|
|
179
179
|
export function isBinaryPayload(
|
|
180
180
|
dpgContext: SdkContext,
|
|
181
181
|
body: Type,
|
|
182
|
-
contentType: string
|
|
182
|
+
contentType: string | string[]
|
|
183
183
|
) {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
contentType
|
|
187
|
-
|
|
188
|
-
contentType
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
184
|
+
const allContentTypes = Array.isArray(contentType)
|
|
185
|
+
? contentType
|
|
186
|
+
: [contentType];
|
|
187
|
+
for (const type of allContentTypes) {
|
|
188
|
+
const contentType = `"${type}"`;
|
|
189
|
+
if (
|
|
190
|
+
contentType !== `"application/json"` &&
|
|
191
|
+
contentType !== `"text/plain"` &&
|
|
192
|
+
contentType !== `"application/json" | "text/plain"` &&
|
|
193
|
+
contentType !== `"text/plain" | "application/json"` &&
|
|
194
|
+
isByteOrByteUnion(dpgContext, body)
|
|
195
|
+
) {
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
193
198
|
}
|
|
194
199
|
return false;
|
|
195
200
|
}
|
|
@@ -530,3 +535,14 @@ export function isIgnoredHeaderParam(param: HttpOperationParameter) {
|
|
|
530
535
|
))
|
|
531
536
|
);
|
|
532
537
|
}
|
|
538
|
+
|
|
539
|
+
export function parseNextLinkName(
|
|
540
|
+
paged: PagedResultMetadata
|
|
541
|
+
): string | undefined {
|
|
542
|
+
return paged.nextLinkProperty?.name;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
export function parseItemName(paged: PagedResultMetadata): string | undefined {
|
|
546
|
+
// TODO: support the nested item names
|
|
547
|
+
return (paged.itemsSegments ?? [])[0];
|
|
548
|
+
}
|