@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,6 +1,11 @@
1
1
  /**
2
- * `nwire lint` — passthrough to `oxlint` wrapped in a listr2 task.
3
- * Honors the consumer project's oxlint config.
2
+ * `nwire lint` — run the consumer's lint. Picks the first available
3
+ * source in order:
4
+ *
5
+ * 1. `scripts.lint` (and `scripts.lint:fix` for `--fix`)
6
+ * 2. Any installed linter — `oxlint`, then `eslint`.
7
+ *
8
+ * Extra positional args / flags pass through.
4
9
  */
5
10
  export declare const lintCommand: import("citty").CommandDef<{
6
11
  fix: {
@@ -9,4 +14,3 @@ export declare const lintCommand: import("citty").CommandDef<{
9
14
  default: false;
10
15
  };
11
16
  }>;
12
- //# sourceMappingURL=lint.d.ts.map
@@ -1,13 +1,19 @@
1
1
  /**
2
- * `nwire lint` — passthrough to `oxlint` wrapped in a listr2 task.
3
- * Honors the consumer project's oxlint config.
2
+ * `nwire lint` — run the consumer's lint. Picks the first available
3
+ * source in order:
4
+ *
5
+ * 1. `scripts.lint` (and `scripts.lint:fix` for `--fix`)
6
+ * 2. Any installed linter — `oxlint`, then `eslint`.
7
+ *
8
+ * Extra positional args / flags pass through.
4
9
  */
5
10
  import { defineCommand } from "citty";
6
- import { runTaskList } from "../lib/run-task.js";
11
+ import { palette } from "../lib/colors.js";
12
+ import { runScriptStrategy } from "../lib/script-runner.js";
7
13
  export const lintCommand = defineCommand({
8
14
  meta: {
9
15
  name: "lint",
10
- description: "Lint the project with oxlint",
16
+ description: "Lint the project (consumer-defined or installed linter)",
11
17
  },
12
18
  args: {
13
19
  fix: {
@@ -17,16 +23,31 @@ export const lintCommand = defineCommand({
17
23
  },
18
24
  },
19
25
  async run({ args, rawArgs }) {
26
+ const cwd = process.cwd();
20
27
  const passthrough = rawArgs.filter((a) => a !== "--fix");
21
- const oxlintArgs = args.fix ? ["--fix", ...passthrough] : passthrough;
22
- const code = await runTaskList([
23
- {
24
- title: args.fix ? "oxlint --fix" : "oxlint",
25
- command: "pnpm",
26
- args: ["exec", "oxlint", ...oxlintArgs],
27
- },
28
- ]);
28
+ const fixArgs = args.fix ? ["--fix"] : [];
29
+ const { code, ran } = await runScriptStrategy(cwd, {
30
+ operationName: "lint",
31
+ consumerScript: args.fix ? "lint:fix" : "lint",
32
+ fallback: [
33
+ {
34
+ title: args.fix ? "oxlint --fix" : "oxlint",
35
+ bin: "oxlint",
36
+ args: [...fixArgs, ...passthrough],
37
+ },
38
+ {
39
+ title: args.fix ? "eslint --fix" : "eslint",
40
+ bin: "eslint",
41
+ args: [...fixArgs, ".", ...passthrough],
42
+ },
43
+ ],
44
+ });
45
+ if (!ran) {
46
+ // eslint-disable-next-line no-console
47
+ console.error(palette.err("nwire lint:") +
48
+ " no `lint` script and no installed linter (oxlint or eslint).");
49
+ process.exit(1);
50
+ }
29
51
  process.exit(code);
30
52
  },
31
53
  });
32
- //# sourceMappingURL=lint.js.map
@@ -18,4 +18,3 @@ export declare const logsCommand: import("citty").CommandDef<{
18
18
  default: false;
19
19
  };
20
20
  }>;
21
- //# sourceMappingURL=logs.d.ts.map
@@ -123,4 +123,3 @@ export const logsCommand = defineCommand({
123
123
  process.on("SIGTERM", stop);
124
124
  },
125
125
  });
126
- //# sourceMappingURL=logs.js.map
@@ -1,5 +1,5 @@
1
1
  /**
2
2
  * `nwire ls` — lists every discovered wire and every action.
3
+ * Runs an incremental scan first so the manifest is fresh.
3
4
  */
4
5
  export declare const lsCommand: import("citty").CommandDef<import("citty").ArgsDef>;
5
- //# sourceMappingURL=ls.d.ts.map
@@ -1,11 +1,13 @@
1
1
  /**
2
2
  * `nwire ls` — lists every discovered wire and every action.
3
+ * Runs an incremental scan first so the manifest is fresh.
3
4
  */
4
5
  import { defineCommand } from "citty";
5
6
  import { resolve, dirname } from "node:path";
6
7
  import { existsSync } from "node:fs";
7
8
  import { fileURLToPath } from "node:url";
8
9
  import { palette } from "../lib/colors.js";
10
+ import { ensureScanFresh } from "../lib/ensure-scan.js";
9
11
  import { viteNode } from "../lib/vite-node.js";
10
12
  const here = dirname(fileURLToPath(import.meta.url));
11
13
  export const lsCommand = defineCommand({
@@ -14,6 +16,7 @@ export const lsCommand = defineCommand({
14
16
  description: "List discovered wires + actions",
15
17
  },
16
18
  async run({ rawArgs }) {
19
+ ensureScanFresh(process.cwd(), { quiet: true });
17
20
  const builderPath = resolve(here, "..", "ls-runner.js");
18
21
  if (!existsSync(builderPath)) {
19
22
  // eslint-disable-next-line no-console
@@ -23,4 +26,3 @@ export const lsCommand = defineCommand({
23
26
  process.exit(viteNode(builderPath, rawArgs));
24
27
  },
25
28
  });
26
- //# sourceMappingURL=ls.js.map
@@ -2,4 +2,3 @@
2
2
  * `nwire mcp` — start the MCP server on stdio for Claude / Cursor clients.
3
3
  */
4
4
  export declare const mcpCommand: import("citty").CommandDef<import("citty").ArgsDef>;
5
- //# sourceMappingURL=mcp.d.ts.map
@@ -3,6 +3,7 @@
3
3
  */
4
4
  import { defineCommand } from "citty";
5
5
  import { serveMcp } from "@nwire/mcp";
6
+ import { cliVersion } from "../lib/version.js";
6
7
  export const mcpCommand = defineCommand({
7
8
  meta: {
8
9
  name: "mcp",
@@ -11,8 +12,7 @@ export const mcpCommand = defineCommand({
11
12
  async run() {
12
13
  await serveMcp({
13
14
  serverName: "nwire",
14
- serverVersion: "0.9.0",
15
+ serverVersion: cliVersion(),
15
16
  });
16
17
  },
17
18
  });
18
- //# sourceMappingURL=mcp.js.map
@@ -10,4 +10,3 @@ export declare const pleaseCommand: import("citty").CommandDef<{
10
10
  description: string;
11
11
  };
12
12
  }>;
13
- //# sourceMappingURL=please.d.ts.map
@@ -43,4 +43,3 @@ export const pleaseCommand = defineCommand({
43
43
  process.exit(viteNode(pleasePath, rawArgs));
44
44
  },
45
45
  });
46
- //# sourceMappingURL=please.js.map
@@ -3,4 +3,3 @@
3
3
  * record under `.nwire/processes/*.json` and renders an ink table.
4
4
  */
5
5
  export declare const psCommand: import("citty").CommandDef<import("citty").ArgsDef>;
6
- //# sourceMappingURL=ps.d.ts.map
@@ -18,4 +18,3 @@ export const psCommand = defineCommand({
18
18
  await waitUntilExit();
19
19
  },
20
20
  });
21
- //# sourceMappingURL=ps.js.map
@@ -42,4 +42,3 @@ export declare const replayCommand: import("citty").CommandDef<{
42
42
  };
43
43
  }>;
44
44
  export {};
45
- //# sourceMappingURL=replay.d.ts.map
@@ -155,4 +155,3 @@ export const replayCommand = defineCommand({
155
155
  }
156
156
  },
157
157
  });
158
- //# sourceMappingURL=replay.js.map
@@ -16,4 +16,3 @@ export declare const runCommand: import("citty").CommandDef<{
16
16
  description: string;
17
17
  };
18
18
  }>;
19
- //# sourceMappingURL=run.d.ts.map
@@ -119,4 +119,3 @@ export const runCommand = defineCommand({
119
119
  process.exit(exitCode);
120
120
  },
121
121
  });
