@azure-tools/typespec-ts 0.37.0 → 0.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/README.md +12 -2
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +23 -19
- package/dist/src/index.js.map +1 -1
- package/dist/src/lib.d.ts.map +1 -1
- package/dist/src/lib.js +10 -2
- package/dist/src/lib.js.map +1 -1
- package/dist/src/modular/buildClassicalClient.js +2 -2
- package/dist/src/modular/buildClassicalClient.js.map +1 -1
- package/dist/src/modular/buildClientContext.d.ts.map +1 -1
- package/dist/src/modular/buildClientContext.js +2 -2
- package/dist/src/modular/buildClientContext.js.map +1 -1
- package/dist/src/modular/buildOperations.d.ts.map +1 -1
- package/dist/src/modular/buildOperations.js +0 -2
- package/dist/src/modular/buildOperations.js.map +1 -1
- package/dist/src/modular/buildProjectFiles.d.ts.map +1 -1
- package/dist/src/modular/buildProjectFiles.js +21 -3
- package/dist/src/modular/buildProjectFiles.js.map +1 -1
- package/dist/src/modular/buildRestorePoller.js +2 -2
- package/dist/src/modular/buildRestorePoller.js.map +1 -1
- package/dist/src/modular/buildRootIndex.d.ts +1 -0
- package/dist/src/modular/buildRootIndex.d.ts.map +1 -1
- package/dist/src/modular/buildRootIndex.js +80 -39
- package/dist/src/modular/buildRootIndex.js.map +1 -1
- package/dist/src/modular/buildSubpathIndex.d.ts +1 -0
- package/dist/src/modular/buildSubpathIndex.d.ts.map +1 -1
- package/dist/src/modular/buildSubpathIndex.js +67 -49
- package/dist/src/modular/buildSubpathIndex.js.map +1 -1
- package/dist/src/modular/emitModels.d.ts +4 -3
- package/dist/src/modular/emitModels.d.ts.map +1 -1
- package/dist/src/modular/emitModels.js +91 -26
- package/dist/src/modular/emitModels.js.map +1 -1
- package/dist/src/modular/helpers/classicalOperationHelpers.d.ts.map +1 -1
- package/dist/src/modular/helpers/classicalOperationHelpers.js +30 -18
- package/dist/src/modular/helpers/classicalOperationHelpers.js.map +1 -1
- package/dist/src/modular/helpers/clientHelpers.js +3 -3
- package/dist/src/modular/helpers/clientHelpers.js.map +1 -1
- package/dist/src/modular/helpers/operationHelpers.d.ts +5 -6
- package/dist/src/modular/helpers/operationHelpers.d.ts.map +1 -1
- package/dist/src/modular/helpers/operationHelpers.js +108 -27
- package/dist/src/modular/helpers/operationHelpers.js.map +1 -1
- package/dist/src/modular/serialization/buildDeserializerFunction.d.ts.map +1 -1
- package/dist/src/modular/serialization/buildDeserializerFunction.js +2 -1
- package/dist/src/modular/serialization/buildDeserializerFunction.js.map +1 -1
- package/dist/src/modular/serialization/buildSerializerFunction.d.ts.map +1 -1
- package/dist/src/modular/serialization/buildSerializerFunction.js +72 -20
- package/dist/src/modular/serialization/buildSerializerFunction.js.map +1 -1
- package/dist/src/modular/static-helpers-metadata.d.ts +12 -0
- package/dist/src/modular/static-helpers-metadata.d.ts.map +1 -1
- package/dist/src/modular/static-helpers-metadata.js +12 -0
- package/dist/src/modular/static-helpers-metadata.js.map +1 -1
- package/dist/src/transform/transfromRLCOptions.d.ts.map +1 -1
- package/dist/src/transform/transfromRLCOptions.js +8 -1
- package/dist/src/transform/transfromRLCOptions.js.map +1 -1
- package/dist/src/utils/modelUtils.d.ts.map +1 -1
- package/dist/src/utils/modelUtils.js +67 -44
- package/dist/src/utils/modelUtils.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +45 -42
- package/src/index.ts +40 -21
- package/src/lib.ts +10 -2
- package/src/modular/buildClassicalClient.ts +2 -2
- package/src/modular/buildClientContext.ts +5 -2
- package/src/modular/buildOperations.ts +0 -2
- package/src/modular/buildProjectFiles.ts +27 -3
- package/src/modular/buildRestorePoller.ts +2 -2
- package/src/modular/buildRootIndex.ts +97 -52
- package/src/modular/buildSubpathIndex.ts +79 -57
- package/src/modular/emitModels.ts +118 -29
- package/src/modular/helpers/classicalOperationHelpers.ts +53 -34
- package/src/modular/helpers/clientHelpers.ts +3 -3
- package/src/modular/helpers/operationHelpers.ts +167 -59
- package/src/modular/serialization/buildDeserializerFunction.ts +2 -1
- package/src/modular/serialization/buildSerializerFunction.ts +90 -25
- package/src/modular/static-helpers-metadata.ts +13 -0
- package/src/transform/transfromRLCOptions.ts +11 -1
- package/src/utils/modelUtils.ts +67 -43
- package/static/static-helpers/multipartHelpers.ts +22 -0
- package/dist/src/modular/buildHelperSerializers.d.ts +0 -3
- package/dist/src/modular/buildHelperSerializers.d.ts.map +0 -1
- package/dist/src/modular/buildHelperSerializers.js +0 -60
- package/dist/src/modular/buildHelperSerializers.js.map +0 -1
- package/src/modular/buildHelperSerializers.ts +0 -72
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import { NameType, normalizeName } from "@azure-tools/rlc-common";
|
|
2
2
|
import { Project, SourceFile } from "ts-morph";
|
|
3
|
-
import {
|
|
4
|
-
getClassicalClientName,
|
|
5
|
-
getClientName
|
|
6
|
-
} from "./helpers/namingHelpers.js";
|
|
3
|
+
import { getClassicalClientName } from "./helpers/namingHelpers.js";
|
|
7
4
|
import { ModularEmitterOptions } from "./interfaces.js";
|
|
8
5
|
import { resolveReference } from "../framework/reference.js";
|
|
9
|
-
import { PagingHelpers } from "./static-helpers-metadata.js";
|
|
6
|
+
import { MultipartHelpers, PagingHelpers } from "./static-helpers-metadata.js";
|
|
10
7
|
import {
|
|
11
8
|
SdkClientType,
|
|
12
9
|
SdkContext,
|
|
@@ -14,6 +11,7 @@ import {
|
|
|
14
11
|
} from "@azure-tools/typespec-client-generator-core";
|
|
15
12
|
import { getModularClientOptions } from "../utils/clientUtils.js";
|
|
16
13
|
import { getMethodHierarchiesMap } from "../utils/operationUtil.js";
|
|
14
|
+
import { join } from "path/posix";
|
|
17
15
|
|
|
18
16
|
export function buildRootIndex(
|
|
19
17
|
context: SdkContext,
|
|
@@ -53,11 +51,12 @@ export function buildRootIndex(
|
|
|
53
51
|
const modelsExportsIndex = rootIndexFile
|
|
54
52
|
.getExportDeclarations()
|
|
55
53
|
?.find((i) => {
|
|
56
|
-
return i.getModuleSpecifierValue()
|
|
54
|
+
return i.getModuleSpecifierValue()?.startsWith(`./models/`);
|
|
57
55
|
});
|
|
58
56
|
if (!modelsExportsIndex) {
|
|
59
57
|
exportModules(rootIndexFile, project, srcPath, clientName, "models", {
|
|
60
|
-
isTopLevel: true
|
|
58
|
+
isTopLevel: true,
|
|
59
|
+
recursive: true
|
|
61
60
|
});
|
|
62
61
|
}
|
|
63
62
|
exportModules(rootIndexFile, project, srcPath, clientName, "api", {
|
|
@@ -71,6 +70,7 @@ export function buildRootIndex(
|
|
|
71
70
|
});
|
|
72
71
|
|
|
73
72
|
exportPagingTypes(context, rootIndexFile);
|
|
73
|
+
exportFileContentsType(context, rootIndexFile);
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
/**
|
|
@@ -109,6 +109,28 @@ function hasPaging(context: SdkContext): boolean {
|
|
|
109
109
|
});
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
+
function exportFileContentsType(
|
|
113
|
+
context: SdkContext,
|
|
114
|
+
rootIndexFile: SourceFile
|
|
115
|
+
) {
|
|
116
|
+
if (
|
|
117
|
+
context.sdkPackage.models.some((x) =>
|
|
118
|
+
x.properties.some(
|
|
119
|
+
(y) => y.kind === "property" && y.multipartOptions?.isFilePart
|
|
120
|
+
)
|
|
121
|
+
)
|
|
122
|
+
) {
|
|
123
|
+
const existingExports = getExistingExports(rootIndexFile);
|
|
124
|
+
const namedExports = [resolveReference(MultipartHelpers.FileContents)];
|
|
125
|
+
|
|
126
|
+
const newNamedExports = getNewNamedExports(namedExports, existingExports);
|
|
127
|
+
|
|
128
|
+
if (newNamedExports.length > 0) {
|
|
129
|
+
addExportsToRootIndexFile(rootIndexFile, newNamedExports);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
112
134
|
function getExistingExports(rootIndexFile: SourceFile): Set<string> {
|
|
113
135
|
return new Set(
|
|
114
136
|
rootIndexFile
|
|
@@ -177,7 +199,7 @@ function exportClassicalClient(
|
|
|
177
199
|
subfolder: string,
|
|
178
200
|
isSubClient: boolean = false
|
|
179
201
|
) {
|
|
180
|
-
const clientName =
|
|
202
|
+
const clientName = client.name;
|
|
181
203
|
indexFile.addExportDeclaration({
|
|
182
204
|
namedExports: [clientName],
|
|
183
205
|
moduleSpecifier: `./${
|
|
@@ -190,6 +212,7 @@ export interface ExportModulesOptions {
|
|
|
190
212
|
interfaceOnly?: boolean;
|
|
191
213
|
isTopLevel?: boolean;
|
|
192
214
|
subfolder?: string;
|
|
215
|
+
recursive?: boolean;
|
|
193
216
|
}
|
|
194
217
|
|
|
195
218
|
function exportModules(
|
|
@@ -201,58 +224,80 @@ function exportModules(
|
|
|
201
224
|
options: ExportModulesOptions = {
|
|
202
225
|
interfaceOnly: false,
|
|
203
226
|
isTopLevel: false,
|
|
204
|
-
subfolder: ""
|
|
227
|
+
subfolder: "",
|
|
228
|
+
recursive: false
|
|
205
229
|
}
|
|
206
230
|
) {
|
|
207
|
-
const
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
231
|
+
const subfolder = options.subfolder ?? "";
|
|
232
|
+
let folders = [];
|
|
233
|
+
if (options.recursive) {
|
|
234
|
+
folders = project
|
|
235
|
+
.getDirectories()
|
|
236
|
+
.filter((dir) => {
|
|
237
|
+
const targetPath = join(srcPath, subfolder, moduleName);
|
|
238
|
+
return dir.getPath().replace(/\\/g, "/").startsWith(targetPath);
|
|
239
|
+
})
|
|
240
|
+
.map((dir) => {
|
|
241
|
+
return dir.getPath();
|
|
242
|
+
});
|
|
243
|
+
} else {
|
|
244
|
+
folders = [join(srcPath, subfolder, moduleName)];
|
|
216
245
|
}
|
|
246
|
+
for (const folder of folders) {
|
|
247
|
+
const apiFilePattern = join(folder, "index.ts");
|
|
248
|
+
const modelsFile = project.getSourceFile(apiFilePattern);
|
|
249
|
+
if (!modelsFile) {
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
217
252
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
.
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
}
|
|
224
|
-
return exDeclaration[1].some((ex) => {
|
|
225
|
-
if (
|
|
226
|
-
options.interfaceOnly &&
|
|
227
|
-
ex.getKindName() !== "InterfaceDeclaration"
|
|
228
|
-
) {
|
|
253
|
+
const exported = [...indexFile.getExportedDeclarations().keys()];
|
|
254
|
+
|
|
255
|
+
const namedExports = [...modelsFile.getExportedDeclarations().entries()]
|
|
256
|
+
.filter((exDeclaration) => {
|
|
257
|
+
if (exDeclaration[0].startsWith("_")) {
|
|
229
258
|
return false;
|
|
230
259
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
260
|
+
return exDeclaration[1].some((ex) => {
|
|
261
|
+
if (
|
|
262
|
+
options.interfaceOnly &&
|
|
263
|
+
ex.getKindName() !== "InterfaceDeclaration"
|
|
264
|
+
) {
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
if (
|
|
268
|
+
moduleName === "models" &&
|
|
269
|
+
ex.getKindName() === "FunctionDeclaration" &&
|
|
270
|
+
(exDeclaration[0].endsWith("Serializer") ||
|
|
271
|
+
exDeclaration[0].endsWith("Deserializer"))
|
|
272
|
+
) {
|
|
273
|
+
return false;
|
|
274
|
+
}
|
|
275
|
+
if (
|
|
276
|
+
options.interfaceOnly &&
|
|
277
|
+
options.isTopLevel &&
|
|
278
|
+
exDeclaration[0].endsWith("Context")
|
|
279
|
+
) {
|
|
280
|
+
return false;
|
|
281
|
+
}
|
|
282
|
+
return true;
|
|
283
|
+
});
|
|
284
|
+
})
|
|
285
|
+
.map((exDeclaration) => {
|
|
286
|
+
if (exported.indexOf(exDeclaration[0]) > -1) {
|
|
287
|
+
return `${exDeclaration[0]} as ${clientName}${exDeclaration[0]}`;
|
|
237
288
|
}
|
|
238
|
-
return
|
|
289
|
+
return exDeclaration[0];
|
|
239
290
|
});
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
}
|
|
245
|
-
|
|
291
|
+
const moduleSpecifier = `.${modelsFile
|
|
292
|
+
.getFilePath()
|
|
293
|
+
.replace(indexFile.getDirectoryPath(), "")
|
|
294
|
+
.replace(/\\/g, "/")
|
|
295
|
+
.replace(".ts", "")}.js`;
|
|
296
|
+
indexFile.addExportDeclaration({
|
|
297
|
+
moduleSpecifier,
|
|
298
|
+
namedExports
|
|
246
299
|
});
|
|
247
|
-
|
|
248
|
-
options.isTopLevel && options.subfolder !== "" && options.subfolder
|
|
249
|
-
? options.subfolder + "/"
|
|
250
|
-
: ""
|
|
251
|
-
}${moduleName}/index.js`;
|
|
252
|
-
indexFile.addExportDeclaration({
|
|
253
|
-
moduleSpecifier,
|
|
254
|
-
namedExports
|
|
255
|
-
});
|
|
300
|
+
}
|
|
256
301
|
}
|
|
257
302
|
|
|
258
303
|
export function buildSubClientIndexFile(
|
|
@@ -267,7 +312,7 @@ export function buildSubClientIndexFile(
|
|
|
267
312
|
undefined,
|
|
268
313
|
{ overwrite: true }
|
|
269
314
|
);
|
|
270
|
-
const clientName = `${
|
|
315
|
+
const clientName = `${getClassicalClientName(client)}`;
|
|
271
316
|
const clientFilePath = `${srcPath}/${
|
|
272
317
|
subfolder && subfolder !== "" ? subfolder + "/" : ""
|
|
273
318
|
}${normalizeName(clientName, NameType.File)}.ts`;
|
|
@@ -11,6 +11,7 @@ import { getModularClientOptions } from "../utils/clientUtils.js";
|
|
|
11
11
|
export interface buildSubpathIndexFileOptions {
|
|
12
12
|
exportIndex?: boolean;
|
|
13
13
|
interfaceOnly?: boolean;
|
|
14
|
+
recursive?: boolean;
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
export function buildSubpathIndexFile(
|
|
@@ -26,73 +27,94 @@ export function buildSubpathIndexFile(
|
|
|
26
27
|
const srcPath = emitterOptions.modularOptions.sourceRoot;
|
|
27
28
|
// Skip to export these files because they are used internally.
|
|
28
29
|
const skipFiles = ["pagingHelpers.ts", "pollingHelpers.ts"];
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
.
|
|
33
|
-
.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
let folders = [];
|
|
31
|
+
if (options.recursive) {
|
|
32
|
+
folders = emitterOptions.project
|
|
33
|
+
.getDirectories()
|
|
34
|
+
.filter((dir) => {
|
|
35
|
+
const targetPath = join(srcPath, subfolder, subpath);
|
|
36
|
+
return (
|
|
37
|
+
dir.getPath().replace(/\\/g, "/").startsWith(targetPath) &&
|
|
38
|
+
!emitterOptions.project.getSourceFile(`${dir}/index.ts`)
|
|
39
|
+
);
|
|
40
|
+
})
|
|
41
|
+
.map((dir) => {
|
|
42
|
+
return dir.getPath();
|
|
43
|
+
});
|
|
44
|
+
} else {
|
|
45
|
+
folders = [join(srcPath, subfolder, subpath)];
|
|
38
46
|
}
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
if (
|
|
49
|
-
continue;
|
|
50
|
-
}
|
|
51
|
-
if (filePath === indexFile.getFilePath()) {
|
|
47
|
+
for (const folder of folders) {
|
|
48
|
+
const apiFilePattern =
|
|
49
|
+
subpath === "models" ? join(folder, "models.ts") : folder;
|
|
50
|
+
const apiFiles = emitterOptions.project.getSourceFiles().filter((file) => {
|
|
51
|
+
return file
|
|
52
|
+
.getFilePath()
|
|
53
|
+
.replace(/\\/g, "/")
|
|
54
|
+
.startsWith(apiFilePattern.replace(/\\/g, "/"));
|
|
55
|
+
});
|
|
56
|
+
if (apiFiles.length === 0) {
|
|
52
57
|
continue;
|
|
53
58
|
}
|
|
59
|
+
const indexFile = emitterOptions.project.createSourceFile(
|
|
60
|
+
`${folder}/index.ts`
|
|
61
|
+
);
|
|
62
|
+
for (const file of apiFiles) {
|
|
63
|
+
const filePath = file.getFilePath();
|
|
64
|
+
if (!options.exportIndex && filePath.endsWith("index.ts")) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
// Skip to export these files because they are used internally.
|
|
68
|
+
if (skipFiles.some((skipFile) => filePath.endsWith(skipFile))) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (filePath === indexFile.getFilePath()) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
54
74
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return false;
|
|
59
|
-
}
|
|
60
|
-
return exDeclaration[1].some((ex) => {
|
|
61
|
-
if (
|
|
62
|
-
options.interfaceOnly &&
|
|
63
|
-
ex.getKindName() !== "InterfaceDeclaration"
|
|
64
|
-
) {
|
|
75
|
+
let namedExports: string[] = [...file.getExportedDeclarations().entries()]
|
|
76
|
+
.filter((exDeclaration) => {
|
|
77
|
+
if (exDeclaration[0].startsWith("_")) {
|
|
65
78
|
return false;
|
|
66
79
|
}
|
|
80
|
+
return exDeclaration[1].some((ex) => {
|
|
81
|
+
if (
|
|
82
|
+
options.interfaceOnly &&
|
|
83
|
+
ex.getKindName() !== "InterfaceDeclaration"
|
|
84
|
+
) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
67
87
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
88
|
+
// skip exporting serializers for models
|
|
89
|
+
if (
|
|
90
|
+
subpath === "models" &&
|
|
91
|
+
ex.getKindName() === "FunctionDeclaration" &&
|
|
92
|
+
(exDeclaration[0].endsWith("Serializer") ||
|
|
93
|
+
exDeclaration[0].endsWith("Deserializer"))
|
|
94
|
+
) {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
77
97
|
|
|
78
|
-
|
|
98
|
+
return true;
|
|
99
|
+
});
|
|
100
|
+
})
|
|
101
|
+
.map((exDeclaration) => {
|
|
102
|
+
return exDeclaration[0];
|
|
79
103
|
});
|
|
80
|
-
|
|
81
|
-
.
|
|
82
|
-
|
|
104
|
+
// Skip to export PagedResult and BuildPagedAsyncIteratorOptions
|
|
105
|
+
if (filePath.endsWith("pagingTypes.ts")) {
|
|
106
|
+
namedExports = namedExports.filter(
|
|
107
|
+
(ex) =>
|
|
108
|
+
!["PagedResult", "BuildPagedAsyncIteratorOptions"].includes(ex)
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
indexFile.addExportDeclaration({
|
|
112
|
+
moduleSpecifier: `.${filePath
|
|
113
|
+
.replace(indexFile.getDirectoryPath(), "")
|
|
114
|
+
.replace(/\\/g, "/")
|
|
115
|
+
.replace(".ts", "")}.js`,
|
|
116
|
+
namedExports
|
|
83
117
|
});
|
|
84
|
-
// Skip to export PagedResult and BuildPagedAsyncIteratorOptions
|
|
85
|
-
if (filePath.endsWith("pagingTypes.ts")) {
|
|
86
|
-
namedExports = namedExports.filter(
|
|
87
|
-
(ex) => !["PagedResult", "BuildPagedAsyncIteratorOptions"].includes(ex)
|
|
88
|
-
);
|
|
89
118
|
}
|
|
90
|
-
indexFile.addExportDeclaration({
|
|
91
|
-
moduleSpecifier: `.${filePath
|
|
92
|
-
.replace(indexFile.getDirectoryPath(), "")
|
|
93
|
-
.replace(/\\/g, "/")
|
|
94
|
-
.replace(".ts", "")}.js`,
|
|
95
|
-
namedExports
|
|
96
|
-
});
|
|
97
119
|
}
|
|
98
120
|
}
|
|
@@ -35,7 +35,6 @@ import {
|
|
|
35
35
|
|
|
36
36
|
import { SdkContext } from "../utils/interfaces.js";
|
|
37
37
|
import { addDeclaration } from "../framework/declaration.js";
|
|
38
|
-
import { addImportBySymbol } from "../utils/importHelper.js";
|
|
39
38
|
import { buildModelDeserializer } from "./serialization/buildDeserializerFunction.js";
|
|
40
39
|
import { buildModelSerializer } from "./serialization/buildSerializerFunction.js";
|
|
41
40
|
import { extractPagedMetadataNested } from "../utils/operationUtil.js";
|
|
@@ -46,7 +45,7 @@ import {
|
|
|
46
45
|
import path from "path";
|
|
47
46
|
import { refkey } from "../framework/refkey.js";
|
|
48
47
|
import { useContext } from "../contextManager.js";
|
|
49
|
-
import { isMetadata } from "@typespec/http";
|
|
48
|
+
import { isMetadata, isOrExtendsHttpFile } from "@typespec/http";
|
|
50
49
|
import {
|
|
51
50
|
isAzureCoreErrorType,
|
|
52
51
|
isAzureCoreLroType
|
|
@@ -56,6 +55,8 @@ import { isDiscriminatedUnion } from "./serialization/serializeUtils.js";
|
|
|
56
55
|
import { reportDiagnostic } from "../lib.js";
|
|
57
56
|
import { NoTarget } from "@typespec/compiler";
|
|
58
57
|
import { emitQueue } from "../framework/hooks/sdkTypes.js";
|
|
58
|
+
import { resolveReference } from "../framework/reference.js";
|
|
59
|
+
import { MultipartHelpers } from "./static-helpers-metadata.js";
|
|
59
60
|
|
|
60
61
|
type InterfaceStructure = OptionalKind<InterfaceDeclarationStructure> & {
|
|
61
62
|
extends?: string[];
|
|
@@ -84,22 +85,9 @@ export function emitTypes(
|
|
|
84
85
|
context: SdkContext,
|
|
85
86
|
{ sourceRoot }: { sourceRoot: string }
|
|
86
87
|
) {
|
|
87
|
-
const { sdkPackage } = context;
|
|
88
88
|
const outputProject = useContext("outputProject");
|
|
89
89
|
|
|
90
|
-
const modelsFilePath = getModelsPath(sourceRoot);
|
|
91
90
|
let sourceFile;
|
|
92
|
-
if (
|
|
93
|
-
emitQueue.size > 0 &&
|
|
94
|
-
(sdkPackage.models.length > 0 || sdkPackage.enums.length > 0)
|
|
95
|
-
) {
|
|
96
|
-
sourceFile = outputProject.createSourceFile(modelsFilePath);
|
|
97
|
-
if (!sourceFile) {
|
|
98
|
-
throw new Error(`Failed to create source file at ${modelsFilePath}`);
|
|
99
|
-
}
|
|
100
|
-
} else {
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
91
|
|
|
104
92
|
for (const type of emitQueue) {
|
|
105
93
|
if (!isGenerableType(type)) {
|
|
@@ -108,19 +96,31 @@ export function emitTypes(
|
|
|
108
96
|
if (isAzureCoreLroType(type.__raw)) {
|
|
109
97
|
continue;
|
|
110
98
|
}
|
|
99
|
+
|
|
100
|
+
const namespaces = getModelNamespaces(context, type);
|
|
101
|
+
const filepath = getModelsPath(sourceRoot, namespaces);
|
|
102
|
+
sourceFile = outputProject.getSourceFile(filepath);
|
|
103
|
+
if (!sourceFile) {
|
|
104
|
+
sourceFile = outputProject.createSourceFile(filepath);
|
|
105
|
+
}
|
|
111
106
|
emitType(context, type, sourceFile);
|
|
112
107
|
}
|
|
113
108
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
109
|
+
const modelFiles = outputProject.getSourceFiles(
|
|
110
|
+
sourceRoot + "/models/**/*.ts"
|
|
111
|
+
);
|
|
112
|
+
for (const modelFile of modelFiles) {
|
|
113
|
+
if (
|
|
114
|
+
modelFile.getInterfaces().length === 0 &&
|
|
115
|
+
modelFile.getTypeAliases().length === 0 &&
|
|
116
|
+
modelFile.getEnums().length === 0
|
|
117
|
+
) {
|
|
118
|
+
modelFile.delete();
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
121
|
}
|
|
122
|
-
|
|
123
|
-
return
|
|
122
|
+
|
|
123
|
+
return modelFiles;
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
function emitType(context: SdkContext, type: SdkType, sourceFile: SourceFile) {
|
|
@@ -128,11 +128,15 @@ function emitType(context: SdkContext, type: SdkType, sourceFile: SourceFile) {
|
|
|
128
128
|
if (isAzureCoreErrorType(context.program, type.__raw)) {
|
|
129
129
|
return;
|
|
130
130
|
}
|
|
131
|
+
if (isOrExtendsHttpFile(context.program, type.__raw!)) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
131
134
|
if (
|
|
132
135
|
!type.usage ||
|
|
133
136
|
(type.usage !== undefined &&
|
|
134
137
|
(type.usage & UsageFlags.Output) !== UsageFlags.Output &&
|
|
135
|
-
(type.usage & UsageFlags.Input) !== UsageFlags.Input
|
|
138
|
+
(type.usage & UsageFlags.Input) !== UsageFlags.Input &&
|
|
139
|
+
(type.usage & UsageFlags.Exception) !== UsageFlags.Exception)
|
|
136
140
|
) {
|
|
137
141
|
return;
|
|
138
142
|
}
|
|
@@ -175,7 +179,9 @@ function emitType(context: SdkContext, type: SdkType, sourceFile: SourceFile) {
|
|
|
175
179
|
const apiVersionEnumOnly = type.usage === UsageFlags.ApiVersionEnum;
|
|
176
180
|
const inputUsage = (type.usage & UsageFlags.Input) === UsageFlags.Input;
|
|
177
181
|
const outputUsage = (type.usage & UsageFlags.Output) === UsageFlags.Output;
|
|
178
|
-
|
|
182
|
+
const exceptionUsage =
|
|
183
|
+
(type.usage & UsageFlags.Exception) === UsageFlags.Exception;
|
|
184
|
+
if (!(inputUsage || outputUsage || apiVersionEnumOnly || exceptionUsage)) {
|
|
179
185
|
return;
|
|
180
186
|
}
|
|
181
187
|
const [enumType, knownValuesEnum] = buildEnumTypes(context, type);
|
|
@@ -217,8 +223,49 @@ export function getApiVersionEnum(context: SdkContext) {
|
|
|
217
223
|
return apiVersionEnum;
|
|
218
224
|
}
|
|
219
225
|
|
|
220
|
-
export function getModelsPath(
|
|
221
|
-
|
|
226
|
+
export function getModelsPath(
|
|
227
|
+
sourceRoot: string,
|
|
228
|
+
modelNamespace: string[] = []
|
|
229
|
+
): string {
|
|
230
|
+
return path.join(
|
|
231
|
+
...[
|
|
232
|
+
sourceRoot,
|
|
233
|
+
"models",
|
|
234
|
+
...modelNamespace.map((n) => normalizeName(n, NameType.File)),
|
|
235
|
+
`models.ts`
|
|
236
|
+
]
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
export function getModelNamespaces(
|
|
241
|
+
context: SdkContext,
|
|
242
|
+
model: SdkType
|
|
243
|
+
): string[] {
|
|
244
|
+
const rootNamespace = context.sdkPackage.rootNamespace.split(".");
|
|
245
|
+
if (
|
|
246
|
+
model.kind === "model" ||
|
|
247
|
+
model.kind === "enum" ||
|
|
248
|
+
model.kind === "union"
|
|
249
|
+
) {
|
|
250
|
+
if (
|
|
251
|
+
model.clientNamespace.startsWith("Azure.ResourceManager") ||
|
|
252
|
+
model.clientNamespace.startsWith("Azure.Core")
|
|
253
|
+
) {
|
|
254
|
+
return [];
|
|
255
|
+
}
|
|
256
|
+
const segments = model.clientNamespace.split(".");
|
|
257
|
+
if (segments.length > rootNamespace.length) {
|
|
258
|
+
while (segments[0] === rootNamespace[0]) {
|
|
259
|
+
segments.shift();
|
|
260
|
+
rootNamespace.shift();
|
|
261
|
+
}
|
|
262
|
+
return segments;
|
|
263
|
+
}
|
|
264
|
+
return [];
|
|
265
|
+
} else if (model.kind === "array" || model.kind === "dict") {
|
|
266
|
+
return getModelNamespaces(context, model.valueType);
|
|
267
|
+
}
|
|
268
|
+
return [];
|
|
222
269
|
}
|
|
223
270
|
|
|
224
271
|
function addSerializationFunctions(
|
|
@@ -524,10 +571,52 @@ function buildModelProperty(
|
|
|
524
571
|
target: NoTarget
|
|
525
572
|
});
|
|
526
573
|
}
|
|
574
|
+
|
|
575
|
+
let typeExpression: string;
|
|
576
|
+
if (property.kind === "property" && property.isMultipartFileInput) {
|
|
577
|
+
const multipartOptions = property.multipartOptions;
|
|
578
|
+
typeExpression = "{";
|
|
579
|
+
typeExpression += `contents: ${resolveReference(MultipartHelpers.FileContents)};`;
|
|
580
|
+
|
|
581
|
+
const isContentTypeOptional =
|
|
582
|
+
multipartOptions?.contentType === undefined ||
|
|
583
|
+
multipartOptions.contentType.optional ||
|
|
584
|
+
multipartOptions.defaultContentTypes.length > 0;
|
|
585
|
+
const isFilenameOptional =
|
|
586
|
+
multipartOptions?.filename === undefined ||
|
|
587
|
+
multipartOptions.filename.optional;
|
|
588
|
+
|
|
589
|
+
const contentTypeType = multipartOptions?.contentType
|
|
590
|
+
? getTypeExpression(context, multipartOptions.contentType.type)
|
|
591
|
+
: "string";
|
|
592
|
+
const filenameType = multipartOptions?.filename
|
|
593
|
+
? getTypeExpression(context, multipartOptions.filename.type)
|
|
594
|
+
: "string";
|
|
595
|
+
|
|
596
|
+
typeExpression += `contentType${isContentTypeOptional ? "?" : ""}: ${contentTypeType};`;
|
|
597
|
+
typeExpression += `filename${isFilenameOptional ? "?" : ""}: ${filenameType};`;
|
|
598
|
+
|
|
599
|
+
typeExpression += "}";
|
|
600
|
+
|
|
601
|
+
if (isContentTypeOptional && isFilenameOptional) {
|
|
602
|
+
// Allow passing content directly if both filename and content type are optional
|
|
603
|
+
typeExpression = `(${resolveReference(MultipartHelpers.FileContents)}) | ${typeExpression}`;
|
|
604
|
+
} else {
|
|
605
|
+
// If either one is required, still accept File at the top level since it requires a filename
|
|
606
|
+
typeExpression = `File | ${typeExpression}`;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
if (property.type.kind === "array") {
|
|
610
|
+
typeExpression = `Array<${typeExpression}>`;
|
|
611
|
+
}
|
|
612
|
+
} else {
|
|
613
|
+
typeExpression = getTypeExpression(context, property.type);
|
|
614
|
+
}
|
|
615
|
+
|
|
527
616
|
const propertyStructure: PropertySignatureStructure = {
|
|
528
617
|
kind: StructureKind.PropertySignature,
|
|
529
618
|
name: normalizedPropName,
|
|
530
|
-
type:
|
|
619
|
+
type: typeExpression,
|
|
531
620
|
hasQuestionToken: property.optional,
|
|
532
621
|
isReadonly: isReadOnly(property as SdkBodyModelPropertyType)
|
|
533
622
|
};
|