@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.
Files changed (52) hide show
  1. package/README.md +52 -15
  2. package/dist/{build-DbGs9-s8.js → build-DkjzFPxe.js} +5 -4
  3. package/dist/build-DkjzFPxe.js.map +1 -0
  4. package/dist/{build-DkMulM4f.js → build-dgEzXPXg.js} +2 -2
  5. package/dist/{build-DkMulM4f.js.map → build-dgEzXPXg.js.map} +1 -1
  6. package/dist/cli.js +4 -4
  7. package/dist/{commands-BkZNThm8.js → commands-DPGDL7ft.js} +3 -3
  8. package/dist/commands-DPGDL7ft.js.map +1 -0
  9. package/dist/{commands-DwqViJ2V.js → commands-hpnmaBM2.js} +4 -4
  10. package/dist/{commands-DwqViJ2V.js.map → commands-hpnmaBM2.js.map} +1 -1
  11. package/dist/{dev-BazJrPZ3.js → dev-CcNBBd4V.js} +2 -2
  12. package/dist/{dev-BazJrPZ3.js.map → dev-CcNBBd4V.js.map} +1 -1
  13. package/dist/{dev-C6HogNjR.js → dev-DqPTgjUh.js} +36 -8
  14. package/dist/dev-DqPTgjUh.js.map +1 -0
  15. package/dist/external-Bk4EESdT.js.map +1 -1
  16. package/dist/index.d.ts +10 -10
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/locales-CxckVWte.js +104 -0
  19. package/dist/locales-CxckVWte.js.map +1 -0
  20. package/dist/log-buffer-D-nj2ZEU.js.map +1 -1
  21. package/dist/none-DEo7zEr9.js.map +1 -1
  22. package/dist/plugin-registrations-0YL8vy7b.js +34 -0
  23. package/dist/plugin-registrations-0YL8vy7b.js.map +1 -0
  24. package/dist/prepare-B0xgciBK.js +3 -0
  25. package/dist/prepare-BjFq1zBC.js +147 -0
  26. package/dist/prepare-BjFq1zBC.js.map +1 -0
  27. package/dist/{prepare-hOwjyelr.js → prepare-Glg8-d0r.js} +4 -4
  28. package/dist/prepare-Glg8-d0r.js.map +1 -0
  29. package/dist/process-supervisor-CJOdmp0W.js.map +1 -1
  30. package/dist/tsc-BqZfDTD0.js.map +1 -1
  31. package/dist/{tsdown-Do8vjnIK.js → tsdown-DySpwiDI.js} +14 -9
  32. package/dist/tsdown-DySpwiDI.js.map +1 -0
  33. package/dist/{tui-C2P91TgW.js → tui-BCGQrMQo.js} +10 -1
  34. package/dist/tui-BCGQrMQo.js.map +1 -0
  35. package/dist/{tunnel-B8Id4-lR.js → tunnel-mGJe2zuE.js} +20 -7
  36. package/dist/tunnel-mGJe2zuE.js.map +1 -0
  37. package/dist/{vite-27ZbreDz.js → vite-fhNA6MyF.js} +8 -2
  38. package/dist/vite-fhNA6MyF.js.map +1 -0
  39. package/package.json +7 -6
  40. package/dist/build-DbGs9-s8.js.map +0 -1
  41. package/dist/builders-NkAoPRdw.js +0 -44
  42. package/dist/builders-NkAoPRdw.js.map +0 -1
  43. package/dist/commands-BkZNThm8.js.map +0 -1
  44. package/dist/dev-C6HogNjR.js.map +0 -1
  45. package/dist/prepare-90XQCoak.js +0 -3
  46. package/dist/prepare-CHLrneYU.js +0 -68
  47. package/dist/prepare-CHLrneYU.js.map +0 -1
  48. package/dist/prepare-hOwjyelr.js.map +0 -1
  49. package/dist/tsdown-Do8vjnIK.js.map +0 -1
  50. package/dist/tui-C2P91TgW.js.map +0 -1
  51. package/dist/tunnel-B8Id4-lR.js.map +0 -1
  52. 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 { CliError, type CliErrorOptions, ConfigError, type ConfigErrorOptions, ExitCode, type OutputMode, type ResolveOutputModeOptions, type ResolvedStarsConfig, exitCodeOf, formatError, isCIEnvironment, loadStarsConfig, prefersReducedMotion, resolveOutputMode, shouldUseColor };
