@pristine-ts/cli 2.0.4 → 2.0.6

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 (140) hide show
  1. package/dist/bin/pristine.cjs +6 -2
  2. package/dist/lib/cjs/bin.js +18 -1
  3. package/dist/lib/cjs/bin.js.map +1 -1
  4. package/dist/lib/cjs/bootstrap/app-module-loader.js +40 -78
  5. package/dist/lib/cjs/bootstrap/app-module-loader.js.map +1 -1
  6. package/dist/lib/cjs/bootstrap/loaded-app-module.js +9 -13
  7. package/dist/lib/cjs/bootstrap/loaded-app-module.js.map +1 -1
  8. package/dist/lib/cjs/bootstrap/plugin-loader.js +3 -3
  9. package/dist/lib/cjs/bootstrap/plugin-loader.js.map +1 -1
  10. package/dist/lib/cjs/cli.js +173 -85
  11. package/dist/lib/cjs/cli.js.map +1 -1
  12. package/dist/lib/cjs/cli.module.js +24 -8
  13. package/dist/lib/cjs/cli.module.js.map +1 -1
  14. package/dist/lib/cjs/commands/build-alias.command.js.map +1 -1
  15. package/dist/lib/cjs/commands/build.command.js +9 -10
  16. package/dist/lib/cjs/commands/build.command.js.map +1 -1
  17. package/dist/lib/cjs/commands/config-print.command.js +1 -2
  18. package/dist/lib/cjs/commands/config-print.command.js.map +1 -1
  19. package/dist/lib/cjs/commands/help-alias.command.js.map +1 -1
  20. package/dist/lib/cjs/commands/help.command.js +1 -2
  21. package/dist/lib/cjs/commands/help.command.js.map +1 -1
  22. package/dist/lib/cjs/commands/info-alias.command.js.map +1 -1
  23. package/dist/lib/cjs/commands/info.command.js +7 -8
  24. package/dist/lib/cjs/commands/info.command.js.map +1 -1
  25. package/dist/lib/cjs/commands/init-alias.command.js.map +1 -1
  26. package/dist/lib/cjs/commands/init.command.js +13 -12
  27. package/dist/lib/cjs/commands/init.command.js.map +1 -1
  28. package/dist/lib/cjs/commands/list-alias.command.js.map +1 -1
  29. package/dist/lib/cjs/commands/list.command.js +1 -2
  30. package/dist/lib/cjs/commands/list.command.js.map +1 -1
  31. package/dist/lib/cjs/commands/start-alias.command.js.map +1 -1
  32. package/dist/lib/cjs/commands/start.command.js +3 -4
  33. package/dist/lib/cjs/commands/start.command.js.map +1 -1
  34. package/dist/lib/cjs/commands/verify-alias.command.js.map +1 -1
  35. package/dist/lib/cjs/commands/verify.command.js +3 -4
  36. package/dist/lib/cjs/commands/verify.command.js.map +1 -1
  37. package/dist/lib/cjs/config/resolved-pristine-config.js +2 -3
  38. package/dist/lib/cjs/config/resolved-pristine-config.js.map +1 -1
  39. package/dist/lib/cjs/errors/cli-error-code.enum.js +17 -0
  40. package/dist/lib/cjs/errors/cli-error-code.enum.js.map +1 -0
  41. package/dist/lib/cjs/errors/command-not-found.error.js +11 -12
  42. package/dist/lib/cjs/errors/command-not-found.error.js.map +1 -1
  43. package/dist/lib/cjs/errors/errors.js +1 -0
  44. package/dist/lib/cjs/errors/errors.js.map +1 -1
  45. package/dist/lib/cjs/event-handlers/cli.event-handler.js +28 -20
  46. package/dist/lib/cjs/event-handlers/cli.event-handler.js.map +1 -1
  47. package/dist/lib/cjs/reporters/cli-error.reporter.js +121 -0
  48. package/dist/lib/cjs/reporters/cli-error.reporter.js.map +1 -0
  49. package/dist/lib/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  50. package/dist/lib/cjs/types/command-event-response.type.js.map +1 -1
  51. package/dist/lib/esm/bin.js +18 -1
  52. package/dist/lib/esm/bin.js.map +1 -1
  53. package/dist/lib/esm/bootstrap/app-module-loader.js +40 -78
  54. package/dist/lib/esm/bootstrap/app-module-loader.js.map +1 -1
  55. package/dist/lib/esm/bootstrap/loaded-app-module.js +9 -13
  56. package/dist/lib/esm/bootstrap/loaded-app-module.js.map +1 -1
  57. package/dist/lib/esm/bootstrap/plugin-loader.js +3 -3
  58. package/dist/lib/esm/bootstrap/plugin-loader.js.map +1 -1
  59. package/dist/lib/esm/cli.js +172 -84
  60. package/dist/lib/esm/cli.js.map +1 -1
  61. package/dist/lib/esm/cli.module.js +24 -8
  62. package/dist/lib/esm/cli.module.js.map +1 -1
  63. package/dist/lib/esm/commands/build-alias.command.js.map +1 -1
  64. package/dist/lib/esm/commands/build.command.js +10 -11
  65. package/dist/lib/esm/commands/build.command.js.map +1 -1
  66. package/dist/lib/esm/commands/config-print.command.js +2 -3
  67. package/dist/lib/esm/commands/config-print.command.js.map +1 -1
  68. package/dist/lib/esm/commands/help-alias.command.js.map +1 -1
  69. package/dist/lib/esm/commands/help.command.js +2 -3
  70. package/dist/lib/esm/commands/help.command.js.map +1 -1
  71. package/dist/lib/esm/commands/info-alias.command.js.map +1 -1
  72. package/dist/lib/esm/commands/info.command.js +8 -9
  73. package/dist/lib/esm/commands/info.command.js.map +1 -1
  74. package/dist/lib/esm/commands/init-alias.command.js.map +1 -1
  75. package/dist/lib/esm/commands/init.command.js +14 -13
  76. package/dist/lib/esm/commands/init.command.js.map +1 -1
  77. package/dist/lib/esm/commands/list-alias.command.js.map +1 -1
  78. package/dist/lib/esm/commands/list.command.js +2 -3
  79. package/dist/lib/esm/commands/list.command.js.map +1 -1
  80. package/dist/lib/esm/commands/start-alias.command.js.map +1 -1
  81. package/dist/lib/esm/commands/start.command.js +4 -5
  82. package/dist/lib/esm/commands/start.command.js.map +1 -1
  83. package/dist/lib/esm/commands/verify-alias.command.js.map +1 -1
  84. package/dist/lib/esm/commands/verify.command.js +4 -5
  85. package/dist/lib/esm/commands/verify.command.js.map +1 -1
  86. package/dist/lib/esm/config/resolved-pristine-config.js +2 -3
  87. package/dist/lib/esm/config/resolved-pristine-config.js.map +1 -1
  88. package/dist/lib/esm/errors/cli-error-code.enum.js +14 -0
  89. package/dist/lib/esm/errors/cli-error-code.enum.js.map +1 -0
  90. package/dist/lib/esm/errors/command-not-found.error.js +12 -13
  91. package/dist/lib/esm/errors/command-not-found.error.js.map +1 -1
  92. package/dist/lib/esm/errors/errors.js +1 -0
  93. package/dist/lib/esm/errors/errors.js.map +1 -1
  94. package/dist/lib/esm/event-handlers/cli.event-handler.js +29 -21
  95. package/dist/lib/esm/event-handlers/cli.event-handler.js.map +1 -1
  96. package/dist/lib/esm/reporters/cli-error.reporter.js +118 -0
  97. package/dist/lib/esm/reporters/cli-error.reporter.js.map +1 -0
  98. package/dist/lib/esm/tsconfig.tsbuildinfo +1 -1
  99. package/dist/lib/esm/types/command-event-response.type.js.map +1 -1
  100. package/dist/types/bin.d.ts +1 -0
  101. package/dist/types/bootstrap/app-module-loader.d.ts +24 -25
  102. package/dist/types/bootstrap/loaded-app-module.d.ts +12 -26
  103. package/dist/types/bootstrap/plugin-loader.d.ts +1 -1
  104. package/dist/types/cli.d.ts +69 -9
  105. package/dist/types/cli.module.d.ts +2 -2
  106. package/dist/types/commands/build-alias.command.d.ts +2 -2
  107. package/dist/types/commands/build.command.d.ts +2 -2
  108. package/dist/types/commands/config-print.command.d.ts +2 -2
  109. package/dist/types/commands/help-alias.command.d.ts +2 -2
  110. package/dist/types/commands/help.command.d.ts +2 -2
  111. package/dist/types/commands/info-alias.command.d.ts +2 -2
  112. package/dist/types/commands/info.command.d.ts +2 -2
  113. package/dist/types/commands/init-alias.command.d.ts +2 -2
  114. package/dist/types/commands/init.command.d.ts +2 -2
  115. package/dist/types/commands/list-alias.command.d.ts +2 -2
  116. package/dist/types/commands/list.command.d.ts +2 -2
  117. package/dist/types/commands/start-alias.command.d.ts +2 -2
  118. package/dist/types/commands/start.command.d.ts +2 -2
  119. package/dist/types/commands/verify-alias.command.d.ts +2 -2
  120. package/dist/types/commands/verify.command.d.ts +2 -2
  121. package/dist/types/config/pristine-config.interface.d.ts +38 -12
  122. package/dist/types/config/resolved-pristine-config.d.ts +4 -6
  123. package/dist/types/errors/cli-error-code.enum.d.ts +12 -0
  124. package/dist/types/errors/command-not-found.error.d.ts +8 -7
  125. package/dist/types/errors/errors.d.ts +1 -0
  126. package/dist/types/event-handlers/cli.event-handler.d.ts +4 -19
  127. package/dist/types/interfaces/command.interface.d.ts +2 -2
  128. package/dist/types/reporters/cli-error.reporter.d.ts +45 -0
  129. package/dist/types/types/command-event-response.type.d.ts +2 -2
  130. package/package.json +9 -9
  131. package/dist/lib/cjs/enums/enums.js +0 -18
  132. package/dist/lib/cjs/enums/enums.js.map +0 -1
  133. package/dist/lib/cjs/enums/exit-code.enum.js +0 -9
  134. package/dist/lib/cjs/enums/exit-code.enum.js.map +0 -1
  135. package/dist/lib/esm/enums/enums.js +0 -2
  136. package/dist/lib/esm/enums/enums.js.map +0 -1
  137. package/dist/lib/esm/enums/exit-code.enum.js +0 -6
  138. package/dist/lib/esm/enums/exit-code.enum.js.map +0 -1
  139. package/dist/types/enums/enums.d.ts +0 -1
  140. package/dist/types/enums/exit-code.enum.d.ts +0 -4