122
- //# sourceMappingURL=run.js.map
@@ -6,4 +6,3 @@
6
6
  * right `.nwire/` and `apps/topologies/`.
7
7
  */
8
8
  export declare const studioCommand: import("citty").CommandDef<import("citty").ArgsDef>;
9
- //# sourceMappingURL=studio.d.ts.map
@@ -11,18 +11,29 @@ import { resolve, dirname } from "node:path";
11
11
  import { existsSync } from "node:fs";
12
12
  import { palette } from "../lib/colors.js";
13
13
  import { spawnInteractive } from "../lib/exec.js";
14
- const localRequire = createRequire(import.meta.url);
15
14
  export const studioCommand = defineCommand({
16
15
  meta: {
17
16
  name: "studio",
18
17
  description: "Boot Nwire Studio (Vue + Vite UI)",
19
18
  },
20
19
  async run({ rawArgs }) {
20
+ // Try resolving @nwire/studio from the consumer's cwd first (so a
21
+ // dev-deps install in their project works), then from the CLI's own
22
+ // location (covers the framework workspace + `pnpm dlx` flows).
21
23
  let studioDir;
22
- try {
23
- studioDir = dirname(localRequire.resolve("@nwire/studio/package.json"));
24
- }
25
- catch {
24
+ const tryResolveFrom = (basePath) => {
25
+ try {
26
+ const req = createRequire(basePath);
27
+ return dirname(req.resolve("@nwire/studio/package.json"));
28
+ }
29
+ catch {
30
+ return undefined;
31
+ }
32
+ };
33
+ studioDir =
34
+ tryResolveFrom(resolve(process.cwd(), "package.json")) ??
35
+ tryResolveFrom(import.meta.url);
36
+ if (!studioDir) {
26
37
  // eslint-disable-next-line no-console
27
38
  console.error(palette.err("nwire studio:") +
28
39
  " @nwire/studio not installed. `pnpm add -D @nwire/studio` first.");
@@ -49,4 +60,3 @@ export const studioCommand = defineCommand({
49
60
  process.exit(await done);
50
61
  },
51
62
  });
52
- //# sourceMappingURL=studio.js.map
@@ -23,4 +23,3 @@ export declare const testCommand: import("citty").CommandDef<{
23
23
  default: false;
24
24
  };
25
25
  }>;
26
- //# sourceMappingURL=test.d.ts.map
@@ -143,4 +143,3 @@ export const testCommand = defineCommand({
143
143
  process.exit(await runTaskList(tasks));
144
144
  },
145
145
  });
146
- //# sourceMappingURL=test.js.map
@@ -37,4 +37,3 @@ export declare const traceCommand: import("citty").CommandDef<{
37
37
  };
38
38
  }>;
39
39
  export {};
40
- //# sourceMappingURL=trace.d.ts.map
@@ -195,4 +195,3 @@ function sleep(ms, signal) {
195
195
  }, { once: true });
