@gtkx/cli 1.0.0-rc.1 → 1.0.0-rc.3
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/dist/builder.d.ts +3 -2
- package/dist/builder.d.ts.map +1 -1
- package/dist/builder.js +2 -1
- package/dist/builder.js.map +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +21 -6
- package/dist/cli.js.map +1 -1
- package/dist/codegen/freshness.d.ts +5 -5
- package/dist/codegen/freshness.d.ts.map +1 -1
- package/dist/codegen/freshness.js +26 -23
- package/dist/codegen/freshness.js.map +1 -1
- package/dist/codegen/report.d.ts +2 -1
- package/dist/codegen/report.d.ts.map +1 -1
- package/dist/codegen/report.js +4 -2
- package/dist/codegen/report.js.map +1 -1
- package/dist/codegen/run-codegen.d.ts +10 -10
- package/dist/codegen/run-codegen.d.ts.map +1 -1
- package/dist/codegen/run-codegen.js +72 -47
- package/dist/codegen/run-codegen.js.map +1 -1
- package/dist/codegen/store-resolver.d.ts +9 -6
- package/dist/codegen/store-resolver.d.ts.map +1 -1
- package/dist/codegen/store-resolver.js +24 -7
- package/dist/codegen/store-resolver.js.map +1 -1
- package/dist/commands/build.d.ts +4 -3
- package/dist/commands/build.d.ts.map +1 -1
- package/dist/commands/build.js +2 -1
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/codegen.d.ts +2 -1
- package/dist/commands/codegen.d.ts.map +1 -1
- package/dist/commands/codegen.js +6 -4
- package/dist/commands/codegen.js.map +1 -1
- package/dist/commands/dev.d.ts +2 -1
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +2 -1
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/docs.d.ts +2 -1
- package/dist/commands/docs.d.ts.map +1 -1
- package/dist/commands/docs.js +25 -7
- package/dist/commands/docs.js.map +1 -1
- package/dist/dev/icon-dir.d.ts +2 -1
- package/dist/dev/icon-dir.d.ts.map +1 -1
- package/dist/dev/icon-dir.js +6 -3
- package/dist/dev/icon-dir.js.map +1 -1
- package/dist/dev/refresh-tracker.d.ts +5 -4
- package/dist/dev/refresh-tracker.d.ts.map +1 -1
- package/dist/dev/refresh-tracker.js +6 -5
- package/dist/dev/refresh-tracker.js.map +1 -1
- package/dist/dev/runner-deps.d.ts +2 -1
- package/dist/dev/runner-deps.d.ts.map +1 -1
- package/dist/dev/runner-deps.js +20 -4
- package/dist/dev/runner-deps.js.map +1 -1
- package/dist/dev/runner-main.d.ts +2 -1
- package/dist/dev/runner-main.d.ts.map +1 -1
- package/dist/dev/runner-main.js +3 -2
- package/dist/dev/runner-main.js.map +1 -1
- package/dist/dev/runner.d.ts +6 -5
- package/dist/dev/runner.d.ts.map +1 -1
- package/dist/dev/runner.js +69 -38
- package/dist/dev/runner.js.map +1 -1
- package/dist/dev/schema-dir.d.ts +2 -1
- package/dist/dev/schema-dir.d.ts.map +1 -1
- package/dist/dev/schema-dir.js +4 -2
- package/dist/dev/schema-dir.js.map +1 -1
- package/dist/dev/supervisor.d.ts +7 -6
- package/dist/dev/supervisor.d.ts.map +1 -1
- package/dist/dev/supervisor.js +107 -67
- package/dist/dev/supervisor.js.map +1 -1
- package/dist/dev/vite-dev-server.d.ts +3 -3
- package/dist/dev/vite-dev-server.d.ts.map +1 -1
- package/dist/dev/vite-dev-server.js +2 -1
- package/dist/dev/vite-dev-server.js.map +1 -1
- package/dist/internal/banner.d.ts +2 -1
- package/dist/internal/banner.d.ts.map +1 -1
- package/dist/internal/banner.js +2 -1
- package/dist/internal/banner.js.map +1 -1
- package/dist/internal/data-dir.d.ts +3 -2
- package/dist/internal/data-dir.d.ts.map +1 -1
- package/dist/internal/data-dir.js +29 -14
- package/dist/internal/data-dir.js.map +1 -1
- package/dist/internal/entry-arg.d.ts +5 -4
- package/dist/internal/entry-arg.d.ts.map +1 -1
- package/dist/internal/entry-arg.js +10 -7
- package/dist/internal/entry-arg.js.map +1 -1
- package/dist/internal/errors.d.ts +3 -2
- package/dist/internal/errors.d.ts.map +1 -1
- package/dist/internal/errors.js +7 -5
- package/dist/internal/errors.js.map +1 -1
- package/dist/internal/list-files.d.ts +3 -2
- package/dist/internal/list-files.d.ts.map +1 -1
- package/dist/internal/list-files.js +5 -3
- package/dist/internal/list-files.js.map +1 -1
- package/dist/internal/resolve-cli-tool.d.ts +2 -1
- package/dist/internal/resolve-cli-tool.d.ts.map +1 -1
- package/dist/internal/resolve-cli-tool.js +17 -10
- package/dist/internal/resolve-cli-tool.js.map +1 -1
- package/dist/internal/staging-dir.d.ts +3 -2
- package/dist/internal/staging-dir.d.ts.map +1 -1
- package/dist/internal/staging-dir.js +3 -2
- package/dist/internal/staging-dir.js.map +1 -1
- package/dist/internal/xdg-data-dirs.d.ts +2 -1
- package/dist/internal/xdg-data-dirs.d.ts.map +1 -1
- package/dist/internal/xdg-data-dirs.js +4 -2
- package/dist/internal/xdg-data-dirs.js.map +1 -1
- package/dist/mcp/client.d.ts +9 -4
- package/dist/mcp/client.d.ts.map +1 -1
- package/dist/mcp/client.js +106 -81
- package/dist/mcp/client.js.map +1 -1
- package/dist/mcp/handlers.d.ts +3 -2
- package/dist/mcp/handlers.d.ts.map +1 -1
- package/dist/mcp/handlers.js +89 -61
- package/dist/mcp/handlers.js.map +1 -1
- package/dist/mcp/index.d.ts +2 -2
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +30 -13
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/serialize-widget.d.ts +3 -3
- package/dist/mcp/serialize-widget.d.ts.map +1 -1
- package/dist/mcp/serialize-widget.js +9 -6
- package/dist/mcp/serialize-widget.js.map +1 -1
- package/dist/mcp/testing-loader.d.ts +3 -4
- package/dist/mcp/testing-loader.d.ts.map +1 -1
- package/dist/mcp/testing-loader.js +43 -21
- package/dist/mcp/testing-loader.js.map +1 -1
- package/dist/mcp/widget-registry.d.ts +3 -2
- package/dist/mcp/widget-registry.d.ts.map +1 -1
- package/dist/mcp/widget-registry.js +4 -3
- package/dist/mcp/widget-registry.js.map +1 -1
- package/dist/refresh-globals.d.ts +2 -0
- package/dist/refresh-globals.d.ts.map +1 -0
- package/dist/refresh-globals.js +8 -0
- package/dist/refresh-globals.js.map +1 -0
- package/dist/refresh-runtime.d.ts +5 -11
- package/dist/refresh-runtime.d.ts.map +1 -1
- package/dist/refresh-runtime.js +16 -14
- package/dist/refresh-runtime.js.map +1 -1
- package/dist/settings/compile.d.ts +2 -1
- package/dist/settings/compile.d.ts.map +1 -1
- package/dist/settings/compile.js +6 -4
- package/dist/settings/compile.js.map +1 -1
- package/dist/settings/parser.d.ts +6 -5
- package/dist/settings/parser.d.ts.map +1 -1
- package/dist/settings/parser.js +26 -22
- package/dist/settings/parser.js.map +1 -1
- package/dist/settings/render.d.ts +3 -2
- package/dist/settings/render.d.ts.map +1 -1
- package/dist/settings/render.js +38 -64
- package/dist/settings/render.js.map +1 -1
- package/dist/settings/schema.d.ts +8 -8
- package/dist/settings/schema.d.ts.map +1 -1
- package/dist/settings/schema.js +61 -43
- package/dist/settings/schema.js.map +1 -1
- package/dist/vite-plugins/asset-extensions.d.ts +4 -3
- package/dist/vite-plugins/asset-extensions.d.ts.map +1 -1
- package/dist/vite-plugins/asset-extensions.js +4 -3
- package/dist/vite-plugins/asset-extensions.js.map +1 -1
- package/dist/vite-plugins/built-url.d.ts +2 -1
- package/dist/vite-plugins/built-url.d.ts.map +1 -1
- package/dist/vite-plugins/built-url.js +19 -13
- package/dist/vite-plugins/built-url.js.map +1 -1
- package/dist/vite-plugins/css.d.ts +2 -1
- package/dist/vite-plugins/css.d.ts.map +1 -1
- package/dist/vite-plugins/css.js +23 -15
- package/dist/vite-plugins/css.js.map +1 -1
- package/dist/vite-plugins/fast-refresh/refresh-filter.d.ts +5 -4
- package/dist/vite-plugins/fast-refresh/refresh-filter.d.ts.map +1 -1
- package/dist/vite-plugins/fast-refresh/refresh-filter.js +11 -7
- package/dist/vite-plugins/fast-refresh/refresh-filter.js.map +1 -1
- package/dist/vite-plugins/fast-refresh/swc-refresh.d.ts +4 -3
- package/dist/vite-plugins/fast-refresh/swc-refresh.d.ts.map +1 -1
- package/dist/vite-plugins/fast-refresh/swc-refresh.js +45 -41
- package/dist/vite-plugins/fast-refresh/swc-refresh.js.map +1 -1
- package/dist/vite-plugins/icons.d.ts +2 -1
- package/dist/vite-plugins/icons.d.ts.map +1 -1
- package/dist/vite-plugins/icons.js +24 -20
- package/dist/vite-plugins/icons.js.map +1 -1
- package/dist/vite-plugins/index.d.ts +2 -1
- package/dist/vite-plugins/index.d.ts.map +1 -1
- package/dist/vite-plugins/index.js +4 -3
- package/dist/vite-plugins/index.js.map +1 -1
- package/dist/vite-plugins/native.d.ts +2 -1
- package/dist/vite-plugins/native.d.ts.map +1 -1
- package/dist/vite-plugins/native.js +6 -4
- package/dist/vite-plugins/native.js.map +1 -1
- package/dist/vite-plugins/react-compiler.d.ts +3 -2
- package/dist/vite-plugins/react-compiler.d.ts.map +1 -1
- package/dist/vite-plugins/react-compiler.js +26 -20
- package/dist/vite-plugins/react-compiler.js.map +1 -1
- package/dist/vite-plugins/react-dom-prebundle.d.ts +2 -1
- package/dist/vite-plugins/react-dom-prebundle.d.ts.map +1 -1
- package/dist/vite-plugins/react-dom-prebundle.js +2 -1
- package/dist/vite-plugins/react-dom-prebundle.js.map +1 -1
- package/dist/vite-plugins/resource-init-module.d.ts +2 -1
- package/dist/vite-plugins/resource-init-module.d.ts.map +1 -1
- package/dist/vite-plugins/resource-init-module.js +39 -38
- package/dist/vite-plugins/resource-init-module.js.map +1 -1
- package/dist/vite-plugins/resource-shared.d.ts +7 -5
- package/dist/vite-plugins/resource-shared.d.ts.map +1 -1
- package/dist/vite-plugins/resource-shared.js +17 -10
- package/dist/vite-plugins/resource-shared.js.map +1 -1
- package/dist/vite-plugins/resources.d.ts +3 -2
- package/dist/vite-plugins/resources.d.ts.map +1 -1
- package/dist/vite-plugins/resources.js +95 -55
- package/dist/vite-plugins/resources.js.map +1 -1
- package/dist/vite-plugins/settings-worker-env.d.ts +2 -1
- package/dist/vite-plugins/settings-worker-env.d.ts.map +1 -1
- package/dist/vite-plugins/settings-worker-env.js +4 -2
- package/dist/vite-plugins/settings-worker-env.js.map +1 -1
- package/dist/vite-plugins/settings.d.ts +2 -1
- package/dist/vite-plugins/settings.d.ts.map +1 -1
- package/dist/vite-plugins/settings.js +56 -32
- package/dist/vite-plugins/settings.js.map +1 -1
- package/dist/vite-plugins/strip-query.d.ts +3 -0
- package/dist/vite-plugins/strip-query.d.ts.map +1 -0
- package/dist/vite-plugins/strip-query.js +6 -0
- package/dist/vite-plugins/strip-query.js.map +1 -0
- package/dist/vite-plugins/undeclared-library.d.ts +3 -1
- package/dist/vite-plugins/undeclared-library.d.ts.map +1 -1
- package/dist/vite-plugins/undeclared-library.js +11 -8
- package/dist/vite-plugins/undeclared-library.js.map +1 -1
- package/dist/vite-plugins/virtual-module.d.ts +2 -2
- package/dist/vite-plugins/virtual-module.d.ts.map +1 -1
- package/dist/vite-plugins/virtual-module.js +5 -3
- package/dist/vite-plugins/virtual-module.js.map +1 -1
- package/dist/vitest-plugin.d.ts.map +1 -1
- package/dist/vitest-plugin.js.map +1 -1
- package/env.d.ts +21 -61
- package/package.json +12 -14
- package/src/babel-modules.d.ts +0 -2
- package/src/builder.ts +7 -6
- package/src/cli.ts +26 -6
- package/src/codegen/freshness.ts +39 -26
- package/src/codegen/report.ts +10 -2
- package/src/codegen/run-codegen.ts +131 -66
- package/src/codegen/store-resolver.ts +52 -15
- package/src/commands/build.ts +3 -2
- package/src/commands/codegen.ts +9 -4
- package/src/commands/dev.ts +3 -4
- package/src/commands/docs.ts +47 -7
- package/src/dev/icon-dir.ts +13 -3
- package/src/dev/refresh-tracker.ts +12 -8
- package/src/dev/runner-deps.ts +30 -7
- package/src/dev/runner-main.ts +4 -3
- package/src/dev/runner.ts +100 -41
- package/src/dev/schema-dir.ts +7 -2
- package/src/dev/supervisor.ts +169 -71
- package/src/dev/vite-dev-server.ts +4 -2
- package/src/internal/banner.ts +5 -1
- package/src/internal/data-dir.ts +47 -16
- package/src/internal/entry-arg.ts +16 -8
- package/src/internal/errors.ts +15 -7
- package/src/internal/list-files.ts +10 -4
- package/src/internal/resolve-cli-tool.ts +28 -12
- package/src/internal/staging-dir.ts +5 -2
- package/src/internal/xdg-data-dirs.ts +8 -2
- package/src/mcp/client.ts +143 -85
- package/src/mcp/handlers.ts +126 -69
- package/src/mcp/index.ts +38 -14
- package/src/mcp/serialize-widget.ts +15 -8
- package/src/mcp/testing-loader.ts +64 -23
- package/src/mcp/widget-registry.ts +11 -5
- package/src/refresh-globals.ts +10 -0
- package/src/refresh-runtime.ts +20 -16
- package/src/settings/compile.ts +7 -4
- package/src/settings/parser.ts +69 -30
- package/src/settings/render.ts +66 -66
- package/src/settings/schema.ts +100 -46
- package/src/vite-plugins/asset-extensions.ts +4 -3
- package/src/vite-plugins/built-url.ts +30 -15
- package/src/vite-plugins/css.ts +35 -20
- package/src/vite-plugins/fast-refresh/refresh-filter.ts +18 -10
- package/src/vite-plugins/fast-refresh/swc-refresh.ts +60 -47
- package/src/vite-plugins/icons.ts +40 -24
- package/src/vite-plugins/index.ts +7 -4
- package/src/vite-plugins/native.ts +14 -5
- package/src/vite-plugins/react-compiler.ts +44 -30
- package/src/vite-plugins/react-dom-prebundle.ts +4 -1
- package/src/vite-plugins/resource-init-module.ts +41 -38
- package/src/vite-plugins/resource-shared.ts +27 -14
- package/src/vite-plugins/resources.ts +154 -60
- package/src/vite-plugins/settings-worker-env.ts +7 -2
- package/src/vite-plugins/settings.ts +107 -42
- package/src/vite-plugins/strip-query.ts +7 -0
- package/src/vite-plugins/undeclared-library.ts +26 -16
- package/src/vite-plugins/virtual-module.ts +9 -2
- package/src/vitest-plugin.ts +1 -2
package/src/dev/supervisor.ts
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
|
+
import { error, exitCodeForSignal, info, installGracefulShutdown } from "@gtkx/utils";
|
|
1
2
|
import { fork as nodeFork } from "node:child_process";
|
|
2
3
|
import { type FSWatcher, watch as watchFs } from "node:fs";
|
|
3
4
|
import { basename, dirname } from "node:path";
|
|
4
5
|
import { fileURLToPath } from "node:url";
|
|
5
|
-
import { error, exitCodeForSignal, info, installGracefulShutdown } from "@gtkx/utils";
|
|
6
|
-
|
|
7
|
-
const DEV_RUNNER_URL = new URL("../../bin/gtkx-dev-runner.js", import.meta.url);
|
|
8
|
-
const FORCE_KILL_TIMEOUT_MS = 5000;
|
|
9
|
-
const CONFIG_DEBOUNCE_MS = 150;
|
|
10
|
-
|
|
11
|
-
export const RESTART_EXIT_CODE = 75;
|
|
12
6
|
|
|
13
|
-
|
|
7
|
+
type SupervisedChild = {
|
|
14
8
|
killed: boolean;
|
|
15
9
|
pid?: number | undefined;
|
|
16
10
|
exitCode: number | null;
|
|
@@ -19,12 +13,9 @@ export type SupervisedChild = {
|
|
|
19
13
|
once(event: "exit", listener: (code: number | null, signal: NodeJS.Signals | null) => void): void;
|
|
20
14
|
};
|
|
21
15
|
|
|
22
|
-
|
|
16
|
+
type ForkRunner = (modulePath: string, args: string[], cwd: string) => SupervisedChild;
|
|
23
17
|
|
|
24
|
-
|
|
25
|
-
nodeFork(modulePath, [...args], { cwd, stdio: "inherit", detached: true });
|
|
26
|
-
|
|
27
|
-
export type DevWatch = {
|
|
18
|
+
type DevWatch = {
|
|
28
19
|
paths: string[];
|
|
29
20
|
regenerate: () => Promise<void>;
|
|
30
21
|
};
|
|
@@ -42,116 +33,221 @@ type SupervisorState = {
|
|
|
42
33
|
capturedChildExit: number | undefined;
|
|
43
34
|
};
|
|
44
35
|
|
|
36
|
+
type DebounceTimer = { handle: NodeJS.Timeout | null };
|
|
37
|
+
|
|
38
|
+
const DEV_RUNNER_URL = new URL("../../bin/gtkx-dev-runner.js", import.meta.url);
|
|
39
|
+
const FORCE_KILL_TIMEOUT_MS = 5000;
|
|
40
|
+
const CONFIG_DEBOUNCE_MS = 150;
|
|
41
|
+
const RESTART_EXIT_CODE = 75;
|
|
42
|
+
|
|
43
|
+
const defaultForkRunner: ForkRunner = (modulePath, args, cwd) =>
|
|
44
|
+
nodeFork(modulePath, [...args], { cwd, stdio: "inherit", detached: true });
|
|
45
|
+
|
|
45
46
|
const forwardSignal = (child: SupervisedChild, signal: NodeJS.Signals): void => {
|
|
46
47
|
if (!child.killed) {
|
|
47
48
|
child.kill(signal);
|
|
48
49
|
}
|
|
49
50
|
};
|
|
50
51
|
|
|
51
|
-
const
|
|
52
|
-
if (!child?.pid || child.exitCode !== null || child.killed)
|
|
52
|
+
const didForceKillChild = (child: SupervisedChild | null): boolean => {
|
|
53
|
+
if (!child?.pid || child.exitCode !== null || child.killed) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
|
|
53
57
|
try {
|
|
54
|
-
process.kill(child.pid, "SIGKILL");
|
|
55
|
-
} catch {
|
|
58
|
+
return process.kill(child.pid, "SIGKILL");
|
|
59
|
+
} catch {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const captureShutdownExit = (state: SupervisorState, code: number | null, signal: NodeJS.Signals | null): void => {
|
|
65
|
+
if (code !== null) {
|
|
66
|
+
state.capturedChildExit = code;
|
|
67
|
+
} else if (signal) {
|
|
68
|
+
state.capturedChildExit = exitCodeForSignal(signal);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const handleChildExit = (state: SupervisorState, code: number | null, signal: NodeJS.Signals | null): void => {
|
|
73
|
+
state.child = null;
|
|
74
|
+
|
|
75
|
+
if (state.restarting) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (state.shuttingDown) {
|
|
80
|
+
captureShutdownExit(state, code, signal);
|
|
81
|
+
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (code === RESTART_EXIT_CODE) {
|
|
86
|
+
info("Restarting dev runner...");
|
|
87
|
+
launch(state);
|
|
88
|
+
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
process.exit(code ?? exitCodeForSignal(signal));
|
|
56
93
|
};
|
|
57
94
|
|
|
58
95
|
const launch = (state: SupervisorState): void => {
|
|
59
96
|
const child = state.fork(state.runnerPath, [state.entryPath], state.cwd);
|
|
60
97
|
state.child = child;
|
|
98
|
+
|
|
61
99
|
child.on("exit", (code, signal) => {
|
|
62
|
-
state
|
|
63
|
-
if (state.restarting) return;
|
|
64
|
-
if (state.shuttingDown) {
|
|
65
|
-
if (code !== null) {
|
|
66
|
-
state.capturedChildExit = code;
|
|
67
|
-
} else if (signal) {
|
|
68
|
-
state.capturedChildExit = exitCodeForSignal(signal);
|
|
69
|
-
}
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
if (code === RESTART_EXIT_CODE) {
|
|
73
|
-
info("Restarting dev runner...");
|
|
74
|
-
launch(state);
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
process.exit(code ?? exitCodeForSignal(signal));
|
|
100
|
+
handleChildExit(state, code, signal);
|
|
78
101
|
});
|
|
79
102
|
};
|
|
80
103
|
|
|
104
|
+
const isRestartBlocked = (state: SupervisorState): boolean => state.restarting || state.shuttingDown;
|
|
105
|
+
|
|
106
|
+
const relaunchAfterExit = (state: SupervisorState): void => {
|
|
107
|
+
state.restarting = false;
|
|
108
|
+
|
|
109
|
+
if (state.shuttingDown) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
info("Restarting dev runner...");
|
|
114
|
+
launch(state);
|
|
115
|
+
};
|
|
116
|
+
|
|
81
117
|
const restart = async (state: SupervisorState): Promise<void> => {
|
|
82
|
-
|
|
118
|
+
const watch = state.watch;
|
|
119
|
+
|
|
120
|
+
if (watch === undefined || isRestartBlocked(state)) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
83
124
|
state.restarting = true;
|
|
84
125
|
info("gtkx.config.ts changed; regenerating bindings...");
|
|
126
|
+
|
|
85
127
|
try {
|
|
86
|
-
await
|
|
87
|
-
} catch (
|
|
88
|
-
error("Codegen failed; keeping the current dev runner. Fix the error and save again.",
|
|
128
|
+
await watch.regenerate();
|
|
129
|
+
} catch (error_) {
|
|
130
|
+
error("Codegen failed; keeping the current dev runner. Fix the error and save again.", error_);
|
|
89
131
|
state.restarting = false;
|
|
132
|
+
|
|
90
133
|
return;
|
|
91
134
|
}
|
|
135
|
+
|
|
92
136
|
if (state.shuttingDown) {
|
|
93
137
|
state.restarting = false;
|
|
138
|
+
|
|
94
139
|
return;
|
|
95
140
|
}
|
|
141
|
+
|
|
96
142
|
const current = state.child;
|
|
143
|
+
|
|
97
144
|
if (current === null) {
|
|
98
145
|
state.restarting = false;
|
|
99
146
|
launch(state);
|
|
147
|
+
|
|
100
148
|
return;
|
|
101
149
|
}
|
|
150
|
+
|
|
102
151
|
current.once("exit", () => {
|
|
103
|
-
state
|
|
104
|
-
if (!state.shuttingDown) {
|
|
105
|
-
info("Restarting dev runner...");
|
|
106
|
-
launch(state);
|
|
107
|
-
}
|
|
152
|
+
relaunchAfterExit(state);
|
|
108
153
|
});
|
|
154
|
+
|
|
109
155
|
forwardSignal(current, "SIGTERM");
|
|
110
156
|
};
|
|
111
157
|
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
158
|
+
const scheduleRestart = (state: SupervisorState, timer: DebounceTimer): void => {
|
|
159
|
+
if (timer.handle !== null) {
|
|
160
|
+
clearTimeout(timer.handle);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
timer.handle = setTimeout(() => void restart(state), CONFIG_DEBOUNCE_MS);
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const isWatchedChange = (state: SupervisorState, names: Set<string>, filename: string | Buffer | null): boolean => {
|
|
167
|
+
if (filename === null || state.shuttingDown) {
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return names.has(basename(filename.toString()));
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
const groupWatchNamesByDirectory = (paths: string[]): Map<string, Set<string>> => {
|
|
175
|
+
const namesByDirectory: Map<string, Set<string>> = new Map();
|
|
176
|
+
|
|
177
|
+
for (const path of paths) {
|
|
118
178
|
const directory = dirname(path);
|
|
119
179
|
const names = namesByDirectory.get(directory) ?? new Set<string>();
|
|
120
180
|
names.add(basename(path));
|
|
121
181
|
namesByDirectory.set(directory, names);
|
|
122
182
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
183
|
+
|
|
184
|
+
return namesByDirectory;
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
const watchConfigDirectory = (
|
|
188
|
+
state: SupervisorState,
|
|
189
|
+
directory: string,
|
|
190
|
+
names: Set<string>,
|
|
191
|
+
timer: DebounceTimer,
|
|
192
|
+
): void => {
|
|
193
|
+
const watcher = watchFs(directory, (_event, filename) => {
|
|
194
|
+
if (isWatchedChange(state, names, filename)) {
|
|
195
|
+
scheduleRestart(state, timer);
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
watcher.on("error", (): void => undefined);
|
|
200
|
+
state.watchers.push(watcher);
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
const installConfigWatchers = (state: SupervisorState): void => {
|
|
204
|
+
const watch = state.watch;
|
|
205
|
+
|
|
206
|
+
if (watch === undefined || watch.paths.length === 0) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const timer: DebounceTimer = { handle: null };
|
|
211
|
+
|
|
212
|
+
for (const [directory, names] of groupWatchNamesByDirectory(watch.paths)) {
|
|
213
|
+
watchConfigDirectory(state, directory, names, timer);
|
|
132
214
|
}
|
|
133
215
|
};
|
|
134
216
|
|
|
217
|
+
const closeWatchers = (state: SupervisorState): void => {
|
|
218
|
+
for (const watcher of state.watchers) {
|
|
219
|
+
watcher.close();
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
const shutdownOnSignal = (state: SupervisorState, signal: NodeJS.Signals): Promise<void> =>
|
|
224
|
+
new Promise<void>((resolve) => {
|
|
225
|
+
state.shuttingDown = true;
|
|
226
|
+
closeWatchers(state);
|
|
227
|
+
|
|
228
|
+
if (!state.child) {
|
|
229
|
+
resolve();
|
|
230
|
+
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
state.child.once("exit", () => {
|
|
235
|
+
resolve();
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
forwardSignal(state.child, signal);
|
|
239
|
+
});
|
|
240
|
+
|
|
135
241
|
const installShutdown = (state: SupervisorState): void => {
|
|
136
242
|
installGracefulShutdown({
|
|
137
|
-
onSignal: (signal) =>
|
|
138
|
-
|
|
139
|
-
state.shuttingDown = true;
|
|
140
|
-
for (const watcher of state.watchers) watcher.close();
|
|
141
|
-
if (!state.child) {
|
|
142
|
-
resolve();
|
|
143
|
-
return;
|
|
144
|
-
}
|
|
145
|
-
state.child.once("exit", () => resolve());
|
|
146
|
-
forwardSignal(state.child, signal);
|
|
147
|
-
}),
|
|
148
|
-
onForce: () => forceKillChild(state.child),
|
|
243
|
+
onSignal: (signal) => shutdownOnSignal(state, signal),
|
|
244
|
+
onForce: () => didForceKillChild(state.child),
|
|
149
245
|
forceKillAfterMs: FORCE_KILL_TIMEOUT_MS,
|
|
150
246
|
exitCode: (signal, graceful) => state.capturedChildExit ?? (graceful ? 0 : exitCodeForSignal(signal)),
|
|
151
247
|
});
|
|
152
248
|
};
|
|
153
249
|
|
|
154
|
-
|
|
250
|
+
const runDevSupervisor = async (
|
|
155
251
|
entryPath: string,
|
|
156
252
|
cwd: string,
|
|
157
253
|
watch?: DevWatch,
|
|
@@ -174,5 +270,7 @@ export const runDevSupervisor = async (
|
|
|
174
270
|
installShutdown(state);
|
|
175
271
|
launch(state);
|
|
176
272
|
|
|
177
|
-
return new Promise<never>(() =>
|
|
273
|
+
return new Promise<never>((): void => undefined);
|
|
178
274
|
};
|
|
275
|
+
|
|
276
|
+
export { RESTART_EXIT_CODE, defaultForkRunner, runDevSupervisor, type SupervisedChild, type ForkRunner, type DevWatch };
|
|
@@ -12,7 +12,7 @@ type DevServerModuleGraph = {
|
|
|
12
12
|
invalidateModule(module: DevServerModule): void;
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
type DevServer = {
|
|
16
16
|
close(): Promise<void>;
|
|
17
17
|
moduleGraph: DevServerModuleGraph;
|
|
18
18
|
ssrLoadModule(id: string): Promise<Record<string, unknown>>;
|
|
@@ -21,7 +21,7 @@ export type DevServer = {
|
|
|
21
21
|
};
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
const createDevServerConfig = (root: string, plugins: Plugin[]): InlineConfig => ({
|
|
25
25
|
root,
|
|
26
26
|
appType: "custom",
|
|
27
27
|
plugins,
|
|
@@ -32,3 +32,5 @@ export const createDevServerConfig = (root: string, plugins: Plugin[]): InlineCo
|
|
|
32
32
|
noExternal: [/^@gtkx\/(?!(?:native|gi|gl|runtime|utils|css)(?:\/|$))/, /[/\\]\.gtkx[/\\]/],
|
|
33
33
|
},
|
|
34
34
|
});
|
|
35
|
+
|
|
36
|
+
export { createDevServerConfig, type DevServer };
|
package/src/internal/banner.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import type { Rollup } from "vite";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
const prependBanner = (options: Rollup.OutputOptions, banner: string): Rollup.OutputOptions => {
|
|
4
4
|
const existing = options.banner;
|
|
5
|
+
|
|
5
6
|
if (typeof existing === "function") {
|
|
6
7
|
return { ...options, banner: async (chunk) => `${banner}\n${await existing(chunk)}` };
|
|
7
8
|
}
|
|
9
|
+
|
|
8
10
|
return { ...options, banner: existing ? `${banner}\n${existing}` : banner };
|
|
9
11
|
};
|
|
12
|
+
|
|
13
|
+
export { prependBanner };
|
package/src/internal/data-dir.ts
CHANGED
|
@@ -1,39 +1,70 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
const DATA_IMPORT_PREFIX = "#data";
|
|
5
|
+
const DATA_IMPORT_KEY = `${DATA_IMPORT_PREFIX}/*`;
|
|
6
|
+
const CONDITION_PRIORITY = ["default", "import", "node"] as const;
|
|
7
|
+
const DATA_TARGET_PATTERN = /^\.?\/?(.+?)\/\*$/;
|
|
5
8
|
|
|
6
|
-
const
|
|
9
|
+
const isConditionMap = (entry: unknown): entry is Record<string, unknown> =>
|
|
10
|
+
entry !== null && typeof entry === "object" && !Array.isArray(entry);
|
|
7
11
|
|
|
8
|
-
const
|
|
12
|
+
const conditionTarget = (conditions: Record<string, unknown>): string | null => {
|
|
13
|
+
for (const condition of CONDITION_PRIORITY) {
|
|
14
|
+
const value = conditions[condition];
|
|
9
15
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
if (entry !== null && typeof entry === "object" && !Array.isArray(entry)) {
|
|
13
|
-
const conditions = entry as Record<string, unknown>;
|
|
14
|
-
for (const condition of CONDITION_PRIORITY) {
|
|
15
|
-
const value = conditions[condition];
|
|
16
|
-
if (typeof value === "string") return value;
|
|
16
|
+
if (typeof value === "string") {
|
|
17
|
+
return value;
|
|
17
18
|
}
|
|
18
19
|
}
|
|
20
|
+
|
|
19
21
|
return null;
|
|
20
22
|
};
|
|
21
23
|
|
|
22
|
-
const
|
|
24
|
+
const targetString = (entry: unknown): string | null => {
|
|
25
|
+
if (typeof entry === "string") {
|
|
26
|
+
return entry;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (isConditionMap(entry)) {
|
|
30
|
+
return conditionTarget(entry);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return null;
|
|
34
|
+
};
|
|
23
35
|
|
|
24
36
|
const directoryFromTarget = (target: string): string | null => {
|
|
25
37
|
const match = DATA_TARGET_PATTERN.exec(target);
|
|
38
|
+
|
|
26
39
|
return match?.[1] ?? null;
|
|
27
40
|
};
|
|
28
41
|
|
|
29
|
-
|
|
30
|
-
let manifest:
|
|
42
|
+
const resolveDataDir = (root: string): string | null => {
|
|
43
|
+
let manifest: unknown;
|
|
44
|
+
|
|
31
45
|
try {
|
|
32
|
-
manifest = JSON.parse(readFileSync(join(root, "package.json"), "
|
|
46
|
+
manifest = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
|
|
33
47
|
} catch {
|
|
34
48
|
return null;
|
|
35
49
|
}
|
|
36
|
-
|
|
37
|
-
if (
|
|
50
|
+
|
|
51
|
+
if (!isConditionMap(manifest)) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const imports = manifest.imports;
|
|
56
|
+
|
|
57
|
+
if (!isConditionMap(imports)) {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const target = targetString(imports[DATA_IMPORT_KEY]);
|
|
62
|
+
|
|
63
|
+
if (target === null) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
|
|
38
67
|
return directoryFromTarget(target);
|
|
39
68
|
};
|
|
69
|
+
|
|
70
|
+
export { DATA_IMPORT_PREFIX, resolveDataDir };
|
|
@@ -1,19 +1,20 @@
|
|
|
1
|
+
import type { PositionalArgDef, StringArgDef } from "citty";
|
|
1
2
|
import { existsSync } from "node:fs";
|
|
2
3
|
import { resolve } from "node:path";
|
|
3
|
-
import type { PositionalArgDef, StringArgDef } from "citty";
|
|
4
4
|
|
|
5
5
|
const DEFAULT_ENTRY_BASE = "src/index";
|
|
6
|
-
const
|
|
6
|
+
const DEFAULT_ENTRY_EXTENSION = ".tsx";
|
|
7
|
+
const DEFAULT_ENTRY_EXTENSIONS = [DEFAULT_ENTRY_EXTENSION, ".jsx", ".ts", ".js"];
|
|
7
8
|
const DEFAULT_ENTRY = `${DEFAULT_ENTRY_BASE}{${DEFAULT_ENTRY_EXTENSIONS.join(",")}}`;
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
const cwdArg: { cwd: StringArgDef } = {
|
|
10
11
|
cwd: {
|
|
11
12
|
type: "string",
|
|
12
13
|
description: "Project root (default: current working directory)",
|
|
13
14
|
},
|
|
14
15
|
};
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
const entryArg: { entry: PositionalArgDef; cwd: StringArgDef } = {
|
|
17
18
|
entry: {
|
|
18
19
|
type: "positional",
|
|
19
20
|
description: `Entry file (default: ${DEFAULT_ENTRY})`,
|
|
@@ -22,17 +23,24 @@ export const entryArg: { entry: PositionalArgDef; cwd: StringArgDef } = {
|
|
|
22
23
|
...cwdArg,
|
|
23
24
|
};
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
const resolveCwd = (args: { cwd?: string }): string => (args.cwd ? resolve(args.cwd) : process.cwd());
|
|
26
27
|
|
|
27
28
|
const resolveDefaultEntry = (cwd: string): string => {
|
|
28
29
|
for (const extension of DEFAULT_ENTRY_EXTENSIONS) {
|
|
29
30
|
const candidate = resolve(cwd, `${DEFAULT_ENTRY_BASE}${extension}`);
|
|
30
|
-
|
|
31
|
+
|
|
32
|
+
if (existsSync(candidate)) {
|
|
33
|
+
return candidate;
|
|
34
|
+
}
|
|
31
35
|
}
|
|
32
|
-
|
|
36
|
+
|
|
37
|
+
return resolve(cwd, `${DEFAULT_ENTRY_BASE}${DEFAULT_ENTRY_EXTENSION}`);
|
|
33
38
|
};
|
|
34
39
|
|
|
35
|
-
|
|
40
|
+
const resolveEntry = (args: { entry?: string; cwd?: string }): { cwd: string; entry: string } => {
|
|
36
41
|
const cwd = resolveCwd(args);
|
|
42
|
+
|
|
37
43
|
return { cwd, entry: args.entry ? resolve(cwd, args.entry) : resolveDefaultEntry(cwd) };
|
|
38
44
|
};
|
|
45
|
+
|
|
46
|
+
export { cwdArg, entryArg, resolveCwd, resolveEntry };
|
package/src/internal/errors.ts
CHANGED
|
@@ -1,28 +1,36 @@
|
|
|
1
|
-
import { logger } from "@gtkx/utils";
|
|
2
1
|
import type { ArgsDef, CommandDef } from "citty";
|
|
2
|
+
import { logger } from "@gtkx/utils";
|
|
3
3
|
|
|
4
4
|
const ERROR_EXIT_CODE = 1;
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
const printError = (cause: unknown): never => {
|
|
7
7
|
const message = cause instanceof Error ? cause.message : String(cause);
|
|
8
8
|
logger.error(message);
|
|
9
|
+
|
|
9
10
|
if (cause instanceof Error && cause.stack !== undefined) {
|
|
10
11
|
logger.debug(cause.stack);
|
|
11
12
|
}
|
|
13
|
+
|
|
12
14
|
process.exit(ERROR_EXIT_CODE);
|
|
13
15
|
};
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
const withErrorBoundary = <T extends ArgsDef>(command: CommandDef<T>): CommandDef<T> => {
|
|
16
18
|
const run = command.run;
|
|
17
|
-
|
|
19
|
+
|
|
20
|
+
if (run === undefined) {
|
|
21
|
+
return command;
|
|
22
|
+
}
|
|
23
|
+
|
|
18
24
|
return {
|
|
19
25
|
...command,
|
|
20
|
-
run: async (context) => {
|
|
26
|
+
run: async (context): Promise<unknown> => {
|
|
21
27
|
try {
|
|
22
28
|
return await run(context);
|
|
23
|
-
} catch (
|
|
24
|
-
printError(
|
|
29
|
+
} catch (error) {
|
|
30
|
+
return printError(error);
|
|
25
31
|
}
|
|
26
32
|
},
|
|
27
33
|
};
|
|
28
34
|
};
|
|
35
|
+
|
|
36
|
+
export { printError, withErrorBoundary };
|
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
import { existsSync, readdirSync } from "node:fs";
|
|
2
2
|
import { join, relative } from "node:path";
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
type ListedFile = {
|
|
5
5
|
absPath: string;
|
|
6
6
|
rel: string;
|
|
7
7
|
};
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
if (!existsSync(dir))
|
|
9
|
+
const listFilesRecursive = (dir: string, shouldInclude?: (name: string) => boolean): ListedFile[] => {
|
|
10
|
+
if (!existsSync(dir)) {
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
|
|
11
14
|
return readdirSync(dir, { recursive: true, withFileTypes: true })
|
|
12
|
-
.filter((entry) => entry.isFile() && (
|
|
15
|
+
.filter((entry) => entry.isFile() && (shouldInclude === undefined || shouldInclude(entry.name)))
|
|
13
16
|
.map((entry) => {
|
|
14
17
|
const absPath = join(entry.parentPath, entry.name);
|
|
18
|
+
|
|
15
19
|
return { absPath, rel: relative(dir, absPath) };
|
|
16
20
|
});
|
|
17
21
|
};
|
|
22
|
+
|
|
23
|
+
export { listFilesRecursive, type ListedFile };
|
|
@@ -1,21 +1,37 @@
|
|
|
1
1
|
import { existsSync, statSync } from "node:fs";
|
|
2
2
|
import { delimiter, join } from "node:path";
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
const cache
|
|
4
|
+
const resolveCliTool = (() => {
|
|
5
|
+
const cache: Map<string, string> = new Map();
|
|
6
6
|
|
|
7
7
|
return (executable: string): string => {
|
|
8
8
|
const cached = cache.get(executable);
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
for (const dir of dirs) {
|
|
13
|
-
const candidate = join(dir, executable);
|
|
14
|
-
if (existsSync(candidate) && statSync(candidate).isFile()) {
|
|
15
|
-
cache.set(executable, candidate);
|
|
16
|
-
return candidate;
|
|
17
|
-
}
|
|
9
|
+
|
|
10
|
+
if (cached) {
|
|
11
|
+
return cached;
|
|
18
12
|
}
|
|
19
|
-
|
|
13
|
+
|
|
14
|
+
const resolved = findInPath(executable);
|
|
15
|
+
cache.set(executable, resolved);
|
|
16
|
+
|
|
17
|
+
return resolved;
|
|
20
18
|
};
|
|
21
19
|
})();
|
|
20
|
+
|
|
21
|
+
const isExecutableFile = (candidate: string): boolean => existsSync(candidate) && statSync(candidate).isFile();
|
|
22
|
+
|
|
23
|
+
const findInPath = (executable: string): string => {
|
|
24
|
+
const dirs = (process.env.PATH ?? "").split(delimiter).filter(Boolean);
|
|
25
|
+
|
|
26
|
+
for (const dir of dirs) {
|
|
27
|
+
const candidate = join(dir, executable);
|
|
28
|
+
|
|
29
|
+
if (isExecutableFile(candidate)) {
|
|
30
|
+
return candidate;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
throw new Error(`${executable} not found in PATH`);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export { resolveCliTool };
|
|
@@ -2,15 +2,18 @@ import { mkdtempSync, rmSync } from "node:fs";
|
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
const removeTempDir = (dir: string): void => {
|
|
6
6
|
rmSync(dir, { recursive: true, force: true, maxRetries: 5 });
|
|
7
7
|
};
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
const withStagingDir = <T>(prefix: string, produce: (dir: string) => T): T => {
|
|
10
10
|
const dir = mkdtempSync(join(tmpdir(), `gtkx-${prefix}-`));
|
|
11
|
+
|
|
11
12
|
try {
|
|
12
13
|
return produce(dir);
|
|
13
14
|
} finally {
|
|
14
15
|
removeTempDir(dir);
|
|
15
16
|
}
|
|
16
17
|
};
|
|
18
|
+
|
|
19
|
+
export { removeTempDir, withStagingDir };
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
const XDG_DATA_DIRS_DEFAULT = "/usr/local/share:/usr/share";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
const prependXdgDataDir = (dir: string, existing: string | undefined): string => {
|
|
4
4
|
const base = existing === undefined || existing.length === 0 ? XDG_DATA_DIRS_DEFAULT : existing;
|
|
5
|
-
|
|
5
|
+
|
|
6
|
+
if (base.split(":").includes(dir)) {
|
|
7
|
+
return base;
|
|
8
|
+
}
|
|
9
|
+
|
|
6
10
|
return `${dir}:${base}`;
|
|
7
11
|
};
|
|
12
|
+
|
|
13
|
+
export { prependXdgDataDir };
|