@nwire/cli 0.9.1 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/dist/cache-runner.d.ts +0 -1
  2. package/dist/cache-runner.js +107 -9
  3. package/dist/cli.d.ts +3 -6
  4. package/dist/cli.js +5 -7
  5. package/dist/commands/bench.d.ts +0 -1
  6. package/dist/commands/bench.js +0 -1
  7. package/dist/commands/build.d.ts +0 -1
  8. package/dist/commands/build.js +13 -17
  9. package/dist/commands/cache.d.ts +3 -3
  10. package/dist/commands/cache.js +7 -17
  11. package/dist/commands/check.d.ts +10 -3
  12. package/dist/commands/check.js +34 -10
  13. package/dist/commands/dev.d.ts +0 -1
  14. package/dist/commands/dev.js +0 -1
  15. package/dist/commands/doctor.d.ts +1 -2
  16. package/dist/commands/doctor.js +14 -15
  17. package/dist/commands/fmt.d.ts +8 -4
  18. package/dist/commands/fmt.js +35 -12
  19. package/dist/commands/greeting.d.ts +0 -1
  20. package/dist/commands/greeting.js +0 -1
  21. package/dist/commands/infra.d.ts +0 -1
  22. package/dist/commands/infra.js +0 -1
  23. package/dist/commands/lint.d.ts +7 -3
  24. package/dist/commands/lint.js +34 -13
  25. package/dist/commands/logs.d.ts +0 -1
  26. package/dist/commands/logs.js +0 -1
  27. package/dist/commands/ls.d.ts +1 -1
  28. package/dist/commands/ls.js +3 -1
  29. package/dist/commands/mcp.d.ts +0 -1
  30. package/dist/commands/mcp.js +2 -2
  31. package/dist/commands/please.d.ts +0 -1
  32. package/dist/commands/please.js +0 -1
  33. package/dist/commands/ps.d.ts +0 -1
  34. package/dist/commands/ps.js +0 -1
  35. package/dist/commands/replay.d.ts +0 -1
  36. package/dist/commands/replay.js +0 -1
  37. package/dist/commands/run.d.ts +0 -1
  38. package/dist/commands/run.js +0 -1
  39. package/dist/commands/studio.d.ts +0 -1
  40. package/dist/commands/studio.js +16 -6
  41. package/dist/commands/test.d.ts +0 -1
  42. package/dist/commands/test.js +0 -1
  43. package/dist/commands/trace.d.ts +0 -1
  44. package/dist/commands/trace.js +0 -1
  45. package/dist/commands/watch.d.ts +0 -1
  46. package/dist/commands/watch.js +0 -1
  47. package/dist/index.d.ts +0 -1
  48. package/dist/index.js +0 -1
  49. package/dist/lib/colors.d.ts +0 -1
  50. package/dist/lib/colors.js +0 -1
  51. package/dist/lib/dev-entry.d.ts +0 -1
  52. package/dist/lib/dev-entry.js +0 -1
  53. package/dist/lib/ensure-scan.d.ts +28 -0
  54. package/dist/lib/ensure-scan.js +41 -0
  55. package/dist/lib/exec.d.ts +0 -1
  56. package/dist/lib/exec.js +0 -1
  57. package/dist/lib/layout.d.ts +40 -0
  58. package/dist/lib/layout.js +128 -0
  59. package/dist/lib/package-manager.d.ts +17 -0
  60. package/dist/lib/package-manager.js +67 -0
  61. package/dist/lib/process-state.d.ts +0 -1
  62. package/dist/lib/process-state.js +0 -1
  63. package/dist/lib/project.d.ts +3 -4
  64. package/dist/lib/project.js +16 -34
  65. package/dist/lib/run-task.d.ts +0 -1
  66. package/dist/lib/run-task.js +0 -1
  67. package/dist/lib/scan-cache.d.ts +27 -0
  68. package/dist/lib/scan-cache.js +102 -0
  69. package/dist/lib/script-runner.d.ts +42 -0
  70. package/dist/lib/script-runner.js +90 -0
  71. package/dist/lib/sse.d.ts +0 -1
  72. package/dist/lib/sse.js +0 -1
  73. package/dist/lib/version.d.ts +8 -0
  74. package/dist/lib/version.js +29 -0
  75. package/dist/lib/vite-node.d.ts +0 -1
  76. package/dist/lib/vite-node.js +0 -1
  77. package/dist/lib/wire-discovery.d.ts +0 -1
  78. package/dist/lib/wire-discovery.js +0 -1
  79. package/dist/load-config.d.ts +0 -1
  80. package/dist/load-config.js +0 -1
  81. package/dist/ls-runner.d.ts +0 -1
  82. package/dist/ls-runner.js +34 -40
  83. package/dist/ui/dev-dashboard.d.ts +0 -1
  84. package/dist/ui/dev-dashboard.js +0 -1
  85. package/dist/ui/greeting.d.ts +0 -1
  86. package/dist/ui/greeting.js +0 -1
  87. package/dist/ui/process-table.d.ts +0 -1
  88. package/dist/ui/process-table.js +0 -1
  89. package/package.json +5 -6
  90. package/dist/__tests__/bench.test.d.ts +0 -2
  91. package/dist/__tests__/bench.test.d.ts.map +0 -1
  92. package/dist/__tests__/bench.test.js +0 -94
  93. package/dist/__tests__/bench.test.js.map +0 -1
  94. package/dist/__tests__/doctor.test.d.ts +0 -10
  95. package/dist/__tests__/doctor.test.d.ts.map +0 -1
  96. package/dist/__tests__/doctor.test.js +0 -105
  97. package/dist/__tests__/doctor.test.js.map +0 -1
  98. package/dist/__tests__/replay.test.d.ts +0 -2
  99. package/dist/__tests__/replay.test.d.ts.map +0 -1
  100. package/dist/__tests__/replay.test.js +0 -203
  101. package/dist/__tests__/replay.test.js.map +0 -1
  102. package/dist/__tests__/trace.test.d.ts +0 -2
  103. package/dist/__tests__/trace.test.d.ts.map +0 -1
  104. package/dist/__tests__/trace.test.js +0 -136
  105. package/dist/__tests__/trace.test.js.map +0 -1
  106. package/dist/__tests__/watch.test.d.ts +0 -2
  107. package/dist/__tests__/watch.test.d.ts.map +0 -1
  108. package/dist/__tests__/watch.test.js +0 -110
  109. package/dist/__tests__/watch.test.js.map +0 -1
  110. package/dist/cache-runner.d.ts.map +0 -1
  111. package/dist/cache-runner.js.map +0 -1
  112. package/dist/cli.d.ts.map +0 -1
  113. package/dist/cli.js.map +0 -1
  114. package/dist/commands/bench.d.ts.map +0 -1
  115. package/dist/commands/bench.js.map +0 -1
  116. package/dist/commands/build.d.ts.map +0 -1
  117. package/dist/commands/build.js.map +0 -1
  118. package/dist/commands/cache.d.ts.map +0 -1
  119. package/dist/commands/cache.js.map +0 -1
  120. package/dist/commands/check.d.ts.map +0 -1
  121. package/dist/commands/check.js.map +0 -1
  122. package/dist/commands/dev.d.ts.map +0 -1
  123. package/dist/commands/dev.js.map +0 -1
  124. package/dist/commands/doctor.d.ts.map +0 -1
  125. package/dist/commands/doctor.js.map +0 -1
  126. package/dist/commands/fmt.d.ts.map +0 -1
  127. package/dist/commands/fmt.js.map +0 -1
  128. package/dist/commands/greeting.d.ts.map +0 -1
  129. package/dist/commands/greeting.js.map +0 -1
  130. package/dist/commands/infra.d.ts.map +0 -1
  131. package/dist/commands/infra.js.map +0 -1
  132. package/dist/commands/lint.d.ts.map +0 -1
  133. package/dist/commands/lint.js.map +0 -1
  134. package/dist/commands/logs.d.ts.map +0 -1
  135. package/dist/commands/logs.js.map +0 -1
  136. package/dist/commands/ls.d.ts.map +0 -1
  137. package/dist/commands/ls.js.map +0 -1
  138. package/dist/commands/mcp.d.ts.map +0 -1
  139. package/dist/commands/mcp.js.map +0 -1
  140. package/dist/commands/please.d.ts.map +0 -1
  141. package/dist/commands/please.js.map +0 -1
  142. package/dist/commands/ps.d.ts.map +0 -1
  143. package/dist/commands/ps.js.map +0 -1
  144. package/dist/commands/replay.d.ts.map +0 -1
  145. package/dist/commands/replay.js.map +0 -1
  146. package/dist/commands/run.d.ts.map +0 -1
  147. package/dist/commands/run.js.map +0 -1
  148. package/dist/commands/studio.d.ts.map +0 -1
  149. package/dist/commands/studio.js.map +0 -1
  150. package/dist/commands/test.d.ts.map +0 -1
  151. package/dist/commands/test.js.map +0 -1
  152. package/dist/commands/trace.d.ts.map +0 -1
  153. package/dist/commands/trace.js.map +0 -1
  154. package/dist/commands/watch.d.ts.map +0 -1
  155. package/dist/commands/watch.js.map +0 -1
  156. package/dist/index.d.ts.map +0 -1
  157. package/dist/index.js.map +0 -1
  158. package/dist/kernel-instance.d.ts +0 -8
  159. package/dist/kernel-instance.d.ts.map +0 -1
  160. package/dist/kernel-instance.js +0 -13
  161. package/dist/kernel-instance.js.map +0 -1
  162. package/dist/lib/colors.d.ts.map +0 -1
  163. package/dist/lib/colors.js.map +0 -1
  164. package/dist/lib/dev-entry.d.ts.map +0 -1
  165. package/dist/lib/dev-entry.js.map +0 -1
  166. package/dist/lib/exec.d.ts.map +0 -1
  167. package/dist/lib/exec.js.map +0 -1
  168. package/dist/lib/process-state.d.ts.map +0 -1
  169. package/dist/lib/process-state.js.map +0 -1
  170. package/dist/lib/project.d.ts.map +0 -1
  171. package/dist/lib/project.js.map +0 -1
  172. package/dist/lib/run-task.d.ts.map +0 -1
  173. package/dist/lib/run-task.js.map +0 -1
  174. package/dist/lib/sse.d.ts.map +0 -1
  175. package/dist/lib/sse.js.map +0 -1
  176. package/dist/lib/vite-node.d.ts.map +0 -1
  177. package/dist/lib/vite-node.js.map +0 -1
  178. package/dist/lib/wire-discovery.d.ts.map +0 -1
  179. package/dist/lib/wire-discovery.js.map +0 -1
  180. package/dist/load-config.d.ts.map +0 -1
  181. package/dist/load-config.js.map +0 -1
  182. package/dist/ls-runner.d.ts.map +0 -1
  183. package/dist/ls-runner.js.map +0 -1
  184. package/dist/ui/dev-dashboard.d.ts.map +0 -1
  185. package/dist/ui/dev-dashboard.js.map +0 -1
  186. package/dist/ui/greeting.d.ts.map +0 -1
  187. package/dist/ui/greeting.js.map +0 -1
  188. package/dist/ui/process-table.d.ts.map +0 -1
  189. package/dist/ui/process-table.js.map +0 -1