196
196
  });
197
197
  }
198
- //# sourceMappingURL=trace.js.map
@@ -30,4 +30,3 @@ export declare const watchCommand: import("citty").CommandDef<{
30
30
  };
31
31
  }>;
32
32
  export {};
33
- //# sourceMappingURL=watch.d.ts.map
@@ -152,4 +152,3 @@ function sleep(ms, signal) {
152
152
  }, { once: true });
153
153
  });
154
154
  }
155
- //# sourceMappingURL=watch.js.map
package/dist/index.d.ts CHANGED
@@ -8,4 +8,3 @@
8
8
  * export default defineConfig({ appsEntry: "./src/app.ts" })
9
9
  */
10
10
  export { defineConfig, type NwireConfig } from "./load-config.js";
11
- //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -8,4 +8,3 @@
8
8
  * export default defineConfig({ appsEntry: "./src/app.ts" })
9
9
  */
10
10
  export { defineConfig } from "./load-config.js";
11
- //# sourceMappingURL=index.js.map
@@ -16,4 +16,3 @@ export declare const palette: {
16
16
  bold: import("picocolors/types").Formatter;
17
17
  hint: import("picocolors/types").Formatter;
18
18
  };
19
- //# sourceMappingURL=colors.d.ts.map
@@ -15,4 +15,3 @@ export const palette = {
15
15
  bold: pc.bold,
16
16
  hint: pc.gray,
17
17
  };
