@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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@azure-tools/typespec-ts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.47.0",
|
|
4
4
|
"description": "An experimental TypeSpec emitter for TypeScript RLC",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -18,14 +18,14 @@
|
|
|
18
18
|
"license": "MIT",
|
|
19
19
|
"devDependencies": {
|
|
20
20
|
"@azure-rest/core-client": "^2.3.1",
|
|
21
|
-
"@typespec/http-specs": "0.1.0-alpha.29-dev.
|
|
22
|
-
"@typespec/spector": "0.1.0-alpha.21-dev.
|
|
23
|
-
"@typespec/spec-api": "0.1.0-alpha.11-dev.
|
|
21
|
+
"@typespec/http-specs": "0.1.0-alpha.29-dev.5",
|
|
22
|
+
"@typespec/spector": "0.1.0-alpha.21-dev.3",
|
|
23
|
+
"@typespec/spec-api": "0.1.0-alpha.11-dev.1",
|
|
24
24
|
"@typespec/tspd": "0.73.1",
|
|
25
|
-
"@azure-tools/azure-http-specs": "0.1.0-alpha.33-dev.
|
|
25
|
+
"@azure-tools/azure-http-specs": "0.1.0-alpha.33-dev.4",
|
|
26
26
|
"@azure-tools/typespec-autorest": "^0.62.0",
|
|
27
27
|
"@azure-tools/typespec-azure-core": "^0.62.0",
|
|
28
|
-
"@azure-tools/typespec-azure-resource-manager": "^0.62.
|
|
28
|
+
"@azure-tools/typespec-azure-resource-manager": "^0.62.1",
|
|
29
29
|
"@azure-tools/typespec-client-generator-core": "^0.62.0",
|
|
30
30
|
"@azure/abort-controller": "^2.1.2",
|
|
31
31
|
"@azure/core-auth": "^1.6.0",
|
|
@@ -38,7 +38,6 @@
|
|
|
38
38
|
"@types/fs-extra": "^9.0.13",
|
|
39
39
|
"@types/lodash": "^4.17.4",
|
|
40
40
|
"@types/mocha": "^10.0.6",
|
|
41
|
-
"@types/node": "^18.0.0",
|
|
42
41
|
"@typescript-eslint/eslint-plugin": "^8.28.0",
|
|
43
42
|
"@typescript-eslint/parser": "^8.28.0",
|
|
44
43
|
"@typespec/compiler": "^1.6.0",
|
|
@@ -51,14 +50,11 @@
|
|
|
51
50
|
"chalk": "^4.0.0",
|
|
52
51
|
"cross-env": "^7.0.3",
|
|
53
52
|
"eslint-plugin-require-extensions": "0.1.3",
|
|
54
|
-
"eslint": "^8.9.0",
|
|
55
53
|
"mkdirp": "^3.0.1",
|
|
56
54
|
"mocha": "^10.4.0",
|
|
57
55
|
"npm-run-all": "~4.1.5",
|
|
58
56
|
"prettier": "^3.3.3",
|
|
59
|
-
"rimraf": "^5.0.0",
|
|
60
57
|
"ts-node": "~10.9.1",
|
|
61
|
-
"typescript": "~5.8.2",
|
|
62
58
|
"vitest": "~1.6.0",
|
|
63
59
|
"@vitest/coverage-v8": "~1.6.0",
|
|
64
60
|
"@vitest/coverage-istanbul": "~1.6.0",
|
|
@@ -77,7 +73,7 @@
|
|
|
77
73
|
"@typespec/xml": "^0.76.0"
|
|
78
74
|
},
|
|
79
75
|
"dependencies": {
|
|
80
|
-
"@azure-tools/rlc-common": "0.
|
|
76
|
+
"@azure-tools/rlc-common": "^0.47.0",
|
|
81
77
|
"fs-extra": "^11.1.0",
|
|
82
78
|
"lodash": "^4.17.21",
|
|
83
79
|
"prettier": "^3.3.3",
|
|
@@ -2,6 +2,8 @@ import { Operation, Type, getNamespaceFullName } from "@typespec/compiler";
|
|
|
2
2
|
import {
|
|
3
3
|
SdkClientType,
|
|
4
4
|
SdkHttpOperation,
|
|
5
|
+
SdkModelPropertyType,
|
|
6
|
+
SdkModelType,
|
|
5
7
|
SdkServiceMethod,
|
|
6
8
|
SdkType,
|
|
7
9
|
getClientType
|
|
@@ -10,12 +12,27 @@ import { provideContext, useContext } from "../../contextManager.js";
|
|
|
10
12
|
|
|
11
13
|
import { visitPackageTypes } from "../../modular/emitModels.js";
|
|
12
14
|
import { SdkContext } from "../../utils/interfaces.js";
|
|
15
|
+
import {
|
|
16
|
+
getAllAncestors,
|
|
17
|
+
getAllProperties
|
|
18
|
+
} from "../../modular/helpers/operationHelpers.js";
|
|
19
|
+
import { normalizeModelPropertyName } from "../../modular/type-expressions/get-type-expression.js";
|
|
20
|
+
import { reportDiagnostic } from "../../lib.js";
|
|
21
|
+
import { NameType, normalizeName } from "@azure-tools/rlc-common";
|
|
13
22
|
|
|
14
23
|
export const emitQueue: Set<SdkType> = new Set<SdkType>();
|
|
24
|
+
export const flattenPropertyModelMap: Map<SdkModelPropertyType, SdkModelType> =
|
|
25
|
+
new Map<SdkModelPropertyType, SdkModelType>();
|
|
15
26
|
|
|
16
27
|
export interface SdkTypeContext {
|
|
17
28
|
operations: Map<Type, SdkServiceMethod<SdkHttpOperation>>;
|
|
18
29
|
types: Map<Type, SdkType>;
|
|
30
|
+
flattenProperties: Map<SdkModelPropertyType, SdkFlattenPropertyContext>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface SdkFlattenPropertyContext {
|
|
34
|
+
baseModel: SdkModelType;
|
|
35
|
+
conflictMap?: Map<SdkModelPropertyType, string>;
|
|
19
36
|
}
|
|
20
37
|
|
|
21
38
|
export function useSdkTypes() {
|
|
@@ -56,11 +73,20 @@ export function useSdkTypes() {
|
|
|
56
73
|
|
|
57
74
|
export function provideSdkTypes(context: SdkContext) {
|
|
58
75
|
const { sdkPackage } = context;
|
|
59
|
-
const sdkTypesContext = {
|
|
76
|
+
const sdkTypesContext: SdkTypeContext = {
|
|
60
77
|
operations: new Map<Type, SdkServiceMethod<SdkHttpOperation>>(),
|
|
61
|
-
types: new Map<Type, SdkType>()
|
|
78
|
+
types: new Map<Type, SdkType>(),
|
|
79
|
+
flattenProperties: new Map<
|
|
80
|
+
SdkModelPropertyType,
|
|
81
|
+
SdkFlattenPropertyContext
|
|
82
|
+
>()
|
|
62
83
|
};
|
|
63
84
|
visitPackageTypes(context);
|
|
85
|
+
enrichFlattenProperties(
|
|
86
|
+
context,
|
|
87
|
+
sdkTypesContext.flattenProperties,
|
|
88
|
+
flattenPropertyModelMap
|
|
89
|
+
);
|
|
64
90
|
for (const sdkModel of emitQueue) {
|
|
65
91
|
switch (sdkModel.kind) {
|
|
66
92
|
case "model":
|
|
@@ -126,6 +152,80 @@ export function provideSdkTypes(context: SdkContext) {
|
|
|
126
152
|
provideContext("sdkTypes", sdkTypesContext);
|
|
127
153
|
}
|
|
128
154
|
|
|
155
|
+
// Enrich flatten properties with their base models and conflict maps
|
|
156
|
+
function enrichFlattenProperties(
|
|
157
|
+
context: SdkContext,
|
|
158
|
+
propertyContextMap: Map<SdkModelPropertyType, SdkFlattenPropertyContext>,
|
|
159
|
+
propertyModelMap: Map<SdkModelPropertyType, SdkModelType>
|
|
160
|
+
) {
|
|
161
|
+
// Build a map of base model to its existing properties excluding flatten properties
|
|
162
|
+
// To check for conflicts later
|
|
163
|
+
const baseModelProperties = new Map<SdkModelType, Set<string>>();
|
|
164
|
+
propertyModelMap.forEach((baseModel, _) => {
|
|
165
|
+
if (!baseModelProperties.has(baseModel)) {
|
|
166
|
+
const propertiesExcludedFlatten = getAllProperties(
|
|
167
|
+
context,
|
|
168
|
+
baseModel,
|
|
169
|
+
getAllAncestors(baseModel)
|
|
170
|
+
)
|
|
171
|
+
.filter((p) => p.flatten === false || p.flatten === undefined)
|
|
172
|
+
.map((p) => normalizeModelPropertyName(context, p));
|
|
173
|
+
baseModelProperties.set(
|
|
174
|
+
baseModel,
|
|
175
|
+
new Set<string>(propertiesExcludedFlatten)
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
for (const [flattenProperty, baseModel] of propertyModelMap) {
|
|
180
|
+
const flattenContext: SdkFlattenPropertyContext = {
|
|
181
|
+
baseModel: baseModel
|
|
182
|
+
};
|
|
183
|
+
propertyContextMap.set(flattenProperty, flattenContext);
|
|
184
|
+
const existingProperties = baseModelProperties.get(baseModel)!;
|
|
185
|
+
const conflictMap = new Map<SdkModelPropertyType, string>();
|
|
186
|
+
const flattenModel = flattenProperty.type;
|
|
187
|
+
|
|
188
|
+
if (flattenModel.kind !== "model") {
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
if (baseModelProperties.has(flattenModel)) {
|
|
192
|
+
// If the flatten model is also a base model of other flatten properties, which means it has multiple consecutive flatten operations
|
|
193
|
+
// Since we cannot handle the flatten transition, report warning and skip it for now
|
|
194
|
+
reportDiagnostic(context.program, {
|
|
195
|
+
code: "unsupported-flatten-transition",
|
|
196
|
+
format: {
|
|
197
|
+
propertyName: flattenProperty.name,
|
|
198
|
+
modelName: baseModel.name
|
|
199
|
+
},
|
|
200
|
+
target: flattenProperty.__raw!
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
const allFlattenProperties = getAllProperties(
|
|
204
|
+
context,
|
|
205
|
+
flattenModel,
|
|
206
|
+
getAllAncestors(flattenModel)
|
|
207
|
+
);
|
|
208
|
+
for (const flattenChildProperty of allFlattenProperties) {
|
|
209
|
+
let childPropertyName = normalizeModelPropertyName(
|
|
210
|
+
context,
|
|
211
|
+
flattenChildProperty
|
|
212
|
+
);
|
|
213
|
+
if (existingProperties.has(childPropertyName)) {
|
|
214
|
+
childPropertyName = normalizeName(
|
|
215
|
+
`${childPropertyName}_${flattenProperty.name}_${childPropertyName}`,
|
|
216
|
+
NameType.Property
|
|
217
|
+
);
|
|
218
|
+
conflictMap.set(flattenChildProperty, childPropertyName);
|
|
219
|
+
}
|
|
220
|
+
existingProperties.add(childPropertyName);
|
|
221
|
+
}
|
|
222
|
+
if (conflictMap.size === 0) {
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
flattenContext.conflictMap = conflictMap;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
129
229
|
export function getAllOperationsFromClient(
|
|
130
230
|
client: SdkClientType<SdkHttpOperation>
|
|
131
231
|
) {
|
package/src/lib.ts
CHANGED
|
@@ -549,6 +549,12 @@ const libDef = {
|
|
|
549
549
|
default: paramMessage`The parameter name ${"parameterName"} has conflicts with others and please use @clientName to rename it.`
|
|
550
550
|
}
|
|
551
551
|
},
|
|
552
|
+
"unsupported-flatten-transition": {
|
|
553
|
+
severity: "warning",
|
|
554
|
+
messages: {
|
|
555
|
+
default: paramMessage`The property "${"propertyName"}" in "${"modelName"}" has multiple consecutive flatten operations. Flatten transitions are not supported so consecutive transitions will be ignored.`
|
|
556
|
+
}
|
|
557
|
+
},
|
|
552
558
|
"unsupported-parameter-type": {
|
|
553
559
|
severity: "error",
|
|
554
560
|
messages: {
|
|
@@ -596,6 +602,12 @@ const libDef = {
|
|
|
596
602
|
messages: {
|
|
597
603
|
default: paramMessage`Error traversing directory ${"directory"}: ${"error"}`
|
|
598
604
|
}
|
|
605
|
+
},
|
|
606
|
+
"detected-model-name-conflict": {
|
|
607
|
+
severity: "warning",
|
|
608
|
+
messages: {
|
|
609
|
+
default: paramMessage`Model name conflict detected: "${"modelName"}" exists in multiple namespaces: ${"namespaces"}. Please use @clientName to rename them.`
|
|
610
|
+
}
|
|
599
611
|
}
|
|
600
612
|
},
|
|
601
613
|
emitter: {
|
|
@@ -31,7 +31,10 @@ import {
|
|
|
31
31
|
SdkServiceMethod,
|
|
32
32
|
SdkServiceOperation
|
|
33
33
|
} from "@azure-tools/typespec-client-generator-core";
|
|
34
|
-
import {
|
|
34
|
+
import {
|
|
35
|
+
getMethodHierarchiesMap,
|
|
36
|
+
isTenantLevelOperation
|
|
37
|
+
} from "../utils/operationUtil.js";
|
|
35
38
|
import { useContext } from "../contextManager.js";
|
|
36
39
|
import { refkey } from "../framework/refkey.js";
|
|
37
40
|
import { SimplePollerHelpers } from "./static-helpers-metadata.js";
|
|
@@ -119,11 +122,28 @@ export function buildClassicalClient(
|
|
|
119
122
|
});
|
|
120
123
|
}
|
|
121
124
|
|
|
122
|
-
//
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
125
|
+
// Check if constructor overloads for subscriptionId is needed
|
|
126
|
+
const hasSubscriptionIdParam = classicalParams.some(
|
|
127
|
+
(param) => param.name.toLowerCase() === "subscriptionid"
|
|
128
|
+
);
|
|
129
|
+
const shouldSubscriptionIdOptional =
|
|
130
|
+
dpgContext.arm &&
|
|
131
|
+
hasSubscriptionIdParam &&
|
|
132
|
+
hasTenantLevelOperations(client, dpgContext);
|
|
133
|
+
|
|
134
|
+
let constructor;
|
|
135
|
+
if (shouldSubscriptionIdOptional) {
|
|
136
|
+
constructor = generateConstructorWithOverloads(
|
|
137
|
+
clientClass,
|
|
138
|
+
classicalParams,
|
|
139
|
+
client
|
|
140
|
+
);
|
|
141
|
+
} else {
|
|
142
|
+
constructor = clientClass.addConstructor({
|
|
143
|
+
docs: getDocsFromDescription(client.doc),
|
|
144
|
+
parameters: classicalParams
|
|
145
|
+
});
|
|
146
|
+
}
|
|
127
147
|
|
|
128
148
|
const paramNames = (contextParams ?? [])
|
|
129
149
|
.map((p) => p.name)
|
|
@@ -134,6 +154,11 @@ export function buildClassicalClient(
|
|
|
134
154
|
emitterOptions,
|
|
135
155
|
"azsdk-js-client"
|
|
136
156
|
)}}`;
|
|
157
|
+
} else if (
|
|
158
|
+
x.toLowerCase() === "subscriptionid" &&
|
|
159
|
+
shouldSubscriptionIdOptional
|
|
160
|
+
) {
|
|
161
|
+
return `subscriptionId ?? ""`;
|
|
137
162
|
} else {
|
|
138
163
|
return x;
|
|
139
164
|
}
|
|
@@ -370,3 +395,88 @@ function addChildClient(
|
|
|
370
395
|
)`
|
|
371
396
|
);
|
|
372
397
|
}
|
|
398
|
+
|
|
399
|
+
function hasTenantLevelOperations(
|
|
400
|
+
client: SdkClientType<SdkServiceOperation>,
|
|
401
|
+
dpgContext: SdkContext
|
|
402
|
+
): boolean {
|
|
403
|
+
const methodMap = getMethodHierarchiesMap(dpgContext, client);
|
|
404
|
+
|
|
405
|
+
for (const [_, operations] of methodMap) {
|
|
406
|
+
for (const op of operations) {
|
|
407
|
+
if (isTenantLevelOperation(op, client)) {
|
|
408
|
+
// Found a tenant-level operation
|
|
409
|
+
return true;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
return false;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
function generateConstructorWithOverloads(
|
|
418
|
+
clientClass: ClassDeclaration,
|
|
419
|
+
classicalParams: any[],
|
|
420
|
+
client: SdkClientType<SdkServiceOperation>
|
|
421
|
+
) {
|
|
422
|
+
const filteredParams = classicalParams.filter(
|
|
423
|
+
(p) =>
|
|
424
|
+
p.name.toLowerCase() !== "subscriptionid" &&
|
|
425
|
+
p.name.toLowerCase() !== "options"
|
|
426
|
+
);
|
|
427
|
+
|
|
428
|
+
const clientConstructor = clientClass.addConstructor({
|
|
429
|
+
docs: getDocsFromDescription(client.doc),
|
|
430
|
+
parameters: [
|
|
431
|
+
...filteredParams,
|
|
432
|
+
{
|
|
433
|
+
name: "subscriptionIdOrOptions",
|
|
434
|
+
type: `string | ${getClassicalClientName(client)}OptionalParams`,
|
|
435
|
+
hasQuestionToken: true
|
|
436
|
+
},
|
|
437
|
+
{
|
|
438
|
+
name: "options",
|
|
439
|
+
type: `${getClassicalClientName(client)}OptionalParams`,
|
|
440
|
+
hasQuestionToken: true
|
|
441
|
+
}
|
|
442
|
+
]
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
clientConstructor.addOverload({
|
|
446
|
+
parameters: [
|
|
447
|
+
...filteredParams,
|
|
448
|
+
{
|
|
449
|
+
name: "options",
|
|
450
|
+
type: `${getClassicalClientName(client)}OptionalParams`,
|
|
451
|
+
hasQuestionToken: true
|
|
452
|
+
}
|
|
453
|
+
]
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
clientConstructor.addOverload({
|
|
457
|
+
parameters: [
|
|
458
|
+
...filteredParams,
|
|
459
|
+
...classicalParams.filter(
|
|
460
|
+
(p) => p.name.toLowerCase() === "subscriptionid"
|
|
461
|
+
),
|
|
462
|
+
{
|
|
463
|
+
name: "options",
|
|
464
|
+
type: `${getClassicalClientName(client)}OptionalParams`,
|
|
465
|
+
hasQuestionToken: true
|
|
466
|
+
}
|
|
467
|
+
]
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
clientConstructor.addStatements([
|
|
471
|
+
`let subscriptionId: string | undefined;`,
|
|
472
|
+
``,
|
|
473
|
+
`if (typeof subscriptionIdOrOptions === "string") {`,
|
|
474
|
+
` subscriptionId = subscriptionIdOrOptions;`,
|
|
475
|
+
`} else if (typeof subscriptionIdOrOptions === "object") {`,
|
|
476
|
+
` options = subscriptionIdOrOptions;`,
|
|
477
|
+
`}`,
|
|
478
|
+
`options = options ?? {};`
|
|
479
|
+
]);
|
|
480
|
+
|
|
481
|
+
return clientConstructor;
|
|
482
|
+
}
|
|
@@ -40,8 +40,14 @@ import {
|
|
|
40
40
|
|
|
41
41
|
import { SdkContext } from "../utils/interfaces.js";
|
|
42
42
|
import { addDeclaration } from "../framework/declaration.js";
|
|
43
|
-
import {
|
|
44
|
-
|
|
43
|
+
import {
|
|
44
|
+
buildModelDeserializer,
|
|
45
|
+
buildPropertyDeserializer
|
|
46
|
+
} from "./serialization/buildDeserializerFunction.js";
|
|
47
|
+
import {
|
|
48
|
+
buildModelSerializer,
|
|
49
|
+
buildPropertySerializer
|
|
50
|
+
} from "./serialization/buildSerializerFunction.js";
|
|
45
51
|
import path from "path";
|
|
46
52
|
import { refkey } from "../framework/refkey.js";
|
|
47
53
|
import { useContext } from "../contextManager.js";
|
|
@@ -50,6 +56,7 @@ import { isAzureCoreErrorType } from "../utils/modelUtils.js";
|
|
|
50
56
|
import { isExtensibleEnum } from "./type-expressions/get-enum-expression.js";
|
|
51
57
|
import {
|
|
52
58
|
getAllDiscriminatedValues,
|
|
59
|
+
getPropertyWithOverrides,
|
|
53
60
|
isDiscriminatedUnion
|
|
54
61
|
} from "./serialization/serializeUtils.js";
|
|
55
62
|
import { reportDiagnostic } from "../lib.js";
|
|
@@ -60,6 +67,7 @@ import {
|
|
|
60
67
|
} from "./type-expressions/get-type-expression.js";
|
|
61
68
|
import {
|
|
62
69
|
emitQueue,
|
|
70
|
+
flattenPropertyModelMap,
|
|
63
71
|
getAllOperationsFromClient
|
|
64
72
|
} from "../framework/hooks/sdkTypes.js";
|
|
65
73
|
import { resolveReference } from "../framework/reference.js";
|
|
@@ -122,6 +130,14 @@ export function emitTypes(
|
|
|
122
130
|
emitType(context, type, sourceFile);
|
|
123
131
|
}
|
|
124
132
|
|
|
133
|
+
// Emit serialization/deserialization functions for flattened properties
|
|
134
|
+
for (const [property, _] of flattenPropertyModelMap) {
|
|
135
|
+
const namespaces = getModelNamespaces(context, property.type);
|
|
136
|
+
const filepath = getModelsPath(sourceRoot, namespaces);
|
|
137
|
+
sourceFile = outputProject.getSourceFile(filepath);
|
|
138
|
+
addSerializationFunctions(context, property, sourceFile!);
|
|
139
|
+
}
|
|
140
|
+
|
|
125
141
|
const modelFiles = outputProject.getSourceFiles(
|
|
126
142
|
sourceRoot + "/models/**/*.ts"
|
|
127
143
|
);
|
|
@@ -310,36 +326,38 @@ export function getModelNamespaces(
|
|
|
310
326
|
|
|
311
327
|
function addSerializationFunctions(
|
|
312
328
|
context: SdkContext,
|
|
313
|
-
|
|
329
|
+
typeOrProperty: SdkType | SdkModelPropertyType,
|
|
314
330
|
sourceFile: SourceFile,
|
|
315
|
-
|
|
331
|
+
skipDiscriminatedUnionSuffix = false
|
|
316
332
|
) {
|
|
317
|
-
const
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
333
|
+
const options = {
|
|
334
|
+
nameOnly: false,
|
|
335
|
+
skipDiscriminatedUnionSuffix
|
|
336
|
+
};
|
|
337
|
+
const serializationFunction =
|
|
338
|
+
typeOrProperty.kind === "property"
|
|
339
|
+
? buildPropertySerializer(context, typeOrProperty, options)
|
|
340
|
+
: buildModelSerializer(context, typeOrProperty, options);
|
|
322
341
|
|
|
323
|
-
const
|
|
324
|
-
const
|
|
342
|
+
const serializerRefKey = refkey(typeOrProperty, "serializer");
|
|
343
|
+
const deserializerRefKey = refkey(typeOrProperty, "deserializer");
|
|
325
344
|
if (
|
|
326
345
|
serializationFunction &&
|
|
327
346
|
typeof serializationFunction !== "string" &&
|
|
328
347
|
serializationFunction.name
|
|
329
348
|
) {
|
|
330
|
-
addDeclaration(sourceFile, serializationFunction,
|
|
349
|
+
addDeclaration(sourceFile, serializationFunction, serializerRefKey);
|
|
331
350
|
}
|
|
332
|
-
const deserializationFunction =
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
);
|
|
351
|
+
const deserializationFunction =
|
|
352
|
+
typeOrProperty.kind === "property"
|
|
353
|
+
? buildPropertyDeserializer(context, typeOrProperty, options)
|
|
354
|
+
: buildModelDeserializer(context, typeOrProperty, options);
|
|
337
355
|
if (
|
|
338
356
|
deserializationFunction &&
|
|
339
357
|
typeof deserializationFunction !== "string" &&
|
|
340
358
|
deserializationFunction.name
|
|
341
359
|
) {
|
|
342
|
-
addDeclaration(sourceFile, deserializationFunction,
|
|
360
|
+
addDeclaration(sourceFile, deserializationFunction, deserializerRefKey);
|
|
343
361
|
}
|
|
344
362
|
}
|
|
345
363
|
|
|
@@ -474,16 +492,47 @@ function buildModelInterface(
|
|
|
474
492
|
context: SdkContext,
|
|
475
493
|
type: SdkModelType
|
|
476
494
|
): InterfaceDeclarationStructure {
|
|
495
|
+
const flattenPropertySet = new Set<SdkModelPropertyType>();
|
|
477
496
|
const interfaceStructure = {
|
|
478
497
|
kind: StructureKind.Interface,
|
|
479
498
|
name: normalizeModelName(context, type, NameType.Interface, true),
|
|
480
499
|
isExported: true,
|
|
481
500
|
properties: type.properties
|
|
482
501
|
.filter((p) => !isMetadata(context.program, p.__raw!))
|
|
502
|
+
.filter((p) => {
|
|
503
|
+
// filter out the flatten property to be processed later
|
|
504
|
+
if (p.flatten) {
|
|
505
|
+
flattenPropertySet.add(p);
|
|
506
|
+
return false;
|
|
507
|
+
}
|
|
508
|
+
return true;
|
|
509
|
+
})
|
|
483
510
|
.map((p) => {
|
|
484
511
|
return buildModelProperty(context, p, type);
|
|
485
512
|
})
|
|
486
513
|
} as InterfaceStructure;
|
|
514
|
+
for (const flatten of flattenPropertySet.keys()) {
|
|
515
|
+
if (flatten.type?.kind !== "model" || !flatten.type.properties) {
|
|
516
|
+
continue;
|
|
517
|
+
}
|
|
518
|
+
const conflictMap =
|
|
519
|
+
useContext("sdkTypes").flattenProperties.get(flatten)?.conflictMap;
|
|
520
|
+
const allProperties = getAllProperties(
|
|
521
|
+
context,
|
|
522
|
+
flatten.type,
|
|
523
|
+
getAllAncestors(flatten.type)
|
|
524
|
+
).filter((p) => !isMetadata(context.program, p.__raw!));
|
|
525
|
+
interfaceStructure.properties!.push(
|
|
526
|
+
...allProperties.map((p) => {
|
|
527
|
+
// when the flattened property is optional, all its child properties should be optional too
|
|
528
|
+
const property = getPropertyWithOverrides(p, {
|
|
529
|
+
allOptional: flatten.optional,
|
|
530
|
+
propertyRenames: conflictMap
|
|
531
|
+
});
|
|
532
|
+
return buildModelProperty(context, property, type);
|
|
533
|
+
})
|
|
534
|
+
);
|
|
535
|
+
}
|
|
487
536
|
|
|
488
537
|
if (type.baseModel) {
|
|
489
538
|
const parentReference = getModelExpression(context, type.baseModel, {
|
|
@@ -635,7 +684,7 @@ function buildModelPolymorphicType(context: SdkContext, type: SdkModelType) {
|
|
|
635
684
|
}
|
|
636
685
|
const typeDeclaration: TypeAliasDeclarationStructure = {
|
|
637
686
|
kind: StructureKind.TypeAlias,
|
|
638
|
-
name: `${
|
|
687
|
+
name: `${normalizeModelName(context, type, NameType.Interface, true)}Union`,
|
|
639
688
|
isExported: true,
|
|
640
689
|
type: directSubtypes
|
|
641
690
|
.filter((p) => {
|
|
@@ -747,6 +796,7 @@ function buildModelProperty(
|
|
|
747
796
|
export function visitPackageTypes(context: SdkContext) {
|
|
748
797
|
const { sdkPackage } = context;
|
|
749
798
|
emitQueue.clear();
|
|
799
|
+
flattenPropertyModelMap.clear();
|
|
750
800
|
// Add all models in the package to the emit queue
|
|
751
801
|
for (const model of sdkPackage.models) {
|
|
752
802
|
visitType(context, model);
|
|
@@ -852,6 +902,9 @@ function visitType(context: SdkContext, type: SdkType | undefined) {
|
|
|
852
902
|
if (!emitQueue.has(property.type)) {
|
|
853
903
|
visitType(context, property.type);
|
|
854
904
|
}
|
|
905
|
+
if (property.flatten && property.type.kind === "model") {
|
|
906
|
+
flattenPropertyModelMap.set(property, type);
|
|
907
|
+
}
|
|
855
908
|
}
|
|
856
909
|
if (type.discriminatedSubtypes) {
|
|
857
910
|
for (const subType of Object.values(type.discriminatedSubtypes)) {
|