69
+ export { type CliErrorOptions, ConfigError, type ConfigErrorOptions, type OutputMode, type ResolveOutputModeOptions, type ResolvedStarsConfig, loadStarsConfig };
70
70
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/lib/errors.ts","../src/lib/output-mode.ts"],"mappings":";;cAEa;WACZ;WACA;WACA;WACA;WACA;WACA;;KAGW,mBAAmB,uBAAuB;UAErC;;EAEhB;;EAEA;EACA,WAAW;EACX;;;;;cAMY,iBAAiB;WACb;WACA;WACA,UAAU;EAE1B,YAAmB,iBAAiB,SAAS;;;;;;;;iBAe9B,YAAY;iBAgBZ,WAAW,iBAAiB;;;KC7DhC;UAEK;;EAEhB;EACA,MAAM,OAAO;;EAEb;;EAEA;EACA;EACA;;EAEA;;;;;;;iBAUe,kBAAkB,UAAS,2BAAgC;iBAkB3D,gBAAgB,MAAK,OAAO;;;;iBAU5B,eAAe,MAAK,OAAO,YAA0B;;;;iBASrD,qBAAqB,MAAK,OAAO"}
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":["#nextId","#entries"],"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,KAAKA;GAAW,MAAM,KAAK,IAAI;GAAG,GAAG;EAAM;EACzE,KAAKC,SAAS,KAAK,KAAK;EACxB,IAAI,KAAKA,SAAS,SAAS,KAAK,UAAU,KAAKA,SAAS,OAAO,GAAG,KAAKA,SAAS,SAAS,KAAK,QAAQ;EACtG,KAAK,KAAK,SAAS,KAAK;EACxB,OAAO;CACR;CAEA,AAAO,UAA+B;EACrC,OAAO,KAAKA;CACb;CAEA,AAAO,OAAO,QAA+B;EAC5C,MAAM,QAAQ,OAAO,OAAO,YAAY,KAAK;EAC7C,OAAO,KAAKA,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,KAAKA,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
+ {"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":["#watcher"],"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,KAAKA,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,KAAKA;EACrB,KAAKA,WAAW;EAChB,MAAM,SAAS,MAAM;CACtB;AACD"}
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,3 @@
1
+ import { n as prepareProject, r as runPrepare, t as prepareAutoImports } from "./prepare-BjFq1zBC.js";
2
+
3
+ export { runPrepare };
@@ -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 the auto imports declaration file (imports.dts)"
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 file is out of date instead of writing it",
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-90XQCoak.js");
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-hOwjyelr.js.map
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":["#state","#child","#startedAt","#setState","#stopping"],"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":"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"}
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"}
@@ -1 +1 @@
1
- {"version":3,"file":"tsc-BqZfDTD0.js","names":["#spawn","#begin","#child","#finish","#firstError","#handleLine","#startedAt"],"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
+ {"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
- #bundles = [];
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.#bundles = await tsdown.build(options);
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.#bundles = await tsdown.build(this.#watchOptions(options));
49
+ this.#handle = await tsdown.build(this.#watchOptions(options));
49
50
  }
50
51
  async close() {
51
- const bundles = this.#bundles;
52
- this.#bundles = [];
53
- await Promise.allSettled(bundles.map((bundle) => bundle[Symbol.asyncDispose]()));
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 = [...await this.#plugins(), ...toArray(user.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 && this.#bundles.length > 0) this.#finish(errorSummary(args));
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-Do8vjnIK.js.map
247
+ //# sourceMappingURL=tsdown-DySpwiDI.js.map