@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.
- package/dist/cache-runner.d.ts +0 -1
- package/dist/cache-runner.js +107 -9
- package/dist/cli.d.ts +3 -6
- package/dist/cli.js +5 -7
- package/dist/commands/bench.d.ts +0 -1
- package/dist/commands/bench.js +0 -1
- package/dist/commands/build.d.ts +0 -1
- package/dist/commands/build.js +13 -17
- package/dist/commands/cache.d.ts +3 -3
- package/dist/commands/cache.js +7 -17
- package/dist/commands/check.d.ts +10 -3
- package/dist/commands/check.js +34 -10
- package/dist/commands/dev.d.ts +0 -1
- package/dist/commands/dev.js +0 -1
- package/dist/commands/doctor.d.ts +1 -2
- package/dist/commands/doctor.js +14 -15
- package/dist/commands/fmt.d.ts +8 -4
- package/dist/commands/fmt.js +35 -12
- package/dist/commands/greeting.d.ts +0 -1
- package/dist/commands/greeting.js +0 -1
- package/dist/commands/infra.d.ts +0 -1
- package/dist/commands/infra.js +0 -1
- package/dist/commands/lint.d.ts +7 -3
- package/dist/commands/lint.js +34 -13
- package/dist/commands/logs.d.ts +0 -1
- package/dist/commands/logs.js +0 -1
- package/dist/commands/ls.d.ts +1 -1
- package/dist/commands/ls.js +3 -1
- package/dist/commands/mcp.d.ts +0 -1
- package/dist/commands/mcp.js +2 -2
- package/dist/commands/please.d.ts +0 -1
- package/dist/commands/please.js +0 -1
- package/dist/commands/ps.d.ts +0 -1
- package/dist/commands/ps.js +0 -1
- package/dist/commands/replay.d.ts +0 -1
- package/dist/commands/replay.js +0 -1
- package/dist/commands/run.d.ts +0 -1
- package/dist/commands/run.js +0 -1
- package/dist/commands/studio.d.ts +0 -1
- package/dist/commands/studio.js +16 -6
- package/dist/commands/test.d.ts +0 -1
- package/dist/commands/test.js +0 -1
- package/dist/commands/trace.d.ts +0 -1
- package/dist/commands/trace.js +0 -1
- package/dist/commands/watch.d.ts +0 -1
- package/dist/commands/watch.js +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/lib/colors.d.ts +0 -1
- package/dist/lib/colors.js +0 -1
- package/dist/lib/dev-entry.d.ts +0 -1
- package/dist/lib/dev-entry.js +0 -1
- package/dist/lib/ensure-scan.d.ts +28 -0
- package/dist/lib/ensure-scan.js +41 -0
- package/dist/lib/exec.d.ts +0 -1
- package/dist/lib/exec.js +0 -1
- package/dist/lib/layout.d.ts +40 -0
- package/dist/lib/layout.js +128 -0
- package/dist/lib/package-manager.d.ts +17 -0
- package/dist/lib/package-manager.js +67 -0
- package/dist/lib/process-state.d.ts +0 -1
- package/dist/lib/process-state.js +0 -1
- package/dist/lib/project.d.ts +3 -4
- package/dist/lib/project.js +16 -34
- package/dist/lib/run-task.d.ts +0 -1
- package/dist/lib/run-task.js +0 -1
- package/dist/lib/scan-cache.d.ts +27 -0
- package/dist/lib/scan-cache.js +102 -0
- package/dist/lib/script-runner.d.ts +42 -0
- package/dist/lib/script-runner.js +90 -0
- package/dist/lib/sse.d.ts +0 -1
- package/dist/lib/sse.js +0 -1
- package/dist/lib/version.d.ts +8 -0
- package/dist/lib/version.js +29 -0
- package/dist/lib/vite-node.d.ts +0 -1
- package/dist/lib/vite-node.js +0 -1
- package/dist/lib/wire-discovery.d.ts +0 -1
- package/dist/lib/wire-discovery.js +0 -1
- package/dist/load-config.d.ts +0 -1
- package/dist/load-config.js +0 -1
- package/dist/ls-runner.d.ts +0 -1
- package/dist/ls-runner.js +34 -40
- package/dist/ui/dev-dashboard.d.ts +0 -1
- package/dist/ui/dev-dashboard.js +0 -1
- package/dist/ui/greeting.d.ts +0 -1
- package/dist/ui/greeting.js +0 -1
- package/dist/ui/process-table.d.ts +0 -1
- package/dist/ui/process-table.js +0 -1
- package/package.json +5 -6
- package/dist/__tests__/bench.test.d.ts +0 -2
- package/dist/__tests__/bench.test.d.ts.map +0 -1
- package/dist/__tests__/bench.test.js +0 -94
- package/dist/__tests__/bench.test.js.map +0 -1
- package/dist/__tests__/doctor.test.d.ts +0 -10
- package/dist/__tests__/doctor.test.d.ts.map +0 -1
- package/dist/__tests__/doctor.test.js +0 -105
- package/dist/__tests__/doctor.test.js.map +0 -1
- package/dist/__tests__/replay.test.d.ts +0 -2
- package/dist/__tests__/replay.test.d.ts.map +0 -1
- package/dist/__tests__/replay.test.js +0 -203
- package/dist/__tests__/replay.test.js.map +0 -1
- package/dist/__tests__/trace.test.d.ts +0 -2
- package/dist/__tests__/trace.test.d.ts.map +0 -1
- package/dist/__tests__/trace.test.js +0 -136
- package/dist/__tests__/trace.test.js.map +0 -1
- package/dist/__tests__/watch.test.d.ts +0 -2
- package/dist/__tests__/watch.test.d.ts.map +0 -1
- package/dist/__tests__/watch.test.js +0 -110
- package/dist/__tests__/watch.test.js.map +0 -1
- package/dist/cache-runner.d.ts.map +0 -1
- package/dist/cache-runner.js.map +0 -1
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/commands/bench.d.ts.map +0 -1
- package/dist/commands/bench.js.map +0 -1
- package/dist/commands/build.d.ts.map +0 -1
- package/dist/commands/build.js.map +0 -1
- package/dist/commands/cache.d.ts.map +0 -1
- package/dist/commands/cache.js.map +0 -1
- package/dist/commands/check.d.ts.map +0 -1
- package/dist/commands/check.js.map +0 -1
- package/dist/commands/dev.d.ts.map +0 -1
- package/dist/commands/dev.js.map +0 -1
- package/dist/commands/doctor.d.ts.map +0 -1
- package/dist/commands/doctor.js.map +0 -1
- package/dist/commands/fmt.d.ts.map +0 -1
- package/dist/commands/fmt.js.map +0 -1
- package/dist/commands/greeting.d.ts.map +0 -1
- package/dist/commands/greeting.js.map +0 -1
- package/dist/commands/infra.d.ts.map +0 -1
- package/dist/commands/infra.js.map +0 -1
- package/dist/commands/lint.d.ts.map +0 -1
- package/dist/commands/lint.js.map +0 -1
- package/dist/commands/logs.d.ts.map +0 -1
- package/dist/commands/logs.js.map +0 -1
- package/dist/commands/ls.d.ts.map +0 -1
- package/dist/commands/ls.js.map +0 -1
- package/dist/commands/mcp.d.ts.map +0 -1
- package/dist/commands/mcp.js.map +0 -1
- package/dist/commands/please.d.ts.map +0 -1
- package/dist/commands/please.js.map +0 -1
- package/dist/commands/ps.d.ts.map +0 -1
- package/dist/commands/ps.js.map +0 -1
- package/dist/commands/replay.d.ts.map +0 -1
- package/dist/commands/replay.js.map +0 -1
- package/dist/commands/run.d.ts.map +0 -1
- package/dist/commands/run.js.map +0 -1
- package/dist/commands/studio.d.ts.map +0 -1
- package/dist/commands/studio.js.map +0 -1
- package/dist/commands/test.d.ts.map +0 -1
- package/dist/commands/test.js.map +0 -1
- package/dist/commands/trace.d.ts.map +0 -1
- package/dist/commands/trace.js.map +0 -1
- package/dist/commands/watch.d.ts.map +0 -1
- package/dist/commands/watch.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/kernel-instance.d.ts +0 -8
- package/dist/kernel-instance.d.ts.map +0 -1
- package/dist/kernel-instance.js +0 -13
- package/dist/kernel-instance.js.map +0 -1
- package/dist/lib/colors.d.ts.map +0 -1
- package/dist/lib/colors.js.map +0 -1
- package/dist/lib/dev-entry.d.ts.map +0 -1
- package/dist/lib/dev-entry.js.map +0 -1
- package/dist/lib/exec.d.ts.map +0 -1
- package/dist/lib/exec.js.map +0 -1
- package/dist/lib/process-state.d.ts.map +0 -1
- package/dist/lib/process-state.js.map +0 -1
- package/dist/lib/project.d.ts.map +0 -1
- package/dist/lib/project.js.map +0 -1
- package/dist/lib/run-task.d.ts.map +0 -1
- package/dist/lib/run-task.js.map +0 -1
- package/dist/lib/sse.d.ts.map +0 -1
- package/dist/lib/sse.js.map +0 -1
- package/dist/lib/vite-node.d.ts.map +0 -1
- package/dist/lib/vite-node.js.map +0 -1
- package/dist/lib/wire-discovery.d.ts.map +0 -1
- package/dist/lib/wire-discovery.js.map +0 -1
- package/dist/load-config.d.ts.map +0 -1
- package/dist/load-config.js.map +0 -1
- package/dist/ls-runner.d.ts.map +0 -1
- package/dist/ls-runner.js.map +0 -1
- package/dist/ui/dev-dashboard.d.ts.map +0 -1
- package/dist/ui/dev-dashboard.js.map +0 -1
- package/dist/ui/greeting.d.ts.map +0 -1
- package/dist/ui/greeting.js.map +0 -1
- package/dist/ui/process-table.d.ts.map +0 -1
- package/dist/ui/process-table.js.map +0 -1
|
@@ -0,0 +1,67 @@
|
|
|
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
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
7
|
+
import { resolve } from "node:path";
|
|
8
|
+
export function detectPackageManager(cwd = process.cwd()) {
|
|
9
|
+
const pkgPath = resolve(cwd, "package.json");
|
|
10
|
+
if (existsSync(pkgPath)) {
|
|
11
|
+
try {
|
|
12
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
13
|
+
if (pkg.packageManager) {
|
|
14
|
+
if (pkg.packageManager.startsWith("pnpm"))
|
|
15
|
+
return "pnpm";
|
|
16
|
+
if (pkg.packageManager.startsWith("yarn"))
|
|
17
|
+
return "yarn";
|
|
18
|
+
if (pkg.packageManager.startsWith("bun"))
|
|
19
|
+
return "bun";
|
|
20
|
+
if (pkg.packageManager.startsWith("npm"))
|
|
21
|
+
return "npm";
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
// fall through to lockfile detection
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
if (existsSync(resolve(cwd, "pnpm-lock.yaml")))
|
|
29
|
+
return "pnpm";
|
|
30
|
+
if (existsSync(resolve(cwd, "yarn.lock")))
|
|
31
|
+
return "yarn";
|
|
32
|
+
if (existsSync(resolve(cwd, "bun.lockb")))
|
|
33
|
+
return "bun";
|
|
34
|
+
if (existsSync(resolve(cwd, "package-lock.json")))
|
|
35
|
+
return "npm";
|
|
36
|
+
return "npm";
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Build the command + args for `<pm> run <script>`.
|
|
40
|
+
*/
|
|
41
|
+
export function runScriptCommand(pm, script) {
|
|
42
|
+
switch (pm) {
|
|
43
|
+
case "pnpm":
|
|
44
|
+
case "yarn":
|
|
45
|
+
case "bun":
|
|
46
|
+
return [pm, ["run", script]];
|
|
47
|
+
case "npm":
|
|
48
|
+
return ["npm", ["run", script]];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Build the command + args for `<pm> exec <bin> [...args]`. yarn 1.x
|
|
53
|
+
* does not have `exec`; we fall back to invoking `node_modules/.bin/<bin>`
|
|
54
|
+
* directly for that case.
|
|
55
|
+
*/
|
|
56
|
+
export function execBinaryCommand(pm, bin, args = []) {
|
|
57
|
+
switch (pm) {
|
|
58
|
+
case "pnpm":
|
|
59
|
+
return ["pnpm", ["exec", bin, ...args]];
|
|
60
|
+
case "yarn":
|
|
61
|
+
return ["yarn", [bin, ...args]];
|
|
62
|
+
case "bun":
|
|
63
|
+
return ["bun", ["x", bin, ...args]];
|
|
64
|
+
case "npm":
|
|
65
|
+
return ["npx", ["--no-install", bin, ...args]];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -27,4 +27,3 @@ export declare function writeRecord(cwd: string, record: ProcessRecord): void;
|
|
|
27
27
|
export declare function readRecord(cwd: string, id: string): ProcessRecord | undefined;
|
|
28
28
|
export declare function listRecords(cwd: string): ProcessRecord[];
|
|
29
29
|
export declare function removeRecord(cwd: string, id: string): void;
|
|
30
|
-
//# sourceMappingURL=process-state.d.ts.map
|
package/dist/lib/project.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Project introspection
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Project introspection. Thin adapter over `detectLayout` — preserves
|
|
3
|
+
* the older `ProjectInfo` shape so existing CLI callers keep working
|
|
4
|
+
* while pointing at the unified layout discoverer.
|
|
5
5
|
*/
|
|
6
6
|
export interface ProjectInfo {
|
|
7
7
|
readonly cwd: string;
|
|
@@ -12,4 +12,3 @@ export interface ProjectInfo {
|
|
|
12
12
|
readonly hasPlease: boolean;
|
|
13
13
|
}
|
|
14
14
|
export declare function detectProject(cwd?: string): ProjectInfo;
|
|
15
|
-
//# sourceMappingURL=project.d.ts.map
|
package/dist/lib/project.js
CHANGED
|
@@ -1,52 +1,34 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Project introspection
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Project introspection. Thin adapter over `detectLayout` — preserves
|
|
3
|
+
* the older `ProjectInfo` shape so existing CLI callers keep working
|
|
4
|
+
* while pointing at the unified layout discoverer.
|
|
5
5
|
*/
|
|
6
|
-
import { existsSync,
|
|
6
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
7
7
|
import { resolve } from "node:path";
|
|
8
|
+
import { detectLayout } from "./layout.js";
|
|
8
9
|
export function detectProject(cwd = process.cwd()) {
|
|
9
|
-
const
|
|
10
|
+
const layout = detectLayout(cwd);
|
|
10
11
|
let name = "(unnamed)";
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
const pkgPath = resolve(cwd, "package.json");
|
|
13
|
+
if (existsSync(pkgPath)) {
|
|
14
|
+
try {
|
|
13
15
|
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
14
16
|
if (pkg.name)
|
|
15
17
|
name = pkg.name;
|
|
16
18
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
// keep default name
|
|
20
|
-
}
|
|
21
|
-
const appsDir = resolve(cwd, "apps");
|
|
22
|
-
const wires = [];
|
|
23
|
-
let hasDevAll = false;
|
|
24
|
-
let hasPlease = false;
|
|
25
|
-
if (existsSync(appsDir)) {
|
|
26
|
-
for (const entry of readdirSync(appsDir, { withFileTypes: true })) {
|
|
27
|
-
if (!entry.isDirectory())
|
|
28
|
-
continue;
|
|
29
|
-
const appDir = resolve(appsDir, entry.name);
|
|
30
|
-
// A wire is any app folder with a recognized entry file. We accept
|
|
31
|
-
// both the older `run.ts` convention and the current `main.ts`
|
|
32
|
-
// convention so the greeting works across projects mid-migration.
|
|
33
|
-
const hasEntry = existsSync(resolve(appDir, "run.ts")) || existsSync(resolve(appDir, "main.ts"));
|
|
34
|
-
if (hasEntry)
|
|
35
|
-
wires.push(entry.name);
|
|
36
|
-
if (entry.name === "dev-all" && existsSync(resolve(appDir, "run.ts"))) {
|
|
37
|
-
hasDevAll = true;
|
|
38
|
-
}
|
|
39
|
-
if (existsSync(resolve(appDir, "run.please.ts")))
|
|
40
|
-
hasPlease = true;
|
|
19
|
+
catch {
|
|
20
|
+
// keep default
|
|
41
21
|
}
|
|
42
22
|
}
|
|
23
|
+
const wires = layout.wires.map((w) => w.name).sort();
|
|
24
|
+
const hasDevAll = wires.includes("dev-all");
|
|
25
|
+
const hasPlease = layout.wires.some((w) => w.entry.endsWith("run.please.ts") || w.entry.endsWith("please.ts"));
|
|
43
26
|
return {
|
|
44
27
|
cwd,
|
|
45
28
|
name,
|
|
46
|
-
hasNwireConfig:
|
|
47
|
-
wires
|
|
29
|
+
hasNwireConfig: !!layout.configPath,
|
|
30
|
+
wires,
|
|
48
31
|
hasDevAll,
|
|
49
32
|
hasPlease,
|
|
50
33
|
};
|
|
51
34
|
}
|
|
52
|
-
//# sourceMappingURL=project.js.map
|
package/dist/lib/run-task.d.ts
CHANGED
package/dist/lib/run-task.js
CHANGED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Incremental scan cache. Walks the project's source tree, computes a
|
|
3
|
+
* fingerprint over file mtimes and sizes, and persists it under
|
|
4
|
+
* `.nwire/scan-fingerprint.json`. `isFresh()` returns true when the
|
|
5
|
+
* current tree matches the saved fingerprint — in that case CLI
|
|
6
|
+
* commands can read the existing `.nwire/manifest.json` without
|
|
7
|
+
* re-running the consumer's app to rebuild it.
|
|
8
|
+
*
|
|
9
|
+
* The fingerprint is intentionally cheap: a single sha1 over a sorted
|
|
10
|
+
* list of `<relative path> <mtimeMs> <size>` lines for every `.ts`,
|
|
11
|
+
* `.mts`, `.js`, `.mjs` file under the project root, excluding
|
|
12
|
+
* `node_modules/`, `dist/`, `.nwire/`, `.turbo/`, and dotfiles.
|
|
13
|
+
*
|
|
14
|
+
* The cost of a fresh fingerprint scan on a typical service-sized tree
|
|
15
|
+
* (hundreds of files) is a few milliseconds — fast enough to run on
|
|
16
|
+
* every CLI invocation that needs it.
|
|
17
|
+
*/
|
|
18
|
+
export declare function fingerprint(cwd: string): string;
|
|
19
|
+
export declare function readFingerprint(cwd: string): string | undefined;
|
|
20
|
+
export declare function writeFingerprint(cwd: string, value: string): void;
|
|
21
|
+
/**
|
|
22
|
+
* True when `.nwire/manifest.json` exists AND the saved fingerprint
|
|
23
|
+
* matches the current tree. The caller passes the fingerprint it just
|
|
24
|
+
* computed so the same scan can serve both "is fresh?" and "what's the
|
|
25
|
+
* new fingerprint to save?"
|
|
26
|
+
*/
|
|
27
|
+
export declare function isFresh(cwd: string, currentFingerprint: string): boolean;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Incremental scan cache. Walks the project's source tree, computes a
|
|
3
|
+
* fingerprint over file mtimes and sizes, and persists it under
|
|
4
|
+
* `.nwire/scan-fingerprint.json`. `isFresh()` returns true when the
|
|
5
|
+
* current tree matches the saved fingerprint — in that case CLI
|
|
6
|
+
* commands can read the existing `.nwire/manifest.json` without
|
|
7
|
+
* re-running the consumer's app to rebuild it.
|
|
8
|
+
*
|
|
9
|
+
* The fingerprint is intentionally cheap: a single sha1 over a sorted
|
|
10
|
+
* list of `<relative path> <mtimeMs> <size>` lines for every `.ts`,
|
|
11
|
+
* `.mts`, `.js`, `.mjs` file under the project root, excluding
|
|
12
|
+
* `node_modules/`, `dist/`, `.nwire/`, `.turbo/`, and dotfiles.
|
|
13
|
+
*
|
|
14
|
+
* The cost of a fresh fingerprint scan on a typical service-sized tree
|
|
15
|
+
* (hundreds of files) is a few milliseconds — fast enough to run on
|
|
16
|
+
* every CLI invocation that needs it.
|
|
17
|
+
*/
|
|
18
|
+
import { createHash } from "node:crypto";
|
|
19
|
+
import { existsSync, readdirSync, statSync, writeFileSync, readFileSync, mkdirSync } from "node:fs";
|
|
20
|
+
import { dirname, relative, resolve } from "node:path";
|
|
21
|
+
const SCAN_EXTENSIONS = [".ts", ".mts", ".js", ".mjs"];
|
|
22
|
+
const SKIP_DIRS = new Set(["node_modules", "dist", ".nwire", ".turbo", ".git", ".vitepress"]);
|
|
23
|
+
function walk(root, out) {
|
|
24
|
+
for (const entry of readdirSync(root, { withFileTypes: true })) {
|
|
25
|
+
if (entry.name.startsWith("."))
|
|
26
|
+
continue;
|
|
27
|
+
if (SKIP_DIRS.has(entry.name))
|
|
28
|
+
continue;
|
|
29
|
+
const full = resolve(root, entry.name);
|
|
30
|
+
if (entry.isDirectory()) {
|
|
31
|
+
walk(full, out);
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (!entry.isFile())
|
|
35
|
+
continue;
|
|
36
|
+
if (entry.name.endsWith(".d.ts"))
|
|
37
|
+
continue;
|
|
38
|
+
if (!SCAN_EXTENSIONS.some((ext) => entry.name.endsWith(ext)))
|
|
39
|
+
continue;
|
|
40
|
+
out.push(full);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export function fingerprint(cwd) {
|
|
44
|
+
const files = [];
|
|
45
|
+
walk(cwd, files);
|
|
46
|
+
files.sort();
|
|
47
|
+
const h = createHash("sha1");
|
|
48
|
+
for (const f of files) {
|
|
49
|
+
try {
|
|
50
|
+
const st = statSync(f);
|
|
51
|
+
h.update(`${relative(cwd, f)} ${st.mtimeMs} ${st.size}\n`);
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
// Race with concurrent rm; skip — the next fingerprint will catch it.
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// Include package.json so dependency edits invalidate too.
|
|
58
|
+
const pkg = resolve(cwd, "package.json");
|
|
59
|
+
if (existsSync(pkg)) {
|
|
60
|
+
const st = statSync(pkg);
|
|
61
|
+
h.update(`package.json ${st.mtimeMs} ${st.size}\n`);
|
|
62
|
+
}
|
|
63
|
+
return h.digest("hex");
|
|
64
|
+
}
|
|
65
|
+
const FILE = "scan-fingerprint.json";
|
|
66
|
+
export function readFingerprint(cwd) {
|
|
67
|
+
const p = resolve(cwd, ".nwire", FILE);
|
|
68
|
+
if (!existsSync(p))
|
|
69
|
+
return undefined;
|
|
70
|
+
try {
|
|
71
|
+
const parsed = JSON.parse(readFileSync(p, "utf8"));
|
|
72
|
+
return parsed.version === 1 ? parsed.fingerprint : undefined;
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
export function writeFingerprint(cwd, value) {
|
|
79
|
+
const dir = resolve(cwd, ".nwire");
|
|
80
|
+
if (!existsSync(dir))
|
|
81
|
+
mkdirSync(dir, { recursive: true });
|
|
82
|
+
const payload = {
|
|
83
|
+
version: 1,
|
|
84
|
+
fingerprint: value,
|
|
85
|
+
generatedAt: new Date().toISOString(),
|
|
86
|
+
};
|
|
87
|
+
writeFileSync(resolve(dir, FILE), JSON.stringify(payload, null, 2));
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* True when `.nwire/manifest.json` exists AND the saved fingerprint
|
|
91
|
+
* matches the current tree. The caller passes the fingerprint it just
|
|
92
|
+
* computed so the same scan can serve both "is fresh?" and "what's the
|
|
93
|
+
* new fingerprint to save?"
|
|
94
|
+
*/
|
|
95
|
+
export function isFresh(cwd, currentFingerprint) {
|
|
96
|
+
const manifest = resolve(cwd, ".nwire", "manifest.json");
|
|
97
|
+
if (!existsSync(manifest))
|
|
98
|
+
return false;
|
|
99
|
+
const saved = readFingerprint(cwd);
|
|
100
|
+
return saved === currentFingerprint;
|
|
101
|
+
}
|
|
102
|
+
void dirname; // silence "imported but unused" in some builds
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run-an-operation-three-ways helper. Every CLI command that exists to
|
|
3
|
+
* orchestrate a check or build follows the same pattern:
|
|
4
|
+
*
|
|
5
|
+
* 1. If the consumer defined a `scripts.<name>` in their package.json,
|
|
6
|
+
* run that. Honors whatever the project already encodes.
|
|
7
|
+
* 2. Otherwise, if a list of sub-scripts is defined (e.g. `check`
|
|
8
|
+
* decomposes into `format:check`, `lint`, `typecheck`), run each
|
|
9
|
+
* that the consumer has defined.
|
|
10
|
+
* 3. Otherwise, fall back to spawning installed binaries — but only
|
|
11
|
+
* if the binary actually exists in `node_modules/.bin`. We never
|
|
12
|
+
* spawn a tool we haven't verified is present, so consumers that
|
|
13
|
+
* use a different formatter / linter / type checker don't see a
|
|
14
|
+
* surprise `ENOENT` from our hardcoded defaults.
|
|
15
|
+
*
|
|
16
|
+
* The result is that `nwire check` reads as "run the project's check,
|
|
17
|
+
* whatever that means in this project" rather than "run our chosen
|
|
18
|
+
* formatter on the project, hope they have it installed."
|
|
19
|
+
*/
|
|
20
|
+
interface FallbackBinary {
|
|
21
|
+
/** Display title for the listr task. */
|
|
22
|
+
readonly title: string;
|
|
23
|
+
/** Binary name as installed under `node_modules/.bin/`. */
|
|
24
|
+
readonly bin: string;
|
|
25
|
+
/** Extra args appended after the binary name. */
|
|
26
|
+
readonly args?: readonly string[];
|
|
27
|
+
}
|
|
28
|
+
export interface ScriptStrategy {
|
|
29
|
+
/** Single script name to try first (e.g. "check"). */
|
|
30
|
+
readonly consumerScript?: string;
|
|
31
|
+
/** Sub-scripts to try in sequence if `consumerScript` is not defined. */
|
|
32
|
+
readonly consumerSubScripts?: readonly string[];
|
|
33
|
+
/** Binaries to try if no consumer scripts apply. */
|
|
34
|
+
readonly fallback?: readonly FallbackBinary[];
|
|
35
|
+
/** Title for the top-level operation; passed to error messages. */
|
|
36
|
+
readonly operationName: string;
|
|
37
|
+
}
|
|
38
|
+
export declare function runScriptStrategy(cwd: string, strategy: ScriptStrategy): Promise<{
|
|
39
|
+
code: number;
|
|
40
|
+
ran: boolean;
|
|
41
|
+
}>;
|
|
42
|
+
export {};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run-an-operation-three-ways helper. Every CLI command that exists to
|
|
3
|
+
* orchestrate a check or build follows the same pattern:
|
|
4
|
+
*
|
|
5
|
+
* 1. If the consumer defined a `scripts.<name>` in their package.json,
|
|
6
|
+
* run that. Honors whatever the project already encodes.
|
|
7
|
+
* 2. Otherwise, if a list of sub-scripts is defined (e.g. `check`
|
|
8
|
+
* decomposes into `format:check`, `lint`, `typecheck`), run each
|
|
9
|
+
* that the consumer has defined.
|
|
10
|
+
* 3. Otherwise, fall back to spawning installed binaries — but only
|
|
11
|
+
* if the binary actually exists in `node_modules/.bin`. We never
|
|
12
|
+
* spawn a tool we haven't verified is present, so consumers that
|
|
13
|
+
* use a different formatter / linter / type checker don't see a
|
|
14
|
+
* surprise `ENOENT` from our hardcoded defaults.
|
|
15
|
+
*
|
|
16
|
+
* The result is that `nwire check` reads as "run the project's check,
|
|
17
|
+
* whatever that means in this project" rather than "run our chosen
|
|
18
|
+
* formatter on the project, hope they have it installed."
|
|
19
|
+
*/
|
|
20
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
21
|
+
import { resolve } from "node:path";
|
|
22
|
+
import { detectPackageManager, execBinaryCommand, runScriptCommand, } from "./package-manager.js";
|
|
23
|
+
import { runTaskList } from "./run-task.js";
|
|
24
|
+
function readScripts(cwd) {
|
|
25
|
+
const p = resolve(cwd, "package.json");
|
|
26
|
+
if (!existsSync(p))
|
|
27
|
+
return {};
|
|
28
|
+
try {
|
|
29
|
+
const pkg = JSON.parse(readFileSync(p, "utf8"));
|
|
30
|
+
return pkg.scripts ?? {};
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return {};
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function binaryInstalled(cwd, bin) {
|
|
37
|
+
return (existsSync(resolve(cwd, "node_modules", ".bin", bin)) ||
|
|
38
|
+
existsSync(resolve(cwd, "node_modules", ".bin", `${bin}.cmd`)));
|
|
39
|
+
}
|
|
40
|
+
function buildTasksForStrategy(cwd, pm, strategy) {
|
|
41
|
+
const scripts = readScripts(cwd);
|
|
42
|
+
if (strategy.consumerScript && scripts[strategy.consumerScript]) {
|
|
43
|
+
const [command, args] = runScriptCommand(pm, strategy.consumerScript);
|
|
44
|
+
return {
|
|
45
|
+
tasks: [
|
|
46
|
+
{
|
|
47
|
+
title: `${pm} run ${strategy.consumerScript}`,
|
|
48
|
+
command,
|
|
49
|
+
args,
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
source: "consumer-script",
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
if (strategy.consumerSubScripts && strategy.consumerSubScripts.length > 0) {
|
|
56
|
+
const available = strategy.consumerSubScripts.filter((s) => scripts[s] !== undefined);
|
|
57
|
+
if (available.length > 0) {
|
|
58
|
+
return {
|
|
59
|
+
tasks: available.map((script) => {
|
|
60
|
+
const [command, args] = runScriptCommand(pm, script);
|
|
61
|
+
return { title: `${pm} run ${script}`, command, args };
|
|
62
|
+
}),
|
|
63
|
+
source: "consumer-subscripts",
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (strategy.fallback && strategy.fallback.length > 0) {
|
|
68
|
+
const available = strategy.fallback.filter((f) => binaryInstalled(cwd, f.bin));
|
|
69
|
+
if (available.length > 0) {
|
|
70
|
+
return {
|
|
71
|
+
tasks: available.map((f) => {
|
|
72
|
+
const [command, args] = execBinaryCommand(pm, f.bin, f.args);
|
|
73
|
+
return { title: f.title, command, args };
|
|
74
|
+
}),
|
|
75
|
+
source: "fallback",
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return { tasks: [], source: "none" };
|
|
80
|
+
}
|
|
81
|
+
export async function runScriptStrategy(cwd, strategy) {
|
|
82
|
+
const pm = detectPackageManager(cwd);
|
|
83
|
+
const { tasks, source } = buildTasksForStrategy(cwd, pm, strategy);
|
|
84
|
+
if (source === "none") {
|
|
85
|
+
return { code: 0, ran: false };
|
|
86
|
+
}
|
|
87
|
+
void source;
|
|
88
|
+
const code = await runTaskList(tasks);
|
|
89
|
+
return { code, ran: true };
|
|
90
|
+
}
|
package/dist/lib/sse.d.ts
CHANGED
package/dist/lib/sse.js
CHANGED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single-source the CLI version from its own package.json. Read once at
|
|
3
|
+
* module import; the result is stable across the process lifetime.
|
|
4
|
+
*
|
|
5
|
+
* Looks for `package.json` next to the compiled `dist/lib/version.js` or
|
|
6
|
+
* next to the source `src/lib/version.ts` (the dev runner path).
|
|
7
|
+
*/
|
|
8
|
+
export declare function cliVersion(): string;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single-source the CLI version from its own package.json. Read once at
|
|
3
|
+
* module import; the result is stable across the process lifetime.
|
|
4
|
+
*
|
|
5
|
+
* Looks for `package.json` next to the compiled `dist/lib/version.js` or
|
|
6
|
+
* next to the source `src/lib/version.ts` (the dev runner path).
|
|
7
|
+
*/
|
|
8
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
9
|
+
import { dirname, resolve } from "node:path";
|
|
10
|
+
import { fileURLToPath } from "node:url";
|
|
11
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
function locate() {
|
|
13
|
+
for (const candidate of [
|
|
14
|
+
resolve(here, "..", "..", "package.json"),
|
|
15
|
+
resolve(here, "..", "..", "..", "package.json"),
|
|
16
|
+
]) {
|
|
17
|
+
if (existsSync(candidate))
|
|
18
|
+
return candidate;
|
|
19
|
+
}
|
|
20
|
+
throw new Error("nwire-cli: package.json not found relative to version.ts");
|
|
21
|
+
}
|
|
22
|
+
let cached;
|
|
23
|
+
export function cliVersion() {
|
|
24
|
+
if (cached)
|
|
25
|
+
return cached;
|
|
26
|
+
const pkg = JSON.parse(readFileSync(locate(), "utf8"));
|
|
27
|
+
cached = pkg.version ?? "0.0.0";
|
|
28
|
+
return cached;
|
|
29
|
+
}
|
package/dist/lib/vite-node.d.ts
CHANGED
package/dist/lib/vite-node.js
CHANGED
package/dist/load-config.d.ts
CHANGED
|
@@ -24,4 +24,3 @@ export interface NwireConfig {
|
|
|
24
24
|
export declare function defineConfig(cfg: NwireConfig): NwireConfig;
|
|
25
25
|
export declare function loadConfig(cwd: string): Promise<NwireConfig>;
|
|
26
26
|
export declare function resolveAppsEntry(cwd: string, config: NwireConfig): string;
|
|
27
|
-
//# sourceMappingURL=load-config.d.ts.map
|
package/dist/load-config.js
CHANGED
package/dist/ls-runner.d.ts
CHANGED
package/dist/ls-runner.js
CHANGED
|
@@ -1,55 +1,49 @@
|
|
|
1
1
|
// `nwire ls` — list every wire + every action across all apps.
|
|
2
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
3
|
import { relative, resolve } from "node:path";
|
|
3
|
-
import {
|
|
4
|
-
function
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
if (!file.startsWith("run") || !file.endsWith(".ts"))
|
|
14
|
-
continue;
|
|
15
|
-
if (file.endsWith(".d.ts"))
|
|
16
|
-
continue;
|
|
17
|
-
const stem = file.slice(0, -3);
|
|
18
|
-
const variant = stem === "run" ? "" : `.${stem.slice(4)}`;
|
|
19
|
-
wires.push({ wire: `${app}${variant}`, path: resolve(appDir, file) });
|
|
20
|
-
}
|
|
4
|
+
import { detectLayout } from "./lib/layout.js";
|
|
5
|
+
function loadManifest(cwd) {
|
|
6
|
+
const p = resolve(cwd, ".nwire", "manifest.json");
|
|
7
|
+
if (!existsSync(p))
|
|
8
|
+
return undefined;
|
|
9
|
+
try {
|
|
10
|
+
return JSON.parse(readFileSync(p, "utf8"));
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return undefined;
|
|
21
14
|
}
|
|
22
|
-
return wires;
|
|
23
15
|
}
|
|
24
16
|
async function main() {
|
|
25
17
|
const cwd = process.cwd();
|
|
26
|
-
const
|
|
27
|
-
const wires = listWires(appsRoot);
|
|
18
|
+
const layout = detectLayout(cwd);
|
|
28
19
|
console.log("Wires:");
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
console.log(` ${wire.padEnd(28)} ${rel}`);
|
|
20
|
+
if (layout.wires.length === 0) {
|
|
21
|
+
console.log(" (none — add an entry under app/, apps/<name>/, or src/)");
|
|
32
22
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
if (existsSync(appsPath)) {
|
|
37
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
38
|
-
const mod = await import(/* @vite-ignore */ appsPath);
|
|
39
|
-
const apps = mod.allApps ?? mod.apps ?? [];
|
|
40
|
-
console.log("Actions:");
|
|
41
|
-
for (const app of apps) {
|
|
42
|
-
for (const module of app.modules) {
|
|
43
|
-
for (const action of module.manifest.actions ?? []) {
|
|
44
|
-
const label = `${action.name}`.padEnd(40);
|
|
45
|
-
console.log(` ${label} ${app.name}/${module.name}`);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
23
|
+
else {
|
|
24
|
+
for (const w of layout.wires) {
|
|
25
|
+
console.log(` ${w.name.padEnd(28)} ${relative(cwd, w.entry)}`);
|
|
48
26
|
}
|
|
49
27
|
}
|
|
28
|
+
console.log();
|
|
29
|
+
const manifest = loadManifest(cwd);
|
|
30
|
+
if (!manifest) {
|
|
31
|
+
console.log("Actions: (run `nwire cache` to populate)");
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const actions = manifest.actions ?? [];
|
|
35
|
+
if (actions.length === 0) {
|
|
36
|
+
console.log("Actions: (none registered)");
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
console.log("Actions:");
|
|
40
|
+
for (const a of actions) {
|
|
41
|
+
const label = a.name.padEnd(40);
|
|
42
|
+
const owner = a.app && a.module ? `${a.app}/${a.module}` : "";
|
|
43
|
+
console.log(` ${label} ${owner}`);
|
|
44
|
+
}
|
|
50
45
|
}
|
|
51
46
|
main().catch((err) => {
|
|
52
47
|
console.error(err);
|
|
53
48
|
process.exit(1);
|
|
54
49
|
});
|
|
55
|
-
//# sourceMappingURL=ls-runner.js.map
|
package/dist/ui/dev-dashboard.js
CHANGED
|
@@ -50,4 +50,3 @@ export function DevDashboard({ title, subtitle, subscribe, maxLines = 18, }) {
|
|
|
50
50
|
const statusLabel = ready.ready ? "running" : "booting";
|
|
51
51
|
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { borderStyle: "round", borderColor: "cyan", flexDirection: "column", paddingX: 2, children: [_jsxs(Box, { children: [_jsx(Text, { bold: true, color: "cyan", children: title }), subtitle ? _jsx(Text, { dimColor: true, children: ` · ${subtitle}` }) : null] }), _jsxs(Box, { marginTop: 1, children: [_jsx(Box, { width: 10, children: _jsx(Text, { dimColor: true, children: "status" }) }), _jsx(Text, { color: statusColor, children: statusLabel }), ready.url ? _jsx(Text, { dimColor: true, children: ` · ${ready.url}` }) : null, ready.elapsed ? _jsx(Text, { dimColor: true, children: ` · ${ready.elapsed}` }) : null] }), _jsxs(Box, { children: [_jsx(Box, { width: 10, children: _jsx(Text, { dimColor: true, children: "output" }) }), _jsx(Text, { dimColor: true, children: `${counter} line${counter === 1 ? "" : "s"}` })] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Press Ctrl+C to stop." }) })] }), _jsx(Box, { flexDirection: "column", marginTop: 1, marginLeft: 1, children: _jsx(Static, { items: lines, children: (chunk) => (_jsx(Box, { children: _jsx(Text, { color: chunk.stream === "stderr" ? "red" : undefined, children: chunk.text }) }, chunk.id)) }) })] }));
|
|
52
52
|
}
|
|
53
|
-
//# sourceMappingURL=dev-dashboard.js.map
|
package/dist/ui/greeting.d.ts
CHANGED
package/dist/ui/greeting.js
CHANGED
|
@@ -13,4 +13,3 @@ export function Greeting({ project, version }) {
|
|
|
13
13
|
? project.wires.join(", ")
|
|
14
14
|
: "(none detected — expected apps/<name>/{run,main}.ts)" })] }), _jsxs(Box, { children: [_jsx(Box, { width: 10, children: _jsx(Text, { dimColor: true, children: "please" }) }), _jsx(Text, { color: project.hasPlease ? "green" : undefined, children: project.hasPlease ? "ready" : "—" })] }), _jsxs(Box, { children: [_jsx(Box, { width: 10, children: _jsx(Text, { dimColor: true, children: "config" }) }), _jsx(Text, { color: project.hasNwireConfig ? "green" : undefined, children: project.hasNwireConfig ? "nwire.config.ts" : "(default)" })] })] }), _jsxs(Box, { flexDirection: "column", marginTop: 1, marginLeft: 1, children: [_jsx(Text, { dimColor: true, children: "Try:" }), suggestions.map((s) => (_jsxs(Box, { children: [_jsx(Text, { color: "magenta", children: " › " }), _jsx(Text, { children: s })] }, s)))] })] }));
|
|
15
15
|
}
|
|
16
|
-
//# sourceMappingURL=greeting.js.map
|