@azure-tools/typespec-ts 0.56.0-dev.3 → 0.56.0-dev.4
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 +9 -0
- package/README.md +31 -21
- package/dist/src/context-manager.d.ts +17 -0
- package/dist/src/context-manager.d.ts.map +1 -1
- package/dist/src/context-manager.js +21 -0
- package/dist/src/context-manager.js.map +1 -1
- package/dist/src/framework/declaration.d.ts.map +1 -1
- package/dist/src/framework/declaration.js +6 -20
- package/dist/src/framework/declaration.js.map +1 -1
- package/dist/src/framework/hooks/sdk-types.d.ts +9 -0
- package/dist/src/framework/hooks/sdk-types.d.ts.map +1 -1
- package/dist/src/framework/hooks/sdk-types.js +13 -0
- package/dist/src/framework/hooks/sdk-types.js.map +1 -1
- package/dist/src/framework/source-file-batch.d.ts +35 -0
- package/dist/src/framework/source-file-batch.d.ts.map +1 -0
- package/dist/src/framework/source-file-batch.js +128 -0
- package/dist/src/framework/source-file-batch.js.map +1 -0
- package/dist/src/index.js +12 -12
- package/dist/src/index.js.map +1 -1
- package/dist/src/interfaces.d.ts +0 -2
- package/dist/src/interfaces.d.ts.map +1 -1
- package/dist/src/interfaces.js.map +1 -1
- package/dist/src/lib.d.ts +15 -2
- package/dist/src/lib.d.ts.map +1 -1
- package/dist/src/lib.js +22 -11
- package/dist/src/lib.js.map +1 -1
- package/dist/src/metadata/build-package-file.d.ts +2 -4
- package/dist/src/metadata/build-package-file.d.ts.map +1 -1
- package/dist/src/metadata/build-package-file.js +2 -17
- package/dist/src/metadata/build-package-file.js.map +1 -1
- package/dist/src/metadata/build-readme-file.d.ts.map +1 -1
- package/dist/src/metadata/build-readme-file.js +17 -70
- package/dist/src/metadata/build-readme-file.js.map +1 -1
- package/dist/src/metadata/build-ts-config.d.ts.map +1 -1
- package/dist/src/metadata/build-ts-config.js +12 -0
- package/dist/src/metadata/build-ts-config.js.map +1 -1
- package/dist/src/metadata/package-json/build-azure-monorepo-package.d.ts +0 -1
- package/dist/src/metadata/package-json/build-azure-monorepo-package.d.ts.map +1 -1
- package/dist/src/metadata/package-json/build-azure-monorepo-package.js +0 -14
- package/dist/src/metadata/package-json/build-azure-monorepo-package.js.map +1 -1
- package/dist/src/metadata/render-template.d.ts +24 -0
- package/dist/src/metadata/render-template.d.ts.map +1 -0
- package/dist/src/metadata/render-template.js +148 -0
- package/dist/src/metadata/render-template.js.map +1 -0
- package/dist/src/metadata/test/build-recorded-client.d.ts.map +1 -1
- package/dist/src/metadata/test/build-recorded-client.js +1 -7
- package/dist/src/metadata/test/build-recorded-client.js.map +1 -1
- package/dist/src/metadata/test/build-sample-test.d.ts.map +1 -1
- package/dist/src/metadata/test/build-sample-test.js +1 -4
- package/dist/src/metadata/test/build-sample-test.js.map +1 -1
- package/dist/src/metadata/test/build-snippets.d.ts.map +1 -1
- package/dist/src/metadata/test/build-snippets.js +2 -4
- package/dist/src/metadata/test/build-snippets.js.map +1 -1
- package/dist/src/metadata/test/template.d.ts +0 -1
- package/dist/src/metadata/test/template.d.ts.map +1 -1
- package/dist/src/metadata/test/template.js +0 -127
- package/dist/src/metadata/test/template.js.map +1 -1
- package/dist/src/modular/build-classical-client.d.ts.map +1 -1
- package/dist/src/modular/build-classical-client.js +2 -2
- package/dist/src/modular/build-classical-client.js.map +1 -1
- package/dist/src/modular/build-root-index.d.ts.map +1 -1
- package/dist/src/modular/build-root-index.js +37 -9
- package/dist/src/modular/build-root-index.js.map +1 -1
- package/dist/src/modular/build-subpath-index.d.ts.map +1 -1
- package/dist/src/modular/build-subpath-index.js +15 -2
- package/dist/src/modular/build-subpath-index.js.map +1 -1
- package/dist/src/modular/emit-models.d.ts.map +1 -1
- package/dist/src/modular/emit-models.js +24 -17
- package/dist/src/modular/emit-models.js.map +1 -1
- package/dist/src/modular/helpers/client-helpers.d.ts +8 -3
- package/dist/src/modular/helpers/client-helpers.d.ts.map +1 -1
- package/dist/src/modular/helpers/client-helpers.js +37 -17
- package/dist/src/modular/helpers/client-helpers.js.map +1 -1
- package/dist/src/modular/helpers/operation-helpers.js +8 -9
- package/dist/src/modular/helpers/operation-helpers.js.map +1 -1
- package/dist/src/transform/transform-client-options.d.ts.map +1 -1
- package/dist/src/transform/transform-client-options.js +1 -5
- package/dist/src/transform/transform-client-options.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +30 -33
- package/src/context-manager.ts +23 -0
- package/src/framework/declaration.ts +8 -20
- package/src/framework/hooks/sdk-types.ts +14 -0
- package/src/framework/source-file-batch.ts +140 -0
- package/src/index.ts +13 -13
- package/src/interfaces.ts +0 -2
- package/src/lib.ts +40 -14
- package/src/metadata/build-package-file.ts +2 -21
- package/src/metadata/build-readme-file.ts +20 -94
- package/src/metadata/build-ts-config.ts +12 -0
- package/src/metadata/package-json/build-azure-monorepo-package.ts +0 -17
- package/src/metadata/render-template.ts +202 -0
- package/src/metadata/test/build-recorded-client.ts +1 -7
- package/src/metadata/test/build-sample-test.ts +1 -4
- package/src/metadata/test/build-snippets.ts +2 -4
- package/src/metadata/test/template.ts +0 -128
- package/src/modular/build-classical-client.ts +2 -6
- package/src/modular/build-root-index.ts +52 -14
- package/src/modular/build-subpath-index.ts +24 -3
- package/src/modular/emit-models.ts +24 -18
- package/src/modular/helpers/client-helpers.ts +43 -25
- package/src/modular/helpers/operation-helpers.ts +10 -10
- package/src/transform/transform-client-options.ts +1 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@azure-tools/typespec-ts",
|
|
3
|
-
"version": "0.56.0-dev.
|
|
3
|
+
"version": "0.56.0-dev.4",
|
|
4
4
|
"description": "A TypeSpec emitter for TypeScript",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -18,15 +18,15 @@
|
|
|
18
18
|
"license": "MIT",
|
|
19
19
|
"devDependencies": {
|
|
20
20
|
"@azure-rest/core-client": "^2.3.1",
|
|
21
|
-
"@typespec/http-specs": "^0.1.0-alpha.
|
|
22
|
-
"@typespec/spector": "^0.1.0-alpha.
|
|
23
|
-
"@typespec/spec-api": "^0.1.0-alpha.
|
|
24
|
-
"@typespec/tspd": "^0.
|
|
25
|
-
"@azure-tools/azure-http-specs": "^0.1.0-alpha.
|
|
26
|
-
"@azure-tools/typespec-autorest": "^0.
|
|
27
|
-
"@azure-tools/typespec-azure-core": "^0.
|
|
28
|
-
"@azure-tools/typespec-azure-resource-manager": "^0.
|
|
29
|
-
"@azure-tools/typespec-client-generator-core": "^0.
|
|
21
|
+
"@typespec/http-specs": "^0.1.0-alpha.39 || >=0.1.0-alpha.40-dev <0.1.0-alpha.40",
|
|
22
|
+
"@typespec/spector": "^0.1.0-alpha.26 || >=0.1.0-alpha.27-dev <0.1.0-alpha.27",
|
|
23
|
+
"@typespec/spec-api": "^0.1.0-alpha.15 || >=0.1.0-alpha.16-dev <0.1.0-alpha.16",
|
|
24
|
+
"@typespec/tspd": "^0.76.0 || >=0.77.0-dev <0.77.0",
|
|
25
|
+
"@azure-tools/azure-http-specs": "^0.1.0-alpha.43 || >=0.1.0-alpha.44-dev <0.1.0-alpha.44",
|
|
26
|
+
"@azure-tools/typespec-autorest": "^0.70.0 || >=0.71.0-dev <0.71.0",
|
|
27
|
+
"@azure-tools/typespec-azure-core": "^0.70.0 || >=0.71.0-dev <0.71.0",
|
|
28
|
+
"@azure-tools/typespec-azure-resource-manager": "^0.70.0 || >=0.71.0-dev <0.71.0",
|
|
29
|
+
"@azure-tools/typespec-client-generator-core": "^0.70.0 || >=0.71.0-dev <0.71.0",
|
|
30
30
|
"@azure/abort-controller": "^2.1.2",
|
|
31
31
|
"@azure/core-auth": "^1.6.0",
|
|
32
32
|
"@azure/core-lro": "^3.1.0",
|
|
@@ -34,17 +34,15 @@
|
|
|
34
34
|
"@azure/core-rest-pipeline": "^1.14.0",
|
|
35
35
|
"@azure/core-util": "^1.4.0",
|
|
36
36
|
"@azure/logger": "^1.0.4",
|
|
37
|
-
"@typespec/compiler": "^1.
|
|
38
|
-
"@typespec/http": "^1.
|
|
39
|
-
"@typespec/openapi": "^1.
|
|
40
|
-
"@typespec/rest": "^0.
|
|
41
|
-
"@typespec/versioning": "^0.
|
|
42
|
-
"@typespec/xml": "^0.
|
|
37
|
+
"@typespec/compiler": "^1.14.0",
|
|
38
|
+
"@typespec/http": "^1.14.0",
|
|
39
|
+
"@typespec/openapi": "^1.14.0",
|
|
40
|
+
"@typespec/rest": "^0.84.0 || >=0.85.0-dev <0.85.0",
|
|
41
|
+
"@typespec/versioning": "^0.84.0 || >=0.85.0-dev <0.85.0",
|
|
42
|
+
"@typespec/xml": "^0.84.0 || >=0.85.0-dev <0.85.0",
|
|
43
43
|
"@typespec/ts-http-runtime": "0.3.6",
|
|
44
44
|
"cross-env": "^10.1.0",
|
|
45
|
-
"
|
|
46
|
-
"npm-run-all": "~4.1.5",
|
|
47
|
-
"prettier": "^3.8.1",
|
|
45
|
+
"concurrently": "^10.0.0",
|
|
48
46
|
"vitest": "^4.1.3",
|
|
49
47
|
"vite": "^8.0.8",
|
|
50
48
|
"@vitest/coverage-v8": "^4.1.3",
|
|
@@ -52,17 +50,16 @@
|
|
|
52
50
|
"yaml": "^2.8.3"
|
|
53
51
|
},
|
|
54
52
|
"peerDependencies": {
|
|
55
|
-
"@azure-tools/typespec-azure-core": "^0.
|
|
56
|
-
"@azure-tools/typespec-client-generator-core": "^0.
|
|
57
|
-
"@typespec/compiler": "^1.
|
|
58
|
-
"@typespec/http": "^1.
|
|
59
|
-
"@typespec/rest": "^0.
|
|
60
|
-
"@typespec/versioning": "^0.
|
|
61
|
-
"@typespec/xml": "^0.
|
|
53
|
+
"@azure-tools/typespec-azure-core": "^0.70.0 || >=0.71.0-dev <0.71.0",
|
|
54
|
+
"@azure-tools/typespec-client-generator-core": "^0.70.0 || >=0.71.0-dev <0.71.0",
|
|
55
|
+
"@typespec/compiler": "^1.14.0",
|
|
56
|
+
"@typespec/http": "^1.14.0",
|
|
57
|
+
"@typespec/rest": "^0.84.0 || >=0.85.0-dev <0.85.0",
|
|
58
|
+
"@typespec/versioning": "^0.84.0 || >=0.85.0-dev <0.85.0",
|
|
59
|
+
"@typespec/xml": "^0.84.0 || >=0.85.0-dev <0.85.0"
|
|
62
60
|
},
|
|
63
61
|
"dependencies": {
|
|
64
62
|
"fast-xml-parser": "^5.7.0",
|
|
65
|
-
"handlebars": "^4.7.7",
|
|
66
63
|
"prettier": "^3.8.1",
|
|
67
64
|
"ts-morph": "^23.0.0",
|
|
68
65
|
"tslib": "^2.3.1"
|
|
@@ -89,14 +86,14 @@
|
|
|
89
86
|
"clean": "rimraf ./dist ./typespec-output",
|
|
90
87
|
"build": "tsc -p .",
|
|
91
88
|
"test": "npm run test-next && npm run unit-test && npm run integration-test-ci",
|
|
92
|
-
"lint": "
|
|
93
|
-
"lint:fix": "
|
|
89
|
+
"lint": "oxlint . --deny-warnings",
|
|
90
|
+
"lint:fix": "oxlint . --fix",
|
|
94
91
|
"check:tree": "node ./test/commands/check-clean-tree.ts",
|
|
95
|
-
"integration-test-ci": "npm
|
|
96
|
-
"spector-test": "
|
|
97
|
-
"start-test-server": "
|
|
92
|
+
"integration-test-ci": "npm run copy:typespec && npm run spector-test",
|
|
93
|
+
"spector-test": "concurrently --kill-others --success first \"npm:start-test-server\" \"npm:generate-and-run\"",
|
|
94
|
+
"start-test-server": "node ./test/commands/start-test-server.js",
|
|
98
95
|
"copy:typespec": "node ./test/commands/copy-typespec.ts",
|
|
99
|
-
"generate-and-run": "npm run generate-tsp-only:client &&
|
|
96
|
+
"generate-and-run": "npm run generate-tsp-only:client && concurrently --kill-others-on-fail \"npm:integration-test:alone\" \"npm:generate-tsp-only:declarations\" && npm run stop-test-server -- -p 3002",
|
|
100
97
|
"generate-tsp-only": "node ./test/commands/gen-spector.js",
|
|
101
98
|
"generate-tsp-only:client": "node ./test/commands/gen-spector.js --phase=client",
|
|
102
99
|
"generate-tsp-only:declarations": "node ./test/commands/gen-spector.js --phase=declarations",
|
package/src/context-manager.ts
CHANGED
|
@@ -72,6 +72,19 @@ class ContextManager {
|
|
|
72
72
|
public getContext<K extends ContextKey>(key: K): Contexts[K] | undefined {
|
|
73
73
|
return this.contexts.get(key) as Contexts[K] | undefined;
|
|
74
74
|
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Clears all stored contexts.
|
|
78
|
+
*
|
|
79
|
+
* The manager is a process-wide singleton, so the values provided during an
|
|
80
|
+
* emit (the `EmitContext`/`Program`, the TCGC `SdkContext`, the ts-morph
|
|
81
|
+
* `Project`, etc.) stay reachable from this map until the next emit overwrites
|
|
82
|
+
* them. Clearing at the end of an emit lets the whole previous program graph
|
|
83
|
+
* be collected instead of being retained until the following emit.
|
|
84
|
+
*/
|
|
85
|
+
public clearContexts(): void {
|
|
86
|
+
this.contexts.clear();
|
|
87
|
+
}
|
|
75
88
|
}
|
|
76
89
|
|
|
77
90
|
// Expose the singleton instance of the context manager.
|
|
@@ -99,3 +112,13 @@ export function useContext<K extends ContextKey>(key: K): Contexts[K] {
|
|
|
99
112
|
export function provideContext<K extends ContextKey>(key: K, value: Contexts[K]): void {
|
|
100
113
|
contextManager.setContext(key, value);
|
|
101
114
|
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Clears all contexts held by the singleton context manager. Call this once an
|
|
118
|
+
* emit has finished writing its output so the retained program graph (compiler
|
|
119
|
+
* `EmitContext`/`Program`, TCGC `SdkContext`, ts-morph `Project`, binder, …) can
|
|
120
|
+
* be garbage collected instead of lingering until the next emit overwrites it.
|
|
121
|
+
*/
|
|
122
|
+
export function clearContexts(): void {
|
|
123
|
+
contextManager.clearContexts();
|
|
124
|
+
}
|
|
@@ -8,12 +8,14 @@ import {
|
|
|
8
8
|
InterfaceDeclaration,
|
|
9
9
|
InterfaceDeclarationStructure,
|
|
10
10
|
SourceFile,
|
|
11
|
+
StatementStructures,
|
|
11
12
|
StructureKind,
|
|
12
13
|
TypeAliasDeclaration,
|
|
13
14
|
TypeAliasDeclarationStructure,
|
|
14
15
|
} from "ts-morph";
|
|
15
16
|
import { useBinder } from "./hooks/binder.js";
|
|
16
17
|
import { refkey as getRefKey } from "./refkey.js";
|
|
18
|
+
import { enqueueStatement } from "./source-file-batch.js";
|
|
17
19
|
export type DeclarationStructures =
|
|
18
20
|
| ClassDeclarationStructure
|
|
19
21
|
| EnumDeclarationStructure
|
|
@@ -80,25 +82,11 @@ export function addDeclaration(
|
|
|
80
82
|
// Update the declaration name to be unique
|
|
81
83
|
const trackedDeclaration = { ...declaration, name: trackedDeclarationName };
|
|
82
84
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
case StructureKind.Enum:
|
|
88
|
-
sourceFile.addEnum(trackedDeclaration);
|
|
89
|
-
break;
|
|
90
|
-
case StructureKind.Function:
|
|
91
|
-
sourceFile.addFunction(trackedDeclaration);
|
|
92
|
-
break;
|
|
93
|
-
case StructureKind.Interface:
|
|
94
|
-
sourceFile.addInterface(trackedDeclaration);
|
|
95
|
-
break;
|
|
96
|
-
case StructureKind.TypeAlias:
|
|
97
|
-
if (trackedDeclaration.type) {
|
|
98
|
-
sourceFile.addTypeAlias(trackedDeclaration);
|
|
99
|
-
}
|
|
100
|
-
break;
|
|
101
|
-
default:
|
|
102
|
-
throw new Error(`Unsupported declaration kind ${(trackedDeclaration as any).kind}`);
|
|
85
|
+
// Skip empty type aliases (they have no body to emit). Done before
|
|
86
|
+
// dispatching so behaviour is identical whether batching or not.
|
|
87
|
+
if (trackedDeclaration.kind === StructureKind.TypeAlias && !trackedDeclaration.type) {
|
|
88
|
+
return;
|
|
103
89
|
}
|
|
90
|
+
|
|
91
|
+
enqueueStatement(sourceFile, trackedDeclaration as StatementStructures);
|
|
104
92
|
}
|
|
@@ -29,6 +29,20 @@ export const flattenPropertyModelMap: Map<SdkModelPropertyType, SdkModelType> =
|
|
|
29
29
|
*/
|
|
30
30
|
export const pagedModelsKeptPublic = new Set<SdkType>();
|
|
31
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Releases the module-level state that accumulates while visiting a package's
|
|
34
|
+
* types. These collections are cleared at the start of every
|
|
35
|
+
* {@link visitPackageTypes} call, but because they live at module scope they
|
|
36
|
+
* otherwise keep the most recently emitted program's SDK types reachable until
|
|
37
|
+
* the next emit runs. Call this once an emit has fully finished so that state
|
|
38
|
+
* can be garbage collected.
|
|
39
|
+
*/
|
|
40
|
+
export function resetSdkTypesState(): void {
|
|
41
|
+
emitQueue.clear();
|
|
42
|
+
flattenPropertyModelMap.clear();
|
|
43
|
+
pagedModelsKeptPublic.clear();
|
|
44
|
+
}
|
|
45
|
+
|
|
32
46
|
export interface SdkTypeContext {
|
|
33
47
|
operations: Map<Type, SdkServiceMethod<SdkHttpOperation>>;
|
|
34
48
|
types: Map<Type, SdkType>;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ExportDeclarationStructure,
|
|
3
|
+
SourceFile,
|
|
4
|
+
StatementStructures,
|
|
5
|
+
StructureKind,
|
|
6
|
+
} from "ts-morph";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Generic per-source-file batch for ts-morph `add*` mutations.
|
|
10
|
+
*
|
|
11
|
+
* Each individual `sourceFile.addInterface/addFunction/addExportDeclaration/...`
|
|
12
|
+
* call re-parses the entire source file in ts-morph. Calling them in a loop
|
|
13
|
+
* therefore grows as O(N × file_size). This module collects structures while
|
|
14
|
+
* a batch is open and, on flush, issues a single `addStatements` call per file,
|
|
15
|
+
* collapsing N re-parses into 1.
|
|
16
|
+
*
|
|
17
|
+
* The batch is reference-counted so nested begin/flush pairs compose safely.
|
|
18
|
+
* Statements flush in insertion order and produce byte-identical output.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
let batchDepth = 0;
|
|
22
|
+
const pendingByFile = new Map<SourceFile, StatementStructures[]>();
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Opens a batching scope. Subsequent `enqueueStatement` calls queue rather
|
|
26
|
+
* than mutate the AST until the matching `flushSourceFileBatch` is called.
|
|
27
|
+
*/
|
|
28
|
+
export function beginSourceFileBatch(): void {
|
|
29
|
+
batchDepth++;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Closes the most recent batching scope. When the outermost scope closes,
|
|
34
|
+
* all pending structures are written to their source files in bulk.
|
|
35
|
+
*/
|
|
36
|
+
export function flushSourceFileBatch(): void {
|
|
37
|
+
if (batchDepth === 0) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
batchDepth--;
|
|
41
|
+
if (batchDepth > 0) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
for (const [sourceFile, statements] of pendingByFile) {
|
|
46
|
+
if (statements.length === 0) {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
sourceFile.addStatements(statements);
|
|
50
|
+
}
|
|
51
|
+
} finally {
|
|
52
|
+
pendingByFile.clear();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Queues a statement structure for bulk-add on flush, or writes it
|
|
58
|
+
* immediately when no batch is open.
|
|
59
|
+
* @param sourceFile - Target source file.
|
|
60
|
+
* @param structure - The statement structure to add.
|
|
61
|
+
*/
|
|
62
|
+
export function enqueueStatement(sourceFile: SourceFile, structure: StatementStructures): void {
|
|
63
|
+
if (batchDepth > 0) {
|
|
64
|
+
let pending = pendingByFile.get(sourceFile);
|
|
65
|
+
if (!pending) {
|
|
66
|
+
pending = [];
|
|
67
|
+
pendingByFile.set(sourceFile, pending);
|
|
68
|
+
}
|
|
69
|
+
pending.push(structure);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
sourceFile.addStatements([structure]);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Returns the set of names exported from `sourceFile` considering both the
|
|
77
|
+
* declarations already present in its AST and any export declarations queued
|
|
78
|
+
* by the current batch. Use this in place of reading `getExportDeclarations`
|
|
79
|
+
* directly when callers dedup against existing exports inside a batch.
|
|
80
|
+
* @param sourceFile - The file to inspect.
|
|
81
|
+
*/
|
|
82
|
+
export function getEffectiveExportedNames(sourceFile: SourceFile): Set<string> {
|
|
83
|
+
const names = new Set<string>();
|
|
84
|
+
for (const decl of sourceFile.getExportDeclarations()) {
|
|
85
|
+
for (const named of decl.getNamedExports()) {
|
|
86
|
+
names.add(named.getAliasNode()?.getText() ?? named.getName());
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const pending = pendingByFile.get(sourceFile);
|
|
90
|
+
if (pending) {
|
|
91
|
+
for (const structure of pending) {
|
|
92
|
+
if (structure.kind !== StructureKind.ExportDeclaration) {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
collectNamedExportNames(structure.namedExports, names);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return names;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Returns the set of named exports queued in the current batch for
|
|
103
|
+
* `sourceFile`. Use this to union with any AST-based view of exports
|
|
104
|
+
* (e.g. `getExportedDeclarations`) when deduplicating against still-pending
|
|
105
|
+
* writes inside a batch.
|
|
106
|
+
* @param sourceFile - The file to inspect.
|
|
107
|
+
*/
|
|
108
|
+
export function getQueuedExportNames(sourceFile: SourceFile): Set<string> {
|
|
109
|
+
const names = new Set<string>();
|
|
110
|
+
const pending = pendingByFile.get(sourceFile);
|
|
111
|
+
if (!pending) {
|
|
112
|
+
return names;
|
|
113
|
+
}
|
|
114
|
+
for (const structure of pending) {
|
|
115
|
+
if (structure.kind !== StructureKind.ExportDeclaration) {
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
collectNamedExportNames(structure.namedExports, names);
|
|
119
|
+
}
|
|
120
|
+
return names;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function collectNamedExportNames(
|
|
124
|
+
named: ExportDeclarationStructure["namedExports"],
|
|
125
|
+
into: Set<string>,
|
|
126
|
+
): void {
|
|
127
|
+
if (!named || typeof named === "function") {
|
|
128
|
+
// WriterFunction form is opaque to us; callers can't dedup by name.
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
for (const item of named) {
|
|
132
|
+
if (typeof item === "string") {
|
|
133
|
+
into.add(item);
|
|
134
|
+
} else if (typeof item === "function") {
|
|
135
|
+
continue;
|
|
136
|
+
} else if (item) {
|
|
137
|
+
into.add(item.alias ?? item.name);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
resolvePath,
|
|
11
11
|
type CompilerHost,
|
|
12
12
|
} from "@typespec/compiler";
|
|
13
|
-
import { provideContext, useContext } from "./context-manager.js";
|
|
13
|
+
import { clearContexts, provideContext, useContext } from "./context-manager.js";
|
|
14
14
|
import { buildRootIndex, buildSubClientIndexFile } from "./modular/build-root-index.js";
|
|
15
15
|
import {
|
|
16
16
|
AzureCoreDependencies,
|
|
@@ -43,7 +43,7 @@ import {
|
|
|
43
43
|
} from "@azure-tools/typespec-client-generator-core";
|
|
44
44
|
import { Project } from "ts-morph";
|
|
45
45
|
import { provideBinder } from "./framework/hooks/binder.js";
|
|
46
|
-
import { provideSdkTypes } from "./framework/hooks/sdk-types.js";
|
|
46
|
+
import { provideSdkTypes, resetSdkTypesState } from "./framework/hooks/sdk-types.js";
|
|
47
47
|
import { loadStaticHelpers } from "./framework/load-static-helpers.js";
|
|
48
48
|
import { ClientModel, ClientOptions } from "./interfaces.js";
|
|
49
49
|
import { EmitterOptions } from "./lib.js";
|
|
@@ -76,7 +76,7 @@ import { buildSampleTest } from "./metadata/test/build-sample-test.js";
|
|
|
76
76
|
import { buildSnippets } from "./metadata/test/build-snippets.js";
|
|
77
77
|
import { buildClassicalClient } from "./modular/build-classical-client.js";
|
|
78
78
|
import { buildClassicOperationFiles } from "./modular/build-classical-operation-groups.js";
|
|
79
|
-
import { buildClientContext
|
|
79
|
+
import { buildClientContext } from "./modular/build-client-context.js";
|
|
80
80
|
import { transformModularEmitterOptions } from "./modular/build-modular-options.js";
|
|
81
81
|
import { buildOperationFiles } from "./modular/build-operations.js";
|
|
82
82
|
import { getModuleExports } from "./modular/build-project-files.js";
|
|
@@ -188,6 +188,15 @@ export async function $onEmit(context: EmitContext) {
|
|
|
188
188
|
|
|
189
189
|
await generateMetadataAndTest(dpgContext);
|
|
190
190
|
|
|
191
|
+
// Release the emitter's process-wide singleton state now that this emit has
|
|
192
|
+
// finished writing output. Without this, the context manager keeps the whole
|
|
193
|
+
// previous program graph (compiler `EmitContext`/`Program`, TCGC `SdkContext`,
|
|
194
|
+
// ts-morph `Project`, binder, …) reachable until the next emit overwrites it.
|
|
195
|
+
// Clearing here lets it be collected between emits, which matters for hosts
|
|
196
|
+
// that run many emits in one process (test suites, benchmarks, watch mode).
|
|
197
|
+
clearContexts();
|
|
198
|
+
resetSdkTypesState();
|
|
199
|
+
|
|
191
200
|
async function enrichDpgContext() {
|
|
192
201
|
const generationPathDetail: GenerationDirDetail = await calculateGenerationDir();
|
|
193
202
|
dpgContext.generationPathDetail = generationPathDetail;
|
|
@@ -446,7 +455,6 @@ export async function $onEmit(context: EmitContext) {
|
|
|
446
455
|
modularPackageInfo = {
|
|
447
456
|
...modularPackageInfo,
|
|
448
457
|
dependencies,
|
|
449
|
-
clientContextPaths: getRelativeContextPaths(context, modularEmitterOptions),
|
|
450
458
|
};
|
|
451
459
|
}
|
|
452
460
|
commonBuilders.push((model) => buildPackageFile(model, modularPackageInfo));
|
|
@@ -499,14 +507,13 @@ export async function $onEmit(context: EmitContext) {
|
|
|
499
507
|
}
|
|
500
508
|
const modularPackageInfo = {
|
|
501
509
|
exports: getModuleExports(context, modularEmitterOptions),
|
|
502
|
-
clientContextPaths: getRelativeContextPaths(context, modularEmitterOptions),
|
|
503
510
|
...(Object.keys(additionalDependencies).length > 0 && {
|
|
504
511
|
dependencies: additionalDependencies,
|
|
505
512
|
}),
|
|
506
513
|
};
|
|
507
514
|
|
|
508
515
|
// Always update package.json (adds #platform/* imports) along with
|
|
509
|
-
// exports
|
|
516
|
+
// exports and LRO deps.
|
|
510
517
|
{
|
|
511
518
|
// Read package.json content via host and pass parsed object
|
|
512
519
|
const pkgSourceFile = await host.readFile(existingPackageFilePath);
|
|
@@ -571,13 +578,6 @@ export async function $onEmit(context: EmitContext) {
|
|
|
571
578
|
);
|
|
572
579
|
}
|
|
573
580
|
}
|
|
574
|
-
|
|
575
|
-
function getRelativeContextPaths(context: SdkContext, options: ModularEmitterOptions) {
|
|
576
|
-
const clientMap = getClientHierarchyMap(context);
|
|
577
|
-
return Array.from(clientMap)
|
|
578
|
-
.map((subClient) => getClientContextPath(subClient, options))
|
|
579
|
-
.map((path) => path.substring(path.indexOf("src")));
|
|
580
|
-
}
|
|
581
581
|
}
|
|
582
582
|
|
|
583
583
|
export async function createContextWithDefaultOptions(
|
package/src/interfaces.ts
CHANGED
|
@@ -223,7 +223,6 @@ export interface ClientOptions {
|
|
|
223
223
|
generateTest?: boolean;
|
|
224
224
|
generateSample?: boolean;
|
|
225
225
|
azureOutputDirectory?: string;
|
|
226
|
-
isTypeSpecTest?: boolean;
|
|
227
226
|
serviceInfo?: ServiceInfo;
|
|
228
227
|
azureArm?: boolean;
|
|
229
228
|
enableOperationGroup?: boolean;
|
|
@@ -335,7 +334,6 @@ export interface PackageDetails {
|
|
|
335
334
|
nameWithoutScope?: string;
|
|
336
335
|
description?: string;
|
|
337
336
|
version?: string;
|
|
338
|
-
isVersionUserProvided?: boolean;
|
|
339
337
|
}
|
|
340
338
|
export interface OperationParameter {
|
|
341
339
|
operationGroup: string;
|
package/src/lib.ts
CHANGED
|
@@ -6,6 +6,21 @@ import { Options } from "prettier";
|
|
|
6
6
|
import { PackageDetails } from "./interfaces.js";
|
|
7
7
|
|
|
8
8
|
export interface EmitterOptions {
|
|
9
|
+
/**
|
|
10
|
+
* Use this flag if you would like to generate the sdk only for a specific version.
|
|
11
|
+
* Also accepts values `latest` and `all`, or a map from service namespace full name to version for multi-service packages.
|
|
12
|
+
*/
|
|
13
|
+
"api-version"?: string | Record<string, string>;
|
|
14
|
+
/**
|
|
15
|
+
* Specifies the directory where the emitter will look for example files.
|
|
16
|
+
* Defaults to an `examples` directory located at the project root.
|
|
17
|
+
*/
|
|
18
|
+
"examples-dir"?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Specifies the namespace you want to override for namespaces set in the spec.
|
|
21
|
+
* With this config, all namespace for the spec types will default to it.
|
|
22
|
+
*/
|
|
23
|
+
namespace?: string;
|
|
9
24
|
/**
|
|
10
25
|
* Indicates whether to include response headers in the generated response type for modular operations.
|
|
11
26
|
* When set to true, modular operation responses with model or void bodies will have their headers
|
|
@@ -39,7 +54,6 @@ export interface EmitterOptions {
|
|
|
39
54
|
*/
|
|
40
55
|
"generate-test"?: boolean;
|
|
41
56
|
"generate-sample"?: boolean;
|
|
42
|
-
"is-typespec-test"?: boolean;
|
|
43
57
|
"azure-arm"?: boolean;
|
|
44
58
|
"enable-operation-group"?: boolean;
|
|
45
59
|
"enable-model-namespace"?: boolean;
|
|
@@ -51,8 +65,6 @@ export interface EmitterOptions {
|
|
|
51
65
|
"ignore-property-name-normalize"?: boolean;
|
|
52
66
|
"typespec-title-map"?: Record<string, string>;
|
|
53
67
|
"ignore-enum-member-name-normalize"?: boolean;
|
|
54
|
-
//TODO should remove this after finish the release tool test
|
|
55
|
-
"should-use-pnpm-dep"?: boolean;
|
|
56
68
|
"ignore-nullable-on-optional"?: boolean;
|
|
57
69
|
/**
|
|
58
70
|
* When set to true (default for Azure services), non-model return types (arrays, scalars, enums,
|
|
@@ -85,6 +97,31 @@ export const EmitterOptionsSchema: JSONSchemaType<EmitterOptions> = {
|
|
|
85
97
|
type: "object",
|
|
86
98
|
additionalProperties: true,
|
|
87
99
|
properties: {
|
|
100
|
+
"api-version": {
|
|
101
|
+
oneOf: [
|
|
102
|
+
{ type: "string", nullable: true },
|
|
103
|
+
{
|
|
104
|
+
type: "object",
|
|
105
|
+
additionalProperties: { type: "string" },
|
|
106
|
+
required: [],
|
|
107
|
+
nullable: true,
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
description:
|
|
111
|
+
"Use this flag if you would like to generate the sdk only for a specific version. Default value is the latest version. Also accepts values `latest` and `all`. For multi-service packages, provide a map from each service namespace's full name to its desired version; services not listed default to their latest version.",
|
|
112
|
+
} as any,
|
|
113
|
+
"examples-dir": {
|
|
114
|
+
type: "string",
|
|
115
|
+
nullable: true,
|
|
116
|
+
description:
|
|
117
|
+
"Specifies the directory where the emitter will look for example files. If the flag isn't set, the emitter defaults to using an `examples` directory located at the project root.",
|
|
118
|
+
},
|
|
119
|
+
namespace: {
|
|
120
|
+
type: "string",
|
|
121
|
+
nullable: true,
|
|
122
|
+
description:
|
|
123
|
+
"Specifies the namespace you want to override for namespaces set in the spec. With this config, all namespace for the spec types will default to it.",
|
|
124
|
+
},
|
|
88
125
|
"include-headers-in-response": {
|
|
89
126
|
type: "boolean",
|
|
90
127
|
nullable: true,
|
|
@@ -100,7 +137,6 @@ export const EmitterOptionsSchema: JSONSchemaType<EmitterOptions> = {
|
|
|
100
137
|
nameWithoutScope: { type: "string", nullable: true },
|
|
101
138
|
description: { type: "string", nullable: true },
|
|
102
139
|
version: { type: "string", nullable: true },
|
|
103
|
-
isVersionUserProvided: { type: "boolean", nullable: true },
|
|
104
140
|
},
|
|
105
141
|
required: ["name"],
|
|
106
142
|
nullable: true,
|
|
@@ -170,11 +206,6 @@ export const EmitterOptionsSchema: JSONSchemaType<EmitterOptions> = {
|
|
|
170
206
|
description:
|
|
171
207
|
"Whether to generate sample files, for basic samples of your generated sdks. Defaults to `undefined`. Management packages' default to `true`.",
|
|
172
208
|
},
|
|
173
|
-
"is-typespec-test": {
|
|
174
|
-
type: "boolean",
|
|
175
|
-
nullable: true,
|
|
176
|
-
description: "Internal option for test",
|
|
177
|
-
},
|
|
178
209
|
"azure-arm": {
|
|
179
210
|
type: "boolean",
|
|
180
211
|
nullable: true,
|
|
@@ -251,11 +282,6 @@ export const EmitterOptionsSchema: JSONSchemaType<EmitterOptions> = {
|
|
|
251
282
|
"```",
|
|
252
283
|
].join("\n"),
|
|
253
284
|
},
|
|
254
|
-
"should-use-pnpm-dep": {
|
|
255
|
-
type: "boolean",
|
|
256
|
-
nullable: true,
|
|
257
|
-
description: "Internal option for test.",
|
|
258
|
-
},
|
|
259
285
|
"ignore-nullable-on-optional": {
|
|
260
286
|
type: "boolean",
|
|
261
287
|
nullable: true,
|
|
@@ -11,12 +11,11 @@ import { getPackageName } from "./utils.js";
|
|
|
11
11
|
interface PackageFileOptions {
|
|
12
12
|
exports?: Record<string, any>;
|
|
13
13
|
dependencies?: Record<string, string>;
|
|
14
|
-
clientContextPaths?: string[];
|
|
15
14
|
}
|
|
16
15
|
|
|
17
16
|
export function buildPackageFile(
|
|
18
17
|
model: ClientModel,
|
|
19
|
-
{ exports, dependencies
|
|
18
|
+
{ exports, dependencies }: PackageFileOptions = {},
|
|
20
19
|
) {
|
|
21
20
|
const config: PackageCommonInfoConfig = {
|
|
22
21
|
description: getDescription(model),
|
|
@@ -35,7 +34,6 @@ export function buildPackageFile(
|
|
|
35
34
|
hasLro: hasPollingOperations(model),
|
|
36
35
|
monorepoPackageDirectory: model.options?.azureOutputDirectory,
|
|
37
36
|
dependencies,
|
|
38
|
-
clientContextPaths,
|
|
39
37
|
};
|
|
40
38
|
|
|
41
39
|
const packageInfo: Record<string, any> = buildAzureMonorepoPackage(extendedConfig);
|
|
@@ -63,17 +61,15 @@ export function buildPackageFile(
|
|
|
63
61
|
* - Adds LRO dependencies (`@azure/core-lro`, `@azure/abort-controller`) when the package has
|
|
64
62
|
* polling operations (for non-monorepo Azure packages).
|
|
65
63
|
* - Updates exports (tshy or warp) when `exports` is provided.
|
|
66
|
-
* - Updates `//metadata.constantPaths` when `clientContextPaths` is provided.
|
|
67
64
|
*/
|
|
68
65
|
export function updatePackageFile(
|
|
69
66
|
model: ClientModel,
|
|
70
67
|
existingFilePathOrContent: string | Record<string, any>,
|
|
71
|
-
{ exports
|
|
68
|
+
{ exports }: PackageFileOptions = {},
|
|
72
69
|
) {
|
|
73
70
|
const hasLro = hasPollingOperations(model);
|
|
74
71
|
const needsLroUpdate = hasLro;
|
|
75
72
|
const needsExportsUpdate = exports;
|
|
76
|
-
const needsConstantPathsUpdate = clientContextPaths && clientContextPaths.length > 0;
|
|
77
73
|
|
|
78
74
|
let packageInfo;
|
|
79
75
|
if (typeof existingFilePathOrContent === "string") {
|
|
@@ -146,21 +142,6 @@ export function updatePackageFile(
|
|
|
146
142
|
};
|
|
147
143
|
}
|
|
148
144
|
|
|
149
|
-
// Update constantPaths metadata for Azure packages
|
|
150
|
-
if (needsConstantPathsUpdate && packageInfo["//metadata"]) {
|
|
151
|
-
const metadata = packageInfo["//metadata"];
|
|
152
|
-
// Filter out existing userAgentInfo entries
|
|
153
|
-
const nonUserAgentPaths = (metadata.constantPaths || []).filter(
|
|
154
|
-
(item: any) => item.prefix !== "userAgentInfo",
|
|
155
|
-
);
|
|
156
|
-
// Add new userAgentInfo entries from clientContextPaths
|
|
157
|
-
const newUserAgentPaths = clientContextPaths!.map((path) => ({
|
|
158
|
-
path: path,
|
|
159
|
-
prefix: "userAgentInfo",
|
|
160
|
-
}));
|
|
161
|
-
metadata.constantPaths = [...nonUserAgentPaths, ...newUserAgentPaths];
|
|
162
|
-
}
|
|
163
|
-
|
|
164
145
|
return {
|
|
165
146
|
path: "package.json",
|
|
166
147
|
content: JSON.stringify(packageInfo, null, 2),
|