18
- //# sourceMappingURL=colors.js.map
@@ -36,4 +36,3 @@ export type DevEntry = {
36
36
  export declare function resolveDevEntry(cwd: string): DevEntry | undefined;
37
37
  /** Same fallback list rendered for the "no dev entry found" error message. */
38
38
  export declare function devEntryCandidates(): readonly string[];
39
- //# sourceMappingURL=dev-entry.d.ts.map
@@ -99,4 +99,3 @@ function relPath(cwd, abs) {
99
99
  const rel = relative(cwd, abs);
100
100
  return rel === "" ? abs : rel;
101
101
  }
102
- //# sourceMappingURL=dev-entry.js.map
@@ -0,0 +1,28 @@
1
+ /**
2
+ * `ensureScanFresh` — guarantee `.nwire/manifest.json` (and the rest of
3
+ * the per-kind JSON files) reflect the current source tree. Called by
4
+ * every CLI command that reads the scan cache.
5
+ *
6
+ * Cheap path: compute fingerprint, compare to saved; if match, return.
7
+ * Expensive path: spawn the cache-runner under vite-node to rebuild,
8
+ * then save the new fingerprint. The expensive path runs at most once
9
+ * per source change.
10
+ */
11
+ export interface EnsureScanOptions {
12
+ /**
13
+ * When `true`, run the cache builder even if the fingerprint matches.
14
+ * Useful for `nwire cache` itself.
15
+ */
16
+ readonly force?: boolean;
17
+ /**
18
+ * When `true`, do not print "scan refreshed" messages. Default `false`.
19
+ */
20
+ readonly quiet?: boolean;
21
+ }
22
+ export interface EnsureScanResult {
23
+ /** Whether the cache was rebuilt during this call. */
24
+ readonly rebuilt: boolean;
25
+ /** The fingerprint that's now saved on disk. */
26
+ readonly fingerprint: string;
27
+ }
28
+ export declare function ensureScanFresh(cwd?: string, opts?: EnsureScanOptions): EnsureScanResult;
@@ -0,0 +1,41 @@
1
+ /**
2
+ * `ensureScanFresh` — guarantee `.nwire/manifest.json` (and the rest of
3
+ * the per-kind JSON files) reflect the current source tree. Called by
4
+ * every CLI command that reads the scan cache.
5
+ *
6
+ * Cheap path: compute fingerprint, compare to saved; if match, return.
7
+ * Expensive path: spawn the cache-runner under vite-node to rebuild,
8
+ * then save the new fingerprint. The expensive path runs at most once
9
+ * per source change.
10
+ */
11
+ import { existsSync } from "node:fs";
12
+ import { dirname, resolve } from "node:path";
13
+ import { fileURLToPath } from "node:url";
14
+ import { palette } from "./colors.js";
15
+ import { execSync } from "./exec.js";
16
+ import { fingerprint, isFresh, writeFingerprint } from "./scan-cache.js";
17
+ const here = dirname(fileURLToPath(import.meta.url));
18
+ export function ensureScanFresh(cwd = process.cwd(), opts = {}) {
19
+ const fp = fingerprint(cwd);
20
+ if (!opts.force && isFresh(cwd, fp)) {
21
+ return { rebuilt: false, fingerprint: fp };
22
+ }
23
+ const builderPath = resolve(here, "..", "cache-runner.js");
24
+ if (!existsSync(builderPath)) {
25
+ // Builder is missing from dist (dev-mode oddity). Skip — commands
26
+ // that need the cache will surface their own "no manifest" error.
27
+ return { rebuilt: false, fingerprint: fp };
28
+ }
29
+ if (!opts.quiet) {
30
+ // eslint-disable-next-line no-console
31
+ console.error(palette.dim("scanning project…"));
32
+ }
33
+ const code = execSync("pnpm", ["exec", "vite-node", builderPath]);
34
+ if (code !== 0) {
35
+ // Cache build failed; keep whatever's on disk. Don't update the
36
+ // fingerprint, so the next call retries.
37
+ return { rebuilt: false, fingerprint: fp };
38
+ }
39
+ writeFingerprint(cwd, fp);
40
+ return { rebuilt: true, fingerprint: fp };
41
+ }
@@ -34,4 +34,3 @@ export declare function spawnInteractive(cmd: string, args: readonly string[], o
34
34
  child: ChildProcess;
35
35
  done: Promise<number>;
36
36
  };
37
- //# sourceMappingURL=exec.d.ts.map
package/dist/lib/exec.js CHANGED
@@ -73,4 +73,3 @@ export function spawnInteractive(cmd, args, opts = {}) {
73
73
  });
74
74
  return { child, done };
