@nwire/cli 0.9.0 → 0.9.2
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/cli.js +2 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/build.d.ts.map +1 -1
- package/dist/commands/build.js +13 -16
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/cache.d.ts +3 -2
- package/dist/commands/cache.d.ts.map +1 -1
- package/dist/commands/cache.js +7 -16
- package/dist/commands/cache.js.map +1 -1
- package/dist/commands/check.d.ts +10 -2
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +34 -9
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/fmt.d.ts +8 -3
- package/dist/commands/fmt.d.ts.map +1 -1
- package/dist/commands/fmt.js +35 -11
- package/dist/commands/fmt.js.map +1 -1
- package/dist/commands/lint.d.ts +7 -2
- package/dist/commands/lint.d.ts.map +1 -1
- package/dist/commands/lint.js +34 -12
- package/dist/commands/lint.js.map +1 -1
- package/dist/commands/ls.d.ts +1 -0
- package/dist/commands/ls.d.ts.map +1 -1
- package/dist/commands/ls.js +3 -0
- package/dist/commands/ls.js.map +1 -1
- package/dist/commands/mcp.d.ts.map +1 -1
- package/dist/commands/mcp.js +2 -1
- package/dist/commands/mcp.js.map +1 -1
- package/dist/lib/ensure-scan.d.ts +29 -0
- package/dist/lib/ensure-scan.d.ts.map +1 -0
- package/dist/lib/ensure-scan.js +42 -0
- package/dist/lib/ensure-scan.js.map +1 -0
- package/dist/lib/layout.d.ts +41 -0
- package/dist/lib/layout.d.ts.map +1 -0
- package/dist/lib/layout.js +129 -0
- package/dist/lib/layout.js.map +1 -0
- package/dist/lib/package-manager.d.ts +18 -0
- package/dist/lib/package-manager.d.ts.map +1 -0
- package/dist/lib/package-manager.js +68 -0
- package/dist/lib/package-manager.js.map +1 -0
- package/dist/lib/project.d.ts +3 -3
- package/dist/lib/project.d.ts.map +1 -1
- package/dist/lib/project.js +16 -33
- package/dist/lib/project.js.map +1 -1
- package/dist/lib/scan-cache.d.ts +28 -0
- package/dist/lib/scan-cache.d.ts.map +1 -0
- package/dist/lib/scan-cache.js +103 -0
- package/dist/lib/scan-cache.js.map +1 -0
- package/dist/lib/script-runner.d.ts +43 -0
- package/dist/lib/script-runner.d.ts.map +1 -0
- package/dist/lib/script-runner.js +91 -0
- package/dist/lib/script-runner.js.map +1 -0
- package/dist/lib/version.d.ts +9 -0
- package/dist/lib/version.d.ts.map +1 -0
- package/dist/lib/version.js +30 -0
- package/dist/lib/version.js.map +1 -0
- package/dist/ls-runner.js +34 -39
- package/dist/ls-runner.js.map +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,41 @@
|
|
|
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;
|
|
41
|
+
//# sourceMappingURL=layout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../src/lib/layout.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,MAAM,WAAW,IAAI;IACnB,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,CAAC;IAChC,+CAA+C;IAC/C,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,gFAAgF;IAChF,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAyED,wBAAgB,YAAY,CAAC,GAAG,GAAE,MAAsB,GAAG,aAAa,CAiCvE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEnF"}
|
|
@@ -0,0 +1,129 @@
|
|
|
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
|
+
}
|
|
129
|
+
//# sourceMappingURL=layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout.js","sourceRoot":"","sources":["../../src/lib/layout.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
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[]];
|
|
18
|
+
//# sourceMappingURL=package-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-manager.d.ts","sourceRoot":"","sources":["../../src/lib/package-manager.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,CAAC;AAE7D,wBAAgB,oBAAoB,CAAC,GAAG,GAAE,MAAsB,GAAG,cAAc,CAoBhF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CASvF;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,EAAE,EAAE,cAAc,EAClB,GAAG,EAAE,MAAM,EACX,IAAI,GAAE,SAAS,MAAM,EAAO,GAC3B,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAWpB"}
|
|
@@ -0,0 +1,68 @@
|
|
|
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
|
+
}
|
|
68
|
+
//# sourceMappingURL=package-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-manager.js","sourceRoot":"","sources":["../../src/lib/package-manager.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,MAAM,UAAU,oBAAoB,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IAC9D,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;IAC7C,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACxB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAgC,CAAC;YACrF,IAAI,GAAG,CAAC,cAAc,EAAE,CAAC;gBACvB,IAAI,GAAG,CAAC,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC;oBAAE,OAAO,MAAM,CAAC;gBACzD,IAAI,GAAG,CAAC,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC;oBAAE,OAAO,MAAM,CAAC;gBACzD,IAAI,GAAG,CAAC,cAAc,CAAC,UAAU,CAAC,KAAK,CAAC;oBAAE,OAAO,KAAK,CAAC;gBACvD,IAAI,GAAG,CAAC,cAAc,CAAC,UAAU,CAAC,KAAK,CAAC;oBAAE,OAAO,KAAK,CAAC;YACzD,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,qCAAqC;QACvC,CAAC;IACH,CAAC;IACD,IAAI,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC;IAC9D,IAAI,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC;IACzD,IAAI,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACxD,IAAI,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,mBAAmB,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAChE,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,EAAkB,EAAE,MAAc;IACjE,QAAQ,EAAE,EAAE,CAAC;QACX,KAAK,MAAM,CAAC;QACZ,KAAK,MAAM,CAAC;QACZ,KAAK,KAAK;YACR,OAAO,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;QAC/B,KAAK,KAAK;YACR,OAAO,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;IACpC,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,EAAkB,EAClB,GAAW,EACX,OAA0B,EAAE;IAE5B,QAAQ,EAAE,EAAE,CAAC;QACX,KAAK,MAAM;YACT,OAAO,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;QAC1C,KAAK,MAAM;YACT,OAAO,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;QAClC,KAAK,KAAK;YACR,OAAO,CAAC,KAAK,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;QACtC,KAAK,KAAK;YACR,OAAO,CAAC,KAAK,EAAE,CAAC,cAAc,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;IACnD,CAAC;AACH,CAAC"}
|
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;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/lib/project.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/lib/project.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAED,wBAAgB,aAAa,CAAC,GAAG,GAAE,MAAsB,GAAG,WAAW,CA4BtE"}
|
package/dist/lib/project.js
CHANGED
|
@@ -1,50 +1,33 @@
|
|
|
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
|
};
|
package/dist/lib/project.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/lib/project.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/lib/project.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAWxC,MAAM,UAAU,aAAa,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IACvD,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IAEjC,IAAI,IAAI,GAAG,WAAW,CAAC;IACvB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;IAC7C,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACxB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAsB,CAAC;YAC3E,IAAI,GAAG,CAAC,IAAI;gBAAE,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACP,eAAe;QACjB,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;IACrD,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC5C,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CACjC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,CAC1E,CAAC;IAEF,OAAO;QACL,GAAG;QACH,IAAI;QACJ,cAAc,EAAE,CAAC,CAAC,MAAM,CAAC,UAAU;QACnC,KAAK;QACL,SAAS;QACT,SAAS;KACV,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
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;
|
|
28
|
+
//# sourceMappingURL=scan-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan-cache.d.ts","sourceRoot":"","sources":["../../src/lib/scan-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAyBH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAoB/C;AAUD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAS/D;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CASjE;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,GAAG,OAAO,CAKxE"}
|
|
@@ -0,0 +1,103 @@
|
|
|
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
|
|
103
|
+
//# sourceMappingURL=scan-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan-cache.js","sourceRoot":"","sources":["../../src/lib/scan-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
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 {};
|
|
43
|
+
//# sourceMappingURL=script-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"script-runner.d.ts","sourceRoot":"","sources":["../../src/lib/script-runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAaH,UAAU,cAAc;IACtB,wCAAwC;IACxC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,2DAA2D;IAC3D,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,cAAc;IAC7B,sDAAsD;IACtD,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,yEAAyE;IACzE,QAAQ,CAAC,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChD,oDAAoD;IACpD,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IAC9C,mEAAmE;IACnE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAyED,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,cAAc,GACvB,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,OAAO,CAAA;CAAE,CAAC,CAWzC"}
|