@@ -1 +1 @@
1
- {"version":3,"file":"command-event-response.type.js","sourceRoot":"","sources":["../../../../src/types/command-event-response.type.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,mBAAmB,CAAC;AAIhD,MAAM,OAAO,oBAAqB,SAAQ,aAAyD;CAClG"}
1
+ {"version":3,"file":"command-event-response.type.js","sourceRoot":"","sources":["../../../../src/types/command-event-response.type.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,mBAAmB,CAAC;AAIhD,MAAM,OAAO,oBAAqB,SAAQ,aAAqD;CAC9F"}
@@ -1 +1,2 @@
1
1
  #!/usr/bin/env node
2
+ declare const Cli: any;
@@ -8,17 +8,21 @@ import { LoadedAppModule } from "./loaded-app-module";
8
8
  import { PluginLoader } from "./plugin-loader";
9
9
  /**
10
10
  * Resolves the consumer's AppModule. The contract is intentionally narrow: there is
11
- * exactly one supported way to specify the module — `appModule.sourcePath` +
12
- * `appModule.outputPath` in `pristine.config.ts` (or `pristine.config.js`).
11
+ * exactly one supported way to specify the module — `cli.appModule.sourcePath` +
12
+ * `cli.appModule.outputPath` in `pristine.config.ts` (or `pristine.config.js`).
13
13
  *
14
14
  * Resolution path:
15
15
  * 1. Read `pristine.config.{ts,js}` via `ConfigLoader`.
16
- * 2. If `appModule` is configured: ensure the build is fresh (manifest check, prompt or
17
- * fail on stale), then dynamically import the configured `outputPath`.
16
+ * 2. If `cli.appModule` is configured: ensure the build is fresh (manifest check, prompt
17
+ * or fail on stale), then dynamically import the configured `outputPath`.
18
18
  * 3. If anything above is missing or broken: fall back to a `CliModule`-only synthetic
19
19
  * AppModule so built-in commands (notably `pristine init`) remain runnable. This is
20
20
  * the only escape hatch — there is no convention scan, no package.json discovery,
21
21
  * no cached prior selection.
22
+ *
23
+ * **Does not read the `config:` block.** Runtime configuration values are read directly
24
+ * by `ConfigurationManager` during kernel boot. This class is concerned only with
25
+ * module-graph assembly.
22
26
  */
23
27
  export declare class AppModuleLoader {
24
28
  private readonly configLoader;
@@ -32,32 +36,27 @@ export declare class AppModuleLoader {
32
36
  private readonly fallbackKeyname;
33
37
  constructor(configLoader: ConfigLoader, pluginLoader: PluginLoader, dynamicImporter: DynamicImporter, buildManifestReader: BuildManifestReader, buildManifestChecker: BuildManifestChecker, buildStalenessPrompt: BuildStalenessPrompt, buildRunner: BuildRunner);
34
38
  /**
35
- * Resolves the consumer's AppModule and the kernel configuration the CLI should boot
36
- * with. The flow has five stages, executed in order:
39
+ * Resolves the consumer's AppModule for the CLI. The flow has five stages:
37
40
  *
38
41
  * 1. **Read the project's pristine.config.{ts,js}** — single source of truth for
39
42
  * where the user's AppModule lives and what plugins to wire in.
40
43
  * 2. **Check the compiled AppModule is in sync with its source** — when both
41
- * `appModule.sourcePath` and `appModule.outputPath` are configured, compare the
42
- * build manifest's recorded source hash against the current source. If they
43
- * diverge (the user edited source but didn't rebuild), prompt to rebuild in an
44
- * interactive terminal, or fail with an actionable error in CI / non-interactive
45
- * contexts.
44
+ * `cli.appModule.sourcePath` and `cli.appModule.outputPath` are configured,
45
+ * compare the build manifest's recorded source hash against the current source.
46
+ * If they diverge (the user edited source but didn't rebuild), prompt to rebuild
47
+ * in an interactive terminal, or fail with an actionable error in CI /
48
+ * non-interactive contexts.
46
49
  * 3. **Dynamically import the compiled AppModule** — load the JS file at
47
50
  * `outputPath` and pull out the configured named export (default `AppModule`).
48
51
  * 4. **Substitute a CliModule-only AppModule when nothing else worked** — when
49
- * there is no config file, no `appModule` block in the config, or the import
52
+ * there is no config file, no `cli.appModule` block in the config, or the import
50
53
  * threw, build a synthetic AppModule that imports just CliModule. This keeps the
51
54
  * bin runnable so the user can run `pristine init`, `pristine help`, etc. to
52
55
  * recover. There is no convention scan, no package.json discovery — only this
53
56
  * one escape hatch.
54
- * 5. **Wrap with config-declared plugins** — load every plugin listed in the
55
- * config's `plugins` array and merge their modules into the AppModule's import
56
- * graph via a synthetic outer module.
57
- *
58
- * Final output: a `LoadedAppModule` carrying the (possibly wrapped) AppModule, the
59
- * kernel configuration overlay, the logging-module-present flag, and the loaded
60
- * plugin list.
57
+ * 5. **Wrap with config-declared plugins** — load every plugin listed in
58
+ * `cli.plugins` and merge their modules into the AppModule's import graph via a
59
+ * synthetic outer module.
61
60
  */
62
61
  load(): Promise<LoadedAppModule>;
63
62
  /**
@@ -72,12 +71,12 @@ export declare class AppModuleLoader {
72
71
  private ensureFreshBuild;
73
72
  private importAppModule;
74
73
  /**
75
- * Builds the safety-net AppModule used when no `appModule` is configured or the configured
76
- * file fails to load. Scrapes any `node_modules/@pristine-ts/*` packages already installed
77
- * so built-in commands they contribute (e.g. `pristine list`) are still available, then
78
- * appends `CliModule` so at minimum the CLI's own commands run. This is intentionally a
79
- * one-way safety net, not a discovery tier — it only fires when nothing else worked.
74
+ * Builds the safety-net AppModule used when no `cli.appModule` is configured or the
75
+ * configured file fails to load. Scrapes any `node_modules/@pristine-ts/*` packages
76
+ * already installed so built-in commands they contribute (e.g. `pristine list`) are
77
+ * still available, then appends `CliModule` so at minimum the CLI's own commands run.
78
+ * This is intentionally a one-way safety net, not a discovery tier — it only fires
79
+ * when nothing else worked.
80
80
  */
81
81
  private buildFallbackAppModule;
82
- private buildKernelConfiguration;
83
82
  }
@@ -1,40 +1,26 @@
1
1
  import { AppModuleInterface } from "@pristine-ts/common";
2
- import { ModuleConfigurationValue } from "@pristine-ts/configuration";
3
2
  import { LoadedPlugin } from "./loaded-plugin";
4
3
  /**
5
- * The fully-resolved AppModule + ambient configuration that the CLI uses to boot the kernel.
4
+ * The fully-resolved AppModule and the plugin list that the CLI uses to boot the kernel.
6
5
  * Returned by `AppModuleLoader.load()`.
6
+ *
7
+ * **No `configuration` field.** Runtime configuration values from `pristine.config.ts:config`
8
+ * are read directly by `ConfigurationManager` during kernel boot, not pre-loaded by the
9
+ * CLI. The CLI is responsible only for module-graph assembly.
7
10
  */
8
11
  export declare class LoadedAppModule {
9
12
  readonly appModule: AppModuleInterface;
10
- readonly configuration: {
11
- [key: string]: ModuleConfigurationValue;
12
- };
13
13
  /**
14
- * True when `LoggingModule` is in the resolved AppModule's import graph. The CLI uses
15
- * this to decide whether to layer in opinionated default logging configuration (Simple
16
- * output mode, Error severity threshold) on top of the kernel configuration.
17
- */
18
- readonly isLoggingModulePresent: boolean;
19
- /**
20
- * Plugins loaded from `pristine.config.ts`'s `plugins` array. Empty when no plugins are
21
- * declared. Carried through so commands like `pristine info` can show what's contributing
22
- * extra modules to the runtime.
14
+ * Plugins loaded from `pristine.config.ts:cli.plugins`. Empty when no plugins are
15
+ * declared. Carried through so commands like `pristine info` can show what's
16
+ * contributing extra modules to the runtime.
23
17
  */
24
18
  readonly plugins: LoadedPlugin[];
25
- constructor(appModule: AppModuleInterface, configuration: {
26
- [key: string]: ModuleConfigurationValue;
27
- },
28
- /**
29
- * True when `LoggingModule` is in the resolved AppModule's import graph. The CLI uses
30
- * this to decide whether to layer in opinionated default logging configuration (Simple
31
- * output mode, Error severity threshold) on top of the kernel configuration.
32
- */
33
- isLoggingModulePresent: boolean,
19
+ constructor(appModule: AppModuleInterface,
34
20
  /**
35
- * Plugins loaded from `pristine.config.ts`'s `plugins` array. Empty when no plugins are
36
- * declared. Carried through so commands like `pristine info` can show what's contributing
37
- * extra modules to the runtime.
21
+ * Plugins loaded from `pristine.config.ts:cli.plugins`. Empty when no plugins are
22
+ * declared. Carried through so commands like `pristine info` can show what's
23
+ * contributing extra modules to the runtime.
38
24
  */
39
25
  plugins: LoadedPlugin[]);
40
26
  }
@@ -3,7 +3,7 @@ import { PristineConfig } from "../config/pristine-config.interface";
3
3
  import { DynamicImporter } from "./dynamic-importer";
4
4
  import { LoadedPlugin } from "./loaded-plugin";
5
5
  /**
6
- * Resolves and loads every plugin declared in `config.plugins`. Plugin packages are resolved
6
+ * Resolves and loads every plugin declared in `config.cli.plugins`. Plugin packages are resolved
7
7
  * from the **consumer's project**, not from the CLI's install location — a plugin lives in
8
8
  * the consumer's `node_modules`, not in `@pristine-ts/cli/node_modules`. Without
9
9
  * `createRequire` pinned to the project location, `import("@my-org/plugin")` would walk up
@@ -1,13 +1,73 @@
1
1
  /**
2
2
  * Boots the CLI: discovers the consumer's AppModule, starts the kernel, and dispatches
3
- * `process.argv` to whichever command matches. Exported so `bin.ts` can call it explicitly
4
- * the auto-invoke at module load was removed so library consumers importing this file for
5
- * its types or `bootstrap` reference do not accidentally trigger an entire kernel boot.
3
+ * `process.argv` to whichever command matches. Returns the process exit code rather than
4
+ * exiting itself `bin.ts` does `new Cli().bootstrap().then(process.exit)`.
6
5
  *
7
- * The bootstrap-layer collaborators (loaders, discoverers, cache, prompt) are instantiated
8
- * by hand here rather than resolved through DI. The kernel container does not exist yet at
9
- * this point, so DI is not available manually wiring the (small, stable) class graph is the
10
- * least surprising option. Once the kernel is up, the kernel itself is registered into its
11
- * own container so commands can inject it.
6
+ * **Error handling is internal.** Every throw from `appModuleLoader.load()`,
7
+ * `kernel.start()`, or the dispatched command funnels through `reportFatalError` and
8
+ * gets rendered via `CliErrorReporter`. The bin doesn't need its own catch.
9
+ *
10
+ * **Per-call state.** `kernel` lives as an instance field so it's available to
11
+ * `reportFatalError` and `warnOnCommandCollisions` without threading it through method
12
+ * parameters. One `Cli` instance per `bootstrap()` invocation — the lifetime matches
13
+ * the CLI process.
14
+ *
15
+ * **No DI.** The kernel container does not exist yet during boot — the bootstrap-layer
16
+ * collaborators (loaders, discoverers, cache, prompt) are hand-wired in `build()`. Once
17
+ * the kernel is up, it registers itself into its own container so commands can inject it.
12
18
  */
13
- export declare const bootstrap: () => Promise<void>;
19
+ export declare class Cli {
20
+ private kernel?;
21
+ bootstrap(): Promise<number>;
22
+ /**
23
+ * Renders any error that escapes the boot/dispatch flow and returns the exit code the
24
+ * bin should pass to `process.exit`.
25
+ *
26
+ * Two resolution paths for `EnvironmentManager`, picked in order of "most likely to be
27
+ * correctly configured":
28
+ *
29
+ * 1. **Kernel up**: resolve `CliErrorReporter` (and its `EnvironmentManager`) through
30
+ * DI. This is the path for command-runtime errors — the configuration system
31
+ * already ran and `pristine.environment` is whatever the user configured.
32
+ *
33
+ * 2. **Kernel-start failed**: peek directly at `pristine.config.ts:config` via
34
+ * `PristineConfigFileLoader`. If a value for `pristine.environment` is set in the
35
+ * file, use it; otherwise default to production. Boot-time errors get sanitized
36
+ * unless the user explicitly opted into `dev` in the file.
37
+ *
38
+ * No `process.env` reads in any branch — the environment flows exclusively through
39
+ * the configuration system or its file source.
40
+ */
41
+ private reportFatalError;
42
+ /**
43
+ * Peeks at `pristine.config.ts:config[pristine.environment]` directly via the shared
44
+ * file loader. Used only by the kernel-down fallback in `reportFatalError`. Failures
45
+ * (file missing, parse error, etc.) silently fall back to production — boot-time
46
+ * sanitized output is the safer default.
47
+ */
48
+ private readEnvironmentFromConfigFile;
49
+ /**
50
+ * Builds a synthetic outer AppModule that imports both the user's AppModule and CliModule.
51
+ * The wrap is unconditional — the kernel dedupes module imports by keyname, so adding
52
+ * CliModule on top of a graph that already contains it is a no-op rather than an error
53
+ * or duplicate registration. Cheaper than walking the user's import tree to detect the
54
+ * already-present case.
55
+ */
56
+ private wrapWithCliModule;
57
+ /**
58
+ * Hand-wired graph of the bootstrap-layer classes. The kernel container does not exist
59
+ * yet, so we cannot resolve via DI — but the class graph here is shallow and stable, so
60
+ * manual wiring stays readable. Each class is `@injectable()` so DI resolution would also
61
+ * work if we ever moved this into a kernel-pre-boot container.
62
+ */
63
+ private buildAppModuleLoader;
64
+ /**
65
+ * Walks every registered Command-tagged service and warns to stderr if multiple share a
66
+ * `name`. The CLI's event dispatcher picks whichever match it sees first — without this
67
+ * warning, a plugin silently shadowing a built-in command (or two plugins shadowing each
68
+ * other) would be invisible until someone debugged "why is my command not running?".
69
+ * Warning rather than throwing keeps the bin runnable; users decide whether to fix the
70
+ * conflict.
71
+ */
72
+ private warnOnCommandCollisions;
73
+ }
@@ -2,7 +2,6 @@ import { ModuleInterface } from "@pristine-ts/common";
2
2
  export * from "./bootstrap/bootstrap";
3
3
  export * from "./commands/commands";
4
4
  export * from "./config/config";
5
- export * from "./enums/enums";
6
5
  export * from "./errors/errors";
7
6
  export * from "./event-handlers/event-handlers";
8
7
  export * from "./event-payloads/event-payloads";
@@ -10,6 +9,7 @@ export * from "./interfaces/interfaces";
10
9
  export * from "./managers/managers";
11
10
  export * from "./mappers/mappers";
12
11
  export * from "./options/options";
12
+ export * from "./reporters/cli-error.reporter";
13
13
  export * from "./types/types";
14
- export { bootstrap } from "./cli";
14
+ export { Cli } from "./cli";
15
15
  export declare const CliModule: ModuleInterface;
@@ -1,5 +1,5 @@
1
+ import { ExitCode } from "@pristine-ts/common";
1
2
  import { CommandInterface } from "../interfaces/command.interface";
2
- import { ExitCodeEnum } from "../enums/exit-code.enum";
3
3
  import { BuildCommand } from "./build.command";
4
4
  /**
5
5
  * Top-level alias for the framework-reserved `p:build` command. Injects the delegate
@@ -11,5 +11,5 @@ export declare class BuildAliasCommand implements CommandInterface<null> {
11
11
  name: string;
12
12
  description: string;
13
13
  constructor(delegate: BuildCommand);
14
- run(args: any): Promise<ExitCodeEnum | number>;
14
+ run(args: any): Promise<ExitCode | number>;
15
15
  }
@@ -1,7 +1,7 @@
1
+ import { ExitCode } from "@pristine-ts/common";
1
2
  import { CommandInterface } from "../interfaces/command.interface";
2
3
  import { ConsoleManager } from "../managers/console.manager";
3
4
  import { ShellManager } from "../managers/shell.manager";
4
- import { ExitCodeEnum } from "../enums/exit-code.enum";
5
5
  import { ConfigLoader } from "../config/config-loader";
6
6
  import { BuildManifestWriter } from "../bootstrap/build-manifest-writer";
7
7
  /**
@@ -34,7 +34,7 @@ export declare class BuildCommand implements CommandInterface<null> {
34
34
  private readonly defaultTsconfig;
35
35
  private readonly defaultFormat;
36
36
  constructor(consoleManager: ConsoleManager, shellManager: ShellManager, configLoader: ConfigLoader, buildManifestWriter: BuildManifestWriter);
37
- run(args: any): Promise<ExitCodeEnum | number>;
37
+ run(args: any): Promise<ExitCode | number>;
38
38
  private writeManifestIfConfigured;
39
39
  /**
40
40
  * For `format: "both"`, we run two passes: the primary tsconfig (assumed ESM-ish), then
@@ -1,6 +1,6 @@
1
+ import { ExitCode } from "@pristine-ts/common";
1
2
  import { CommandInterface } from "../interfaces/command.interface";
2
3
  import { ConsoleManager } from "../managers/console.manager";
3
- import { ExitCodeEnum } from "../enums/exit-code.enum";
4
4
  import { ConfigLoader } from "../config/config-loader";
5
5
  /**
6
6
  * Prints the resolved Pristine configuration plus where it was loaded from. Useful for
@@ -14,5 +14,5 @@ export declare class ConfigPrintCommand implements CommandInterface<null> {
14
14
  name: string;
15
15
  description: string;
16
16
  constructor(consoleManager: ConsoleManager, configLoader: ConfigLoader);
17
- run(args: any): Promise<ExitCodeEnum | number>;
17
+ run(args: any): Promise<ExitCode | number>;
18
18
  }
@@ -1,5 +1,5 @@
1
+ import { ExitCode } from "@pristine-ts/common";
1
2
  import { CommandInterface } from "../interfaces/command.interface";
2
- import { ExitCodeEnum } from "../enums/exit-code.enum";
3
3
  import { HelpCommand } from "./help.command";
4
4
  /**
5
5
  * Top-level alias for the framework-reserved `p:help` command. Injects the delegate
@@ -13,5 +13,5 @@ export declare class HelpAliasCommand implements CommandInterface<null> {
13
13
  name: string;
14
14
  description: string;
15
15
  constructor(delegate: HelpCommand);
16
- run(args: any): Promise<ExitCodeEnum | number>;
16
+ run(args: any): Promise<ExitCode | number>;
17
17
  }
@@ -1,7 +1,7 @@
1
1
  import { DependencyContainer } from "tsyringe";
2
+ import { ExitCode } from "@pristine-ts/common";
2
3
  import { CommandInterface } from "../interfaces/command.interface";
3
4
  import { ConsoleManager } from "../managers/console.manager";
4
- import { ExitCodeEnum } from "../enums/exit-code.enum";
5
5
  /**
6
6
  * Prints a usage banner plus a one-line summary for every registered command. The output is
7
7
  * generated from the actual `CommandInterface[]` resolved from the current DI container, so
@@ -24,5 +24,5 @@ export declare class HelpCommand implements CommandInterface<null> {
24
24
  name: string;
25
25
  description: string;
26
26
  constructor(consoleManager: ConsoleManager, container: DependencyContainer);
27
- run(args: any): Promise<ExitCodeEnum | number>;
27
+ run(args: any): Promise<ExitCode | number>;
28
28
  }
@@ -1,5 +1,5 @@
1
+ import { ExitCode } from "@pristine-ts/common";
1
2
  import { CommandInterface } from "../interfaces/command.interface";
2
- import { ExitCodeEnum } from "../enums/exit-code.enum";
3
3
  import { InfoCommand } from "./info.command";
4
4
  /**
5
5
  * Top-level alias for the framework-reserved `p:info` command. Injects the delegate
@@ -11,5 +11,5 @@ export declare class InfoAliasCommand implements CommandInterface<null> {
11
11
  name: string;
12
12
  description: string;
13
13
  constructor(delegate: InfoCommand);
14
- run(args: any): Promise<ExitCodeEnum | number>;
14
+ run(args: any): Promise<ExitCode | number>;
15
15
  }
@@ -1,6 +1,6 @@
1
+ import { ExitCode } from "@pristine-ts/common";
1
2
  import { CommandInterface } from "../interfaces/command.interface";
2
3
  import { ConsoleManager } from "../managers/console.manager";
3
- import { ExitCodeEnum } from "../enums/exit-code.enum";
4
4
  import { ConfigLoader } from "../config/config-loader";
5
5
  import { AppModuleLoader } from "../bootstrap/app-module-loader";
6
6
  /**
@@ -27,7 +27,7 @@ export declare class InfoCommand implements CommandInterface<null> {
27
27
  */
28
28
  private readonly cliPackageJsonPath;
29
29
  constructor(consoleManager: ConsoleManager, configLoader: ConfigLoader, appModuleLoader: AppModuleLoader);
30
- run(args: any): Promise<ExitCodeEnum | number>;
30
+ run(args: any): Promise<ExitCode | number>;
31
31
  private printRuntimeBanner;
32
32
  private printConfigSection;
33
33
  private printAppModuleSection;
@@ -1,5 +1,5 @@
1
+ import { ExitCode } from "@pristine-ts/common";
1
2
  import { CommandInterface } from "../interfaces/command.interface";
2
- import { ExitCodeEnum } from "../enums/exit-code.enum";
3
3
  import { InitCommand } from "./init.command";
4
4
  import { InitCommandOptions } from "./init.command-options";
5
5
  /**
@@ -12,5 +12,5 @@ export declare class InitAliasCommand implements CommandInterface<InitCommandOpt
12
12
  name: string;
13
13
  description: string;
14
14
  constructor(delegate: InitCommand);
15
- run(args: InitCommandOptions): Promise<ExitCodeEnum | number>;
15
+ run(args: InitCommandOptions): Promise<ExitCode | number>;
16
16
  }
@@ -1,6 +1,6 @@
1
+ import { ExitCode } from "@pristine-ts/common";
1
2
  import { CommandInterface } from "../interfaces/command.interface";
2
3
  import { ConsoleManager } from "../managers/console.manager";
3
- import { ExitCodeEnum } from "../enums/exit-code.enum";
4
4
  import { InitCommandOptions } from "./init.command-options";
5
5
  import { InitPrompt } from "../bootstrap/init-prompt";
6
6
  /**
@@ -27,7 +27,7 @@ export declare class InitCommand implements CommandInterface<InitCommandOptions>
27
27
  private readonly configFileName;
28
28
  private readonly gitignoreEntry;
29
29
  constructor(consoleManager: ConsoleManager, initPrompt: InitPrompt);
30
- run(args: InitCommandOptions): Promise<ExitCodeEnum | number>;
30
+ run(args: InitCommandOptions): Promise<ExitCode | number>;
31
31
  /**
32
32
  * Fills in answers from CLI flags first, then prompts (in TTY) for whatever's missing.
33
33
  * Returns undefined when running non-TTY with insufficient flags so the caller can exit
@@ -1,5 +1,5 @@
1
+ import { ExitCode } from "@pristine-ts/common";
1
2
  import { CommandInterface } from "../interfaces/command.interface";
2
- import { ExitCodeEnum } from "../enums/exit-code.enum";
3
3
  import { ListCommand } from "./list.command";
4
4
  /**
5
5
  * Top-level alias for the framework-reserved `p:list` command. Injects the delegate
@@ -11,5 +11,5 @@ export declare class ListAliasCommand implements CommandInterface<null> {
11
11
  name: string;
12
12
  description: string;
13
13
  constructor(delegate: ListCommand);
14
- run(args: any): Promise<ExitCodeEnum | number>;
14
+ run(args: any): Promise<ExitCode | number>;
15
15
  }
@@ -1,7 +1,7 @@
1
+ import { ExitCode } from "@pristine-ts/common";
1
2
  import { DependencyContainer } from "tsyringe";
2
3
  import { CommandInterface } from "../interfaces/command.interface";
3
4
  import { ConsoleManager } from "../managers/console.manager";
4
- import { ExitCodeEnum } from "../enums/exit-code.enum";
5
5
  /**
6
6
  * Lists every registered command's name. Like `HelpCommand`, this resolves the command set
7
7
  * lazily inside `run()` via the injected child container to avoid the self-referential cycle
@@ -14,5 +14,5 @@ export declare class ListCommand implements CommandInterface<null> {
14
14
  name: string;
15
15
  description: string;
16
16
  constructor(consoleManager: ConsoleManager, container: DependencyContainer);
17
- run(args: any): Promise<ExitCodeEnum | number>;
17
+ run(args: any): Promise<ExitCode | number>;
18
18
  }
@@ -1,5 +1,5 @@
1
+ import { ExitCode } from "@pristine-ts/common";
1
2
  import { CommandInterface } from "../interfaces/command.interface";
2
- import { ExitCodeEnum } from "../enums/exit-code.enum";
3
3
  import { StartCommand } from "./start.command";
4
4
  import { StartCommandOptions } from "./start.command-options";
5
5
  /**
@@ -12,5 +12,5 @@ export declare class StartAliasCommand implements CommandInterface<StartCommandO
12
12
  name: string;
13
13
  description: string;
14
14
  constructor(delegate: StartCommand);
15
- run(args: StartCommandOptions): Promise<ExitCodeEnum | number>;
15
+ run(args: StartCommandOptions): Promise<ExitCode | number>;
16
16
  }
@@ -1,7 +1,7 @@
1
+ import { ExitCode } from "@pristine-ts/common";
1
2
  import { Kernel, RuntimeServerInterface } from "@pristine-ts/core";
2
3
  import { CommandInterface } from "../interfaces/command.interface";
3
4
  import { ConsoleManager } from "../managers/console.manager";
4
- import { ExitCodeEnum } from "../enums/exit-code.enum";
5
5
  import { StartCommandOptions } from "./start.command-options";
6
6
  /**
7
7
  * Boots the AppModule, starts every registered `RuntimeServerInterface` (HTTP server, gRPC
@@ -43,5 +43,5 @@ export declare class StartCommand implements CommandInterface<StartCommandOption
43
43
  private static readonly HARD_EXIT_TIMEOUT_MS;
44
44
  private readonly defaultRuntimeServerName;
45
45
  constructor(consoleManager: ConsoleManager, kernel: Kernel, servers: RuntimeServerInterface[]);
46
- run(args: StartCommandOptions): Promise<ExitCodeEnum | number>;
46
+ run(args: StartCommandOptions): Promise<ExitCode | number>;
47
47
  }
@@ -1,5 +1,5 @@
1
+ import { ExitCode } from "@pristine-ts/common";
1
2
  import { CommandInterface } from "../interfaces/command.interface";
2
- import { ExitCodeEnum } from "../enums/exit-code.enum";
3
3
  import { VerifyCommand } from "./verify.command";
4
4
  /**
5
5
  * Top-level alias for the framework-reserved `p:verify` command. Injects the delegate
@@ -11,5 +11,5 @@ export declare class VerifyAliasCommand implements CommandInterface<null> {
11
11
  name: string;
12
12
  description: string;
13
13
  constructor(delegate: VerifyCommand);
14
- run(args: any): Promise<ExitCodeEnum | number>;
14
+ run(args: any): Promise<ExitCode | number>;
15
15
  }
@@ -1,6 +1,6 @@
1
+ import { ExitCode } from "@pristine-ts/common";
1
2
  import { LogHandlerInterface } from "@pristine-ts/logging";
2
3
  import { CommandInterface } from "../interfaces/command.interface";
3
- import { ExitCodeEnum } from "../enums/exit-code.enum";
4
4
  import { AppModuleLoader } from "../bootstrap/app-module-loader";
5
5
  /**
6
6
  * Verifies that the consumer's AppModule can be instantiated against its configuration.
@@ -20,5 +20,5 @@ export declare class VerifyCommand implements CommandInterface<null> {
20
20
  name: string;
21
21
  description: string;
22
22
  constructor(logHandler: LogHandlerInterface, appModuleLoader: AppModuleLoader);
23
- run(args: any): Promise<ExitCodeEnum | number>;
23
+ run(args: any): Promise<ExitCode | number>;
24
24
  }
@@ -1,8 +1,14 @@
1
1
  /**
2
- * The shape of `pristine.config.ts` (or `pristine.config.js`). The `appModule` block is
3
- * the canonical (and only) way to tell the CLI where your AppModule lives. When that
4
- * block is present, both `sourcePath` and `outputPath` must be provided so the build
5
- * manifest can keep them in sync.
2
+ * The shape of `pristine.config.ts` (or `pristine.config.js`). Two top-level blocks:
3
+ *
4
+ * - **`cli:`** CLI tool–specific configuration. Where the AppModule lives, which
5
+ * plugins to load, build/start options. Read by `@pristine-ts/cli` before the kernel
6
+ * exists, since this is what tells the CLI which app to assemble.
7
+ * - **`config:`** — runtime configuration values keyed by
8
+ * `configurationDefinition.parameterName`. Read by `@pristine-ts/configuration` during
9
+ * kernel boot. Sits in the resolver precedence chain *above* per-key
10
+ * `defaultResolvers` (env vars, secrets) and *below* explicit overrides passed to
11
+ * `kernel.start()`.
6
12
  *
7
13
  * Authored as a `.ts` file by default; use `defineConfig()` (re-exported from
8
14
  * `@pristine-ts/cli`) for full IDE autocomplete:
@@ -11,9 +17,15 @@
11
17
  * import {defineConfig} from "@pristine-ts/cli";
12
18
  *
13
19
  * export default defineConfig({
14
- * appModule: {
15
- * sourcePath: "src/app.module.ts",
16
- * outputPath: "dist/app.module.js",
20
+ * cli: {
21
+ * appModule: {
22
+ * sourcePath: "src/app.module.ts",
23
+ * outputPath: "dist/app.module.js",
24
+ * },
25
+ * },
26
+ * config: {
27
+ * "pristine.environment": "dev",
28
+ * "pristine.logging.consoleLoggerActivated": true,
17
29
  * },
18
30
  * });
19
31
  * ```
@@ -21,6 +33,25 @@
21
33
  * Run `pristine init` to generate this file interactively.
22
34
  */
23
35
  export interface PristineConfig {
36
+ /**
37
+ * CLI tool–specific configuration. Tells the CLI where to find the user's AppModule,
38
+ * which plugins to layer in, and how `pristine build` / `pristine start` should behave.
39
+ * Read by `@pristine-ts/cli` before the kernel exists.
40
+ */
41
+ cli?: PristineCliConfig;
42
+ /**
43
+ * Runtime configuration values keyed by `configurationDefinition.parameterName`. Read
44
+ * by `@pristine-ts/configuration` during kernel boot. A key here overrides the owning
45
+ * module's resolver chain and `defaultValue`, but loses to explicit overrides passed
46
+ * to `kernel.start()`.
47
+ */
48
+ config?: Record<string, unknown>;
49
+ }
50
+ /**
51
+ * Inner shape of the `cli:` block. Owned by `@pristine-ts/cli`; the framework's
52
+ * configuration system never inspects these fields.
53
+ */
54
+ export interface PristineCliConfig {
24
55
  /**
25
56
  * Where the AppModule lives. Both `sourcePath` and `outputPath` are required when
26
57
  * `appModule` is set. Paths are resolved relative to the directory containing the
@@ -59,9 +90,4 @@ export interface PristineConfig {
59
90
  name: string;
60
91
  options?: unknown;
61
92
  }>;
62
- /**
63
- * Default `kernel.start()` configuration values, merged on top of the CLI's defaults. Lets
64
- * you keep CLI-only runtime overrides out of your AppModule.
65
- */
66
- kernelConfiguration?: Record<string, unknown>;
67
93
  }
@@ -10,9 +10,8 @@ export declare class ResolvedPristineConfig {
10
10
  readonly configFilePath: string | undefined;
11
11
  /**
12
12
  * Per-top-level-field provenance markers, mainly for `pristine p:config:print`. Keys are
13
- * top-level fields of `PristineConfig` (`appModule`, `build`, `start`, `plugins`,
14
- * `kernelConfiguration`); values are the `ConfigProvenanceEnum` describing where each
15
- * came from.
13
+ * top-level fields of `PristineConfig` (`cli`, `config`); values are the
14
+ * `ConfigProvenanceEnum` describing where each came from.
16
15
  */
17
16
  readonly provenance: Record<string, ConfigProvenanceEnum>;
18
17
  constructor(config: PristineConfig,
@@ -20,9 +19,8 @@ export declare class ResolvedPristineConfig {
20
19
  configFilePath: string | undefined,
21
20
  /**
22
21
  * Per-top-level-field provenance markers, mainly for `pristine p:config:print`. Keys are
23
- * top-level fields of `PristineConfig` (`appModule`, `build`, `start`, `plugins`,
24
- * `kernelConfiguration`); values are the `ConfigProvenanceEnum` describing where each
25
- * came from.
22
+ * top-level fields of `PristineConfig` (`cli`, `config`); values are the
23
+ * `ConfigProvenanceEnum` describing where each came from.
26
24
  */
27
25
  provenance: Record<string, ConfigProvenanceEnum>);
28
26
  }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Error-code catalog owned by `@pristine-ts/cli`. Surfaced via `PristineErrorOptions.code`
3
+ * (typed `PristineErrorCode | string`, so any enum value is accepted).
4
+ *
5
+ * Codes here describe CLI-specific failures — command resolution, argument mapping,
6
+ * and argument validation.
7
+ */
8
+ export declare enum CliErrorCode {
9
+ CommandNotFound = "COMMAND_NOT_FOUND",
10
+ ArgumentMappingFailed = "ARGUMENT_MAPPING_FAILED",
11
+ ArgumentValidationFailed = "ARGUMENT_VALIDATION_FAILED"
12
+ }
@@ -1,12 +1,13 @@
1
- import { LoggableError } from "@pristine-ts/common";
1
+ import { UsageError } from "@pristine-ts/common";
2
2
  /**
3
- * The CommandNotFoundError error when the command specified is not implemented.
3
+ * Thrown when the user invokes a CLI command name that isn't registered with the kernel.
4
+ *
5
+ * Extends `UsageError` (which carries `exitCode: 64` / `EX_USAGE`, `kind: PristineErrorKind.UserError`) so
6
+ * the `CliErrorReporter` renders it as a clean one-line stderr message rather than a
7
+ * crash dump. The unknown command name is preserved as a structured `details.commandName`
8
+ * field, which surfaces under the error code in the stderr output.
4
9
  */
5
- export declare class CommandNotFoundError extends LoggableError {
10
+ export declare class CommandNotFoundError extends UsageError {
6
11
  readonly commandName: string;
7
- /**
8
- * This Error is the base class for CommandNotFoundError errors.
9
- * @param commandName The name of the command that could not be found
10
- */
11
12
  constructor(commandName: string);
12
13
  }