75
75
  }
76
- //# sourceMappingURL=exec.js.map
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Canonical layout discovery for the CLI. Every command that needs to
3
+ * know what shape the consumer's project is in reads this module —
4
+ * one source of truth for "what is a wire and where is it."
5
+ *
6
+ * Discovery proceeds in priority order. The first match wins:
7
+ *
8
+ * 1. `nwire.config.{ts,js,mts,mjs}` declares an apps entry explicitly.
9
+ * 2. `package.json#nwire.wires` lists wires explicitly.
10
+ * 3. `apps/<name>/{run,main}.ts` — multi-wire layout. Each subdir is
11
+ * a wire named after its directory.
12
+ * 4. `app/{run,main}.ts` — single-wire layout. One wire named after
13
+ * the package (or "app" if the package is unnamed).
14
+ * 5. `src/{main,index}.ts` and `./{main,index}.ts` — small-project
15
+ * conventions; one wire named after the package.
16
+ *
17
+ * Returns an empty `wires` list when nothing matches — callers print a
18
+ * helpful message rather than crashing on undefined.
19
+ */
20
+ export interface Wire {
21
+ /** Display name. Used by `nwire build <wire>`, `nwire ls`, status output. */
22
+ readonly name: string;
23
+ /** Absolute path to the entry file (.ts / .mts / .js / .mjs). */
24
+ readonly entry: string;
25
+ }
26
+ export interface ProjectLayout {
27
+ readonly cwd: string;
28
+ readonly packageName: string;
29
+ readonly wires: readonly Wire[];
30
+ /** Path to nwire.config.* if one was found. */
31
+ readonly configPath?: string;
32
+ /** True when the project declared wires explicitly (config or package.json). */
33
+ readonly explicit: boolean;
34
+ }
35
+ export declare function detectLayout(cwd?: string): ProjectLayout;
36
+ /**
37
+ * Resolve a named wire to its entry file. `nwire build foo` calls this
38
+ * with `foo`; we return the entry path or `undefined` if unknown.
39
+ */
40
+ export declare function resolveWire(layout: ProjectLayout, name: string): string | undefined;
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Canonical layout discovery for the CLI. Every command that needs to
3
+ * know what shape the consumer's project is in reads this module —
4
+ * one source of truth for "what is a wire and where is it."
5
+ *
6
+ * Discovery proceeds in priority order. The first match wins:
7
+ *
8
+ * 1. `nwire.config.{ts,js,mts,mjs}` declares an apps entry explicitly.
9
+ * 2. `package.json#nwire.wires` lists wires explicitly.
10
+ * 3. `apps/<name>/{run,main}.ts` — multi-wire layout. Each subdir is
11
+ * a wire named after its directory.
12
+ * 4. `app/{run,main}.ts` — single-wire layout. One wire named after
13
+ * the package (or "app" if the package is unnamed).
14
+ * 5. `src/{main,index}.ts` and `./{main,index}.ts` — small-project
15
+ * conventions; one wire named after the package.
16
+ *
17
+ * Returns an empty `wires` list when nothing matches — callers print a
18
+ * helpful message rather than crashing on undefined.
19
+ */
20
+ import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
21
+ import { resolve } from "node:path";
22
+ const CONFIG_NAMES = ["nwire.config.ts", "nwire.config.mts", "nwire.config.js", "nwire.config.mjs"];
23
+ const ENTRY_NAMES = ["run.ts", "main.ts", "index.ts", "app.ts", "run.mts", "main.mts"];
24
+ function readPackage(cwd) {
25
+ const pkgPath = resolve(cwd, "package.json");
26
+ if (!existsSync(pkgPath))
27
+ return {};
28
+ try {
29
+ return JSON.parse(readFileSync(pkgPath, "utf8"));
30
+ }
31
+ catch {
32
+ return {};
33
+ }
34
+ }
35
+ function firstExistingEntry(dir) {
36
+ for (const name of ENTRY_NAMES) {
37
+ const p = resolve(dir, name);
38
+ if (existsSync(p))
39
+ return p;
40
+ }
41
+ return undefined;
42
+ }
43
+ function findAppsLayout(cwd) {
44
+ const appsDir = resolve(cwd, "apps");
45
+ if (!existsSync(appsDir))
46
+ return [];
47
+ const out = [];
48
+ for (const entry of readdirSync(appsDir, { withFileTypes: true })) {
49
+ if (!entry.isDirectory())
50
+ continue;
51
+ const wireDir = resolve(appsDir, entry.name);
52
+ const wireEntry = firstExistingEntry(wireDir);
53
+ if (wireEntry)
54
+ out.push({ name: entry.name, entry: wireEntry });
55
+ // `apps/foo/run.<variant>.ts` — siblings of run.ts (e.g. run.worker.ts)
56
+ // become distinct wires named `foo.<variant>`. Preserves the multi-wire
57
+ // per-app convention without forcing every project into it.
58
+ for (const f of readdirSync(wireDir)) {
59
+ if (!f.startsWith("run.") || !f.endsWith(".ts") || f.endsWith(".d.ts"))
60
+ continue;
61
+ if (f === "run.ts")
62
+ continue; // covered above
63
+ const variant = f.slice(4, -3);
64
+ out.push({ name: `${entry.name}.${variant}`, entry: resolve(wireDir, f) });
65
+ }
66
+ }
67
+ return out;
68
+ }
69
+ function findSingleAppLayout(cwd, packageName) {
70
+ const appDir = resolve(cwd, "app");
71
+ if (!existsSync(appDir) || !statSync(appDir).isDirectory())
72
+ return [];
73
+ const e = firstExistingEntry(appDir);
74
+ return e ? [{ name: packageName, entry: e }] : [];
75
+ }
76
+ function findFlatLayout(cwd, packageName) {
77
+ for (const dir of [resolve(cwd, "src"), cwd]) {
78
+ const e = firstExistingEntry(dir);
79
+ if (e)
80
+ return [{ name: packageName, entry: e }];
81
+ }
82
+ return [];
83
+ }
84
+ function locateConfig(cwd) {
85
+ for (const name of CONFIG_NAMES) {
86
+ const p = resolve(cwd, name);
87
+ if (existsSync(p))
88
+ return p;
89
+ }
90
+ return undefined;
91
+ }
92
+ export function detectLayout(cwd = process.cwd()) {
93
+ const pkg = readPackage(cwd);
94
+ const packageName = pkg.name?.replace(/^@[^/]+\//, "") || "app";
95
+ const configPath = locateConfig(cwd);
96
+ const declared = pkg.nwire?.wires;
97
+ if (declared && declared.length > 0) {
98
+ return {
99
+ cwd,
100
+ packageName,
101
+ configPath,
102
+ explicit: true,
103
+ wires: declared.map((d) => ({ name: d.name, entry: resolve(cwd, d.entry) })),
104
+ };
105
+ }
106
+ const appsWires = findAppsLayout(cwd);
107
+ if (appsWires.length > 0) {
108
+ return { cwd, packageName, configPath, explicit: false, wires: appsWires };
109
+ }
110
+ const singleAppWires = findSingleAppLayout(cwd, packageName);
111
+ if (singleAppWires.length > 0) {
112
+ return { cwd, packageName, configPath, explicit: false, wires: singleAppWires };
113
+ }
114
+ return {
115
+ cwd,
116
+ packageName,
117
+ configPath,
118
+ explicit: false,
119
+ wires: findFlatLayout(cwd, packageName),
120
+ };
121
+ }
122
+ /**
123
+ * Resolve a named wire to its entry file. `nwire build foo` calls this
124
+ * with `foo`; we return the entry path or `undefined` if unknown.
125
+ */
126
+ export function resolveWire(layout, name) {
127
+ return layout.wires.find((w) => w.name === name)?.entry;
128
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Detect the consumer's package manager from lockfile / packageManager
3
+ * field. `pnpm` is preferred when ambiguous (matches Nwire's own dev
4
+ * convention) but the CLI follows whatever the project already uses.
5
+ */
6
+ export type PackageManager = "pnpm" | "yarn" | "npm" | "bun";
7
+ export declare function detectPackageManager(cwd?: string): PackageManager;
8
+ /**
9
+ * Build the command + args for `<pm> run <script>`.
10
+ */
11
+ export declare function runScriptCommand(pm: PackageManager, script: string): [string, string[]];
12
+ /**
13
+ * Build the command + args for `<pm> exec <bin> [...args]`. yarn 1.x
14
+ * does not have `exec`; we fall back to invoking `node_modules/.bin/<bin>`
15
+ * directly for that case.
16
+ */
17
+ export declare function execBinaryCommand(pm: PackageManager, bin: string, args?: readonly string[]): [string, string[]];