@@ -1,2 +1 @@
1
1
  export {};
2
- //# sourceMappingURL=cache-runner.d.ts.map
@@ -31,10 +31,21 @@ async function main() {
31
31
  // "App" means either:
32
32
  // - `AppDefinition` (legacy `defineApp(name, { modules })`)
33
33
  // - bootable `App` (modern `createApp({ modules })`)
34
- // Both expose `modules: ModuleDefinition[]` which is all the scanner
35
- // needs we normalize them into the AppDefinition shape buildCache
36
- // expects.
34
+ // Resolve the app(s). 0.10 createApp returns an App marked with
35
+ // `$nwireApp: true`. Recognized export names:
36
+ // - allApps: App[] | apps: App[]
37
+ // - default: App | App[]
38
+ // - app: App
39
+ // - buildApp(): App | Promise<App> ← 0.10 factory pattern
40
+ // - bootstrap(): { app: App, ... } ← test-bootstrap pattern
41
+ // - bootstrap(opts): { app: App, ... }
42
+ //
43
+ // Factory results that boot the App themselves (bootstrap functions
44
+ // that call .start() and run an endpoint) are also accepted — we
45
+ // pull the App handle off the return value and skip the start/stop
46
+ // dance.
37
47
  let apps = [];
48
+ let appsAlreadyBooted = false;
38
49
  if (Array.isArray(mod.allApps))
39
50
  apps = mod.allApps;
40
51
  else if (Array.isArray(mod.apps))
@@ -45,26 +56,100 @@ async function main() {
45
56
  apps = [mod.default];
46
57
  else if (isAppLike(mod.app))
47
58
  apps = [mod.app];
48
- else {
59
+ else if (typeof mod.buildApp === "function") {
60
+ const built = await mod.buildApp();
61
+ const candidate = isAppLike(built) ? built : findAppInResult(built);
62
+ if (isAppLike(candidate))
63
+ apps = [candidate];
64
+ }
65
+ else if (typeof mod.bootstrap === "function") {
66
+ // Bootstrap usually starts the App and runs an endpoint. We try
67
+ // common signatures: `bootstrap({port,test})`, `bootstrap(port?)`.
68
+ // Returned shape is anything from { app, running } to { nest, nwireApp }
69
+ // to a bare App — we duck-find the first $nwireApp value in the result.
70
+ //
71
+ // 10s watchdog: some bootstrap functions never resolve (e.g. they
72
+ // wait on Nest's signal-driven lifecycle). The scanner falls back to
73
+ // "no apps found" rather than hanging the build pipeline.
74
+ const callWithTimeout = async (fn) => {
75
+ return await Promise.race([
76
+ fn(),
77
+ new Promise((_, reject) => setTimeout(() => reject(new Error("bootstrap watchdog (10s)")), 10_000)),
78
+ ]);
79
+ };
80
+ let result;
81
+ try {
82
+ result = await callWithTimeout(() => mod.bootstrap({ port: 0, test: true }));
83
+ }
84
+ catch {
85
+ try {
86
+ result = await callWithTimeout(() => mod.bootstrap(0));
87
+ }
88
+ catch {
89
+ /* unscannable — leave apps empty */
90
+ }
91
+ }
92
+ const candidate = isAppLike(result) ? result : findAppInResult(result);
93
+ if (isAppLike(candidate)) {
94
+ apps = [candidate];
95
+ appsAlreadyBooted = true;
96
+ // Tear down the endpoint the bootstrap opened — we only need the
97
+ // App's runtime state for the scan.
98
+ const r = result;
99
+ if (typeof r?.running?.shutdown === "function") {
100
+ try {
101
+ await r.running.shutdown("scan");
102
+ }
103
+ catch {
104
+ /* ignore */
105
+ }
106
+ }
107
+ }
108
+ }
109
+ if (apps.length === 0) {
49
110
  apps = Object.values(mod).filter(isAppLike);
50
111
  }
51
112
  if (apps.length === 0) {
52
113
  console.error(`nwire cache: no apps found in ${appsPath}.\n` +
53
- `Expected: exported \`app\`, \`apps\`, or \`allApps\` either an AppDefinition (\`defineApp\`) or a runnable App (\`createApp\`).\n` +
114
+ `Expected one of: exported \`app\`, \`apps\`, \`allApps\`, or a \`buildApp()\` factory returning an App from createApp.\n` +
54
115
  `Optional: nwire.config.ts with { appsEntry: "..." } to point at a custom location.`);
55
116
  process.exit(1);
56
117
  }
118
+ // The forge plugin registers handlers/actors/projections/queries on the
119
+ // dispatcher during the AppBooting hook — so the dispatcher is only
120
+ // populated AFTER `app.start()`. Boot each app for the scan (unless the
121
+ // bootstrap factory already did), then stop it.
122
+ if (!appsAlreadyBooted) {
123
+ for (const a of apps) {
124
+ const app = a;
125
+ if (app.$nwireApp && typeof app.start === "function") {
126
+ await app.start();
127
+ }
128
+ }
129
+ }
57
130
  const normalized = apps.map(toAppDefinitionShape);
58
- // Route bindings are declared at the app layer via `httpInterface().wire()`
59
- // and surface in Studio through the running wire's `/_nwire/*` introspection
60
- // mount, not through the cache. The scan is module-domain-only.
61
131
  const cache = buildCache(normalized);
132
+ for (const a of apps) {
133
+ const app = a;
134
+ if (app.$nwireApp && typeof app.stop === "function") {
135
+ try {
136
+ await app.stop();
137
+ }
138
+ catch {
139
+ /* ignore — the bootstrap may have already torn things down */
140
+ }
141
+ }
142
+ }
62
143
  const outDir = resolve(cwd, config.cacheDir ?? ".nwire");
63
144
  await writeCache(cache, outDir);
64
145
  // eslint-disable-next-line no-console
65
146
  console.log(`nwire cache: wrote ${cache.apps.length} apps, ${cache.modules.length} modules, ` +
66
147
  `${cache.actions.length} actions, ${cache.events.length} events, ` +
67
148
  `${cache.resolvers.length} resolvers to ${outDir}/`);
149
+ // Some bootstrap functions leave foreign-framework servers (Nest,
150
+ // Fastify) listening even after we tear down the Nwire side. Force
151
+ // process exit so the scan doesn't hang the CI pipeline.
152
+ process.exit(0);
68
153
  }
69
154
  function isAppLike(x) {
70
155
  if (typeof x !== "object" || x === null)
@@ -72,6 +157,20 @@ function isAppLike(x) {
72
157
  const a = x;
73
158
  return a.$kind === "app-definition" || a.$nwireApp === true;
74
159
  }
160
+ /**
161
+ * Bootstrap/factory functions return wrapper objects in many shapes —
162
+ * `{ app, running }`, `{ nest, nwireApp }`, `{ app, close }`, etc.
163
+ * Find the first property whose value is App-like.
164
+ */
165
+ function findAppInResult(result) {
166
+ if (typeof result !== "object" || result === null)
167
+ return undefined;
168
+ for (const value of Object.values(result)) {
169
+ if (isAppLike(value))
170
+ return value;
171
+ }
172
+ return undefined;
173
+ }
75
174
  /**
76
175
  * Normalize either flavor of "app" into the AppDefinition shape the
77
176
  * scanner reads. `createApp` returns an `App` with `appName` + the
@@ -103,4 +202,3 @@ main().catch((err) => {
103
202
  console.error(err);
104
203
  process.exit(1);
105
204
  });
106
- //# sourceMappingURL=cache-runner.js.map
package/dist/cli.d.ts CHANGED
@@ -2,15 +2,12 @@
2
2
  /**
3
3
  * `nwire` — the umbrella CLI. Built on citty: one root command, one
4
4
  * subcommand per file under `commands/`. The CLI is intentionally thin —
5
- * every command delegates to either the kernel (long-lived processes,
6
- * future cross-surface dispatch) or a small set of execution helpers
7
- * (`viteNode`, `spawnInteractive`).
5
+ * every command delegates to a small set of execution helpers
6
+ * (`viteNode`, `spawnInteractive`) and, where needed, an in-tree
7
+ * RunnerSupervisor for long-lived processes.
8
8
  *
9
9
  * Adding a new command:
10
10
  * 1. write packages/nwire-cli/src/commands/<name>.ts using `defineCommand`
11
11
  * 2. import + register it below
12
- * 3. (later) when it should be reachable from Studio/MCP, also
13
- * `kernel.router.register("<name>", handler)` in kernel-instance.ts
14
12
  */
15
13
  export {};
16
- //# sourceMappingURL=cli.d.ts.map
package/dist/cli.js CHANGED
@@ -2,15 +2,13 @@
2
2
  /**
3
3
  * `nwire` — the umbrella CLI. Built on citty: one root command, one
4
4
  * subcommand per file under `commands/`. The CLI is intentionally thin —
5
- * every command delegates to either the kernel (long-lived processes,
6
- * future cross-surface dispatch) or a small set of execution helpers
7
- * (`viteNode`, `spawnInteractive`).
5
+ * every command delegates to a small set of execution helpers
6
+ * (`viteNode`, `spawnInteractive`) and, where needed, an in-tree
7
+ * RunnerSupervisor for long-lived processes.
8
8
  *
9
9
  * Adding a new command:
10
10
  * 1. write packages/nwire-cli/src/commands/<name>.ts using `defineCommand`
11
11
  * 2. import + register it below
12
- * 3. (later) when it should be reachable from Studio/MCP, also
13
- * `kernel.router.register("<name>", handler)` in kernel-instance.ts
14
12
  */
15
13
  import { defineCommand, runMain } from "citty";
16
14
  import { benchCommand } from "./commands/bench.js";
@@ -34,10 +32,11 @@ import { studioCommand } from "./commands/studio.js";
34
32
  import { testCommand } from "./commands/test.js";
35
33
  import { traceCommand } from "./commands/trace.js";
36
34
  import { watchCommand } from "./commands/watch.js";
35
+ import { cliVersion } from "./lib/version.js";
37
36
  const main = defineCommand({
38
37
  meta: {
39
38
  name: "nwire",
40
- version: "0.8.17",
39
+ version: cliVersion(),
41
40
  description: "Nwire — event-driven framework. Dev, build, please, ps, logs, studio, …",
42
41
  },
43
42
  subCommands: {
@@ -74,4 +73,3 @@ if (userArgs.length === 0) {
74
73
  else {
75
74
  void runMain(main);
76
75
  }
77
- //# sourceMappingURL=cli.js.map
@@ -100,4 +100,3 @@ export declare const benchCommand: import("citty").CommandDef<{
100
100
  };
101
101
  }>;
102
102
  export {};
103
- //# sourceMappingURL=bench.d.ts.map
@@ -202,4 +202,3 @@ export const benchCommand = defineCommand({
202
202
  process.exit(0);
203
203
  },
204
204
  });
205
- //# sourceMappingURL=bench.js.map
@@ -10,4 +10,3 @@ export declare const buildCommand: import("citty").CommandDef<{
10
10
  description: string;
11
11
  };
12
12
  }>;
13
- //# sourceMappingURL=build.d.ts.map
@@ -5,18 +5,9 @@
5
5
  */
6
6
  import { defineCommand } from "citty";
7
7
  import { resolve } from "node:path";
8
- import { existsSync } from "node:fs";
9
8
  import { palette } from "../lib/colors.js";
10
- import { detectProject } from "../lib/project.js";
9
+ import { detectLayout, resolveWire } from "../lib/layout.js";
11
10
  import { runTaskList } from "../lib/run-task.js";
12
- function resolveEntry(cwd, wireName) {
13
- const appDir = resolve(cwd, "apps", wireName);
14
- for (const candidate of [resolve(appDir, "run.ts"), resolve(appDir, "main.ts")]) {
15
- if (existsSync(candidate))
16
- return candidate;
17
- }
18
- return undefined;
19
- }
20
11
  export const buildCommand = defineCommand({
21
12
  meta: {
22
13
  name: "build",
@@ -31,16 +22,22 @@ export const buildCommand = defineCommand({
31
22
  },
32
23
  async run({ args }) {
33
24
  const cwd = process.cwd();
34
- const project = detectProject(cwd);
35
- const wires = args.wire ? [String(args.wire)] : [...project.wires];
36
- if (wires.length === 0) {
25
+ const layout = detectLayout(cwd);
26
+ if (layout.wires.length === 0) {
37
27
  // eslint-disable-next-line no-console
38
- console.error(palette.err("nwire build:") + " no wires detected (expected apps/<name>/{run,main}.ts)");
28
+ console.error(palette.err("nwire build:") +
29
+ " no wires detected. Expected one of: " +
30
+ "app/{run,main}.ts (single-wire), apps/<name>/{run,main}.ts (multi-wire), " +
31
+ "src/{main,index}.ts (flat), or a nwire.config.ts.");
39
32
  process.exit(1);
40
33
  }
41
- const tasks = wires.flatMap((wire) => {
42
- const entry = resolveEntry(cwd, wire);
34
+ const requested = args.wire ? [String(args.wire)] : layout.wires.map((w) => w.name);
35
+ const tasks = requested.flatMap((wire) => {
36
+ const entry = resolveWire(layout, wire);
43
37
  if (!entry) {
38
+ // eslint-disable-next-line no-console
39
+ console.error(palette.err(`nwire build: unknown wire "${wire}". `) +
40
+ `Known wires: ${layout.wires.map((w) => w.name).join(", ") || "(none)"}.`);
44
41
  return [
45
42
  {
46
43
  title: `${wire} — entry missing`,
@@ -71,4 +68,3 @@ export const buildCommand = defineCommand({
71
68
  process.exit(await runTaskList(tasks));
72
69
  },
73
70
  });
74
- //# sourceMappingURL=build.js.map
@@ -1,6 +1,6 @@
1
1
  /**
2
- * `nwire cache` — rebuilds `.nwire/` (manifest + per-kind JSON files) by
3
- * invoking the bundled cache-runner script under vite-node.
2
+ * `nwire cache` — rebuild `.nwire/` (manifest + per-kind JSON files).
3
+ * Equivalent to `ensureScanFresh({ force: true })`: skips the
4
+ * fingerprint cheap-path and always re-runs the cache builder.
4
5
  */
5
6
  export declare const cacheCommand: import("citty").CommandDef<import("citty").ArgsDef>;
6
- //# sourceMappingURL=cache.d.ts.map
@@ -1,27 +1,17 @@
1
1
  /**
2
- * `nwire cache` — rebuilds `.nwire/` (manifest + per-kind JSON files) by
3
- * invoking the bundled cache-runner script under vite-node.
2
+ * `nwire cache` — rebuild `.nwire/` (manifest + per-kind JSON files).
3
+ * Equivalent to `ensureScanFresh({ force: true })`: skips the
4
+ * fingerprint cheap-path and always re-runs the cache builder.
4
5
  */
5
6
  import { defineCommand } from "citty";
6
- import { resolve, dirname } from "node:path";
7
- import { existsSync } from "node:fs";
8
- import { fileURLToPath } from "node:url";
9
- import { palette } from "../lib/colors.js";
10
- import { viteNode } from "../lib/vite-node.js";
11
- const here = dirname(fileURLToPath(import.meta.url));
7
+ import { ensureScanFresh } from "../lib/ensure-scan.js";
12
8
  export const cacheCommand = defineCommand({
13
9
  meta: {
14
10
  name: "cache",
15
11
  description: "Rebuild .nwire/ cache (manifest + per-kind JSON)",
16
12
  },
17
- async run({ rawArgs }) {
18
- const builderPath = resolve(here, "..", "cache-runner.js");
19
- if (!existsSync(builderPath)) {
20
- // eslint-disable-next-line no-console
21
- console.error(palette.err("nwire cache:") + ` cache runner missing at ${builderPath}`);
22
- process.exit(1);
23
- }
24
- process.exit(viteNode(builderPath, rawArgs));
13
+ async run() {
14
+ const { rebuilt } = ensureScanFresh(process.cwd(), { force: true });
15
+ process.exit(rebuilt ? 0 : 1);
25
16
  },
26
17
  });
27
- //# sourceMappingURL=cache.js.map
@@ -1,6 +1,13 @@
1
1
  /**
2
- * `nwire check` — composed quality gate. Runs format-check, lint, and
3
- * typecheck in sequence. Use before pushing or in CI.
2
+ * `nwire check` — composed quality gate. Reads the consumer's
3
+ * package.json scripts and runs whatever they've defined.
4
+ *
5
+ * 1. `scripts.check` — single entrypoint wins.
6
+ * 2. `scripts.format:check`, `scripts.lint`, `scripts.typecheck` —
7
+ * whichever subset is defined, in that order.
8
+ * 3. Fallback to any installed formatter / linter / type checker:
9
+ * `oxfmt --check`, `biome check`, `prettier --check`; `oxlint`,
10
+ * `eslint`; `tsc --noEmit`. Only spawns binaries that exist in
11
+ * `node_modules/.bin`.
4
12
  */
5
13
  export declare const checkCommand: import("citty").CommandDef<import("citty").ArgsDef>;
6
- //# sourceMappingURL=check.d.ts.map
@@ -1,21 +1,45 @@
1
1
  /**
2
- * `nwire check` — composed quality gate. Runs format-check, lint, and
3
- * typecheck in sequence. Use before pushing or in CI.
2
+ * `nwire check` — composed quality gate. Reads the consumer's
3
+ * package.json scripts and runs whatever they've defined.
4
+ *
5
+ * 1. `scripts.check` — single entrypoint wins.
6
+ * 2. `scripts.format:check`, `scripts.lint`, `scripts.typecheck` —
7
+ * whichever subset is defined, in that order.
8
+ * 3. Fallback to any installed formatter / linter / type checker:
9
+ * `oxfmt --check`, `biome check`, `prettier --check`; `oxlint`,
10
+ * `eslint`; `tsc --noEmit`. Only spawns binaries that exist in
11
+ * `node_modules/.bin`.
4
12
  */
5
13
  import { defineCommand } from "citty";
6
- import { runTaskList } from "../lib/run-task.js";
14
+ import { palette } from "../lib/colors.js";
15
+ import { runScriptStrategy } from "../lib/script-runner.js";
7
16
  export const checkCommand = defineCommand({
8
17
  meta: {
9
18
  name: "check",
10
- description: "Run format-check + lint + typecheck",
19
+ description: "Run format-check + lint + typecheck (consumer-defined or sensible defaults)",
11
20
  },
12
21
  async run() {
13
- const code = await runTaskList([
14
- { title: "format (oxfmt --check)", command: "pnpm", args: ["exec", "oxfmt", "--check"] },
15
- { title: "lint (oxlint)", command: "pnpm", args: ["exec", "oxlint"] },
16
- { title: "typecheck (tsc)", command: "pnpm", args: ["exec", "tsc", "--noEmit"] },
17
- ]);
22
+ const cwd = process.cwd();
23
+ const { code, ran } = await runScriptStrategy(cwd, {
24
+ operationName: "check",
25
+ consumerScript: "check",
26
+ consumerSubScripts: ["format:check", "lint", "typecheck"],
27
+ fallback: [
28
+ { title: "format (oxfmt --check)", bin: "oxfmt", args: ["--check"] },
29
+ { title: "format (biome check)", bin: "biome", args: ["check"] },
30
+ { title: "format (prettier --check)", bin: "prettier", args: ["--check", "."] },
31
+ { title: "lint (oxlint)", bin: "oxlint" },
32
+ { title: "lint (eslint)", bin: "eslint", args: ["."] },
33
+ { title: "typecheck (tsc --noEmit)", bin: "tsc", args: ["--noEmit"] },
34
+ ],
35
+ });
36
+ if (!ran) {
37
+ // eslint-disable-next-line no-console
38
+ console.error(palette.err("nwire check:") +
39
+ " no `check`, `format:check`, `lint`, or `typecheck` script in package.json " +
40
+ "and none of oxfmt/oxlint/biome/prettier/eslint/tsc are installed locally.");
41
+ process.exit(1);
42
+ }
18
43
  process.exit(code);
19
44
  },
20
45
  });
21
- //# sourceMappingURL=check.js.map
@@ -8,4 +8,3 @@
8
8
  * sees the dev session from any other shell.
9
9
  */
10
10
  export declare const devCommand: import("citty").CommandDef<import("citty").ArgsDef>;
11
- //# sourceMappingURL=dev.d.ts.map
@@ -173,4 +173,3 @@ export const devCommand = defineCommand({
173
173
  process.exit(exitCode);
174
174
  },
175
175
  });
176
- //# sourceMappingURL=dev.js.map
@@ -6,7 +6,7 @@
6
6
  * failures (warnings still allow boot), 1 otherwise.
7
7
  *
8
8
  * Born from the Phase F dev-loop bugs: lightship port collisions, missing
9
- * `api.inspect(app)`, stale `.nwire/` cache, wrong probe paths. Each
9
+ * httpKoa inspect mount, stale `.nwire/` cache, wrong probe paths. Each
10
10
  * check here exists because Alex hit the bug live; the doctor exists so
11
11
  * the next team member doesn't.
12
12
  *
@@ -56,4 +56,3 @@ export declare const doctorCommand: import("citty").CommandDef<{
56
56
  description: string;
57
57
  };
58
58
  }>;
59
- //# sourceMappingURL=doctor.d.ts.map
@@ -6,7 +6,7 @@
6
6
  * failures (warnings still allow boot), 1 otherwise.
7
7
  *
8
8
  * Born from the Phase F dev-loop bugs: lightship port collisions, missing
9
- * `api.inspect(app)`, stale `.nwire/` cache, wrong probe paths. Each
9
+ * httpKoa inspect mount, stale `.nwire/` cache, wrong probe paths. Each
10
10
  * check here exists because Alex hit the bug live; the doctor exists so
11
11
  * the next team member doesn't.
12
12
  *
@@ -79,7 +79,7 @@ const workspaceCheck = {
79
79
  return {
80
80
  status: "warn",
81
81
  message: "no apps/, src/, or nwire.config.ts",
82
- hint: "if this is a L1/L2 starter that's fine; for L4 add apps/<name>/main.ts",
82
+ hint: "single-folder starters use app/main.ts; multi-bounded-context layouts use apps/<name>/main.ts",
83
83
  };
84
84
  }
85
85
  return { status: "pass", message: `apps:${hasApps} src:${hasSrc} config:${hasConfig}` };
@@ -164,11 +164,11 @@ const composeCollisionCheck = {
164
164
  };
165
165
  const inspectMountCheck = {
166
166
  name: "inspect-mount",
167
- description: "Every L4 example calls `api.inspect(app)`",
167
+ description: "Every entry boots `httpKoa({ inspect: true })` for Studio",
168
168
  run: (ctx) => {
169
- // Scan apps/*/main.ts (or apps/*/<name>/main.ts) for createApp + missing .inspect().
170
- // Best-effort grep — produces warnings not failures, since not every app
171
- // wants the introspection surface in production wires.
169
+ // Scan apps/*/main.ts (or apps/*/<name>/main.ts) for httpKoa missing
170
+ // inspect. Best-effort grep — produces warnings not failures, since
171
+ // production wires usually want inspect gated by auth middleware.
172
172
  const appsDir = join(ctx.cwd, "apps");
173
173
  if (!existsSync(appsDir))
174
174
  return { status: "info", message: "no apps/ folder" };
@@ -177,17 +177,17 @@ const inspectMountCheck = {
177
177
  if (!entry.endsWith("main.ts") && !entry.endsWith("main.js"))
178
178
  continue;
179
179
  const text = readFileSync(entry, "utf8");
180
- const looksLikeL4 = /createApp|app\.start\(\)/.test(text);
181
- const hasInspect = /\.inspect\(/.test(text);
182
- if (looksLikeL4 && !hasInspect) {
180
+ const usesKoa = /\bhttpKoa\s*\(/.test(text);
181
+ const hasInspect = /inspect\s*:\s*(true|\{)/.test(text);
182
+ if (usesKoa && !hasInspect) {
183
183
  offenders.push(relative(ctx.cwd, entry));
184
184
  }
185
185
  }
186
186
  if (offenders.length === 0)
187
- return { status: "pass", message: "all L4 mains mount inspect" };
187
+ return { status: "pass", message: "all entries mount inspect" };
188
188
  return {
189
189
  status: "warn",
190
- message: `${offenders.length} app${offenders.length === 1 ? "" : "s"} missing api.inspect(app)`,
190
+ message: `${offenders.length} entr${offenders.length === 1 ? "y" : "ies"} missing httpKoa({inspect:true})`,
191
191
  hint: `Studio's Live/Trace pages will 404 against:\n - ${offenders.join("\n - ")}`,
192
192
  };
193
193
  },
@@ -251,9 +251,9 @@ const templatesCheck = {
251
251
  // This check exists so users running `nwire doctor` see what they can
252
252
  // scaffold without leaving the terminal.
253
253
  const available = [
254
- "L1minimal (httpInterface + endpoint; folder-organized routes/)",
255
- "L2service (resources/errors/middleware/store/routes folders; in-memory CRUD)",
256
- "L4enterprise (modules/<bc>/{events,actions,workflows,projections,routes})",
254
+ "minimalcreateApp + httpKoa; one folder, no DI",
255
+ "servicecontainer plugin, structured errors, route middleware, in-memory store",
256
+ "enterpriseforge: actions + events + actors + workflow + projection",
257
257
  ];
258
258
  return {
259
259
  status: "info",
@@ -420,4 +420,3 @@ export const doctorCommand = defineCommand({
420
420
  process.exit(hasFail ? 1 : 0);
421
421
  },
422
422
  });
423
- //# sourceMappingURL=doctor.js.map
@@ -1,7 +1,12 @@
1
1
  /**
2
- * `nwire fmt` — passthrough to `oxfmt` wrapped in a listr2 task so the
3
- * output shape matches `lint`, `check`, and `build`. Honors any
4
- * oxfmt config in the consumer's project.
2
+ * `nwire fmt` — run the consumer's formatter. Picks the first
3
+ * available source in order:
4
+ *
5
+ * 1. `scripts.format` (and `scripts.format:check` for `--check`)
6
+ * 2. Any installed formatter — `oxfmt`, then `biome format --write`,
7
+ * then `prettier --write`.
8
+ *
9
+ * Extra positional args / flags pass through.
5
10
  */
6
11
  export declare const fmtCommand: import("citty").CommandDef<{
7
12
  check: {
@@ -10,4 +15,3 @@ export declare const fmtCommand: import("citty").CommandDef<{
10
15
  default: false;
11
16
  };
12
17
  }>;
13
- //# sourceMappingURL=fmt.d.ts.map
@@ -1,14 +1,20 @@
1
1
  /**
2
- * `nwire fmt` — passthrough to `oxfmt` wrapped in a listr2 task so the
3
- * output shape matches `lint`, `check`, and `build`. Honors any
4
- * oxfmt config in the consumer's project.
2
+ * `nwire fmt` — run the consumer's formatter. Picks the first
3
+ * available source in order:
4
+ *
5
+ * 1. `scripts.format` (and `scripts.format:check` for `--check`)
6
+ * 2. Any installed formatter — `oxfmt`, then `biome format --write`,
7
+ * then `prettier --write`.
8
+ *
9
+ * Extra positional args / flags pass through.
5
10
  */
6
11
  import { defineCommand } from "citty";
7
- import { runTaskList } from "../lib/run-task.js";
12
+ import { palette } from "../lib/colors.js";
13
+ import { runScriptStrategy } from "../lib/script-runner.js";
8
14
  export const fmtCommand = defineCommand({
9
15
  meta: {
10
16
  name: "fmt",
11
- description: "Format the project with oxfmt",
17
+ description: "Format the project (consumer-defined or installed formatter)",
12
18
  },
13
19
  args: {
14
20
  check: {
@@ -18,16 +24,33 @@ export const fmtCommand = defineCommand({
18
24
  },
19
25
  },
20
26
  async run({ args, rawArgs }) {
27
+ const cwd = process.cwd();
21
28
  const passthrough = rawArgs.filter((a) => a !== "--check" && a !== "-c");
22
- const oxfmtArgs = args.check ? ["--check", ...passthrough] : passthrough;
23
- const code = await runTaskList([
29
+ const writeFallback = [
30
+ { title: "oxfmt", bin: "oxfmt", args: passthrough },
31
+ { title: "biome format --write", bin: "biome", args: ["format", "--write", ...passthrough] },
32
+ { title: "prettier --write", bin: "prettier", args: ["--write", ".", ...passthrough] },
33
+ ];
34
+ const checkFallback = [
35
+ { title: "oxfmt --check", bin: "oxfmt", args: ["--check", ...passthrough] },
36
+ { title: "biome check", bin: "biome", args: ["check", ...passthrough] },
24
37
  {
25
- title: args.check ? "oxfmt --check" : "oxfmt",
26
- command: "pnpm",
27
- args: ["exec", "oxfmt", ...oxfmtArgs],
38
+ title: "prettier --check",
39
+ bin: "prettier",
40
+ args: ["--check", ".", ...passthrough],
28
41
  },
29
- ]);
42
+ ];
43
+ const { code, ran } = await runScriptStrategy(cwd, {
44
+ operationName: "fmt",
45
+ consumerScript: args.check ? "format:check" : "format",
46
+ fallback: args.check ? checkFallback : writeFallback,
47
+ });
48
+ if (!ran) {
49
+ // eslint-disable-next-line no-console
50
+ console.error(palette.err("nwire fmt:") +
51
+ " no `format` script and no installed formatter (oxfmt, biome, or prettier).");
52
+ process.exit(1);
53
+ }
30
54
  process.exit(code);
31
55
  },
32
56
  });
33
- //# sourceMappingURL=fmt.js.map
@@ -3,4 +3,3 @@
3
3
  * ink so the panel is a single declarative tree we can grow over time.
4
4
  */
5
5
  export declare const greetingCommand: import("citty").CommandDef<import("citty").ArgsDef>;
6
- //# sourceMappingURL=greeting.d.ts.map
@@ -22,4 +22,3 @@ export const greetingCommand = defineCommand({
22
22
  await waitUntilExit().catch(() => { });
23
23
  },
24
24
  });
25
- //# sourceMappingURL=greeting.js.map
@@ -11,4 +11,3 @@
11
11
  * nwire infra logs <svc> # tail one service's logs
12
12
  */
13
13
  export declare const infraCommand: import("citty").CommandDef<import("citty").ArgsDef>;
14
- //# sourceMappingURL=infra.d.ts.map
@@ -150,4 +150,3 @@ export const infraCommand = defineCommand({
150
150
  }
151
151
  },
152
152
  });
153
- //# sourceMappingURL=infra.js.map