@gtkx/codegen 1.0.0 → 1.1.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/README.md +1 -1
- package/dist/analysis/descriptor-render.d.ts +12 -15
- package/dist/analysis/descriptor-render.d.ts.map +1 -1
- package/dist/analysis/descriptor-render.js +48 -31
- package/dist/analysis/descriptor-render.js.map +1 -1
- package/dist/analysis/descriptor.d.ts +16 -7
- package/dist/analysis/descriptor.d.ts.map +1 -1
- package/dist/analysis/descriptor.js +15 -3
- package/dist/analysis/descriptor.js.map +1 -1
- package/dist/analysis/inheritance.d.ts +4 -2
- package/dist/analysis/inheritance.d.ts.map +1 -1
- package/dist/analysis/inheritance.js +80 -38
- package/dist/analysis/inheritance.js.map +1 -1
- package/dist/analysis/interface-conflicts.d.ts +23 -0
- package/dist/analysis/interface-conflicts.d.ts.map +1 -0
- package/dist/analysis/interface-conflicts.js +144 -0
- package/dist/analysis/interface-conflicts.js.map +1 -0
- package/dist/analysis/param-capability.d.ts.map +1 -1
- package/dist/analysis/param-capability.js +3 -4
- package/dist/analysis/param-capability.js.map +1 -1
- package/dist/analysis/param-structure.js +2 -2
- package/dist/analysis/param-structure.js.map +1 -1
- package/dist/analysis/ts-type.d.ts.map +1 -1
- package/dist/analysis/ts-type.js +10 -17
- package/dist/analysis/ts-type.js.map +1 -1
- package/dist/analysis/type-key.d.ts +5 -0
- package/dist/analysis/type-key.d.ts.map +1 -0
- package/dist/analysis/type-key.js +9 -0
- package/dist/analysis/type-key.js.map +1 -0
- package/dist/compile.d.ts +12 -3
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +73 -24
- package/dist/compile.js.map +1 -1
- package/dist/docs/api-reference.d.ts.map +1 -1
- package/dist/docs/api-reference.js +10 -9
- package/dist/docs/api-reference.js.map +1 -1
- package/dist/docs/element-page.d.ts.map +1 -1
- package/dist/docs/element-page.js +5 -3
- package/dist/docs/element-page.js.map +1 -1
- package/dist/docs/pipeline.d.ts.map +1 -1
- package/dist/docs/pipeline.js +85 -18
- package/dist/docs/pipeline.js.map +1 -1
- package/dist/docs/render.d.ts +2 -1
- package/dist/docs/render.d.ts.map +1 -1
- package/dist/docs/render.js +5 -4
- package/dist/docs/render.js.map +1 -1
- package/dist/docs/symbol-page.d.ts.map +1 -1
- package/dist/docs/symbol-page.js +9 -6
- package/dist/docs/symbol-page.js.map +1 -1
- package/dist/fingerprint.d.ts +12 -1
- package/dist/fingerprint.d.ts.map +1 -1
- package/dist/fingerprint.js +44 -28
- package/dist/fingerprint.js.map +1 -1
- package/dist/gi.d.ts.map +1 -1
- package/dist/gi.js +1 -0
- package/dist/gi.js.map +1 -1
- package/dist/gir/ancestry.d.ts +7 -1
- package/dist/gir/ancestry.d.ts.map +1 -1
- package/dist/gir/ancestry.js +9 -1
- package/dist/gir/ancestry.js.map +1 -1
- package/dist/gir/annotations.d.ts +1 -2
- package/dist/gir/annotations.d.ts.map +1 -1
- package/dist/gir/annotations.js +1 -1
- package/dist/gir/annotations.js.map +1 -1
- package/dist/gir/cursor-overrides.d.ts +8 -0
- package/dist/gir/cursor-overrides.d.ts.map +1 -0
- package/dist/gir/cursor-overrides.js +6 -0
- package/dist/gir/cursor-overrides.js.map +1 -0
- package/dist/gir/emittable.d.ts +7 -0
- package/dist/gir/emittable.d.ts.map +1 -0
- package/dist/gir/emittable.js +3 -0
- package/dist/gir/emittable.js.map +1 -0
- package/dist/gir/function.d.ts.map +1 -1
- package/dist/gir/function.js +28 -2
- package/dist/gir/function.js.map +1 -1
- package/dist/gir/library.js +1 -1
- package/dist/gir/library.js.map +1 -1
- package/dist/gir/namespace.d.ts +5 -1
- package/dist/gir/namespace.d.ts.map +1 -1
- package/dist/gir/namespace.js +4 -2
- package/dist/gir/namespace.js.map +1 -1
- package/dist/gir/parameter.d.ts +13 -1
- package/dist/gir/parameter.d.ts.map +1 -1
- package/dist/gir/parameter.js +1 -0
- package/dist/gir/parameter.js.map +1 -1
- package/dist/gir/parse.d.ts.map +1 -1
- package/dist/gir/parse.js +3 -6
- package/dist/gir/parse.js.map +1 -1
- package/dist/guards.d.ts +16 -0
- package/dist/guards.d.ts.map +1 -0
- package/dist/guards.js +11 -0
- package/dist/guards.js.map +1 -0
- package/dist/internal.d.ts +2 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +2 -0
- package/dist/internal.js.map +1 -1
- package/dist/json.d.ts +3 -0
- package/dist/json.d.ts.map +1 -0
- package/dist/json.js +11 -0
- package/dist/json.js.map +1 -0
- package/dist/khronos/modules.d.ts.map +1 -1
- package/dist/khronos/modules.js +22 -7
- package/dist/khronos/modules.js.map +1 -1
- package/dist/khronos/parse.d.ts.map +1 -1
- package/dist/khronos/parse.js +3 -4
- package/dist/khronos/parse.js.map +1 -1
- package/dist/khronos/pipeline.d.ts +1 -1
- package/dist/khronos/pipeline.d.ts.map +1 -1
- package/dist/khronos/pipeline.js.map +1 -1
- package/dist/khronos/plan.d.ts +1 -7
- package/dist/khronos/plan.d.ts.map +1 -1
- package/dist/khronos/plan.js +1 -1
- package/dist/khronos/plan.js.map +1 -1
- package/dist/runner.d.ts +5 -1
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +16 -0
- package/dist/runner.js.map +1 -1
- package/dist/staging.d.ts +5 -0
- package/dist/staging.d.ts.map +1 -0
- package/dist/staging.js +57 -0
- package/dist/staging.js.map +1 -0
- package/dist/store/compile-store.d.ts.map +1 -1
- package/dist/store/compile-store.js +4 -2
- package/dist/store/compile-store.js.map +1 -1
- package/dist/store/gi/callables.d.ts +7 -2
- package/dist/store/gi/callables.d.ts.map +1 -1
- package/dist/store/gi/callables.js +25 -30
- package/dist/store/gi/callables.js.map +1 -1
- package/dist/store/gi/callback.d.ts.map +1 -1
- package/dist/store/gi/callback.js +9 -5
- package/dist/store/gi/callback.js.map +1 -1
- package/dist/store/gi/class.d.ts.map +1 -1
- package/dist/store/gi/class.js +59 -38
- package/dist/store/gi/class.js.map +1 -1
- package/dist/store/gi/companion.d.ts.map +1 -1
- package/dist/store/gi/companion.js +6 -6
- package/dist/store/gi/companion.js.map +1 -1
- package/dist/store/gi/constant.d.ts.map +1 -1
- package/dist/store/gi/constant.js +10 -2
- package/dist/store/gi/constant.js.map +1 -1
- package/dist/store/gi/constructor-props.js +1 -1
- package/dist/store/gi/constructor-props.js.map +1 -1
- package/dist/store/gi/enum.d.ts.map +1 -1
- package/dist/store/gi/enum.js +28 -8
- package/dist/store/gi/enum.js.map +1 -1
- package/dist/store/gi/function.d.ts +1 -3
- package/dist/store/gi/function.d.ts.map +1 -1
- package/dist/store/gi/function.js +24 -18
- package/dist/store/gi/function.js.map +1 -1
- package/dist/store/gi/gtype-binding.d.ts.map +1 -1
- package/dist/store/gi/gtype-binding.js +4 -1
- package/dist/store/gi/gtype-binding.js.map +1 -1
- package/dist/store/gi/interface.d.ts.map +1 -1
- package/dist/store/gi/interface.js +32 -17
- package/dist/store/gi/interface.js.map +1 -1
- package/dist/store/gi/method.d.ts +7 -6
- package/dist/store/gi/method.d.ts.map +1 -1
- package/dist/store/gi/method.js +13 -21
- package/dist/store/gi/method.js.map +1 -1
- package/dist/store/gi/param-marshal.d.ts +3 -2
- package/dist/store/gi/param-marshal.d.ts.map +1 -1
- package/dist/store/gi/param-marshal.js +50 -5
- package/dist/store/gi/param-marshal.js.map +1 -1
- package/dist/store/gi/pipeline.d.ts.map +1 -1
- package/dist/store/gi/pipeline.js +21 -10
- package/dist/store/gi/pipeline.js.map +1 -1
- package/dist/store/gi/properties.d.ts +2 -1
- package/dist/store/gi/properties.d.ts.map +1 -1
- package/dist/store/gi/properties.js +6 -3
- package/dist/store/gi/properties.js.map +1 -1
- package/dist/store/gi/property-accessor.d.ts +10 -5
- package/dist/store/gi/property-accessor.d.ts.map +1 -1
- package/dist/store/gi/property-accessor.js +95 -44
- package/dist/store/gi/property-accessor.js.map +1 -1
- package/dist/store/gi/record-constructor.d.ts +8 -1
- package/dist/store/gi/record-constructor.d.ts.map +1 -1
- package/dist/store/gi/record-constructor.js +31 -10
- package/dist/store/gi/record-constructor.js.map +1 -1
- package/dist/store/gi/record-field-accessor.d.ts.map +1 -1
- package/dist/store/gi/record-field-accessor.js +5 -1
- package/dist/store/gi/record-field-accessor.js.map +1 -1
- package/dist/store/gi/record-layout.d.ts +6 -1
- package/dist/store/gi/record-layout.d.ts.map +1 -1
- package/dist/store/gi/record-layout.js +8 -1
- package/dist/store/gi/record-layout.js.map +1 -1
- package/dist/store/gi/record.d.ts.map +1 -1
- package/dist/store/gi/record.js +19 -8
- package/dist/store/gi/record.js.map +1 -1
- package/dist/store/gi/registration.js +2 -2
- package/dist/store/gi/registration.js.map +1 -1
- package/dist/store/gi/signal.d.ts +2 -1
- package/dist/store/gi/signal.d.ts.map +1 -1
- package/dist/store/gi/signal.js +30 -24
- package/dist/store/gi/signal.js.map +1 -1
- package/dist/store/gi/value-marshalable.d.ts.map +1 -1
- package/dist/store/gi/value-marshalable.js +2 -1
- package/dist/store/gi/value-marshalable.js.map +1 -1
- package/dist/store/gi/vtable.d.ts +4 -1
- package/dist/store/gi/vtable.d.ts.map +1 -1
- package/dist/store/gi/vtable.js +60 -17
- package/dist/store/gi/vtable.js.map +1 -1
- package/dist/store/gi-store.d.ts +1 -0
- package/dist/store/gi-store.d.ts.map +1 -1
- package/dist/store/gi-store.js +15 -20
- package/dist/store/gi-store.js.map +1 -1
- package/dist/store/jsx/generated-elements.d.ts +2 -1
- package/dist/store/jsx/generated-elements.d.ts.map +1 -1
- package/dist/store/jsx/generated-elements.js +13 -7
- package/dist/store/jsx/generated-elements.js.map +1 -1
- package/dist/store/jsx/jsx.js +3 -3
- package/dist/store/jsx/jsx.js.map +1 -1
- package/dist/store/jsx/metadata.d.ts.map +1 -1
- package/dist/store/jsx/metadata.js +3 -1
- package/dist/store/jsx/metadata.js.map +1 -1
- package/dist/store/jsx-store.d.ts.map +1 -1
- package/dist/store/jsx-store.js +3 -3
- package/dist/store/jsx-store.js.map +1 -1
- package/dist/store/resolve-store.d.ts +14 -3
- package/dist/store/resolve-store.d.ts.map +1 -1
- package/dist/store/resolve-store.js +98 -15
- package/dist/store/resolve-store.js.map +1 -1
- package/dist/store/store-fs.d.ts +9 -6
- package/dist/store/store-fs.d.ts.map +1 -1
- package/dist/store/store-fs.js +59 -25
- package/dist/store/store-fs.js.map +1 -1
- package/dist/store/store-links.d.ts +3 -0
- package/dist/store/store-links.d.ts.map +1 -0
- package/dist/store/store-links.js +39 -0
- package/dist/store/store-links.js.map +1 -0
- package/dist/writer/comparison-context.d.ts +4 -0
- package/dist/writer/comparison-context.d.ts.map +1 -0
- package/dist/writer/comparison-context.js +13 -0
- package/dist/writer/comparison-context.js.map +1 -0
- package/dist/writer/context.d.ts +3 -3
- package/dist/writer/context.d.ts.map +1 -1
- package/dist/writer/context.js +11 -6
- package/dist/writer/context.js.map +1 -1
- package/dist/writer/module.d.ts +13 -5
- package/dist/writer/module.d.ts.map +1 -1
- package/dist/writer/module.js +68 -11
- package/dist/writer/module.js.map +1 -1
- package/dist/xml.d.ts +7 -1
- package/dist/xml.d.ts.map +1 -1
- package/dist/xml.js +43 -1
- package/dist/xml.js.map +1 -1
- package/package.json +14 -3
- package/src/analysis/descriptor-render.ts +90 -45
- package/src/analysis/descriptor.ts +35 -8
- package/src/analysis/inheritance.ts +134 -44
- package/src/analysis/interface-conflicts.ts +237 -0
- package/src/analysis/param-capability.ts +3 -6
- package/src/analysis/param-structure.ts +2 -2
- package/src/analysis/ts-type.ts +13 -17
- package/src/analysis/type-key.ts +14 -0
- package/src/compile.ts +110 -26
- package/src/docs/api-reference.ts +10 -9
- package/src/docs/element-page.ts +5 -2
- package/src/docs/pipeline.ts +129 -19
- package/src/docs/render.ts +7 -3
- package/src/docs/symbol-page.ts +12 -7
- package/src/fingerprint.ts +86 -31
- package/src/gi.ts +1 -0
- package/src/gir/ancestry.ts +17 -1
- package/src/gir/annotations.ts +1 -1
- package/src/gir/cursor-overrides.ts +12 -0
- package/src/gir/emittable.ts +8 -0
- package/src/gir/function.ts +45 -9
- package/src/gir/library.ts +1 -1
- package/src/gir/namespace.ts +8 -2
- package/src/gir/parameter.ts +15 -0
- package/src/gir/parse.ts +5 -7
- package/src/guards.ts +23 -0
- package/src/internal.ts +2 -0
- package/src/json.ts +11 -0
- package/src/khronos/modules.ts +25 -9
- package/src/khronos/parse.ts +3 -4
- package/src/khronos/pipeline.ts +1 -1
- package/src/khronos/plan.ts +0 -1
- package/src/runner.ts +19 -1
- package/src/staging.ts +69 -0
- package/src/store/compile-store.ts +6 -4
- package/src/store/gi/callables.ts +41 -33
- package/src/store/gi/callback.ts +9 -9
- package/src/store/gi/class.ts +79 -48
- package/src/store/gi/companion.ts +7 -6
- package/src/store/gi/constant.ts +12 -2
- package/src/store/gi/constructor-props.ts +1 -1
- package/src/store/gi/enum.ts +35 -21
- package/src/store/gi/function.ts +30 -24
- package/src/store/gi/gtype-binding.ts +7 -2
- package/src/store/gi/interface.ts +37 -18
- package/src/store/gi/method.ts +28 -29
- package/src/store/gi/param-marshal.ts +77 -6
- package/src/store/gi/pipeline.ts +25 -15
- package/src/store/gi/properties.ts +8 -4
- package/src/store/gi/property-accessor.ts +156 -73
- package/src/store/gi/record-constructor.ts +50 -18
- package/src/store/gi/record-field-accessor.ts +8 -1
- package/src/store/gi/record-layout.ts +11 -1
- package/src/store/gi/record.ts +20 -12
- package/src/store/gi/registration.ts +2 -2
- package/src/store/gi/signal.ts +36 -38
- package/src/store/gi/value-marshalable.ts +3 -1
- package/src/store/gi/vtable.ts +97 -20
- package/src/store/gi-store.ts +26 -31
- package/src/store/jsx/generated-elements.ts +17 -8
- package/src/store/jsx/jsx.ts +3 -3
- package/src/store/jsx/metadata.ts +4 -1
- package/src/store/jsx-store.ts +3 -3
- package/src/store/resolve-store.ts +133 -18
- package/src/store/store-fs.ts +87 -34
- package/src/store/store-links.ts +49 -0
- package/src/writer/comparison-context.ts +18 -0
- package/src/writer/context.ts +12 -6
- package/src/writer/module.ts +101 -14
- package/src/xml.ts +61 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync, realpathSync } from "node:fs";
|
|
2
|
-
import { dirname, join, parse } from "node:path";
|
|
2
|
+
import { dirname, join, parse, relative, sep } from "node:path";
|
|
3
3
|
import type { StoreOptions } from "./store-fs.js";
|
|
4
|
+
import { sweepStagingDirs } from "../staging.js";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Where a project's generated stores live, ready to spread into `runCodegen`. `jsx` is null when the
|
|
@@ -15,10 +16,20 @@ type ResolvedStore = {
|
|
|
15
16
|
reactSubexports: string[];
|
|
16
17
|
};
|
|
17
18
|
|
|
18
|
-
type ResolvedPackage = { dir: string; version: string };
|
|
19
|
+
type ResolvedPackage = { dir: string; nodeModules: string; version: string };
|
|
20
|
+
type StoreConsumer = { name: string; nodeModules: string };
|
|
19
21
|
|
|
20
22
|
const STORE_DIR = ".gtkx";
|
|
21
23
|
const SCOPE = "@gtkx";
|
|
24
|
+
const STORE_NAMES: string[] = ["gi", "jsx"];
|
|
25
|
+
|
|
26
|
+
const STORE_CONSUMERS: string[] = [
|
|
27
|
+
"@gtkx/cli",
|
|
28
|
+
"@gtkx/components",
|
|
29
|
+
"@gtkx/css",
|
|
30
|
+
"@gtkx/react",
|
|
31
|
+
"@gtkx/testing",
|
|
32
|
+
];
|
|
22
33
|
|
|
23
34
|
const readManifest = (path: string): { version?: string; exports?: Record<string, unknown> } =>
|
|
24
35
|
JSON.parse(readFileSync(path, "utf8")) as { version?: string; exports?: Record<string, unknown> };
|
|
@@ -28,14 +39,14 @@ const subexportNames = (packageDir: string): string[] =>
|
|
|
28
39
|
.filter((key) => key.startsWith("./") && key !== "./package.json")
|
|
29
40
|
.map((key) => key.slice(2));
|
|
30
41
|
|
|
31
|
-
const loadPackage = (manifest: string): ResolvedPackage | null => {
|
|
42
|
+
const loadPackage = (manifest: string, nodeModules: string): ResolvedPackage | null => {
|
|
32
43
|
if (!existsSync(manifest)) {
|
|
33
44
|
return null;
|
|
34
45
|
}
|
|
35
46
|
|
|
36
47
|
const real = realpathSync(manifest);
|
|
37
48
|
|
|
38
|
-
return { dir: dirname(real), version: readManifest(real).version ?? "0.0.0" };
|
|
49
|
+
return { dir: dirname(real), nodeModules, version: readManifest(real).version ?? "0.0.0" };
|
|
39
50
|
};
|
|
40
51
|
|
|
41
52
|
const nodeModulesChain = function* (projectRoot: string): Generator<string> {
|
|
@@ -52,49 +63,153 @@ const nodeModulesChain = function* (projectRoot: string): Generator<string> {
|
|
|
52
63
|
|
|
53
64
|
const resolvePackage = (projectRoot: string, packageName: string): ResolvedPackage | null => {
|
|
54
65
|
for (const nodeModules of nodeModulesChain(projectRoot)) {
|
|
55
|
-
const found = loadPackage(join(nodeModules, packageName, "package.json"));
|
|
66
|
+
const found = loadPackage(join(nodeModules, packageName, "package.json"), nodeModules);
|
|
56
67
|
|
|
57
68
|
if (found !== null) {
|
|
58
69
|
return found;
|
|
59
70
|
}
|
|
60
71
|
}
|
|
61
72
|
|
|
62
|
-
|
|
73
|
+
const unscoped = packageName.replace(/^@[^/]+\//, "");
|
|
74
|
+
|
|
75
|
+
return loadPackage(join(projectRoot, "packages", unscoped, "package.json"), join(projectRoot, "node_modules"));
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const isWithin = (parent: string, child: string): boolean => {
|
|
79
|
+
const path = relative(parent, child);
|
|
80
|
+
|
|
81
|
+
return path === "" || (path !== ".." && !path.startsWith(`..${sep}`));
|
|
63
82
|
};
|
|
64
83
|
|
|
84
|
+
const canImport = (fromNodeModules: string, targetNodeModules: string): boolean =>
|
|
85
|
+
isWithin(dirname(targetNodeModules), dirname(fromNodeModules));
|
|
86
|
+
|
|
65
87
|
const storeOptions = (nodeModules: string, name: string, version: string): StoreOptions => ({
|
|
66
88
|
storeDir: join(nodeModules, STORE_DIR, name),
|
|
67
89
|
linkDir: join(nodeModules, SCOPE, name),
|
|
68
90
|
version,
|
|
69
91
|
});
|
|
70
92
|
|
|
93
|
+
const resolveRuntime = (projectRoot: string): ResolvedPackage => {
|
|
94
|
+
const runtime = resolvePackage(projectRoot, "@gtkx/runtime");
|
|
95
|
+
|
|
96
|
+
if (runtime === null) {
|
|
97
|
+
throw new Error(`Cannot resolve @gtkx/runtime from ${projectRoot}; is it installed?`);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return runtime;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const storeNodeModules = (runtime: ResolvedPackage, react: ResolvedPackage | null): string => {
|
|
104
|
+
if (react !== null && canImport(react.nodeModules, runtime.nodeModules)) {
|
|
105
|
+
return react.nodeModules;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return runtime.nodeModules;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const findUnreachableConsumer = (projectRoot: string, nodeModules: string): StoreConsumer | null => {
|
|
112
|
+
for (const name of STORE_CONSUMERS) {
|
|
113
|
+
const consumer = resolvePackage(projectRoot, name);
|
|
114
|
+
|
|
115
|
+
if (consumer !== null && !canImport(consumer.nodeModules, nodeModules)) {
|
|
116
|
+
return { name, nodeModules: consumer.nodeModules };
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return null;
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const unreachableConsumerMessage = (consumer: StoreConsumer, nodeModules: string): string =>
|
|
124
|
+
`Cannot write the generated store to ${nodeModules}: ${consumer.name} is installed in ` +
|
|
125
|
+
`${consumer.nodeModules}, above it, so that copy can never import the generated @gtkx/gi. Install every ` +
|
|
126
|
+
"@gtkx package in one node_modules, then run gtkx codegen again.";
|
|
127
|
+
|
|
128
|
+
const checkConsumers = (projectRoot: string, nodeModules: string): void => {
|
|
129
|
+
const consumer = findUnreachableConsumer(projectRoot, nodeModules);
|
|
130
|
+
|
|
131
|
+
if (consumer !== null) {
|
|
132
|
+
throw new Error(unreachableConsumerMessage(consumer, nodeModules));
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const jsxOptions = (react: ResolvedPackage | null, nodeModules: string): StoreOptions | null =>
|
|
137
|
+
react === null ? null : storeOptions(nodeModules, "jsx", react.version);
|
|
138
|
+
|
|
139
|
+
const getReactSubexports = (react: ResolvedPackage | null): string[] =>
|
|
140
|
+
react === null ? [] : subexportNames(react.dir);
|
|
141
|
+
|
|
142
|
+
const storePaths = (nodeModules: string): string[] =>
|
|
143
|
+
STORE_NAMES.flatMap((name) => [join(nodeModules, STORE_DIR, name), join(nodeModules, SCOPE, name)]);
|
|
144
|
+
|
|
145
|
+
const findStoreNodeModules = (projectRoot: string): string | null => {
|
|
146
|
+
const runtime = resolvePackage(projectRoot, "@gtkx/runtime");
|
|
147
|
+
|
|
148
|
+
if (runtime === null) {
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return storeNodeModules(runtime, resolvePackage(projectRoot, "@gtkx/react"));
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const getShadowingStorePaths = (projectRoot: string): string[] => {
|
|
156
|
+
const nodeModules = join(projectRoot, "node_modules");
|
|
157
|
+
const anchored = findStoreNodeModules(projectRoot);
|
|
158
|
+
|
|
159
|
+
if (anchored === null || anchored === nodeModules) {
|
|
160
|
+
return [];
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return storePaths(nodeModules);
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const stagingRoots = (projectRoot: string): string[] => {
|
|
167
|
+
const nodeModules = join(projectRoot, "node_modules");
|
|
168
|
+
const anchored = findStoreNodeModules(projectRoot);
|
|
169
|
+
|
|
170
|
+
return anchored === null || anchored === nodeModules ? [nodeModules] : [nodeModules, anchored];
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
const sweepProjectStaging = (projectRoot: string): void => {
|
|
174
|
+
for (const nodeModules of stagingRoots(projectRoot)) {
|
|
175
|
+
for (const name of STORE_NAMES) {
|
|
176
|
+
sweepStagingDirs(join(nodeModules, STORE_DIR, name));
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
|
|
71
181
|
/**
|
|
72
182
|
* Resolves where a project's `@gtkx/gi` and `@gtkx/jsx` stores belong, from the project root alone. The
|
|
73
183
|
* result supplies every `runCodegen` input except `libraries` and `girPath`, so a caller that has
|
|
74
184
|
* already resolved those can spread it straight into the call.
|
|
75
185
|
*
|
|
186
|
+
* Both stores go in one `node_modules`, found by walking the project's `node_modules` chain upwards:
|
|
187
|
+
* the one `@gtkx/react` resolves from, or `@gtkx/runtime`'s when no React is installed. That is the
|
|
188
|
+
* project's own directory when it installs those packages itself, and the workspace root when npm or
|
|
189
|
+
* yarn hoisted them there. Keeping the pair together is what lets the jsx store import the gi store, and
|
|
190
|
+
* anchoring them where the `@gtkx` packages sit is what lets `@gtkx/react`, the CLI, and the project's
|
|
191
|
+
* sources all reach the bindings. A package manager that hoists therefore gives every project sharing
|
|
192
|
+
* that `node_modules` one shared store.
|
|
193
|
+
*
|
|
76
194
|
* Store versions come from the installed `@gtkx/runtime` and `@gtkx/react`, so a dependency upgrade
|
|
77
195
|
* invalidates the stores. Pass explicit `gi` or `jsx` options to `runCodegen` to override any of it.
|
|
78
196
|
*
|
|
79
|
-
* @param projectRoot Directory holding the project's `package.json
|
|
197
|
+
* @param projectRoot Directory holding the project's `package.json`, whose `node_modules` chain is walked.
|
|
80
198
|
* @returns The store locations and the React subexports that shape the jsx store.
|
|
81
|
-
* @throws If `@gtkx/runtime` cannot be resolved from the project
|
|
199
|
+
* @throws If `@gtkx/runtime` cannot be resolved from the project, or a `@gtkx` package that imports the
|
|
200
|
+
* bindings is installed above the `node_modules` the stores would go in, since it could not reach them.
|
|
82
201
|
*/
|
|
83
202
|
const resolveStore = (projectRoot: string): ResolvedStore => {
|
|
84
|
-
const runtime =
|
|
85
|
-
|
|
86
|
-
if (runtime === null) {
|
|
87
|
-
throw new Error(`Cannot resolve @gtkx/runtime from ${projectRoot}; is it installed?`);
|
|
88
|
-
}
|
|
89
|
-
|
|
203
|
+
const runtime = resolveRuntime(projectRoot);
|
|
90
204
|
const react = resolvePackage(projectRoot, "@gtkx/react");
|
|
91
|
-
const nodeModules =
|
|
205
|
+
const nodeModules = storeNodeModules(runtime, react);
|
|
206
|
+
checkConsumers(projectRoot, nodeModules);
|
|
92
207
|
|
|
93
208
|
return {
|
|
94
209
|
gi: storeOptions(nodeModules, "gi", runtime.version),
|
|
95
|
-
jsx: react
|
|
96
|
-
reactSubexports:
|
|
210
|
+
jsx: jsxOptions(react, nodeModules),
|
|
211
|
+
reactSubexports: getReactSubexports(react),
|
|
97
212
|
};
|
|
98
213
|
};
|
|
99
214
|
|
|
100
|
-
export { resolveStore, type ResolvedStore };
|
|
215
|
+
export { getShadowingStorePaths, resolveStore, sweepProjectStaging, type ResolvedStore };
|
package/src/store/store-fs.ts
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { errorMessage } from "@gtkx/utils";
|
|
2
|
+
import {
|
|
3
|
+
chmodSync,
|
|
4
|
+
existsSync,
|
|
5
|
+
mkdirSync,
|
|
6
|
+
realpathSync,
|
|
7
|
+
renameSync,
|
|
8
|
+
rmSync,
|
|
9
|
+
symlinkSync,
|
|
10
|
+
writeFileSync,
|
|
11
|
+
} from "node:fs";
|
|
2
12
|
import { dirname, join, relative } from "node:path";
|
|
13
|
+
import { keepFailedProject, type SourceModule } from "../compile.js";
|
|
14
|
+
import { createStagingDir } from "../staging.js";
|
|
3
15
|
import { compileStore } from "./compile-store.js";
|
|
4
16
|
|
|
5
17
|
/** Where one generated store is written and how it is reached. */
|
|
@@ -12,10 +24,7 @@ type StoreOptions = {
|
|
|
12
24
|
version: string;
|
|
13
25
|
};
|
|
14
26
|
|
|
15
|
-
type
|
|
16
|
-
fileName: string;
|
|
17
|
-
source: string;
|
|
18
|
-
};
|
|
27
|
+
type StoreLink = Pick<StoreOptions, "storeDir" | "linkDir">;
|
|
19
28
|
|
|
20
29
|
type Manifest = {
|
|
21
30
|
name: string;
|
|
@@ -38,19 +47,25 @@ type RawFile = { relativePath: string; content: string };
|
|
|
38
47
|
type WriteStoreParams = {
|
|
39
48
|
storeDir: string;
|
|
40
49
|
linkDir: string;
|
|
41
|
-
files:
|
|
50
|
+
files: SourceModule[];
|
|
42
51
|
manifest: Manifest;
|
|
43
52
|
rawFiles?: RawFile[];
|
|
44
53
|
requiresEnvReference?: boolean;
|
|
45
54
|
};
|
|
46
55
|
|
|
47
56
|
const STORE_DIR_MODE = 0o755;
|
|
57
|
+
const FAILED_STORE_SUFFIX = ".failed";
|
|
48
58
|
|
|
49
59
|
const subpathExport = (stem: string): { types: string; default: string } => ({
|
|
50
60
|
types: `./${stem}.d.ts`,
|
|
51
61
|
default: `./${stem}.js`,
|
|
52
62
|
});
|
|
53
63
|
|
|
64
|
+
const namespaceBarrel = (directory: string): { fileName: string; source: string } => ({
|
|
65
|
+
fileName: `${directory}/index.ts`,
|
|
66
|
+
source: `export * from "./${directory}.js";\n`,
|
|
67
|
+
});
|
|
68
|
+
|
|
54
69
|
const buildManifest = (input: ManifestInput): Manifest => {
|
|
55
70
|
const manifest: Manifest = {
|
|
56
71
|
name: input.name,
|
|
@@ -69,29 +84,36 @@ const buildManifest = (input: ManifestInput): Manifest => {
|
|
|
69
84
|
|
|
70
85
|
const writeStore = (params: WriteStoreParams): void => {
|
|
71
86
|
const tmp = createTempStore(params.storeDir);
|
|
87
|
+
const keepAt = `${params.storeDir}${FAILED_STORE_SUFFIX}`;
|
|
72
88
|
|
|
73
89
|
try {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
90
|
+
buildTempStore(tmp, params);
|
|
91
|
+
swapStore(tmp, params.storeDir);
|
|
92
|
+
ensureStoreLink(params);
|
|
93
|
+
} catch (error) {
|
|
94
|
+
throw keepFailedProject({ projectDir: tmp, keepAt, error });
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
rmSync(keepAt, { recursive: true, force: true });
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const buildTempStore = (tmp: string, params: WriteStoreParams): void => {
|
|
101
|
+
for (const file of params.files) {
|
|
102
|
+
writeSourceFile(tmp, file.fileName, file.source);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
compileStore({
|
|
106
|
+
storeDir: tmp,
|
|
107
|
+
files: params.files,
|
|
108
|
+
packageName: params.manifest.name,
|
|
109
|
+
...(params.requiresEnvReference !== undefined && { requiresEnvReference: params.requiresEnvReference }),
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
writePackageJson(tmp, params.manifest);
|
|
113
|
+
const rawFiles = params.rawFiles ?? [];
|
|
114
|
+
|
|
115
|
+
for (const raw of rawFiles) {
|
|
116
|
+
writeFileSync(join(tmp, raw.relativePath), raw.content);
|
|
95
117
|
}
|
|
96
118
|
};
|
|
97
119
|
|
|
@@ -111,7 +133,7 @@ const writePackageJson = (storeDir: string, manifest: Manifest): void => {
|
|
|
111
133
|
writeFileSync(join(storeDir, "package.json"), `${JSON.stringify(manifest, null, 2)}\n`);
|
|
112
134
|
};
|
|
113
135
|
|
|
114
|
-
const swapStore = (tmp: string, storeDir: string
|
|
136
|
+
const swapStore = (tmp: string, storeDir: string): void => {
|
|
115
137
|
const previous = `${storeDir}.old`;
|
|
116
138
|
rmSync(previous, { recursive: true, force: true });
|
|
117
139
|
|
|
@@ -121,15 +143,46 @@ const swapStore = (tmp: string, storeDir: string, visibleLink: string): void =>
|
|
|
121
143
|
|
|
122
144
|
renameSync(tmp, storeDir);
|
|
123
145
|
rmSync(previous, { recursive: true, force: true });
|
|
124
|
-
symlinkRelative(visibleLink, storeDir);
|
|
125
146
|
};
|
|
126
147
|
|
|
148
|
+
const isStoreLinked = (link: StoreLink): boolean => {
|
|
149
|
+
try {
|
|
150
|
+
return realpathSync(link.linkDir) === realpathSync(link.storeDir);
|
|
151
|
+
} catch {
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
const ensureStoreLink = (link: StoreLink): void => {
|
|
157
|
+
if (!existsSync(join(link.storeDir, "package.json")) || isStoreLinked(link)) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
symlinkRelative(link.linkDir, link.storeDir);
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
const storeWriteMessage = (storeDir: string, error: unknown): string =>
|
|
165
|
+
`Cannot write the generated store to ${storeDir}: ${errorMessage(error)}. ` +
|
|
166
|
+
"Codegen writes the store into the node_modules the @gtkx packages resolve from, " +
|
|
167
|
+
`so ${dirname(storeDir)} has to be writable.`;
|
|
168
|
+
|
|
127
169
|
const createTempStore = (storeDir: string): string => {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
170
|
+
try {
|
|
171
|
+
const tmp = createStagingDir(storeDir);
|
|
172
|
+
chmodSync(tmp, STORE_DIR_MODE);
|
|
131
173
|
|
|
132
|
-
|
|
174
|
+
return tmp;
|
|
175
|
+
} catch (error) {
|
|
176
|
+
throw new Error(storeWriteMessage(storeDir, error), { cause: error });
|
|
177
|
+
}
|
|
133
178
|
};
|
|
134
179
|
|
|
135
|
-
export {
|
|
180
|
+
export {
|
|
181
|
+
subpathExport,
|
|
182
|
+
buildManifest,
|
|
183
|
+
ensureStoreLink,
|
|
184
|
+
namespaceBarrel,
|
|
185
|
+
writeStore,
|
|
186
|
+
type StoreOptions,
|
|
187
|
+
type RawFile,
|
|
188
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { type ResolvedStore, resolveStore } from "./resolve-store.js";
|
|
4
|
+
import { ensureStoreLink } from "./store-fs.js";
|
|
5
|
+
|
|
6
|
+
const resolvedStores: Map<string, ResolvedStore> = new Map();
|
|
7
|
+
|
|
8
|
+
const resolveStoreOrNull = (projectRoot: string): ResolvedStore | null => {
|
|
9
|
+
try {
|
|
10
|
+
return resolveStore(projectRoot);
|
|
11
|
+
} catch {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const isStoreDirPresent = (store: ResolvedStore): boolean => existsSync(join(store.gi.storeDir, "package.json"));
|
|
17
|
+
|
|
18
|
+
const storeFor = (projectRoot: string): ResolvedStore | null => {
|
|
19
|
+
const cached = resolvedStores.get(projectRoot);
|
|
20
|
+
|
|
21
|
+
if (cached !== undefined && isStoreDirPresent(cached)) {
|
|
22
|
+
return cached;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const resolved = resolveStoreOrNull(projectRoot);
|
|
26
|
+
resolvedStores.delete(projectRoot);
|
|
27
|
+
|
|
28
|
+
if (resolved !== null) {
|
|
29
|
+
resolvedStores.set(projectRoot, resolved);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return resolved;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const ensureStoreLinks = (projectRoot: string): void => {
|
|
36
|
+
const store = storeFor(projectRoot);
|
|
37
|
+
|
|
38
|
+
if (store === null) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
for (const unit of [store.gi, store.jsx]) {
|
|
43
|
+
if (unit !== null) {
|
|
44
|
+
ensureStoreLink(unit);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export { ensureStoreLinks };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ModuleContext } from "./context.js";
|
|
2
|
+
|
|
3
|
+
const COMPARISON_CONTEXTS: WeakMap<ModuleContext, ModuleContext> = new WeakMap();
|
|
4
|
+
|
|
5
|
+
const comparisonContextFor = (context: ModuleContext): ModuleContext => {
|
|
6
|
+
const existing = COMPARISON_CONTEXTS.get(context);
|
|
7
|
+
|
|
8
|
+
if (existing !== undefined) {
|
|
9
|
+
return existing;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const created = new ModuleContext(context.namespace, context.library);
|
|
13
|
+
COMPARISON_CONTEXTS.set(context, created);
|
|
14
|
+
|
|
15
|
+
return created;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export { comparisonContextFor };
|
package/src/writer/context.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Library } from "../gir/library.js";
|
|
2
2
|
import type { GirNamespace } from "../gir/namespace.js";
|
|
3
|
-
import { type
|
|
3
|
+
import { type Declaration, ModuleBuilder } from "./module.js";
|
|
4
4
|
|
|
5
5
|
class ModuleContext {
|
|
6
6
|
public module: ModuleBuilder = new ModuleBuilder();
|
|
@@ -55,16 +55,22 @@ class ModuleContext {
|
|
|
55
55
|
return namespaceName;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
declare(declaration: Declaration): void {
|
|
59
|
+
const { name, code, owner } = declaration;
|
|
60
|
+
|
|
61
|
+
this.module.appendDeclaration({
|
|
62
|
+
name,
|
|
63
|
+
code,
|
|
64
|
+
owner: owner === undefined ? undefined : `${this.namespace.name}.${owner}`,
|
|
65
|
+
});
|
|
60
66
|
}
|
|
61
67
|
|
|
62
|
-
qualify(namespaceName: string,
|
|
68
|
+
qualify(namespaceName: string, name: string): string {
|
|
63
69
|
if (namespaceName === this.namespace.name) {
|
|
64
|
-
return
|
|
70
|
+
return name;
|
|
65
71
|
}
|
|
66
72
|
|
|
67
|
-
return `${this.addCrossNamespaceImport(namespaceName)}.${
|
|
73
|
+
return `${this.addCrossNamespaceImport(namespaceName)}.${name}`;
|
|
68
74
|
}
|
|
69
75
|
}
|
|
70
76
|
|
package/src/writer/module.ts
CHANGED
|
@@ -1,30 +1,109 @@
|
|
|
1
1
|
import { ImportsBuilder } from "./imports.js";
|
|
2
2
|
|
|
3
|
-
type
|
|
3
|
+
type Declaration = {
|
|
4
4
|
name: string;
|
|
5
|
-
|
|
5
|
+
code: string;
|
|
6
|
+
owner?: string | undefined;
|
|
6
7
|
};
|
|
7
8
|
|
|
9
|
+
type ExportedDeclaration = {
|
|
10
|
+
name: string;
|
|
11
|
+
spaces: string[];
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const EXPORTED_DECLARATION = /^export (?:abstract )?(class|const|enum|function|interface|type) ([A-Za-z_$][\w$]*)/mu;
|
|
15
|
+
|
|
16
|
+
const SPACES_BY_KEYWORD: Map<string, string[]> = new Map([
|
|
17
|
+
["class", ["value", "type"]],
|
|
18
|
+
["const", ["value"]],
|
|
19
|
+
["enum", ["value", "type"]],
|
|
20
|
+
["function", ["value"]],
|
|
21
|
+
["interface", []],
|
|
22
|
+
["type", ["type"]],
|
|
23
|
+
]);
|
|
24
|
+
|
|
25
|
+
const getExportedDeclaration = (code: string): ExportedDeclaration | undefined => {
|
|
26
|
+
const match = EXPORTED_DECLARATION.exec(code);
|
|
27
|
+
const spaces = SPACES_BY_KEYWORD.get(match?.[1] ?? "");
|
|
28
|
+
const name = match?.[2];
|
|
29
|
+
|
|
30
|
+
return spaces === undefined || name === undefined ? undefined : { name, spaces };
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const exportedNameText = (exported: ExportedDeclaration | undefined): string =>
|
|
34
|
+
exported === undefined ? "no name at all" : `'${exported.name}'`;
|
|
35
|
+
|
|
8
36
|
class ModuleBuilder {
|
|
9
37
|
private bindings: string[] = [];
|
|
10
38
|
private bindingNames: Set<string> = new Set();
|
|
11
39
|
private hoistedDescriptors: Map<string, string> = new Map();
|
|
40
|
+
private claimedSpaces: Set<string> = new Set();
|
|
12
41
|
private declarations: string[] = [];
|
|
42
|
+
private declaredNames: Set<string> = new Set();
|
|
13
43
|
private declaredTypes: Map<string, string> = new Map();
|
|
14
44
|
private registrations: string[] = [];
|
|
45
|
+
private requiredNames: Set<string> = new Set();
|
|
15
46
|
public imports: ImportsBuilder = new ImportsBuilder();
|
|
16
47
|
|
|
17
|
-
private
|
|
18
|
-
const
|
|
48
|
+
private claimSpace(name: string, space: string): void {
|
|
49
|
+
const key = `${space} ${name}`;
|
|
50
|
+
|
|
51
|
+
if (this.claimedSpaces.has(key)) {
|
|
52
|
+
throw new Error(
|
|
53
|
+
`The generated module declares '${name}' twice in its ${space} space. ` +
|
|
54
|
+
"A module may declare each exported name once per declaration space.",
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
this.claimedSpaces.add(key);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private claimExportedName(declaration: Declaration): void {
|
|
62
|
+
const exported = getExportedDeclaration(declaration.code);
|
|
63
|
+
const spaces = exported?.name === declaration.name ? exported.spaces : undefined;
|
|
64
|
+
|
|
65
|
+
if (spaces === undefined) {
|
|
66
|
+
throw new Error(
|
|
67
|
+
`The declaration recorded as '${declaration.name}' exports ${exportedNameText(exported)}. ` +
|
|
68
|
+
"A declaration may only be recorded under the name its own code exports.",
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
for (const space of spaces) {
|
|
73
|
+
this.claimSpace(declaration.name, space);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private claimTypeName(declaration: Declaration): void {
|
|
78
|
+
const { name, owner } = declaration;
|
|
79
|
+
|
|
80
|
+
if (owner === undefined) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const previous = this.declaredTypes.get(name);
|
|
19
85
|
|
|
20
|
-
if (
|
|
86
|
+
if (previous !== undefined && previous !== owner) {
|
|
21
87
|
throw new Error(
|
|
22
|
-
`The generated type '${
|
|
88
|
+
`The generated type '${name}' is declared for both ${previous} and ${owner}. ` +
|
|
23
89
|
"Rename one of them, or drop the namespace from the configuration.",
|
|
24
90
|
);
|
|
25
91
|
}
|
|
26
92
|
|
|
27
|
-
this.declaredTypes.set(
|
|
93
|
+
this.declaredTypes.set(name, owner);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
private verifyRegistrations(): void {
|
|
97
|
+
const missing = [...this.requiredNames].filter((name) => !this.declaredNames.has(name));
|
|
98
|
+
|
|
99
|
+
if (missing.length === 0) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
throw new Error(
|
|
104
|
+
`The generated module registers ${missing.join(", ")}, which it never declares. ` +
|
|
105
|
+
"A registration may only name a symbol whose declaration the same module emits.",
|
|
106
|
+
);
|
|
28
107
|
}
|
|
29
108
|
|
|
30
109
|
appendBinding(code: string, name?: string): void {
|
|
@@ -53,19 +132,27 @@ class ModuleBuilder {
|
|
|
53
132
|
return name;
|
|
54
133
|
}
|
|
55
134
|
|
|
56
|
-
appendDeclaration(
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
135
|
+
appendDeclaration(declaration: Declaration): void {
|
|
136
|
+
this.claimExportedName(declaration);
|
|
137
|
+
this.claimTypeName(declaration);
|
|
138
|
+
this.declaredNames.add(declaration.name);
|
|
139
|
+
this.declarations.push(declaration.code);
|
|
140
|
+
}
|
|
60
141
|
|
|
61
|
-
|
|
142
|
+
hasExports(): boolean {
|
|
143
|
+
return this.declaredNames.size > 0;
|
|
62
144
|
}
|
|
63
145
|
|
|
64
|
-
appendRegistration(code: string): void {
|
|
146
|
+
appendRegistration(code: string, requires: string[] = []): void {
|
|
147
|
+
for (const name of requires) {
|
|
148
|
+
this.requiredNames.add(name);
|
|
149
|
+
}
|
|
150
|
+
|
|
65
151
|
this.registrations.push(code);
|
|
66
152
|
}
|
|
67
153
|
|
|
68
154
|
toSource(): string {
|
|
155
|
+
this.verifyRegistrations();
|
|
69
156
|
const sections: string[] = [];
|
|
70
157
|
const importsBlock = this.imports.toSource();
|
|
71
158
|
|
|
@@ -89,4 +176,4 @@ class ModuleBuilder {
|
|
|
89
176
|
}
|
|
90
177
|
}
|
|
91
178
|
|
|
92
|
-
export { type
|
|
179
|
+
export { type Declaration, ModuleBuilder };
|