@wolfstar/cli 0.3.0 → 0.6.0-next-20260914203525
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 +52 -15
- package/dist/{build-DbGs9-s8.js → build-DkjzFPxe.js} +5 -4
- package/dist/build-DkjzFPxe.js.map +1 -0
- package/dist/{build-DkMulM4f.js → build-dgEzXPXg.js} +2 -2
- package/dist/{build-DkMulM4f.js.map → build-dgEzXPXg.js.map} +1 -1
- package/dist/cli.js +4 -4
- package/dist/{commands-BkZNThm8.js → commands-DPGDL7ft.js} +3 -3
- package/dist/commands-DPGDL7ft.js.map +1 -0
- package/dist/{commands-DwqViJ2V.js → commands-hpnmaBM2.js} +4 -4
- package/dist/{commands-DwqViJ2V.js.map → commands-hpnmaBM2.js.map} +1 -1
- package/dist/{dev-BazJrPZ3.js → dev-CcNBBd4V.js} +2 -2
- package/dist/{dev-BazJrPZ3.js.map → dev-CcNBBd4V.js.map} +1 -1
- package/dist/{dev-C6HogNjR.js → dev-DqPTgjUh.js} +36 -8
- package/dist/dev-DqPTgjUh.js.map +1 -0
- package/dist/external-Bk4EESdT.js.map +1 -1
- package/dist/index.d.ts +10 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/locales-CxckVWte.js +104 -0
- package/dist/locales-CxckVWte.js.map +1 -0
- package/dist/log-buffer-D-nj2ZEU.js.map +1 -1
- package/dist/none-DEo7zEr9.js.map +1 -1
- package/dist/plugin-registrations-0YL8vy7b.js +34 -0
- package/dist/plugin-registrations-0YL8vy7b.js.map +1 -0
- package/dist/prepare-B0xgciBK.js +3 -0
- package/dist/prepare-BjFq1zBC.js +147 -0
- package/dist/prepare-BjFq1zBC.js.map +1 -0
- package/dist/{prepare-hOwjyelr.js → prepare-Glg8-d0r.js} +4 -4
- package/dist/prepare-Glg8-d0r.js.map +1 -0
- package/dist/process-supervisor-CJOdmp0W.js.map +1 -1
- package/dist/tsc-BqZfDTD0.js.map +1 -1
- package/dist/{tsdown-Do8vjnIK.js → tsdown-DySpwiDI.js} +14 -9
- package/dist/tsdown-DySpwiDI.js.map +1 -0
- package/dist/{tui-C2P91TgW.js → tui-BCGQrMQo.js} +10 -1
- package/dist/tui-BCGQrMQo.js.map +1 -0
- package/dist/{tunnel-B8Id4-lR.js → tunnel-mGJe2zuE.js} +20 -7
- package/dist/tunnel-mGJe2zuE.js.map +1 -0
- package/dist/{vite-27ZbreDz.js → vite-fhNA6MyF.js} +8 -2
- package/dist/vite-fhNA6MyF.js.map +1 -0
- package/package.json +7 -6
- package/dist/build-DbGs9-s8.js.map +0 -1
- package/dist/builders-NkAoPRdw.js +0 -44
- package/dist/builders-NkAoPRdw.js.map +0 -1
- package/dist/commands-BkZNThm8.js.map +0 -1
- package/dist/dev-C6HogNjR.js.map +0 -1
- package/dist/prepare-90XQCoak.js +0 -3
- package/dist/prepare-CHLrneYU.js +0 -68
- package/dist/prepare-CHLrneYU.js.map +0 -1
- package/dist/prepare-hOwjyelr.js.map +0 -1
- package/dist/tsdown-Do8vjnIK.js.map +0 -1
- package/dist/tui-C2P91TgW.js.map +0 -1
- package/dist/tunnel-B8Id4-lR.js.map +0 -1
- package/dist/vite-27ZbreDz.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ConfigError, ConfigErrorOptions, ResolvedStarsConfig, loadStarsConfig } from "@wolfstar/http-framework/config";
|
|
2
2
|
//#region src/lib/errors.d.ts
|
|
3
|
-
declare const ExitCode: {
|
|
3
|
+
export declare const ExitCode: {
|
|
4
4
|
readonly Ok: 0;
|
|
5
5
|
readonly Error: 1;
|
|
6
6
|
readonly InvalidConfig: 2;
|
|
@@ -8,7 +8,7 @@ declare const ExitCode: {
|
|
|
8
8
|
readonly Interrupted: 130;
|
|
9
9
|
readonly Terminated: 143;
|
|
10
10
|
};
|
|
11
|
-
type ExitCode = (typeof ExitCode)[keyof typeof ExitCode];
|
|
11
|
+
export type ExitCode = (typeof ExitCode)[keyof typeof ExitCode];
|
|
12
12
|
interface CliErrorOptions {
|
|
13
13
|
/** A stable, machine readable code. */
|
|
14
14
|
code: string;
|
|
@@ -20,7 +20,7 @@ interface CliErrorOptions {
|
|
|
20
20
|
/**
|
|
21
21
|
* An error the CLI reports to the user without a stack trace.
|
|
22
22
|
*/
|
|
23
|
-
declare class CliError extends Error {
|
|
23
|
+
export declare class CliError extends Error {
|
|
24
24
|
readonly code: string;
|
|
25
25
|
readonly hint: string | null;
|
|
26
26
|
readonly exitCode: ExitCode;
|
|
@@ -32,8 +32,8 @@ declare class CliError extends Error {
|
|
|
32
32
|
* `ConfigError` comes from `@wolfstar/http-framework/config`: the framework validates `stars.config.*` and throws a
|
|
33
33
|
* plain data error, the CLI decides how it looks on a terminal and which exit code it gets ({@link exitCodeOf}).
|
|
34
34
|
*/
|
|
35
|
-
declare function formatError(error: unknown): string;
|
|
36
|
-
declare function exitCodeOf(error: unknown): ExitCode;
|
|
35
|
+
export declare function formatError(error: unknown): string;
|
|
36
|
+
export declare function exitCodeOf(error: unknown): ExitCode;
|
|
37
37
|
//#endregion
|
|
38
38
|
//#region src/lib/output-mode.d.ts
|
|
39
39
|
type OutputMode = 'tui' | 'plain';
|
|
@@ -55,16 +55,16 @@ interface ResolveOutputModeOptions {
|
|
|
55
55
|
*
|
|
56
56
|
* Precedence: `--no-tui` › `STARS_TUI=plain` › non-interactive stdout, CI or `TERM=dumb`.
|
|
57
57
|
*/
|
|
58
|
-
declare function resolveOutputMode(options?: ResolveOutputModeOptions): OutputMode;
|
|
59
|
-
declare function isCIEnvironment(env?: NodeJS.ProcessEnv): boolean;
|
|
58
|
+
export declare function resolveOutputMode(options?: ResolveOutputModeOptions): OutputMode;
|
|
59
|
+
export declare function isCIEnvironment(env?: NodeJS.ProcessEnv): boolean;
|
|
60
60
|
/**
|
|
61
61
|
* Whether colours should be emitted, honouring `NO_COLOR` and `FORCE_COLOR`.
|
|
62
62
|
*/
|
|
63
|
-
declare function shouldUseColor(env?: NodeJS.ProcessEnv, isTTY?: boolean): boolean;
|
|
63
|
+
export declare function shouldUseColor(env?: NodeJS.ProcessEnv, isTTY?: boolean): boolean;
|
|
64
64
|
/**
|
|
65
65
|
* Whether animations (spinners, blinking status) should be avoided.
|
|
66
66
|
*/
|
|
67
|
-
declare function prefersReducedMotion(env?: NodeJS.ProcessEnv): boolean;
|
|
67
|
+
export declare function prefersReducedMotion(env?: NodeJS.ProcessEnv): boolean;
|
|
68
68
|
//#endregion
|
|
69
|
-
export {
|
|
69
|
+
export { type CliErrorOptions, ConfigError, type ConfigErrorOptions, type OutputMode, type ResolveOutputModeOptions, type ResolvedStarsConfig, loadStarsConfig };
|
|
70
70
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/lib/errors.ts","../src/lib/output-mode.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/lib/errors.ts","../src/lib/output-mode.ts"],"mappings":";;qBAEa;WACZ;WACA;WACA;WACA;WACA;WACA;;YAGW,mBAAmB,uBAAuB;UAErC;;EAEhB;;EAEA;EACA,WAAW;EACX;;;;;qBAMY,iBAAiB;WACb;WACA;WACA,UAAU;EAE1B,YAAmB,iBAAiB,SAAS;;;;;;;;wBAe9B,YAAY;wBAgBZ,WAAW,iBAAiB;;;KC7DhC;UAEK;;EAEhB;EACA,MAAM,OAAO;;EAEb;;EAEA;EACA;EACA;;EAEA;;;;;;;wBAUe,kBAAkB,UAAS,2BAAgC;wBAkB3D,gBAAgB,MAAK,OAAO;;;;wBAU5B,eAAe,MAAK,OAAO,YAA0B;;;;wBASrD,qBAAqB,MAAK,OAAO"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { t as CliError } from "./errors-Bket6XFn.js";
|
|
2
|
+
import { cpSync, existsSync, mkdirSync, rmSync } from "node:fs";
|
|
3
|
+
import { dirname, join, relative } from "node:path";
|
|
4
|
+
import { EventEmitter } from "node:events";
|
|
5
|
+
|
|
6
|
+
//#region src/lib/builders/index.ts
|
|
7
|
+
/**
|
|
8
|
+
* Fails on experiments the CLI cannot honour yet, before a command gets far enough to look like it worked.
|
|
9
|
+
*
|
|
10
|
+
* Called by `stars dev`/`stars build` up front, since a project whose build tool needs no build at all would
|
|
11
|
+
* otherwise return early and never reach {@link createBuilder}.
|
|
12
|
+
*/
|
|
13
|
+
function assertSupportedExperiments(config) {
|
|
14
|
+
if (config.experimental.enableNitro) throw new CliError("`experimental.enableNitro` is not implemented yet", {
|
|
15
|
+
code: "EXPERIMENT_UNAVAILABLE",
|
|
16
|
+
hint: "Nitro needs the framework's Fetch adapter (wolfstar-project/stars-components#81); until it lands, use `build.tool` 'tsdown', 'vite' or 'tsc'."
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
async function createBuilder(config) {
|
|
20
|
+
assertSupportedExperiments(config);
|
|
21
|
+
if (config.experimental.enableExternalVite) {
|
|
22
|
+
const { ExternalBuilder } = await import("./external-Bk4EESdT.js");
|
|
23
|
+
return new ExternalBuilder(config);
|
|
24
|
+
}
|
|
25
|
+
switch (config.build.tool) {
|
|
26
|
+
case "tsdown": {
|
|
27
|
+
const { TsdownBuilder } = await import("./tsdown-DySpwiDI.js");
|
|
28
|
+
return new TsdownBuilder(config);
|
|
29
|
+
}
|
|
30
|
+
case "vite": {
|
|
31
|
+
const { ViteBuilder } = await import("./vite-fhNA6MyF.js");
|
|
32
|
+
return new ViteBuilder(config);
|
|
33
|
+
}
|
|
34
|
+
case "tsc": {
|
|
35
|
+
const { TscBuilder } = await import("./tsc-CovVAtfo.js");
|
|
36
|
+
return new TscBuilder(config);
|
|
37
|
+
}
|
|
38
|
+
case "none": {
|
|
39
|
+
const { NoneBuilder } = await import("./none-DEo7zEr9.js");
|
|
40
|
+
return new NoneBuilder(config);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
//#endregion
|
|
46
|
+
//#region src/lib/locales.ts
|
|
47
|
+
/** Keeps the conventional `src/locales` data directory next to the compiled application. */
|
|
48
|
+
var Locales = class extends EventEmitter {
|
|
49
|
+
config;
|
|
50
|
+
source;
|
|
51
|
+
destination;
|
|
52
|
+
#watcher = null;
|
|
53
|
+
constructor(config) {
|
|
54
|
+
super();
|
|
55
|
+
this.config = config;
|
|
56
|
+
this.source = join(config.root, "src", "locales");
|
|
57
|
+
this.destination = join(config.build.outDir, "locales");
|
|
58
|
+
}
|
|
59
|
+
copy() {
|
|
60
|
+
if (this.config.build.tool === "none" || !existsSync(this.source)) return false;
|
|
61
|
+
mkdirSync(this.destination, { recursive: true });
|
|
62
|
+
cpSync(this.source, this.destination, {
|
|
63
|
+
recursive: true,
|
|
64
|
+
force: true
|
|
65
|
+
});
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
async watch() {
|
|
69
|
+
if (this.config.build.tool === "none" || !existsSync(this.source) || this.#watcher) return;
|
|
70
|
+
const { watch } = await import("chokidar");
|
|
71
|
+
const watcher = watch(this.source, { ignoreInitial: true });
|
|
72
|
+
this.#watcher = watcher;
|
|
73
|
+
watcher.on("all", (event, path) => {
|
|
74
|
+
try {
|
|
75
|
+
const target = join(this.destination, relative(this.source, path));
|
|
76
|
+
if (event === "unlink" || event === "unlinkDir") rmSync(target, {
|
|
77
|
+
recursive: event === "unlinkDir",
|
|
78
|
+
force: true
|
|
79
|
+
});
|
|
80
|
+
else if (existsSync(path)) {
|
|
81
|
+
mkdirSync(dirname(target), { recursive: true });
|
|
82
|
+
cpSync(path, target, {
|
|
83
|
+
recursive: event === "addDir",
|
|
84
|
+
force: true
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
this.emit("change");
|
|
88
|
+
} catch (error) {
|
|
89
|
+
this.emit("log", "error", `Failed to copy locales: ${error instanceof Error ? error.message : String(error)}`);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
watcher.on("error", (error) => this.emit("log", "error", error instanceof Error ? error.message : String(error)));
|
|
93
|
+
await new Promise((resolve) => watcher.once("ready", resolve));
|
|
94
|
+
}
|
|
95
|
+
async close() {
|
|
96
|
+
const watcher = this.#watcher;
|
|
97
|
+
this.#watcher = null;
|
|
98
|
+
await watcher?.close();
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
//#endregion
|
|
103
|
+
export { assertSupportedExperiments as n, createBuilder as r, Locales as t };
|
|
104
|
+
//# sourceMappingURL=locales-CxckVWte.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locales-CxckVWte.js","names":[],"sources":["../src/lib/builders/index.ts","../src/lib/locales.ts"],"sourcesContent":["import type { ResolvedStarsConfig } from '@wolfstar/http-framework/config';\nimport { CliError } from '../errors.js';\nimport type { Builder } from './types.js';\n\n/**\n * Fails on experiments the CLI cannot honour yet, before a command gets far enough to look like it worked.\n *\n * Called by `stars dev`/`stars build` up front, since a project whose build tool needs no build at all would\n * otherwise return early and never reach {@link createBuilder}.\n */\nexport function assertSupportedExperiments(config: ResolvedStarsConfig): void {\n\tif (config.experimental.enableNitro) {\n\t\tthrow new CliError('`experimental.enableNitro` is not implemented yet', {\n\t\t\tcode: 'EXPERIMENT_UNAVAILABLE',\n\t\t\thint: \"Nitro needs the framework's Fetch adapter (wolfstar-project/stars-components#81); until it lands, use `build.tool` 'tsdown', 'vite' or 'tsc'.\"\n\t\t});\n\t}\n}\n\nexport async function createBuilder(config: ResolvedStarsConfig): Promise<Builder> {\n\tassertSupportedExperiments(config);\n\n\t// The project runs its own build, so the CLI only watches what it writes (see `ExternalBuilder`).\n\tif (config.experimental.enableExternalVite) {\n\t\tconst { ExternalBuilder } = await import('./external.js');\n\t\treturn new ExternalBuilder(config);\n\t}\n\n\tswitch (config.build.tool) {\n\t\tcase 'tsdown': {\n\t\t\tconst { TsdownBuilder } = await import('./tsdown.js');\n\t\t\treturn new TsdownBuilder(config);\n\t\t}\n\t\tcase 'vite': {\n\t\t\tconst { ViteBuilder } = await import('./vite.js');\n\t\t\treturn new ViteBuilder(config);\n\t\t}\n\t\tcase 'tsc': {\n\t\t\tconst { TscBuilder } = await import('./tsc.js');\n\t\t\treturn new TscBuilder(config);\n\t\t}\n\t\tcase 'none': {\n\t\t\tconst { NoneBuilder } = await import('./none.js');\n\t\t\treturn new NoneBuilder(config);\n\t\t}\n\t}\n}\n\nexport type { Builder, BuilderEvents, BuildOutcome } from './types.js';\n","import { EventEmitter } from 'node:events';\nimport { cpSync, existsSync, mkdirSync, rmSync } from 'node:fs';\nimport { dirname, join, relative } from 'node:path';\nimport type { ResolvedStarsConfig } from '@wolfstar/http-framework/config';\nimport type { LogLevel } from './log-buffer.js';\n\nexport interface LocalesEvents {\n\tchange: [];\n\tlog: [level: LogLevel, text: string];\n}\n\n/** Keeps the conventional `src/locales` data directory next to the compiled application. */\nexport class Locales extends EventEmitter<LocalesEvents> {\n\treadonly source: string;\n\treadonly destination: string;\n\t#watcher: { close(): Promise<void> } | null = null;\n\n\tpublic constructor(private readonly config: ResolvedStarsConfig) {\n\t\tsuper();\n\t\tthis.source = join(config.root, 'src', 'locales');\n\t\tthis.destination = join(config.build.outDir, 'locales');\n\t}\n\n\tpublic copy(): boolean {\n\t\tif (this.config.build.tool === 'none' || !existsSync(this.source)) return false;\n\t\tmkdirSync(this.destination, { recursive: true });\n\t\tcpSync(this.source, this.destination, { recursive: true, force: true });\n\t\treturn true;\n\t}\n\n\tpublic async watch(): Promise<void> {\n\t\tif (this.config.build.tool === 'none' || !existsSync(this.source) || this.#watcher) return;\n\t\tconst { watch } = await import('chokidar');\n\t\tconst watcher = watch(this.source, { ignoreInitial: true });\n\t\tthis.#watcher = watcher;\n\n\t\twatcher.on('all', (event, path) => {\n\t\t\ttry {\n\t\t\t\tconst target = join(this.destination, relative(this.source, path));\n\t\t\t\tif (event === 'unlink' || event === 'unlinkDir') rmSync(target, { recursive: event === 'unlinkDir', force: true });\n\t\t\t\telse if (existsSync(path)) {\n\t\t\t\t\tmkdirSync(dirname(target), { recursive: true });\n\t\t\t\t\tcpSync(path, target, { recursive: event === 'addDir', force: true });\n\t\t\t\t}\n\t\t\t\tthis.emit('change');\n\t\t\t} catch (error) {\n\t\t\t\tthis.emit('log', 'error', `Failed to copy locales: ${error instanceof Error ? error.message : String(error)}`);\n\t\t\t}\n\t\t});\n\t\twatcher.on('error', (error) => this.emit('log', 'error', error instanceof Error ? error.message : String(error)));\n\t\tawait new Promise<void>((resolve) => watcher.once('ready', resolve));\n\t}\n\n\tpublic async close(): Promise<void> {\n\t\tconst watcher = this.#watcher;\n\t\tthis.#watcher = null;\n\t\tawait watcher?.close();\n\t}\n}\n"],"mappings":";;;;;;;;;;;;AAUA,SAAgB,2BAA2B,QAAmC;CAC7E,IAAI,OAAO,aAAa,aACvB,MAAM,IAAI,SAAS,qDAAqD;EACvE,MAAM;EACN,MAAM;CACP,CAAC;AAEH;AAEA,eAAsB,cAAc,QAA+C;CAClF,2BAA2B,MAAM;CAGjC,IAAI,OAAO,aAAa,oBAAoB;EAC3C,MAAM,EAAE,oBAAoB,MAAM,OAAO;EACzC,OAAO,IAAI,gBAAgB,MAAM;CAClC;CAEA,QAAQ,OAAO,MAAM,MAArB;EACC,KAAK,UAAU;GACd,MAAM,EAAE,kBAAkB,MAAM,OAAO;GACvC,OAAO,IAAI,cAAc,MAAM;EAChC;EACA,KAAK,QAAQ;GACZ,MAAM,EAAE,gBAAgB,MAAM,OAAO;GACrC,OAAO,IAAI,YAAY,MAAM;EAC9B;EACA,KAAK,OAAO;GACX,MAAM,EAAE,eAAe,MAAM,OAAO;GACpC,OAAO,IAAI,WAAW,MAAM;EAC7B;EACA,KAAK,QAAQ;GACZ,MAAM,EAAE,gBAAgB,MAAM,OAAO;GACrC,OAAO,IAAI,YAAY,MAAM;EAC9B;CACD;AACD;;;;;AClCA,IAAa,UAAb,cAA6B,aAA4B;CAKpB;CAJpC,AAAS;CACT,AAAS;CACT,WAA8C;CAE9C,AAAO,YAAY,AAAiB,QAA6B;EAChE,MAAM;EAD6B;EAEnC,KAAK,SAAS,KAAK,OAAO,MAAM,OAAO,SAAS;EAChD,KAAK,cAAc,KAAK,OAAO,MAAM,QAAQ,SAAS;CACvD;CAEA,AAAO,OAAgB;EACtB,IAAI,KAAK,OAAO,MAAM,SAAS,UAAU,CAAC,WAAW,KAAK,MAAM,GAAG,OAAO;EAC1E,UAAU,KAAK,aAAa,EAAE,WAAW,KAAK,CAAC;EAC/C,OAAO,KAAK,QAAQ,KAAK,aAAa;GAAE,WAAW;GAAM,OAAO;EAAK,CAAC;EACtE,OAAO;CACR;CAEA,MAAa,QAAuB;EACnC,IAAI,KAAK,OAAO,MAAM,SAAS,UAAU,CAAC,WAAW,KAAK,MAAM,KAAK,KAAK,UAAU;EACpF,MAAM,EAAE,UAAU,MAAM,OAAO;EAC/B,MAAM,UAAU,MAAM,KAAK,QAAQ,EAAE,eAAe,KAAK,CAAC;EAC1D,KAAK,WAAW;EAEhB,QAAQ,GAAG,QAAQ,OAAO,SAAS;GAClC,IAAI;IACH,MAAM,SAAS,KAAK,KAAK,aAAa,SAAS,KAAK,QAAQ,IAAI,CAAC;IACjE,IAAI,UAAU,YAAY,UAAU,aAAa,OAAO,QAAQ;KAAE,WAAW,UAAU;KAAa,OAAO;IAAK,CAAC;SAC5G,IAAI,WAAW,IAAI,GAAG;KAC1B,UAAU,QAAQ,MAAM,GAAG,EAAE,WAAW,KAAK,CAAC;KAC9C,OAAO,MAAM,QAAQ;MAAE,WAAW,UAAU;MAAU,OAAO;KAAK,CAAC;IACpE;IACA,KAAK,KAAK,QAAQ;GACnB,SAAS,OAAO;IACf,KAAK,KAAK,OAAO,SAAS,2BAA2B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAAG;GAC9G;EACD,CAAC;EACD,QAAQ,GAAG,UAAU,UAAU,KAAK,KAAK,OAAO,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,CAAC;EAChH,MAAM,IAAI,SAAe,YAAY,QAAQ,KAAK,SAAS,OAAO,CAAC;CACpE;CAEA,MAAa,QAAuB;EACnC,MAAM,UAAU,KAAK;EACrB,KAAK,WAAW;EAChB,MAAM,SAAS,MAAM;CACtB;AACD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log-buffer-D-nj2ZEU.js","names":[
|
|
1
|
+
{"version":3,"file":"log-buffer-D-nj2ZEU.js","names":[],"sources":["../src/lib/log-buffer.ts"],"sourcesContent":["import { EventEmitter } from 'node:events';\nimport { stripVTControlCharacters } from 'node:util';\n\nexport type LogSource = 'stars' | 'build' | 'app' | 'tsc' | 'tunnel';\nexport type LogLevel = 'debug' | 'info' | 'success' | 'warn' | 'error';\n\nexport interface LogEntry {\n\treadonly id: number;\n\treadonly time: number;\n\treadonly source: LogSource;\n\treadonly level: LogLevel;\n\treadonly text: string;\n}\n\nexport interface LogFilter {\n\tsource?: LogSource | null;\n\tlevel?: LogLevel | null;\n\tquery?: string | null;\n}\n\nexport type LogInput = Omit<LogEntry, 'id' | 'time'>;\n\n/**\n * A bounded, in-memory log store shared by the dev service and its renderers.\n */\nexport class LogBuffer extends EventEmitter<{ entry: [LogEntry]; clear: [] }> {\n\t#entries: LogEntry[] = [];\n\t#nextId = 1;\n\n\tpublic constructor(public readonly capacity = 2000) {\n\t\tsuper();\n\t}\n\n\tpublic push(input: LogInput): LogEntry {\n\t\tconst entry: LogEntry = { id: this.#nextId++, time: Date.now(), ...input };\n\t\tthis.#entries.push(entry);\n\t\tif (this.#entries.length > this.capacity) this.#entries.splice(0, this.#entries.length - this.capacity);\n\t\tthis.emit('entry', entry);\n\t\treturn entry;\n\t}\n\n\tpublic entries(): readonly LogEntry[] {\n\t\treturn this.#entries;\n\t}\n\n\tpublic filter(filter: LogFilter): LogEntry[] {\n\t\tconst query = filter.query?.toLowerCase() ?? null;\n\t\treturn this.#entries.filter(\n\t\t\t(entry) =>\n\t\t\t\t(!filter.source || entry.source === filter.source) &&\n\t\t\t\t(!filter.level || matchesLevel(entry.level, filter.level)) &&\n\t\t\t\t(!query || entry.text.toLowerCase().includes(query))\n\t\t);\n\t}\n\n\tpublic clear(): void {\n\t\tthis.#entries = [];\n\t\tthis.emit('clear');\n\t}\n}\n\nconst LEVEL_ORDER: Record<LogLevel, number> = { debug: 0, info: 1, success: 1, warn: 2, error: 3 };\n\n/**\n * Whether `level` is at least as severe as `minimum`.\n */\nexport function matchesLevel(level: LogLevel, minimum: LogLevel): boolean {\n\treturn LEVEL_ORDER[level] >= LEVEL_ORDER[minimum];\n}\n\n/**\n * Whether an application stderr line only continues the preceding JavaScript error. Stack frames and the fields\n * Node prints after an `Error` are useful log lines, but they must not each increment the panel's error counter.\n */\nexport function isErrorDetail(entry: Pick<LogEntry, 'source' | 'level' | 'text'>): boolean {\n\tif (entry.source !== 'app' || entry.level !== 'error') return false;\n\tconst text = stripVTControlCharacters(entry.text);\n\treturn /^\\s+at\\s/.test(text) || /^\\s+(?:type|path|code|cause|errno|syscall|address|port):/.test(text) || /^\\s*}\\s*$/.test(text) || !text.trim();\n}\n\n/** stderr is a transport, not a severity: Node and many loggers also send warnings there. */\nexport function classifyAppLine(text: string, fallback: LogLevel): LogLevel {\n\tconst plain = stripVTControlCharacters(text);\n\tif (/\\b(?:Error|ERROR|FATAL)\\b|\\bERR_[A-Z_]+\\b/.test(plain)) return 'error';\n\tif (/\\b(?:Warning|WARN|WARNING|DeprecationWarning|ExperimentalWarning)\\b/.test(plain) || /^\\(node:\\d+\\).*warning/i.test(plain)) return 'warn';\n\tif (/^\\s*(?:\\(Use .*--trace-warnings|\\[(?:info|debug)\\]|INFO\\b|DEBUG\\b|[◇ℹ✔])/.test(plain)) return 'info';\n\treturn fallback;\n}\n"],"mappings":";;;;;;;AAyBA,IAAa,YAAb,cAA+B,aAA+C;CAI1C;CAHnC,WAAuB,CAAC;CACxB,UAAU;CAEV,AAAO,YAAY,AAAgB,WAAW,KAAM;EACnD,MAAM;EAD4B;CAEnC;CAEA,AAAO,KAAK,OAA2B;EACtC,MAAM,QAAkB;GAAE,IAAI,KAAK;GAAW,MAAM,KAAK,IAAI;GAAG,GAAG;EAAM;EACzE,KAAK,SAAS,KAAK,KAAK;EACxB,IAAI,KAAK,SAAS,SAAS,KAAK,UAAU,KAAK,SAAS,OAAO,GAAG,KAAK,SAAS,SAAS,KAAK,QAAQ;EACtG,KAAK,KAAK,SAAS,KAAK;EACxB,OAAO;CACR;CAEA,AAAO,UAA+B;EACrC,OAAO,KAAK;CACb;CAEA,AAAO,OAAO,QAA+B;EAC5C,MAAM,QAAQ,OAAO,OAAO,YAAY,KAAK;EAC7C,OAAO,KAAK,SAAS,QACnB,WACC,CAAC,OAAO,UAAU,MAAM,WAAW,OAAO,YAC1C,CAAC,OAAO,SAAS,aAAa,MAAM,OAAO,OAAO,KAAK,OACvD,CAAC,SAAS,MAAM,KAAK,YAAY,CAAC,CAAC,SAAS,KAAK,EACpD;CACD;CAEA,AAAO,QAAc;EACpB,KAAK,WAAW,CAAC;EACjB,KAAK,KAAK,OAAO;CAClB;AACD;AAEA,MAAM,cAAwC;CAAE,OAAO;CAAG,MAAM;CAAG,SAAS;CAAG,MAAM;CAAG,OAAO;AAAE;;;;AAKjG,SAAgB,aAAa,OAAiB,SAA4B;CACzE,OAAO,YAAY,UAAU,YAAY;AAC1C;;;;;AAMA,SAAgB,cAAc,OAA6D;CAC1F,IAAI,MAAM,WAAW,SAAS,MAAM,UAAU,SAAS,OAAO;CAC9D,MAAM,OAAO,yBAAyB,MAAM,IAAI;CAChD,OAAO,WAAW,KAAK,IAAI,KAAK,2DAA2D,KAAK,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,KAAK,KAAK;AAC/I;;AAGA,SAAgB,gBAAgB,MAAc,UAA8B;CAC3E,MAAM,QAAQ,yBAAyB,IAAI;CAC3C,IAAI,4CAA4C,KAAK,KAAK,GAAG,OAAO;CACpE,IAAI,sEAAsE,KAAK,KAAK,KAAK,0BAA0B,KAAK,KAAK,GAAG,OAAO;CACvI,IAAI,2EAA2E,KAAK,KAAK,GAAG,OAAO;CACnG,OAAO;AACR"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"none-DEo7zEr9.js","names":[
|
|
1
|
+
{"version":3,"file":"none-DEo7zEr9.js","names":[],"sources":["../src/lib/builders/none.ts"],"sourcesContent":["import { EventEmitter } from 'node:events';\nimport type { ResolvedStarsConfig } from '@wolfstar/http-framework/config';\nimport type { Builder, BuilderEvents, BuildOutcome } from './types.js';\n\n/**\n * No build step: watches the configured paths and reports every change as an instant successful \"build\".\n */\nexport class NoneBuilder extends EventEmitter<BuilderEvents> implements Builder {\n\tpublic readonly tool = 'none' as const;\n\t#watcher: { close(): Promise<void> } | null = null;\n\n\tpublic constructor(private readonly config: ResolvedStarsConfig) {\n\t\tsuper();\n\t}\n\n\tpublic build(): Promise<BuildOutcome> {\n\t\tthis.emit('start');\n\t\tconst outcome: BuildOutcome = { ok: true, durationMs: 0, message: null };\n\t\tthis.emit('success', outcome);\n\t\treturn Promise.resolve(outcome);\n\t}\n\n\tpublic async watch(): Promise<void> {\n\t\tconst { watch } = await import('chokidar');\n\t\tconst watcher = watch([...this.config.dev.watch], {\n\t\t\tignored: [...this.config.dev.ignore],\n\t\t\tignoreInitial: true,\n\t\t\tcwd: this.config.root\n\t\t});\n\t\tthis.#watcher = watcher;\n\n\t\twatcher.on('all', (event, path) => {\n\t\t\tthis.emit('log', 'info', `${event}: ${path}`);\n\t\t\tvoid this.build();\n\t\t});\n\t\twatcher.on('error', (error) => this.emit('log', 'error', error instanceof Error ? error.message : String(error)));\n\n\t\tawait new Promise<void>((resolve) => watcher.once('ready', resolve));\n\t\tawait this.build();\n\t}\n\n\tpublic async close(): Promise<void> {\n\t\tconst watcher = this.#watcher;\n\t\tthis.#watcher = null;\n\t\tawait watcher?.close();\n\t}\n}\n"],"mappings":";;;;;;AAOA,IAAa,cAAb,cAAiC,aAA+C;CAI3C;CAHpC,AAAgB,OAAO;CACvB,WAA8C;CAE9C,AAAO,YAAY,AAAiB,QAA6B;EAChE,MAAM;EAD6B;CAEpC;CAEA,AAAO,QAA+B;EACrC,KAAK,KAAK,OAAO;EACjB,MAAM,UAAwB;GAAE,IAAI;GAAM,YAAY;GAAG,SAAS;EAAK;EACvE,KAAK,KAAK,WAAW,OAAO;EAC5B,OAAO,QAAQ,QAAQ,OAAO;CAC/B;CAEA,MAAa,QAAuB;EACnC,MAAM,EAAE,UAAU,MAAM,OAAO;EAC/B,MAAM,UAAU,MAAM,CAAC,GAAG,KAAK,OAAO,IAAI,KAAK,GAAG;GACjD,SAAS,CAAC,GAAG,KAAK,OAAO,IAAI,MAAM;GACnC,eAAe;GACf,KAAK,KAAK,OAAO;EAClB,CAAC;EACD,KAAK,WAAW;EAEhB,QAAQ,GAAG,QAAQ,OAAO,SAAS;GAClC,KAAK,KAAK,OAAO,QAAQ,GAAG,MAAM,IAAI,MAAM;GAC5C,AAAK,KAAK,MAAM;EACjB,CAAC;EACD,QAAQ,GAAG,UAAU,UAAU,KAAK,KAAK,OAAO,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,CAAC;EAEhH,MAAM,IAAI,SAAe,YAAY,QAAQ,KAAK,SAAS,OAAO,CAAC;EACnE,MAAM,KAAK,MAAM;CAClB;CAEA,MAAa,QAAuB;EACnC,MAAM,UAAU,KAAK;EACrB,KAAK,WAAW;EAChB,MAAM,SAAS,MAAM;CACtB;AACD"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
|
|
4
|
+
//#region src/lib/plugin-registrations.ts
|
|
5
|
+
const PLUGIN_PACKAGE = /^@wolfstar\/plugin-[^/]+$/;
|
|
6
|
+
/**
|
|
7
|
+
* Activates installed WolfStar plugins without making applications maintain a list
|
|
8
|
+
* of side-effect-only plugin registration imports in their entry point.
|
|
9
|
+
*/
|
|
10
|
+
function pluginRegistrations(config) {
|
|
11
|
+
const plugins = findPluginDependencies(config.root);
|
|
12
|
+
const entry = resolve(config.entry);
|
|
13
|
+
return {
|
|
14
|
+
name: "stars:plugin-registrations",
|
|
15
|
+
transform(code, id) {
|
|
16
|
+
if (plugins.length === 0 || cleanId(id) !== entry) return null;
|
|
17
|
+
return {
|
|
18
|
+
code: `${plugins.map((name) => `import ${JSON.stringify(`${name}/register`)};`).join("\n")}\n${code}`,
|
|
19
|
+
map: null
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function findPluginDependencies(root) {
|
|
25
|
+
const packageJson = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
|
|
26
|
+
return [.../* @__PURE__ */ new Set([...Object.keys(packageJson.dependencies ?? {}), ...Object.keys(packageJson.optionalDependencies ?? {})])].filter((name) => PLUGIN_PACKAGE.test(name)).sort();
|
|
27
|
+
}
|
|
28
|
+
function cleanId(id) {
|
|
29
|
+
return resolve(id.replace(/^\0/, "").split("?", 1)[0]);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
//#endregion
|
|
33
|
+
export { pluginRegistrations as t };
|
|
34
|
+
//# sourceMappingURL=plugin-registrations-0YL8vy7b.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-registrations-0YL8vy7b.js","names":[],"sources":["../src/lib/plugin-registrations.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport type { ResolvedStarsConfig } from '@wolfstar/http-framework/config';\n\ninterface PackageJson {\n\tdependencies?: Record<string, string>;\n\toptionalDependencies?: Record<string, string>;\n}\n\nconst PLUGIN_PACKAGE = /^@wolfstar\\/plugin-[^/]+$/;\n\n/**\n * Activates installed WolfStar plugins without making applications maintain a list\n * of side-effect-only plugin registration imports in their entry point.\n */\nexport function pluginRegistrations(config: ResolvedStarsConfig): object {\n\tconst plugins = findPluginDependencies(config.root);\n\tconst entry = resolve(config.entry);\n\n\treturn {\n\t\tname: 'stars:plugin-registrations',\n\t\ttransform(code: string, id: string) {\n\t\t\tif (plugins.length === 0 || cleanId(id) !== entry) return null;\n\n\t\t\tconst registrations = plugins.map((name) => `import ${JSON.stringify(`${name}/register`)};`).join('\\n');\n\t\t\treturn { code: `${registrations}\\n${code}`, map: null };\n\t\t}\n\t};\n}\n\nfunction findPluginDependencies(root: string): string[] {\n\tconst packageJson = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8')) as PackageJson;\n\treturn [...new Set([...Object.keys(packageJson.dependencies ?? {}), ...Object.keys(packageJson.optionalDependencies ?? {})])]\n\t\t.filter((name) => PLUGIN_PACKAGE.test(name))\n\t\t.sort();\n}\n\nfunction cleanId(id: string): string {\n\treturn resolve(id.replace(/^\\0/, '').split('?', 1)[0]!);\n}\n"],"mappings":";;;;AASA,MAAM,iBAAiB;;;;;AAMvB,SAAgB,oBAAoB,QAAqC;CACxE,MAAM,UAAU,uBAAuB,OAAO,IAAI;CAClD,MAAM,QAAQ,QAAQ,OAAO,KAAK;CAElC,OAAO;EACN,MAAM;EACN,UAAU,MAAc,IAAY;GACnC,IAAI,QAAQ,WAAW,KAAK,QAAQ,EAAE,MAAM,OAAO,OAAO;GAG1D,OAAO;IAAE,MAAM,GADO,QAAQ,KAAK,SAAS,UAAU,KAAK,UAAU,GAAG,KAAK,UAAU,EAAE,EAAE,CAAC,CAAC,KAAK,IACpE,EAAE,IAAI;IAAQ,KAAK;GAAK;EACvD;CACD;AACD;AAEA,SAAS,uBAAuB,MAAwB;CACvD,MAAM,cAAc,KAAK,MAAM,aAAa,KAAK,MAAM,cAAc,GAAG,MAAM,CAAC;CAC/E,OAAO,CAAC,mBAAG,IAAI,IAAI,CAAC,GAAG,OAAO,KAAK,YAAY,gBAAgB,CAAC,CAAC,GAAG,GAAG,OAAO,KAAK,YAAY,wBAAwB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAC3H,QAAQ,SAAS,eAAe,KAAK,IAAI,CAAC,CAAC,CAC3C,KAAK;AACR;AAEA,SAAS,QAAQ,IAAoB;CACpC,OAAO,QAAQ,GAAG,QAAQ,OAAO,EAAE,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,EAAG;AACvD"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { n as ExitCode, t as CliError } from "./errors-Bket6XFn.js";
|
|
2
|
+
import { i as shouldUseColor } from "./output-mode-Cxes6YUW.js";
|
|
3
|
+
import { n as resolveCwd } from "./args-Ch1KXUMn.js";
|
|
4
|
+
import { createRequire } from "node:module";
|
|
5
|
+
import { displayPath, loadStarsConfig } from "@wolfstar/http-framework/config";
|
|
6
|
+
import { dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
7
|
+
import { createColors } from "colorette";
|
|
8
|
+
import { generateAutoImportsDts } from "@wolfstar/http-framework/auto-imports";
|
|
9
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
10
|
+
|
|
11
|
+
//#region src/lib/tsconfig.ts
|
|
12
|
+
const require = createRequire(import.meta.url);
|
|
13
|
+
const sapphireOptions = Object.assign({}, ...[
|
|
14
|
+
"@sapphire/ts-config",
|
|
15
|
+
"@sapphire/ts-config/extra-strict",
|
|
16
|
+
"@sapphire/ts-config/decorators"
|
|
17
|
+
].map((id) => require(id).compilerOptions));
|
|
18
|
+
/** Generates an extendable config without changing the project's own tsconfig. */
|
|
19
|
+
async function prepareTsconfig(config, check = false) {
|
|
20
|
+
const path = join(config.root, ".stars", "tsconfig.json");
|
|
21
|
+
const fromGenerated = (target) => `./${relative(dirname(path), target).replaceAll("\\", "/")}`;
|
|
22
|
+
const paths = {};
|
|
23
|
+
if (config.build.tool === "tsdown") {
|
|
24
|
+
const source = dirname(config.entry);
|
|
25
|
+
const aliases = {
|
|
26
|
+
...config.build.configFile === null ? {
|
|
27
|
+
"~": source,
|
|
28
|
+
"@": source,
|
|
29
|
+
"~~": config.root,
|
|
30
|
+
"@@": config.root
|
|
31
|
+
} : {},
|
|
32
|
+
...config.tsdown.alias
|
|
33
|
+
};
|
|
34
|
+
for (const [alias, target] of Object.entries(aliases)) {
|
|
35
|
+
if (typeof target !== "string" || !isAbsolute(target) && !/^\.\.?[/\\]/.test(target)) continue;
|
|
36
|
+
const resolved = fromGenerated(resolve(config.root, target));
|
|
37
|
+
paths[alias] = [resolved];
|
|
38
|
+
paths[`${alias}/*`] = [`${resolved}/*`];
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const content = `${JSON.stringify({
|
|
42
|
+
compilerOptions: {
|
|
43
|
+
...sapphireOptions,
|
|
44
|
+
...config.build.tool === "tsdown" || config.build.tool === "vite" ? {
|
|
45
|
+
module: "ESNext",
|
|
46
|
+
moduleResolution: "Bundler",
|
|
47
|
+
moduleDetection: "force",
|
|
48
|
+
isolatedModules: true,
|
|
49
|
+
verbatimModuleSyntax: true,
|
|
50
|
+
allowJs: true,
|
|
51
|
+
allowImportingTsExtensions: true,
|
|
52
|
+
resolvePackageJsonImports: true,
|
|
53
|
+
lib: ["ESNext", "DOM"],
|
|
54
|
+
noEmit: true
|
|
55
|
+
} : {},
|
|
56
|
+
target: "ES2022",
|
|
57
|
+
forceConsistentCasingInFileNames: true,
|
|
58
|
+
skipLibCheck: true,
|
|
59
|
+
tsBuildInfoFile: "./tsconfig.tsbuildinfo",
|
|
60
|
+
paths
|
|
61
|
+
},
|
|
62
|
+
include: [`${fromGenerated(dirname(config.entry))}/**/*`, ...config.imports.enabled ? [fromGenerated(config.imports.dts)] : []],
|
|
63
|
+
exclude: [fromGenerated(join(config.root, "node_modules")), fromGenerated(config.build.outDir)]
|
|
64
|
+
}, null, 2)}\n`;
|
|
65
|
+
if (check) return {
|
|
66
|
+
path,
|
|
67
|
+
status: await readFile(path, "utf-8").catch(() => null) === content ? "up-to-date" : "outdated"
|
|
68
|
+
};
|
|
69
|
+
await mkdir(dirname(path), { recursive: true });
|
|
70
|
+
await writeFile(path, content);
|
|
71
|
+
return {
|
|
72
|
+
path,
|
|
73
|
+
status: "written"
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
//#endregion
|
|
78
|
+
//#region src/lib/tasks/prepare.ts
|
|
79
|
+
/**
|
|
80
|
+
* Generates `.stars/tsconfig.json` and `imports.dts` (see {@link StarsImportsConfig} in `@wolfstar/http-framework/config`), the way `nuxt
|
|
81
|
+
* prepare` regenerates `.nuxt/imports.d.ts`. Run automatically by `stars dev` and `stars build` before the first
|
|
82
|
+
* build; `--check` fails instead of writing, for CI.
|
|
83
|
+
*/
|
|
84
|
+
async function runPrepare(options) {
|
|
85
|
+
const stdout = options.stdout ?? process.stdout;
|
|
86
|
+
const colors = createColors({ useColor: shouldUseColor() && !options.json });
|
|
87
|
+
const config = await loadStarsConfig({
|
|
88
|
+
cwd: resolveCwd(options),
|
|
89
|
+
configFile: options.config
|
|
90
|
+
});
|
|
91
|
+
const result = await prepareProject(config, Boolean(options.check));
|
|
92
|
+
if (options.json) stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
93
|
+
else {
|
|
94
|
+
const paintConfig = result.tsconfig.status === "outdated" ? colors.red : colors.green;
|
|
95
|
+
stdout.write(`${colors.dim("stars")} tsconfig: ${paintConfig(result.tsconfig.status)} ${displayPath(config.root, result.tsconfig.path)}\n`);
|
|
96
|
+
if (result.enabled) {
|
|
97
|
+
const paint = result.status === "outdated" ? colors.red : colors.green;
|
|
98
|
+
stdout.write(`${colors.dim("stars")} imports: ${paint(result.status)} ${displayPath(config.root, result.dts)}\n`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (result.status === "outdated" || result.tsconfig.status === "outdated") throw new CliError("The generated project files are out of date, run `stars prepare` to update it.", {
|
|
102
|
+
code: "PREPARE_OUTDATED",
|
|
103
|
+
exitCode: ExitCode.Error
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Regenerates `imports.dts` unconditionally, used by `stars dev`/`stars build` before the first build so the
|
|
108
|
+
* declaration file exists (and is current) even when the user never ran `stars prepare` themselves.
|
|
109
|
+
*/
|
|
110
|
+
async function prepareAutoImports(config, check = false) {
|
|
111
|
+
if (!config.imports.enabled) return {
|
|
112
|
+
enabled: false,
|
|
113
|
+
dts: null,
|
|
114
|
+
status: null
|
|
115
|
+
};
|
|
116
|
+
const { dirs, presets, exclude, dts } = config.imports;
|
|
117
|
+
const content = await generateAutoImportsDts({
|
|
118
|
+
root: config.root,
|
|
119
|
+
dirs,
|
|
120
|
+
presets,
|
|
121
|
+
exclude
|
|
122
|
+
});
|
|
123
|
+
if (check) return {
|
|
124
|
+
enabled: true,
|
|
125
|
+
dts,
|
|
126
|
+
status: await readFile(dts, "utf-8").catch(() => null) === content ? "up-to-date" : "outdated"
|
|
127
|
+
};
|
|
128
|
+
await mkdir(dirname(dts), { recursive: true });
|
|
129
|
+
await writeFile(dts, content);
|
|
130
|
+
return {
|
|
131
|
+
enabled: true,
|
|
132
|
+
dts,
|
|
133
|
+
status: "written"
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
/** Prepares TypeScript configuration and auto import declarations before building. */
|
|
137
|
+
async function prepareProject(config, check = false) {
|
|
138
|
+
const tsconfig = await prepareTsconfig(config, check);
|
|
139
|
+
return {
|
|
140
|
+
...await prepareAutoImports(config, check),
|
|
141
|
+
tsconfig
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
//#endregion
|
|
146
|
+
export { prepareProject as n, runPrepare as r, prepareAutoImports as t };
|
|
147
|
+
//# sourceMappingURL=prepare-BjFq1zBC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prepare-BjFq1zBC.js","names":[],"sources":["../src/lib/tsconfig.ts","../src/lib/tasks/prepare.ts"],"sourcesContent":["import type { ResolvedStarsConfig } from '@wolfstar/http-framework/config';\nimport { createRequire } from 'node:module';\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { dirname, isAbsolute, join, relative, resolve } from 'node:path';\n\nconst require = createRequire(import.meta.url);\nconst sapphireOptions = Object.assign(\n\t{},\n\t...['@sapphire/ts-config', '@sapphire/ts-config/extra-strict', '@sapphire/ts-config/decorators'].map(\n\t\t(id) => (require(id) as { compilerOptions: Record<string, unknown> }).compilerOptions\n\t)\n) as Record<string, unknown>;\n\n/** Generates an extendable config without changing the project's own tsconfig. */\nexport async function prepareTsconfig(config: ResolvedStarsConfig, check = false) {\n\tconst path = join(config.root, '.stars', 'tsconfig.json');\n\tconst fromGenerated = (target: string) => `./${relative(dirname(path), target).replaceAll('\\\\', '/')}`;\n\tconst paths: Record<string, string[]> = {};\n\tif (config.build.tool === 'tsdown') {\n\t\tconst source = dirname(config.entry);\n\t\tconst defaults = config.build.configFile === null ? { '~': source, '@': source, '~~': config.root, '@@': config.root } : {};\n\t\tconst aliases = { ...defaults, ...(config.tsdown.alias as Record<string, unknown> | undefined) };\n\t\tfor (const [alias, target] of Object.entries(aliases)) {\n\t\t\t// Module redirects belong to the bundler; only filesystem targets become TypeScript paths.\n\t\t\tif (typeof target !== 'string' || (!isAbsolute(target) && !/^\\.\\.?[/\\\\]/.test(target))) continue;\n\t\t\tconst resolved = fromGenerated(resolve(config.root, target));\n\t\t\tpaths[alias] = [resolved];\n\t\t\tpaths[`${alias}/*`] = [`${resolved}/*`];\n\t\t}\n\t}\n\tconst content = `${JSON.stringify(\n\t\t{\n\t\t\tcompilerOptions: {\n\t\t\t\t...sapphireOptions,\n\t\t\t\t// Bundlers emit the application; TypeScript only checks it. Keep Node16 emit for tsc.\n\t\t\t\t...(config.build.tool === 'tsdown' || config.build.tool === 'vite'\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tmodule: 'ESNext',\n\t\t\t\t\t\t\tmoduleResolution: 'Bundler',\n\t\t\t\t\t\t\tmoduleDetection: 'force',\n\t\t\t\t\t\t\tisolatedModules: true,\n\t\t\t\t\t\t\tverbatimModuleSyntax: true,\n\t\t\t\t\t\t\tallowJs: true,\n\t\t\t\t\t\t\tallowImportingTsExtensions: true,\n\t\t\t\t\t\t\tresolvePackageJsonImports: true,\n\t\t\t\t\t\t\tlib: ['ESNext', 'DOM'],\n\t\t\t\t\t\t\tnoEmit: true\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t\ttarget: 'ES2022',\n\t\t\t\tforceConsistentCasingInFileNames: true,\n\t\t\t\tskipLibCheck: true,\n\t\t\t\ttsBuildInfoFile: './tsconfig.tsbuildinfo',\n\t\t\t\tpaths\n\t\t\t},\n\t\t\tinclude: [`${fromGenerated(dirname(config.entry))}/**/*`, ...(config.imports.enabled ? [fromGenerated(config.imports.dts)] : [])],\n\t\t\texclude: [fromGenerated(join(config.root, 'node_modules')), fromGenerated(config.build.outDir)]\n\t\t},\n\t\tnull,\n\t\t2\n\t)}\\n`;\n\tif (check) {\n\t\tconst existing = await readFile(path, 'utf-8').catch(() => null);\n\t\treturn { path, status: existing === content ? ('up-to-date' as const) : ('outdated' as const) };\n\t}\n\tawait mkdir(dirname(path), { recursive: true });\n\tawait writeFile(path, content);\n\treturn { path, status: 'written' as const };\n}\n","import { generateAutoImportsDts } from '@wolfstar/http-framework/auto-imports';\nimport { displayPath, loadStarsConfig, type ResolvedStarsConfig } from '@wolfstar/http-framework/config';\nimport { createColors } from 'colorette';\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { dirname } from 'node:path';\nimport type { ProjectArgs } from '../args.js';\nimport { resolveCwd } from '../args.js';\nimport { CliError, ExitCode } from '../errors.js';\nimport { shouldUseColor } from '../output-mode.js';\nimport { prepareTsconfig } from '../tsconfig.js';\n\nexport interface PrepareTaskOptions extends ProjectArgs {\n\tcheck?: boolean;\n\tjson?: boolean;\n\tstdout?: NodeJS.WritableStream;\n}\n\nexport type PrepareResult =\n\t| { enabled: false; dts: null; status: null }\n\t| { enabled: true; dts: string; status: 'written' | 'up-to-date' | 'outdated' };\n\n/**\n * Generates `.stars/tsconfig.json` and `imports.dts` (see {@link StarsImportsConfig} in `@wolfstar/http-framework/config`), the way `nuxt\n * prepare` regenerates `.nuxt/imports.d.ts`. Run automatically by `stars dev` and `stars build` before the first\n * build; `--check` fails instead of writing, for CI.\n */\nexport async function runPrepare(options: PrepareTaskOptions): Promise<void> {\n\tconst stdout = options.stdout ?? process.stdout;\n\tconst colors = createColors({ useColor: shouldUseColor() && !options.json });\n\tconst config = await loadStarsConfig({ cwd: resolveCwd(options), configFile: options.config });\n\tconst result = await prepareProject(config, Boolean(options.check));\n\n\tif (options.json) {\n\t\tstdout.write(`${JSON.stringify(result, null, 2)}\\n`);\n\t} else {\n\t\tconst paintConfig = result.tsconfig.status === 'outdated' ? colors.red : colors.green;\n\t\tstdout.write(`${colors.dim('stars')} tsconfig: ${paintConfig(result.tsconfig.status)} ${displayPath(config.root, result.tsconfig.path)}\\n`);\n\t\tif (result.enabled) {\n\t\t\tconst paint = result.status === 'outdated' ? colors.red : colors.green;\n\t\t\tstdout.write(`${colors.dim('stars')} imports: ${paint(result.status)} ${displayPath(config.root, result.dts)}\\n`);\n\t\t}\n\t}\n\n\tif (result.status === 'outdated' || result.tsconfig.status === 'outdated') {\n\t\tthrow new CliError('The generated project files are out of date, run `stars prepare` to update it.', {\n\t\t\tcode: 'PREPARE_OUTDATED',\n\t\t\texitCode: ExitCode.Error\n\t\t});\n\t}\n}\n\n/**\n * Regenerates `imports.dts` unconditionally, used by `stars dev`/`stars build` before the first build so the\n * declaration file exists (and is current) even when the user never ran `stars prepare` themselves.\n */\nexport async function prepareAutoImports(config: ResolvedStarsConfig, check = false): Promise<PrepareResult> {\n\tif (!config.imports.enabled) return { enabled: false, dts: null, status: null };\n\n\tconst { dirs, presets, exclude, dts } = config.imports;\n\tconst content = await generateAutoImportsDts({ root: config.root, dirs, presets, exclude });\n\n\tif (check) {\n\t\tconst existing = await readFile(dts, 'utf-8').catch(() => null);\n\t\treturn { enabled: true, dts, status: existing === content ? 'up-to-date' : 'outdated' };\n\t}\n\n\tawait mkdir(dirname(dts), { recursive: true });\n\tawait writeFile(dts, content);\n\treturn { enabled: true, dts, status: 'written' };\n}\n\n/** Prepares TypeScript configuration and auto import declarations before building. */\nexport async function prepareProject(config: ResolvedStarsConfig, check = false) {\n\tconst tsconfig = await prepareTsconfig(config, check);\n\treturn { ...(await prepareAutoImports(config, check)), tsconfig };\n}\n"],"mappings":"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"}
|
|
@@ -5,13 +5,13 @@ import { defineCommand } from "citty";
|
|
|
5
5
|
var prepare_default = defineCommand({
|
|
6
6
|
meta: {
|
|
7
7
|
name: "prepare",
|
|
8
|
-
description: "Generate
|
|
8
|
+
description: "Generate TypeScript configuration and auto imports declarations"
|
|
9
9
|
},
|
|
10
10
|
args: {
|
|
11
11
|
...projectArgs,
|
|
12
12
|
check: {
|
|
13
13
|
type: "boolean",
|
|
14
|
-
description: "Fail when the generated
|
|
14
|
+
description: "Fail when the generated files are out of date instead of writing it",
|
|
15
15
|
default: false
|
|
16
16
|
},
|
|
17
17
|
json: {
|
|
@@ -21,7 +21,7 @@ var prepare_default = defineCommand({
|
|
|
21
21
|
}
|
|
22
22
|
},
|
|
23
23
|
async run({ args }) {
|
|
24
|
-
const { runPrepare } = await import("./prepare-
|
|
24
|
+
const { runPrepare } = await import("./prepare-B0xgciBK.js");
|
|
25
25
|
await runPrepare({
|
|
26
26
|
config: args.config,
|
|
27
27
|
cwd: args.cwd,
|
|
@@ -33,4 +33,4 @@ var prepare_default = defineCommand({
|
|
|
33
33
|
|
|
34
34
|
//#endregion
|
|
35
35
|
export { prepare_default as default };
|
|
36
|
-
//# sourceMappingURL=prepare-
|
|
36
|
+
//# sourceMappingURL=prepare-Glg8-d0r.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prepare-Glg8-d0r.js","names":[],"sources":["../src/commands/prepare.ts"],"sourcesContent":["import { defineCommand } from 'citty';\nimport { projectArgs } from '../lib/args.js';\n\nexport default defineCommand({\n\tmeta: {\n\t\tname: 'prepare',\n\t\tdescription: 'Generate TypeScript configuration and auto imports declarations'\n\t},\n\targs: {\n\t\t...projectArgs,\n\t\tcheck: {\n\t\t\ttype: 'boolean',\n\t\t\tdescription: 'Fail when the generated files are out of date instead of writing it',\n\t\t\tdefault: false\n\t\t},\n\t\tjson: {\n\t\t\ttype: 'boolean',\n\t\t\tdescription: 'Print machine-readable JSON',\n\t\t\tdefault: false\n\t\t}\n\t},\n\tasync run({ args }) {\n\t\tconst { runPrepare } = await import('../lib/tasks/prepare.js');\n\t\tawait runPrepare({ config: args.config, cwd: args.cwd, check: args.check, json: args.json });\n\t}\n});\n"],"mappings":";;;;AAGA,sBAAe,cAAc;CAC5B,MAAM;EACL,MAAM;EACN,aAAa;CACd;CACA,MAAM;EACL,GAAG;EACH,OAAO;GACN,MAAM;GACN,aAAa;GACb,SAAS;EACV;EACA,MAAM;GACL,MAAM;GACN,aAAa;GACb,SAAS;EACV;CACD;CACA,MAAM,IAAI,EAAE,QAAQ;EACnB,MAAM,EAAE,eAAe,MAAM,OAAO;EACpC,MAAM,WAAW;GAAE,QAAQ,KAAK;GAAQ,KAAK,KAAK;GAAK,OAAO,KAAK;GAAO,MAAM,KAAK;EAAK,CAAC;CAC5F;AACD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-supervisor-CJOdmp0W.js","names":[
|
|
1
|
+
{"version":3,"file":"process-supervisor-CJOdmp0W.js","names":[],"sources":["../src/lib/process-supervisor.ts"],"sourcesContent":["import { spawn, type ChildProcess } from 'node:child_process';\nimport { EventEmitter } from 'node:events';\n\nexport type ProcessState = 'idle' | 'starting' | 'running' | 'stopping' | 'stopped' | 'crashed';\n\nexport interface ProcessExit {\n\tcode: number | null;\n\tsignal: NodeJS.Signals | null;\n\t/** Whether the exit was requested through {@link ProcessSupervisor.stop}. */\n\trequested: boolean;\n}\n\nexport interface ProcessSupervisorOptions {\n\tcommand: string;\n\targs: readonly string[];\n\tcwd: string;\n\tenv: NodeJS.ProcessEnv;\n\t/** Milliseconds to wait after `SIGTERM` before sending `SIGKILL`. */\n\tkillTimeout: number;\n}\n\nexport interface ProcessSupervisorEvents {\n\tstate: [state: ProcessState];\n\tstdout: [line: string];\n\tstderr: [line: string];\n\texit: [exit: ProcessExit];\n\terror: [error: Error];\n}\n\n/**\n * Owns a single child process: starts it, streams its output line by line and stops it gracefully.\n */\nexport class ProcessSupervisor extends EventEmitter<ProcessSupervisorEvents> {\n\t#child: ChildProcess | null = null;\n\t#state: ProcessState = 'idle';\n\t#startedAt: number | null = null;\n\t#stopping: Promise<void> | null = null;\n\n\tpublic constructor(private readonly options: ProcessSupervisorOptions) {\n\t\tsuper();\n\t}\n\n\tpublic get state(): ProcessState {\n\t\treturn this.#state;\n\t}\n\n\tpublic get pid(): number | null {\n\t\treturn this.#child?.pid ?? null;\n\t}\n\n\tpublic get startedAt(): number | null {\n\t\treturn this.#startedAt;\n\t}\n\n\tpublic get running(): boolean {\n\t\treturn this.#state === 'starting' || this.#state === 'running';\n\t}\n\n\tpublic start(): void {\n\t\tif (this.#child) throw new Error('The process is already running, call stop() or restart() first.');\n\n\t\tconst { command, args, cwd, env } = this.options;\n\t\tthis.#setState('starting');\n\n\t\tconst child = spawn(command, args, { cwd, env, stdio: ['ignore', 'pipe', 'pipe'], windowsHide: true });\n\t\tthis.#child = child;\n\t\tthis.#startedAt = Date.now();\n\n\t\tlet requested = false;\n\t\tconst stdout = createLineSplitter((line) => this.emit('stdout', line));\n\t\tconst stderr = createLineSplitter((line) => this.emit('stderr', line));\n\t\tchild.stdout?.on('data', stdout.push);\n\t\tchild.stderr?.on('data', stderr.push);\n\n\t\tchild.once('spawn', () => {\n\t\t\tif (this.#child === child) this.#setState('running');\n\t\t});\n\n\t\tchild.once('error', (error) => {\n\t\t\tthis.emit('error', error);\n\t\t});\n\n\t\tchild.once('exit', (code, signal) => {\n\t\t\tstdout.flush();\n\t\t\tstderr.flush();\n\t\t\trequested = this.#state === 'stopping';\n\t\t\tthis.#child = null;\n\t\t\tthis.#startedAt = null;\n\t\t\tthis.#setState(requested || code === 0 ? 'stopped' : 'crashed');\n\t\t\tthis.emit('exit', { code, signal, requested });\n\t\t});\n\t}\n\n\t/**\n\t * Sends `SIGTERM`, escalates to `SIGKILL` after `killTimeout` and resolves once the process exited.\n\t */\n\tpublic stop(): Promise<void> {\n\t\tconst child = this.#child;\n\t\tif (!child) return Promise.resolve();\n\t\tif (this.#stopping) return this.#stopping;\n\n\t\tthis.#setState('stopping');\n\t\tthis.#stopping = new Promise<void>((resolve) => {\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tif (child.exitCode === null && child.signalCode === null) child.kill('SIGKILL');\n\t\t\t}, this.options.killTimeout);\n\t\t\ttimer.unref();\n\n\t\t\tchild.once('exit', () => {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\tthis.#stopping = null;\n\t\t\t\tresolve();\n\t\t\t});\n\n\t\t\tif (!child.kill('SIGTERM')) {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\tthis.#stopping = null;\n\t\t\t\tresolve();\n\t\t\t}\n\t\t});\n\n\t\treturn this.#stopping;\n\t}\n\n\tpublic async restart(): Promise<void> {\n\t\tawait this.stop();\n\t\tthis.start();\n\t}\n\n\t#setState(state: ProcessState): void {\n\t\tif (this.#state === state) return;\n\t\tthis.#state = state;\n\t\tthis.emit('state', state);\n\t}\n}\n\n/**\n * Splits a byte stream into complete lines, keeping the trailing partial line until the next chunk.\n */\nexport function createLineSplitter(onLine: (line: string) => void) {\n\tlet remainder = '';\n\treturn {\n\t\tpush(chunk: Buffer | string) {\n\t\t\tremainder += chunk.toString();\n\t\t\tconst lines = remainder.split(/\\r?\\n/);\n\t\t\tremainder = lines.pop() ?? '';\n\t\t\tfor (const line of lines) onLine(line);\n\t\t},\n\t\tflush() {\n\t\t\tif (remainder.length > 0) onLine(remainder);\n\t\t\tremainder = '';\n\t\t}\n\t};\n}\n"],"mappings":";;;;;;;AAgCA,IAAa,oBAAb,cAAuC,aAAsC;CAMxC;CALpC,SAA8B;CAC9B,SAAuB;CACvB,aAA4B;CAC5B,YAAkC;CAElC,AAAO,YAAY,AAAiB,SAAmC;EACtE,MAAM;EAD6B;CAEpC;CAEA,IAAW,QAAsB;EAChC,OAAO,KAAK;CACb;CAEA,IAAW,MAAqB;EAC/B,OAAO,KAAK,QAAQ,OAAO;CAC5B;CAEA,IAAW,YAA2B;EACrC,OAAO,KAAK;CACb;CAEA,IAAW,UAAmB;EAC7B,OAAO,KAAK,WAAW,cAAc,KAAK,WAAW;CACtD;CAEA,AAAO,QAAc;EACpB,IAAI,KAAK,QAAQ,MAAM,IAAI,MAAM,iEAAiE;EAElG,MAAM,EAAE,SAAS,MAAM,KAAK,QAAQ,KAAK;EACzC,KAAK,UAAU,UAAU;EAEzB,MAAM,QAAQ,MAAM,SAAS,MAAM;GAAE;GAAK;GAAK,OAAO;IAAC;IAAU;IAAQ;GAAM;GAAG,aAAa;EAAK,CAAC;EACrG,KAAK,SAAS;EACd,KAAK,aAAa,KAAK,IAAI;EAE3B,IAAI,YAAY;EAChB,MAAM,SAAS,oBAAoB,SAAS,KAAK,KAAK,UAAU,IAAI,CAAC;EACrE,MAAM,SAAS,oBAAoB,SAAS,KAAK,KAAK,UAAU,IAAI,CAAC;EACrE,MAAM,QAAQ,GAAG,QAAQ,OAAO,IAAI;EACpC,MAAM,QAAQ,GAAG,QAAQ,OAAO,IAAI;EAEpC,MAAM,KAAK,eAAe;GACzB,IAAI,KAAK,WAAW,OAAO,KAAK,UAAU,SAAS;EACpD,CAAC;EAED,MAAM,KAAK,UAAU,UAAU;GAC9B,KAAK,KAAK,SAAS,KAAK;EACzB,CAAC;EAED,MAAM,KAAK,SAAS,MAAM,WAAW;GACpC,OAAO,MAAM;GACb,OAAO,MAAM;GACb,YAAY,KAAK,WAAW;GAC5B,KAAK,SAAS;GACd,KAAK,aAAa;GAClB,KAAK,UAAU,aAAa,SAAS,IAAI,YAAY,SAAS;GAC9D,KAAK,KAAK,QAAQ;IAAE;IAAM;IAAQ;GAAU,CAAC;EAC9C,CAAC;CACF;;;;CAKA,AAAO,OAAsB;EAC5B,MAAM,QAAQ,KAAK;EACnB,IAAI,CAAC,OAAO,OAAO,QAAQ,QAAQ;EACnC,IAAI,KAAK,WAAW,OAAO,KAAK;EAEhC,KAAK,UAAU,UAAU;EACzB,KAAK,YAAY,IAAI,SAAe,YAAY;GAC/C,MAAM,QAAQ,iBAAiB;IAC9B,IAAI,MAAM,aAAa,QAAQ,MAAM,eAAe,MAAM,MAAM,KAAK,SAAS;GAC/E,GAAG,KAAK,QAAQ,WAAW;GAC3B,MAAM,MAAM;GAEZ,MAAM,KAAK,cAAc;IACxB,aAAa,KAAK;IAClB,KAAK,YAAY;IACjB,QAAQ;GACT,CAAC;GAED,IAAI,CAAC,MAAM,KAAK,SAAS,GAAG;IAC3B,aAAa,KAAK;IAClB,KAAK,YAAY;IACjB,QAAQ;GACT;EACD,CAAC;EAED,OAAO,KAAK;CACb;CAEA,MAAa,UAAyB;EACrC,MAAM,KAAK,KAAK;EAChB,KAAK,MAAM;CACZ;CAEA,UAAU,OAA2B;EACpC,IAAI,KAAK,WAAW,OAAO;EAC3B,KAAK,SAAS;EACd,KAAK,KAAK,SAAS,KAAK;CACzB;AACD;;;;AAKA,SAAgB,mBAAmB,QAAgC;CAClE,IAAI,YAAY;CAChB,OAAO;EACN,KAAK,OAAwB;GAC5B,aAAa,MAAM,SAAS;GAC5B,MAAM,QAAQ,UAAU,MAAM,OAAO;GACrC,YAAY,MAAM,IAAI,KAAK;GAC3B,KAAK,MAAM,QAAQ,OAAO,OAAO,IAAI;EACtC;EACA,QAAQ;GACP,IAAI,UAAU,SAAS,GAAG,OAAO,SAAS;GAC1C,YAAY;EACb;CACD;AACD"}
|
package/dist/tsc-BqZfDTD0.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tsc-BqZfDTD0.js","names":[
|
|
1
|
+
{"version":3,"file":"tsc-BqZfDTD0.js","names":[],"sources":["../src/lib/builders/tsc.ts"],"sourcesContent":["import { spawn, type ChildProcess } from 'node:child_process';\nimport { EventEmitter } from 'node:events';\nimport type { ResolvedStarsConfig } from '@wolfstar/http-framework/config';\nimport { CliError } from '../errors.js';\nimport { createLineSplitter } from '../process-supervisor.js';\nimport { resolveBinary } from '../project.js';\nimport type { Builder, BuilderEvents, BuildOutcome } from './types.js';\n\nconst INSTALL_HINT = \"Install it with `pnpm add -D typescript`, or set `build.tool` to 'tsdown' or 'none'.\";\nconst WATCH_START = /Starting (incremental )?compilation/;\nconst WATCH_DONE = /Found (\\d+) errors?\\. Watching for file changes/;\nconst ERROR_LINE = /error TS\\d+:/;\n\n/**\n * Builds through the project's `tsc -b`, parsing its output to report progress.\n */\nexport class TscBuilder extends EventEmitter<BuilderEvents> implements Builder {\n\tpublic readonly tool = 'tsc' as const;\n\t#child: ChildProcess | null = null;\n\t#startedAt = 0;\n\t#firstError: string | null = null;\n\n\tpublic constructor(private readonly config: ResolvedStarsConfig) {\n\t\tsuper();\n\t}\n\n\tpublic build(): Promise<BuildOutcome> {\n\t\tconst child = this.#spawn([]);\n\t\tthis.#begin();\n\n\t\treturn new Promise((resolve) => {\n\t\t\tchild.once('exit', (code) => {\n\t\t\t\tthis.#child = null;\n\t\t\t\tresolve(this.#finish(code === 0 ? null : (this.#firstError ?? `tsc exited with code ${code}`)));\n\t\t\t});\n\t\t});\n\t}\n\n\tpublic watch(): Promise<void> {\n\t\tthis.#spawn(['--watch', '--preserveWatchOutput']);\n\t\tthis.#begin();\n\t\treturn Promise.resolve();\n\t}\n\n\tpublic close(): Promise<void> {\n\t\tconst child = this.#child;\n\t\tthis.#child = null;\n\t\tif (!child || child.exitCode !== null) return Promise.resolve();\n\n\t\treturn new Promise((resolve) => {\n\t\t\tchild.once('exit', () => resolve());\n\t\t\tchild.kill();\n\t\t});\n\t}\n\n\t#spawn(extraArgs: string[]): ChildProcess {\n\t\tconst tsc = resolveTscBinary(this.config.root);\n\t\tif (!tsc) throw new CliError(`\"typescript\" is not installed in ${this.config.root}`, { code: 'DEPENDENCY_MISSING', hint: INSTALL_HINT });\n\n\t\tconst child = spawn(process.execPath, [tsc, '-b', this.config.build.tsconfig!, '--pretty', 'false', ...extraArgs], {\n\t\t\tcwd: this.config.root,\n\t\t\tenv: process.env,\n\t\t\tstdio: ['ignore', 'pipe', 'pipe'],\n\t\t\twindowsHide: true\n\t\t});\n\t\tthis.#child = child;\n\n\t\tconst handleLine = (line: string) => this.#handleLine(line);\n\t\tconst stdout = createLineSplitter(handleLine);\n\t\tconst stderr = createLineSplitter(handleLine);\n\t\tchild.stdout?.on('data', stdout.push);\n\t\tchild.stderr?.on('data', stderr.push);\n\t\tchild.once('exit', () => {\n\t\t\tstdout.flush();\n\t\t\tstderr.flush();\n\t\t});\n\t\tchild.once('error', (error) => this.emit('log', 'error', error.message));\n\n\t\treturn child;\n\t}\n\n\t#handleLine(line: string): void {\n\t\tconst text = line.trim();\n\t\tif (text.length === 0) return;\n\n\t\tif (WATCH_START.test(text)) {\n\t\t\tif (this.#startedAt === 0) this.#begin();\n\t\t\treturn;\n\t\t}\n\n\t\tif (ERROR_LINE.test(text)) {\n\t\t\tthis.#firstError ??= text;\n\t\t\tthis.emit('log', 'error', text);\n\t\t\treturn;\n\t\t}\n\n\t\tconst done = WATCH_DONE.exec(text);\n\t\tif (done) {\n\t\t\tconst errors = Number(done[1]);\n\t\t\tthis.emit('log', errors === 0 ? 'success' : 'error', text);\n\t\t\tthis.#finish(errors === 0 ? null : (this.#firstError ?? text));\n\t\t\treturn;\n\t\t}\n\n\t\tthis.emit('log', 'info', text);\n\t}\n\n\t#begin(): void {\n\t\tthis.#firstError = null;\n\t\tthis.#startedAt = performance.now();\n\t\tthis.emit('start');\n\t}\n\n\t#finish(message: string | null): BuildOutcome {\n\t\tconst outcome: BuildOutcome = { ok: message === null, durationMs: Math.round(performance.now() - this.#startedAt), message };\n\t\tthis.#startedAt = 0;\n\t\tthis.emit(outcome.ok ? 'success' : 'failure', outcome);\n\t\treturn outcome;\n\t}\n}\n\n/**\n * Locates the `tsc` script of the project's TypeScript through its `package.json#bin`, which works for both the\n * classic `lib/tsc.js` layout (TypeScript ≤ 6) and the native `bin/tsc` launcher (TypeScript 7, whose `exports` map\n * hides `lib/`).\n */\nexport function resolveTscBinary(root: string): string | null {\n\treturn resolveBinary(root, 'typescript', 'tsc');\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { n as importFromProject } from "./project-DHF3qdm-.js";
|
|
2
|
+
import { t as pluginRegistrations } from "./plugin-registrations-0YL8vy7b.js";
|
|
2
3
|
import { dirname, extname, relative, resolve } from "node:path";
|
|
3
4
|
import { EventEmitter } from "node:events";
|
|
4
5
|
|
|
@@ -23,7 +24,7 @@ const RELATIVE_PATH = /^\.\.?[/\\]/;
|
|
|
23
24
|
var TsdownBuilder = class extends EventEmitter {
|
|
24
25
|
config;
|
|
25
26
|
tool = "tsdown";
|
|
26
|
-
#
|
|
27
|
+
#handle = null;
|
|
27
28
|
#hadError = false;
|
|
28
29
|
#startedAt = 0;
|
|
29
30
|
constructor(config) {
|
|
@@ -35,7 +36,7 @@ var TsdownBuilder = class extends EventEmitter {
|
|
|
35
36
|
const options = await this.#options();
|
|
36
37
|
this.#begin();
|
|
37
38
|
try {
|
|
38
|
-
this.#
|
|
39
|
+
this.#handle = await tsdown.build(options);
|
|
39
40
|
return this.#finish(this.#hadError ? "The build reported errors" : null);
|
|
40
41
|
} catch (error) {
|
|
41
42
|
return this.#finish(error instanceof Error ? error.message : String(error));
|
|
@@ -45,12 +46,12 @@ var TsdownBuilder = class extends EventEmitter {
|
|
|
45
46
|
const tsdown = await this.#load();
|
|
46
47
|
const options = await this.#options();
|
|
47
48
|
this.#begin();
|
|
48
|
-
this.#
|
|
49
|
+
this.#handle = await tsdown.build(this.#watchOptions(options));
|
|
49
50
|
}
|
|
50
51
|
async close() {
|
|
51
|
-
const
|
|
52
|
-
this.#
|
|
53
|
-
await
|
|
52
|
+
const handle = this.#handle;
|
|
53
|
+
this.#handle = null;
|
|
54
|
+
await handle?.watch.close();
|
|
54
55
|
}
|
|
55
56
|
#load() {
|
|
56
57
|
return importFromProject(this.config.root, "tsdown", INSTALL_HINT);
|
|
@@ -62,7 +63,11 @@ var TsdownBuilder = class extends EventEmitter {
|
|
|
62
63
|
async #options() {
|
|
63
64
|
const user = this.config.tsdown;
|
|
64
65
|
const defaults = this.config.build.configFile === null ? this.#defaults() : {};
|
|
65
|
-
const plugins = [
|
|
66
|
+
const plugins = [
|
|
67
|
+
pluginRegistrations(this.config),
|
|
68
|
+
...await this.#plugins(),
|
|
69
|
+
...toArray(user.plugins)
|
|
70
|
+
];
|
|
66
71
|
const alias = {
|
|
67
72
|
...defaults.alias,
|
|
68
73
|
...this.#alias(user.alias)
|
|
@@ -220,7 +225,7 @@ var TsdownBuilder = class extends EventEmitter {
|
|
|
220
225
|
error: (...args) => {
|
|
221
226
|
this.#hadError = true;
|
|
222
227
|
log("error", args);
|
|
223
|
-
if (this.#startedAt !== 0
|
|
228
|
+
if (this.#startedAt !== 0) this.#finish(errorSummary(args));
|
|
224
229
|
},
|
|
225
230
|
success: () => {},
|
|
226
231
|
clearScreen: () => {}
|
|
@@ -239,4 +244,4 @@ function errorSummary(args) {
|
|
|
239
244
|
|
|
240
245
|
//#endregion
|
|
241
246
|
export { TsdownBuilder };
|
|
242
|
-
//# sourceMappingURL=tsdown-
|
|
247
|
+
//# sourceMappingURL=tsdown-DySpwiDI.js.map
|