remnem 0.1.8 → 0.1.10
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/README.md +63 -67
- package/bin/remnem.js +77 -194
- package/package.json +14 -39
- package/index.d.ts +0 -68
- package/index.js +0 -591
package/README.md
CHANGED
|
@@ -1,33 +1,51 @@
|
|
|
1
1
|
# remnem
|
|
2
2
|
|
|
3
|
-
**r**e**m**ove **n**ode_**m**odules — find every nested `node_modules` in a project (root + all workspaces + any nested ones) and delete them all,
|
|
3
|
+
**r**e**m**ove **n**ode_**m**odules — find every nested `node_modules` in a project (root + all workspaces + any nested ones) and delete them all, **instantly**.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
A single self-contained CLI written in **Rust**: a lean, parallel, directory-only walker finds every `node_modules`, then each one is disposed of by an **O(1) rename** rather than a slow recursive unlink — so clearing a 1000-package monorepo takes a couple hundred milliseconds instead of tens of seconds.
|
|
6
6
|
|
|
7
7
|
```
|
|
8
8
|
$ remnem
|
|
9
9
|
root: /Users/you/dev/my-monorepo
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
10
|
+
found 1947 node_modules:
|
|
11
|
+
node_modules
|
|
12
|
+
apps/web/node_modules
|
|
13
|
+
...
|
|
14
|
+
permanently delete these 1947 directories? [y/N] y
|
|
15
|
+
|
|
16
|
+
deleted: 1947/1947 node_modules in 130ms
|
|
17
|
+
(space is being reclaimed in the background)
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
##
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
20
|
+
## How it's instant
|
|
21
|
+
|
|
22
|
+
Physically deleting `node_modules` means unlinking hundreds of thousands of
|
|
23
|
+
files — that is I/O-bound and unavoidably slow (tens of seconds on a big
|
|
24
|
+
monorepo). remnem sidesteps that on the critical path:
|
|
25
|
+
|
|
26
|
+
1. **Find** — a parallel, directory-only walk. It reads directory entries via
|
|
27
|
+
`readdir`'s `d_type` (no per-file `stat`), never looks at regular files, and
|
|
28
|
+
never descends *into* a `node_modules` (the whole subtree is going anyway).
|
|
29
|
+
So the walk is proportional to your *source* tree, not the installed
|
|
30
|
+
dependency tree.
|
|
31
|
+
2. **Rename out of the repo** — each `node_modules` is `rename`d out of the
|
|
32
|
+
repository entirely, into a per-run staging directory under the OS temp dir
|
|
33
|
+
(`$TMPDIR/remnem-<pid>/`). On one filesystem that is an O(1) metadata
|
|
34
|
+
operation no matter how large the tree is. The instant it returns,
|
|
35
|
+
`node_modules` is gone from its location — **a clean reinstall can start
|
|
36
|
+
immediately** — and because the staged copy lives outside the repo, it can
|
|
37
|
+
never be picked up by `git status` / `git add`.
|
|
38
|
+
3. **Reclaim in the background** — a detached background process `rm -rf`s the
|
|
39
|
+
staging directory, so the disk-freeing I/O never blocks you. Space comes back
|
|
40
|
+
within a few seconds, hands-free.
|
|
41
|
+
|
|
42
|
+
Pass **`--sync`** if you'd rather block until the space is actually reclaimed
|
|
43
|
+
(e.g. a script that measures free disk right after) — that mode deletes in place
|
|
44
|
+
instead of staging.
|
|
45
|
+
|
|
46
|
+
If the OS temp dir happens to be on a *different* filesystem than the repo (so a
|
|
47
|
+
`rename` would need a slow cross-device copy), remnem detects it and falls back
|
|
48
|
+
to a synchronous in-place delete — still never leaving anything in the tree.
|
|
31
49
|
|
|
32
50
|
## Install
|
|
33
51
|
|
|
@@ -36,36 +54,29 @@ npm install -g remnem
|
|
|
36
54
|
# or: bun install -g remnem
|
|
37
55
|
```
|
|
38
56
|
|
|
39
|
-
The right prebuilt
|
|
40
|
-
|
|
41
|
-
|
|
57
|
+
The right prebuilt binary is pulled in automatically for your platform via
|
|
58
|
+
`optionalDependencies` — the main `remnem` package is a tiny launcher that execs
|
|
59
|
+
it. Supported: **macOS** (arm64, x64), **Linux** (arm64 & x64, glibc & musl),
|
|
60
|
+
**Windows** (arm64, x64).
|
|
42
61
|
|
|
43
62
|
Then from any repo root:
|
|
44
63
|
|
|
45
64
|
```sh
|
|
46
|
-
remnem
|
|
65
|
+
remnem # or: npx remnem / bunx remnem
|
|
47
66
|
```
|
|
48
67
|
|
|
49
68
|
### From source
|
|
50
69
|
|
|
51
70
|
```sh
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
bun link # makes `remnem` available on your PATH
|
|
71
|
+
cargo build --release # produces target/release/remnem
|
|
72
|
+
./target/release/remnem --help
|
|
55
73
|
```
|
|
56
74
|
|
|
57
75
|
## What it clears
|
|
58
76
|
|
|
59
77
|
**Every `node_modules` directory** under the given root — the root's own, every
|
|
60
78
|
workspace package's, and any stray nested ones — leaving all your source and
|
|
61
|
-
`package.json` files untouched.
|
|
62
|
-
`node_modules` (the whole subtree is going to be removed anyway), so it stays
|
|
63
|
-
fast even on trees with hundreds of thousands of files.
|
|
64
|
-
|
|
65
|
-
Workspace resolution (reading `package.json#workspaces` for bun/npm/yarn, or
|
|
66
|
-
`pnpm-workspace.yaml#packages` for pnpm) is used to **report** the workspace
|
|
67
|
-
layout; clearing always targets every nested `node_modules`, not only workspace
|
|
68
|
-
packages.
|
|
79
|
+
`package.json` files untouched.
|
|
69
80
|
|
|
70
81
|
## Usage
|
|
71
82
|
|
|
@@ -76,22 +87,26 @@ Arguments:
|
|
|
76
87
|
path Project root to clean (default: current directory)
|
|
77
88
|
|
|
78
89
|
Options:
|
|
79
|
-
-t, --trash Move to the Trash instead of deleting (instant, recoverable)
|
|
80
90
|
-l, --list List what would be cleared; touch nothing
|
|
81
|
-
|
|
91
|
+
-m, --measure Size each node_modules (slow: walks every dependency tree)
|
|
92
|
+
-w, --workspace Also resolve & report the bun/pnpm workspace layout (slow)
|
|
93
|
+
--sync Wait for the disk space to actually free before returning
|
|
82
94
|
--json Print the raw result as JSON
|
|
83
95
|
-y, --yes Skip the confirmation prompt
|
|
84
96
|
-h, --help Show this help
|
|
85
97
|
```
|
|
86
98
|
|
|
87
|
-
By default `remnem`
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
99
|
+
By default `remnem` deletes each `node_modules` after printing what it found and
|
|
100
|
+
asking for confirmation (skipped with `-y`, or when stdin isn't a TTY, e.g. in
|
|
101
|
+
CI). Use `-l` to list without touching anything, or `--sync` to wait for the
|
|
102
|
+
space to be reclaimed before returning.
|
|
91
103
|
|
|
92
|
-
|
|
104
|
+
Sizing (`-m`) and workspace-layout resolution (`-w`) each require an extra tree
|
|
105
|
+
walk, so they are **off by default** — the fast path does neither.
|
|
93
106
|
|
|
94
|
-
|
|
107
|
+
## Workspace resolution (`-w`)
|
|
108
|
+
|
|
109
|
+
With `-w`, `remnem` reports the workspace layout the way bun and pnpm resolve it:
|
|
95
110
|
|
|
96
111
|
| Source | Field | Example |
|
|
97
112
|
| --- | --- | --- |
|
|
@@ -108,34 +123,15 @@ matcher bun/npm/yarn use):
|
|
|
108
123
|
- `!pattern` excludes previously-matched directories (`!**/test/**` drops a
|
|
109
124
|
directory named `test` and its contents)
|
|
110
125
|
|
|
111
|
-
|
|
112
|
-
`
|
|
113
|
-
|
|
114
|
-
## API
|
|
115
|
-
|
|
116
|
-
The napi-rs core is also usable directly from JavaScript:
|
|
117
|
-
|
|
118
|
-
```js
|
|
119
|
-
const { clean, resolveWorkspace } = require("remnem");
|
|
120
|
-
|
|
121
|
-
// Clear every nested node_modules under a root.
|
|
122
|
-
// trash: false (default) → permanent parallel delete; true → move to Trash.
|
|
123
|
-
const result = clean({ root: "/path/to/repo", dryRun: false, measure: true, trash: false });
|
|
124
|
-
// → { root, workspaceKind, workspacePackages, cleaned: [{ path, bytes, deleted, trashed, error }], totalBytes, count, failed }
|
|
125
|
-
|
|
126
|
-
// Just inspect how bun/pnpm would see the workspace (no deletion).
|
|
127
|
-
const ws = resolveWorkspace("/path/to/repo");
|
|
128
|
-
// → { workspaceKind: "pnpm" | "package.json" | "none", workspacePackages: [...] }
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
See `index.d.ts` for the full typed surface.
|
|
126
|
+
This is purely informational: clearing always targets every nested
|
|
127
|
+
`node_modules`, not only workspace packages.
|
|
132
128
|
|
|
133
129
|
## Development
|
|
134
130
|
|
|
135
131
|
```sh
|
|
136
132
|
cargo test # Rust unit tests (workspace resolution + glob semantics)
|
|
137
|
-
|
|
138
|
-
|
|
133
|
+
cargo build --release # release build (LTO)
|
|
134
|
+
node __test__/smoke.mjs ./target/release/remnem # end-to-end smoke test
|
|
139
135
|
```
|
|
140
136
|
|
|
141
137
|
## License
|
package/bin/remnem.js
CHANGED
|
@@ -1,213 +1,96 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
json: false,
|
|
38
|
-
yes: false,
|
|
39
|
-
help: false,
|
|
40
|
-
};
|
|
41
|
-
for (let i = 0; i < argv.length; i++) {
|
|
42
|
-
const arg = argv[i];
|
|
43
|
-
switch (arg) {
|
|
44
|
-
case "-h":
|
|
45
|
-
case "--help":
|
|
46
|
-
opts.help = true;
|
|
47
|
-
break;
|
|
48
|
-
case "-l":
|
|
49
|
-
case "--list":
|
|
50
|
-
opts.list = true;
|
|
51
|
-
break;
|
|
52
|
-
case "-t":
|
|
53
|
-
case "--trash":
|
|
54
|
-
opts.trash = true;
|
|
55
|
-
break;
|
|
56
|
-
case "--no-measure":
|
|
57
|
-
opts.measure = false;
|
|
58
|
-
break;
|
|
59
|
-
case "--measure":
|
|
60
|
-
opts.measure = true;
|
|
61
|
-
break;
|
|
62
|
-
case "--json":
|
|
63
|
-
opts.json = true;
|
|
64
|
-
break;
|
|
65
|
-
case "-y":
|
|
66
|
-
case "--yes":
|
|
67
|
-
opts.yes = true;
|
|
68
|
-
break;
|
|
69
|
-
default:
|
|
70
|
-
if (arg.startsWith("-")) {
|
|
71
|
-
process.stderr.write(`remnem: unknown option ${arg}\n\n${HELP}`);
|
|
72
|
-
process.exit(2);
|
|
73
|
-
}
|
|
74
|
-
if (opts.root !== undefined) {
|
|
75
|
-
process.stderr.write(`remnem: unexpected extra argument ${arg}\n`);
|
|
76
|
-
process.exit(2);
|
|
77
|
-
}
|
|
78
|
-
opts.root = arg;
|
|
4
|
+
// Thin launcher. remnem ships as a compiled Rust binary, one per platform, in an
|
|
5
|
+
// optional dependency package (@leonsilicon/remnem-<platform>). This shim
|
|
6
|
+
// resolves the binary for the current platform and hands off to it with the same
|
|
7
|
+
// argv, stdio, and exit code — so `remnem` behaves exactly like the native
|
|
8
|
+
// executable while still installing through npm's platform-package mechanism.
|
|
9
|
+
|
|
10
|
+
const { spawnSync } = require("child_process");
|
|
11
|
+
const { existsSync } = require("fs");
|
|
12
|
+
const { join } = require("path");
|
|
13
|
+
|
|
14
|
+
// Map Node's platform/arch to the npm sub-package that carries the binary. Keep
|
|
15
|
+
// this in sync with the `optionalDependencies` in package.json and the `npm/*`
|
|
16
|
+
// package directories.
|
|
17
|
+
const PACKAGES = {
|
|
18
|
+
"darwin-arm64": "@leonsilicon/remnem-darwin-arm64",
|
|
19
|
+
"darwin-x64": "@leonsilicon/remnem-darwin-x64",
|
|
20
|
+
"linux-arm64-gnu": "@leonsilicon/remnem-linux-arm64-gnu",
|
|
21
|
+
"linux-arm64-musl": "@leonsilicon/remnem-linux-arm64-musl",
|
|
22
|
+
"linux-x64-gnu": "@leonsilicon/remnem-linux-x64-gnu",
|
|
23
|
+
"linux-x64-musl": "@leonsilicon/remnem-linux-x64-musl",
|
|
24
|
+
"win32-arm64-msvc": "@leonsilicon/remnem-win32-arm64-msvc",
|
|
25
|
+
"win32-x64-msvc": "@leonsilicon/remnem-win32-x64-msvc",
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// On Linux, tell glibc from musl so we pick the matching binary package.
|
|
29
|
+
function isMusl() {
|
|
30
|
+
if (process.platform !== "linux") return false;
|
|
31
|
+
try {
|
|
32
|
+
// `process.report` exposes the runtime's libc in its header on modern Node.
|
|
33
|
+
if (process.report && typeof process.report.getReport === "function") {
|
|
34
|
+
const report = process.report.getReport();
|
|
35
|
+
const header = report.header || {};
|
|
36
|
+
if (typeof header.glibcVersionRuntime === "string") return false;
|
|
79
37
|
}
|
|
80
|
-
}
|
|
81
|
-
return opts;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
function formatBytes(n) {
|
|
85
|
-
const bytes = typeof n === "bigint" ? Number(n) : n;
|
|
86
|
-
if (!bytes) return "0 B";
|
|
87
|
-
const units = ["B", "KB", "MB", "GB", "TB"];
|
|
88
|
-
const exp = Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), units.length - 1);
|
|
89
|
-
const value = bytes / 1024 ** exp;
|
|
90
|
-
return `${value.toFixed(value >= 10 || exp === 0 ? 0 : 1)} ${units[exp]}`;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function relativizePath(root, p) {
|
|
94
|
-
if (p === root) return ".";
|
|
95
|
-
if (p.startsWith(root + "/")) return p.slice(root.length + 1);
|
|
96
|
-
return p;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Confirmation prompt (synchronous) so a bare `remnem` in a real repo can't nuke
|
|
100
|
-
// node_modules by a stray keystroke. Skipped with -y, with --list, or when not
|
|
101
|
-
// attached to a TTY (CI / piped).
|
|
102
|
-
function confirm(question) {
|
|
103
|
-
if (!process.stdin.isTTY) return true;
|
|
104
|
-
const fs = require("fs");
|
|
105
|
-
process.stdout.write(question);
|
|
106
|
-
const buf = Buffer.alloc(64);
|
|
107
|
-
let bytesRead = 0;
|
|
38
|
+
} catch {}
|
|
108
39
|
try {
|
|
109
|
-
|
|
40
|
+
// Fallback: the ldd on musl systems mentions musl.
|
|
41
|
+
return require("fs").readFileSync("/usr/bin/ldd", "utf8").includes("musl");
|
|
110
42
|
} catch {
|
|
43
|
+
// Default to gnu; if wrong the resolution below fails loudly with guidance.
|
|
111
44
|
return false;
|
|
112
45
|
}
|
|
113
|
-
const answer = buf.toString("utf8", 0, bytesRead).trim().toLowerCase();
|
|
114
|
-
return answer === "y" || answer === "yes";
|
|
115
46
|
}
|
|
116
47
|
|
|
117
|
-
function
|
|
118
|
-
const
|
|
119
|
-
if (
|
|
120
|
-
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// Phase 1: dry-run scan so we can show the user exactly what will go, then
|
|
125
|
-
// (unless -y / non-TTY) confirm before the real deletion.
|
|
126
|
-
const scan = clean({ root: opts.root, dryRun: true, measure: opts.measure });
|
|
127
|
-
|
|
128
|
-
const kindLabel =
|
|
129
|
-
scan.workspaceKind === "none"
|
|
130
|
-
? "no workspace config"
|
|
131
|
-
: `${scan.workspaceKind} workspace (${scan.workspacePackages.length} package${
|
|
132
|
-
scan.workspacePackages.length === 1 ? "" : "s"
|
|
133
|
-
})`;
|
|
134
|
-
|
|
135
|
-
if (opts.json && opts.list) {
|
|
136
|
-
process.stdout.write(JSON.stringify(scan, replacer, 2) + "\n");
|
|
137
|
-
return;
|
|
48
|
+
function platformKey() {
|
|
49
|
+
const { platform, arch } = process;
|
|
50
|
+
if (platform === "linux") {
|
|
51
|
+
return `linux-${arch}-${isMusl() ? "musl" : "gnu"}`;
|
|
138
52
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
process.stdout.write(`remnem: no node_modules found under ${scan.root} (${kindLabel})\n`);
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
process.stdout.write(`root: ${scan.root}\n`);
|
|
146
|
-
process.stdout.write(` ${kindLabel}\n`);
|
|
147
|
-
process.stdout.write(
|
|
148
|
-
`found ${scan.count} node_modules${
|
|
149
|
-
opts.measure ? ` totalling ${formatBytes(scan.totalBytes)}` : ""
|
|
150
|
-
}:\n`,
|
|
151
|
-
);
|
|
152
|
-
for (const dir of scan.cleaned) {
|
|
153
|
-
const size = opts.measure ? ` ${formatBytes(dir.bytes).padStart(8)}` : "";
|
|
154
|
-
process.stdout.write(`${size} ${relativizePath(scan.root, dir.path)}\n`);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
if (opts.list) {
|
|
158
|
-
process.stdout.write(`\n(list only — nothing ${opts.trash ? "trashed" : "deleted"})\n`);
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const verb = opts.trash ? "move to Trash" : "permanently delete";
|
|
163
|
-
if (!opts.yes && !confirm(`\n${verb} these ${scan.count} directories? [y/N] `)) {
|
|
164
|
-
process.stdout.write("aborted.\n");
|
|
165
|
-
process.exit(1);
|
|
53
|
+
if (platform === "win32") {
|
|
54
|
+
return `win32-${arch}-msvc`;
|
|
166
55
|
}
|
|
56
|
+
return `${platform}-${arch}`;
|
|
57
|
+
}
|
|
167
58
|
|
|
168
|
-
|
|
169
|
-
const
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
if (opts.json) {
|
|
174
|
-
process.stdout.write(JSON.stringify(result, replacer, 2) + "\n");
|
|
175
|
-
return;
|
|
59
|
+
function resolveBinary() {
|
|
60
|
+
const key = platformKey();
|
|
61
|
+
const pkg = PACKAGES[key];
|
|
62
|
+
if (!pkg) {
|
|
63
|
+
return { error: `remnem: unsupported platform ${process.platform}-${process.arch}` };
|
|
176
64
|
}
|
|
65
|
+
const exe = process.platform === "win32" ? "remnem.exe" : "remnem";
|
|
177
66
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
`\n${action}: ${done}/${result.count} node_modules${
|
|
193
|
-
opts.measure ? ` (${formatBytes(scan.totalBytes)})` : ""
|
|
194
|
-
} in ${elapsedMs.toFixed(0)}ms\n`,
|
|
195
|
-
);
|
|
196
|
-
if (opts.trash && trashedCount > 0) {
|
|
197
|
-
process.stdout.write(`empty the Trash to reclaim the space (or re-run without -t to delete).\n`);
|
|
198
|
-
}
|
|
199
|
-
if (result.failed > 0) {
|
|
200
|
-
for (const dir of result.cleaned) {
|
|
201
|
-
if (dir.error) {
|
|
202
|
-
process.stderr.write(` failed: ${relativizePath(result.root, dir.path)} — ${dir.error}\n`);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
process.exit(1);
|
|
206
|
-
}
|
|
67
|
+
// Prefer resolving through the package's own manifest so we find it wherever
|
|
68
|
+
// the package manager placed it (hoisted, nested, pnpm store, etc.).
|
|
69
|
+
try {
|
|
70
|
+
const manifest = require.resolve(`${pkg}/package.json`);
|
|
71
|
+
const binPath = join(manifest, "..", exe);
|
|
72
|
+
if (existsSync(binPath)) return { binPath };
|
|
73
|
+
} catch {}
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
error:
|
|
77
|
+
`remnem: could not find the ${pkg} package for your platform.\n` +
|
|
78
|
+
`Install it with your package manager, or reinstall remnem so npm can pull the\n` +
|
|
79
|
+
`matching optional dependency (${pkg}).`,
|
|
80
|
+
};
|
|
207
81
|
}
|
|
208
82
|
|
|
209
|
-
|
|
210
|
-
|
|
83
|
+
const { binPath, error } = resolveBinary();
|
|
84
|
+
if (error) {
|
|
85
|
+
process.stderr.write(error + "\n");
|
|
86
|
+
process.exit(1);
|
|
211
87
|
}
|
|
212
88
|
|
|
213
|
-
|
|
89
|
+
// Hand off: inherit stdio so the interactive confirmation prompt and all output
|
|
90
|
+
// pass straight through, and propagate the binary's exit code.
|
|
91
|
+
const result = spawnSync(binPath, process.argv.slice(2), { stdio: "inherit" });
|
|
92
|
+
if (result.error) {
|
|
93
|
+
process.stderr.write(`remnem: failed to run ${binPath}: ${result.error.message}\n`);
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
process.exit(result.status === null ? 1 : result.status);
|
package/package.json
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "remnem",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Find and delete every nested node_modules in a project as fast as possible (
|
|
3
|
+
"version": "0.1.10",
|
|
4
|
+
"description": "Find and delete every nested node_modules in a project as fast as possible (Rust binary)",
|
|
5
5
|
"type": "commonjs",
|
|
6
|
-
"main": "index.js",
|
|
7
|
-
"types": "index.d.ts",
|
|
8
6
|
"license": "MIT",
|
|
9
7
|
"author": "Leon Si",
|
|
10
8
|
"homepage": "https://github.com/leonsilicon/remnem#readme",
|
|
@@ -22,7 +20,6 @@
|
|
|
22
20
|
"clean",
|
|
23
21
|
"cleaner",
|
|
24
22
|
"delete",
|
|
25
|
-
"napi-rs",
|
|
26
23
|
"rust",
|
|
27
24
|
"bun",
|
|
28
25
|
"pnpm"
|
|
@@ -31,52 +28,30 @@
|
|
|
31
28
|
"remnem": "bin/remnem.js"
|
|
32
29
|
},
|
|
33
30
|
"files": [
|
|
34
|
-
"index.js",
|
|
35
|
-
"index.d.ts",
|
|
36
31
|
"bin/remnem.js",
|
|
37
32
|
"README.md",
|
|
38
33
|
"LICENSE"
|
|
39
34
|
],
|
|
40
|
-
"napi": {
|
|
41
|
-
"binaryName": "remnem",
|
|
42
|
-
"targets": [
|
|
43
|
-
"x86_64-apple-darwin",
|
|
44
|
-
"aarch64-apple-darwin",
|
|
45
|
-
"x86_64-unknown-linux-gnu",
|
|
46
|
-
"aarch64-unknown-linux-gnu",
|
|
47
|
-
"x86_64-unknown-linux-musl",
|
|
48
|
-
"aarch64-unknown-linux-musl",
|
|
49
|
-
"x86_64-pc-windows-msvc",
|
|
50
|
-
"aarch64-pc-windows-msvc"
|
|
51
|
-
],
|
|
52
|
-
"packageName": "@leonsilicon/remnem"
|
|
53
|
-
},
|
|
54
35
|
"engines": {
|
|
55
36
|
"node": ">= 18"
|
|
56
37
|
},
|
|
57
38
|
"optionalDependencies": {
|
|
58
|
-
"@leonsilicon/remnem-darwin-x64": "0.1.
|
|
59
|
-
"@leonsilicon/remnem-darwin-arm64": "0.1.
|
|
60
|
-
"@leonsilicon/remnem-linux-x64-gnu": "0.1.
|
|
61
|
-
"@leonsilicon/remnem-linux-arm64-gnu": "0.1.
|
|
62
|
-
"@leonsilicon/remnem-linux-x64-musl": "0.1.
|
|
63
|
-
"@leonsilicon/remnem-linux-arm64-musl": "0.1.
|
|
64
|
-
"@leonsilicon/remnem-win32-x64-msvc": "0.1.
|
|
65
|
-
"@leonsilicon/remnem-win32-arm64-msvc": "0.1.
|
|
39
|
+
"@leonsilicon/remnem-darwin-x64": "0.1.10",
|
|
40
|
+
"@leonsilicon/remnem-darwin-arm64": "0.1.10",
|
|
41
|
+
"@leonsilicon/remnem-linux-x64-gnu": "0.1.10",
|
|
42
|
+
"@leonsilicon/remnem-linux-arm64-gnu": "0.1.10",
|
|
43
|
+
"@leonsilicon/remnem-linux-x64-musl": "0.1.10",
|
|
44
|
+
"@leonsilicon/remnem-linux-arm64-musl": "0.1.10",
|
|
45
|
+
"@leonsilicon/remnem-win32-x64-msvc": "0.1.10",
|
|
46
|
+
"@leonsilicon/remnem-win32-arm64-msvc": "0.1.10"
|
|
66
47
|
},
|
|
67
48
|
"publishConfig": {
|
|
68
49
|
"access": "public",
|
|
69
50
|
"provenance": true
|
|
70
51
|
},
|
|
71
52
|
"scripts": {
|
|
72
|
-
"build": "
|
|
73
|
-
"
|
|
74
|
-
"artifacts": "napi artifacts",
|
|
75
|
-
"prepublishOnly": "napi prepublish -t npm",
|
|
76
|
-
"test": "cargo test",
|
|
77
|
-
"version": "napi version"
|
|
53
|
+
"build": "cargo build --release",
|
|
54
|
+
"test": "cargo test"
|
|
78
55
|
},
|
|
79
|
-
"devDependencies": {
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
}
|
|
56
|
+
"devDependencies": {}
|
|
57
|
+
}
|
package/index.d.ts
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
/* auto-generated by NAPI-RS */
|
|
2
|
-
/* eslint-disable */
|
|
3
|
-
/**
|
|
4
|
-
* Find every nested `node_modules` under `root` and (unless `dry_run`) delete
|
|
5
|
-
* them in parallel. Returns a structured summary.
|
|
6
|
-
*/
|
|
7
|
-
export declare function clean(options?: CleanOptions | undefined | null): CleanResult
|
|
8
|
-
|
|
9
|
-
/** A single deleted (or would-be-deleted) `node_modules` directory. */
|
|
10
|
-
export interface CleanedDir {
|
|
11
|
-
path: string
|
|
12
|
-
/** Bytes the directory held (0 when `measure` is false). */
|
|
13
|
-
bytes: bigint
|
|
14
|
-
/** `true` if this directory was (or would be) disposed of successfully. */
|
|
15
|
-
deleted: boolean
|
|
16
|
-
/** `true` if it was moved to the Trash (vs. permanently removed). */
|
|
17
|
-
trashed: boolean
|
|
18
|
-
/** Error message if disposal failed. */
|
|
19
|
-
error?: string
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/** Options for [`clean`]. */
|
|
23
|
-
export interface CleanOptions {
|
|
24
|
-
/** Project root to clean. Defaults to the current working directory. */
|
|
25
|
-
root?: string
|
|
26
|
-
/** When `true`, only find (do not delete). Defaults to `false`. */
|
|
27
|
-
dryRun?: boolean
|
|
28
|
-
/**
|
|
29
|
-
* When `true`, measure the on-disk size of each `node_modules` before
|
|
30
|
-
* deleting (a second parallel pass). Defaults to `true`.
|
|
31
|
-
*/
|
|
32
|
-
measure?: boolean
|
|
33
|
-
/**
|
|
34
|
-
* When `true`, move each `node_modules` to the OS Trash — a same-volume
|
|
35
|
-
* rename, effectively instant, recoverable in Finder; space is reclaimed
|
|
36
|
-
* when the Trash is emptied. When `false` (the default), permanently
|
|
37
|
-
* `remove_dir_all` them in parallel (reclaims space immediately, not
|
|
38
|
-
* recoverable).
|
|
39
|
-
*/
|
|
40
|
-
trash?: boolean
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/** Result of a [`clean`] run. */
|
|
44
|
-
export interface CleanResult {
|
|
45
|
-
/** Absolute project root that was cleaned. */
|
|
46
|
-
root: string
|
|
47
|
-
/** Which workspace manifest drove resolution: `"none" | "package.json" | "pnpm"`. */
|
|
48
|
-
workspaceKind: string
|
|
49
|
-
/**
|
|
50
|
-
* Resolved workspace-package directories (absolute paths). Informational —
|
|
51
|
-
* deletion targets every nested `node_modules`, not just these.
|
|
52
|
-
*/
|
|
53
|
-
workspacePackages: Array<string>
|
|
54
|
-
/** Every `node_modules` directory found (and, unless `dry_run`, deleted). */
|
|
55
|
-
cleaned: Array<CleanedDir>
|
|
56
|
-
/** Total bytes across all found directories (0 when `measure` is false). */
|
|
57
|
-
totalBytes: bigint
|
|
58
|
-
/** Total directories found. */
|
|
59
|
-
count: number
|
|
60
|
-
/** Directories that failed to delete. */
|
|
61
|
-
failed: number
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Resolve workspace layout without deleting anything. Useful for inspecting how
|
|
66
|
-
* bun/pnpm would see the workspace.
|
|
67
|
-
*/
|
|
68
|
-
export declare function resolveWorkspace(root?: string | undefined | null): CleanResult
|
package/index.js
DELETED
|
@@ -1,591 +0,0 @@
|
|
|
1
|
-
// prettier-ignore
|
|
2
|
-
/* eslint-disable */
|
|
3
|
-
// @ts-nocheck
|
|
4
|
-
/* auto-generated by NAPI-RS */
|
|
5
|
-
|
|
6
|
-
const { readFileSync } = require('fs')
|
|
7
|
-
let nativeBinding = null
|
|
8
|
-
const loadErrors = []
|
|
9
|
-
|
|
10
|
-
const isMusl = () => {
|
|
11
|
-
let musl = false
|
|
12
|
-
if (process.platform === 'linux') {
|
|
13
|
-
musl = isMuslFromFilesystem()
|
|
14
|
-
if (musl === null) {
|
|
15
|
-
musl = isMuslFromReport()
|
|
16
|
-
}
|
|
17
|
-
if (musl === null) {
|
|
18
|
-
musl = isMuslFromChildProcess()
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
return musl
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const isFileMusl = (f) => f.includes('libc.musl-') || f.includes('ld-musl-')
|
|
25
|
-
|
|
26
|
-
const isMuslFromFilesystem = () => {
|
|
27
|
-
try {
|
|
28
|
-
return readFileSync('/usr/bin/ldd', 'utf-8').includes('musl')
|
|
29
|
-
} catch {
|
|
30
|
-
return null
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const isMuslFromReport = () => {
|
|
35
|
-
let report = null
|
|
36
|
-
if (process.report && typeof process.report.getReport === 'function') {
|
|
37
|
-
process.report.excludeNetwork = true
|
|
38
|
-
report = process.report.getReport()
|
|
39
|
-
}
|
|
40
|
-
if (!report) {
|
|
41
|
-
return null
|
|
42
|
-
}
|
|
43
|
-
if (report.header && report.header.glibcVersionRuntime) {
|
|
44
|
-
return false
|
|
45
|
-
}
|
|
46
|
-
if (Array.isArray(report.sharedObjects)) {
|
|
47
|
-
if (report.sharedObjects.some(isFileMusl)) {
|
|
48
|
-
return true
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
return false
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const isMuslFromChildProcess = () => {
|
|
55
|
-
try {
|
|
56
|
-
return require('child_process').execSync('ldd --version', { encoding: 'utf8' }).includes('musl')
|
|
57
|
-
} catch (e) {
|
|
58
|
-
// If we reach this case, we don't know if the system is musl or not, so is better to just fallback to false
|
|
59
|
-
return false
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function requireNative() {
|
|
64
|
-
if (process.env.NAPI_RS_NATIVE_LIBRARY_PATH) {
|
|
65
|
-
try {
|
|
66
|
-
return require(process.env.NAPI_RS_NATIVE_LIBRARY_PATH);
|
|
67
|
-
} catch (err) {
|
|
68
|
-
loadErrors.push(err)
|
|
69
|
-
}
|
|
70
|
-
} else if (process.platform === 'android') {
|
|
71
|
-
if (process.arch === 'arm64') {
|
|
72
|
-
try {
|
|
73
|
-
return require('./remnem.android-arm64.node')
|
|
74
|
-
} catch (e) {
|
|
75
|
-
loadErrors.push(e)
|
|
76
|
-
}
|
|
77
|
-
try {
|
|
78
|
-
const binding = require('@leonsilicon/remnem-android-arm64')
|
|
79
|
-
const bindingPackageVersion = require('@leonsilicon/remnem-android-arm64/package.json').version
|
|
80
|
-
if (bindingPackageVersion !== '0.1.8' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
81
|
-
throw new Error(`Native binding package version mismatch, expected 0.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
82
|
-
}
|
|
83
|
-
return binding
|
|
84
|
-
} catch (e) {
|
|
85
|
-
loadErrors.push(e)
|
|
86
|
-
}
|
|
87
|
-
} else if (process.arch === 'arm') {
|
|
88
|
-
try {
|
|
89
|
-
return require('./remnem.android-arm-eabi.node')
|
|
90
|
-
} catch (e) {
|
|
91
|
-
loadErrors.push(e)
|
|
92
|
-
}
|
|
93
|
-
try {
|
|
94
|
-
const binding = require('@leonsilicon/remnem-android-arm-eabi')
|
|
95
|
-
const bindingPackageVersion = require('@leonsilicon/remnem-android-arm-eabi/package.json').version
|
|
96
|
-
if (bindingPackageVersion !== '0.1.8' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
97
|
-
throw new Error(`Native binding package version mismatch, expected 0.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
98
|
-
}
|
|
99
|
-
return binding
|
|
100
|
-
} catch (e) {
|
|
101
|
-
loadErrors.push(e)
|
|
102
|
-
}
|
|
103
|
-
} else {
|
|
104
|
-
loadErrors.push(new Error(`Unsupported architecture on Android ${process.arch}`))
|
|
105
|
-
}
|
|
106
|
-
} else if (process.platform === 'win32') {
|
|
107
|
-
if (process.arch === 'x64') {
|
|
108
|
-
if ((process.config && process.config.variables && process.config.variables.shlib_suffix === 'dll.a') || (process.config && process.config.variables && process.config.variables.node_target_type === 'shared_library')) {
|
|
109
|
-
try {
|
|
110
|
-
return require('./remnem.win32-x64-gnu.node')
|
|
111
|
-
} catch (e) {
|
|
112
|
-
loadErrors.push(e)
|
|
113
|
-
}
|
|
114
|
-
try {
|
|
115
|
-
const binding = require('@leonsilicon/remnem-win32-x64-gnu')
|
|
116
|
-
const bindingPackageVersion = require('@leonsilicon/remnem-win32-x64-gnu/package.json').version
|
|
117
|
-
if (bindingPackageVersion !== '0.1.8' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
118
|
-
throw new Error(`Native binding package version mismatch, expected 0.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
119
|
-
}
|
|
120
|
-
return binding
|
|
121
|
-
} catch (e) {
|
|
122
|
-
loadErrors.push(e)
|
|
123
|
-
}
|
|
124
|
-
} else {
|
|
125
|
-
try {
|
|
126
|
-
return require('./remnem.win32-x64-msvc.node')
|
|
127
|
-
} catch (e) {
|
|
128
|
-
loadErrors.push(e)
|
|
129
|
-
}
|
|
130
|
-
try {
|
|
131
|
-
const binding = require('@leonsilicon/remnem-win32-x64-msvc')
|
|
132
|
-
const bindingPackageVersion = require('@leonsilicon/remnem-win32-x64-msvc/package.json').version
|
|
133
|
-
if (bindingPackageVersion !== '0.1.8' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
134
|
-
throw new Error(`Native binding package version mismatch, expected 0.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
135
|
-
}
|
|
136
|
-
return binding
|
|
137
|
-
} catch (e) {
|
|
138
|
-
loadErrors.push(e)
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
} else if (process.arch === 'ia32') {
|
|
142
|
-
try {
|
|
143
|
-
return require('./remnem.win32-ia32-msvc.node')
|
|
144
|
-
} catch (e) {
|
|
145
|
-
loadErrors.push(e)
|
|
146
|
-
}
|
|
147
|
-
try {
|
|
148
|
-
const binding = require('@leonsilicon/remnem-win32-ia32-msvc')
|
|
149
|
-
const bindingPackageVersion = require('@leonsilicon/remnem-win32-ia32-msvc/package.json').version
|
|
150
|
-
if (bindingPackageVersion !== '0.1.8' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
151
|
-
throw new Error(`Native binding package version mismatch, expected 0.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
152
|
-
}
|
|
153
|
-
return binding
|
|
154
|
-
} catch (e) {
|
|
155
|
-
loadErrors.push(e)
|
|
156
|
-
}
|
|
157
|
-
} else if (process.arch === 'arm64') {
|
|
158
|
-
try {
|
|
159
|
-
return require('./remnem.win32-arm64-msvc.node')
|
|
160
|
-
} catch (e) {
|
|
161
|
-
loadErrors.push(e)
|
|
162
|
-
}
|
|
163
|
-
try {
|
|
164
|
-
const binding = require('@leonsilicon/remnem-win32-arm64-msvc')
|
|
165
|
-
const bindingPackageVersion = require('@leonsilicon/remnem-win32-arm64-msvc/package.json').version
|
|
166
|
-
if (bindingPackageVersion !== '0.1.8' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
167
|
-
throw new Error(`Native binding package version mismatch, expected 0.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
168
|
-
}
|
|
169
|
-
return binding
|
|
170
|
-
} catch (e) {
|
|
171
|
-
loadErrors.push(e)
|
|
172
|
-
}
|
|
173
|
-
} else {
|
|
174
|
-
loadErrors.push(new Error(`Unsupported architecture on Windows: ${process.arch}`))
|
|
175
|
-
}
|
|
176
|
-
} else if (process.platform === 'darwin') {
|
|
177
|
-
try {
|
|
178
|
-
return require('./remnem.darwin-universal.node')
|
|
179
|
-
} catch (e) {
|
|
180
|
-
loadErrors.push(e)
|
|
181
|
-
}
|
|
182
|
-
try {
|
|
183
|
-
const binding = require('@leonsilicon/remnem-darwin-universal')
|
|
184
|
-
const bindingPackageVersion = require('@leonsilicon/remnem-darwin-universal/package.json').version
|
|
185
|
-
if (bindingPackageVersion !== '0.1.8' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
186
|
-
throw new Error(`Native binding package version mismatch, expected 0.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
187
|
-
}
|
|
188
|
-
return binding
|
|
189
|
-
} catch (e) {
|
|
190
|
-
loadErrors.push(e)
|
|
191
|
-
}
|
|
192
|
-
if (process.arch === 'x64') {
|
|
193
|
-
try {
|
|
194
|
-
return require('./remnem.darwin-x64.node')
|
|
195
|
-
} catch (e) {
|
|
196
|
-
loadErrors.push(e)
|
|
197
|
-
}
|
|
198
|
-
try {
|
|
199
|
-
const binding = require('@leonsilicon/remnem-darwin-x64')
|
|
200
|
-
const bindingPackageVersion = require('@leonsilicon/remnem-darwin-x64/package.json').version
|
|
201
|
-
if (bindingPackageVersion !== '0.1.8' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
202
|
-
throw new Error(`Native binding package version mismatch, expected 0.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
203
|
-
}
|
|
204
|
-
return binding
|
|
205
|
-
} catch (e) {
|
|
206
|
-
loadErrors.push(e)
|
|
207
|
-
}
|
|
208
|
-
} else if (process.arch === 'arm64') {
|
|
209
|
-
try {
|
|
210
|
-
return require('./remnem.darwin-arm64.node')
|
|
211
|
-
} catch (e) {
|
|
212
|
-
loadErrors.push(e)
|
|
213
|
-
}
|
|
214
|
-
try {
|
|
215
|
-
const binding = require('@leonsilicon/remnem-darwin-arm64')
|
|
216
|
-
const bindingPackageVersion = require('@leonsilicon/remnem-darwin-arm64/package.json').version
|
|
217
|
-
if (bindingPackageVersion !== '0.1.8' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
218
|
-
throw new Error(`Native binding package version mismatch, expected 0.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
219
|
-
}
|
|
220
|
-
return binding
|
|
221
|
-
} catch (e) {
|
|
222
|
-
loadErrors.push(e)
|
|
223
|
-
}
|
|
224
|
-
} else {
|
|
225
|
-
loadErrors.push(new Error(`Unsupported architecture on macOS: ${process.arch}`))
|
|
226
|
-
}
|
|
227
|
-
} else if (process.platform === 'freebsd') {
|
|
228
|
-
if (process.arch === 'x64') {
|
|
229
|
-
try {
|
|
230
|
-
return require('./remnem.freebsd-x64.node')
|
|
231
|
-
} catch (e) {
|
|
232
|
-
loadErrors.push(e)
|
|
233
|
-
}
|
|
234
|
-
try {
|
|
235
|
-
const binding = require('@leonsilicon/remnem-freebsd-x64')
|
|
236
|
-
const bindingPackageVersion = require('@leonsilicon/remnem-freebsd-x64/package.json').version
|
|
237
|
-
if (bindingPackageVersion !== '0.1.8' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
238
|
-
throw new Error(`Native binding package version mismatch, expected 0.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
239
|
-
}
|
|
240
|
-
return binding
|
|
241
|
-
} catch (e) {
|
|
242
|
-
loadErrors.push(e)
|
|
243
|
-
}
|
|
244
|
-
} else if (process.arch === 'arm64') {
|
|
245
|
-
try {
|
|
246
|
-
return require('./remnem.freebsd-arm64.node')
|
|
247
|
-
} catch (e) {
|
|
248
|
-
loadErrors.push(e)
|
|
249
|
-
}
|
|
250
|
-
try {
|
|
251
|
-
const binding = require('@leonsilicon/remnem-freebsd-arm64')
|
|
252
|
-
const bindingPackageVersion = require('@leonsilicon/remnem-freebsd-arm64/package.json').version
|
|
253
|
-
if (bindingPackageVersion !== '0.1.8' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
254
|
-
throw new Error(`Native binding package version mismatch, expected 0.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
255
|
-
}
|
|
256
|
-
return binding
|
|
257
|
-
} catch (e) {
|
|
258
|
-
loadErrors.push(e)
|
|
259
|
-
}
|
|
260
|
-
} else {
|
|
261
|
-
loadErrors.push(new Error(`Unsupported architecture on FreeBSD: ${process.arch}`))
|
|
262
|
-
}
|
|
263
|
-
} else if (process.platform === 'linux') {
|
|
264
|
-
if (process.arch === 'x64') {
|
|
265
|
-
if (isMusl()) {
|
|
266
|
-
try {
|
|
267
|
-
return require('./remnem.linux-x64-musl.node')
|
|
268
|
-
} catch (e) {
|
|
269
|
-
loadErrors.push(e)
|
|
270
|
-
}
|
|
271
|
-
try {
|
|
272
|
-
const binding = require('@leonsilicon/remnem-linux-x64-musl')
|
|
273
|
-
const bindingPackageVersion = require('@leonsilicon/remnem-linux-x64-musl/package.json').version
|
|
274
|
-
if (bindingPackageVersion !== '0.1.8' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
275
|
-
throw new Error(`Native binding package version mismatch, expected 0.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
276
|
-
}
|
|
277
|
-
return binding
|
|
278
|
-
} catch (e) {
|
|
279
|
-
loadErrors.push(e)
|
|
280
|
-
}
|
|
281
|
-
} else {
|
|
282
|
-
try {
|
|
283
|
-
return require('./remnem.linux-x64-gnu.node')
|
|
284
|
-
} catch (e) {
|
|
285
|
-
loadErrors.push(e)
|
|
286
|
-
}
|
|
287
|
-
try {
|
|
288
|
-
const binding = require('@leonsilicon/remnem-linux-x64-gnu')
|
|
289
|
-
const bindingPackageVersion = require('@leonsilicon/remnem-linux-x64-gnu/package.json').version
|
|
290
|
-
if (bindingPackageVersion !== '0.1.8' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
291
|
-
throw new Error(`Native binding package version mismatch, expected 0.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
292
|
-
}
|
|
293
|
-
return binding
|
|
294
|
-
} catch (e) {
|
|
295
|
-
loadErrors.push(e)
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
} else if (process.arch === 'arm64') {
|
|
299
|
-
if (isMusl()) {
|
|
300
|
-
try {
|
|
301
|
-
return require('./remnem.linux-arm64-musl.node')
|
|
302
|
-
} catch (e) {
|
|
303
|
-
loadErrors.push(e)
|
|
304
|
-
}
|
|
305
|
-
try {
|
|
306
|
-
const binding = require('@leonsilicon/remnem-linux-arm64-musl')
|
|
307
|
-
const bindingPackageVersion = require('@leonsilicon/remnem-linux-arm64-musl/package.json').version
|
|
308
|
-
if (bindingPackageVersion !== '0.1.8' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
309
|
-
throw new Error(`Native binding package version mismatch, expected 0.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
310
|
-
}
|
|
311
|
-
return binding
|
|
312
|
-
} catch (e) {
|
|
313
|
-
loadErrors.push(e)
|
|
314
|
-
}
|
|
315
|
-
} else {
|
|
316
|
-
try {
|
|
317
|
-
return require('./remnem.linux-arm64-gnu.node')
|
|
318
|
-
} catch (e) {
|
|
319
|
-
loadErrors.push(e)
|
|
320
|
-
}
|
|
321
|
-
try {
|
|
322
|
-
const binding = require('@leonsilicon/remnem-linux-arm64-gnu')
|
|
323
|
-
const bindingPackageVersion = require('@leonsilicon/remnem-linux-arm64-gnu/package.json').version
|
|
324
|
-
if (bindingPackageVersion !== '0.1.8' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
325
|
-
throw new Error(`Native binding package version mismatch, expected 0.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
326
|
-
}
|
|
327
|
-
return binding
|
|
328
|
-
} catch (e) {
|
|
329
|
-
loadErrors.push(e)
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
} else if (process.arch === 'arm') {
|
|
333
|
-
if (isMusl()) {
|
|
334
|
-
try {
|
|
335
|
-
return require('./remnem.linux-arm-musleabihf.node')
|
|
336
|
-
} catch (e) {
|
|
337
|
-
loadErrors.push(e)
|
|
338
|
-
}
|
|
339
|
-
try {
|
|
340
|
-
const binding = require('@leonsilicon/remnem-linux-arm-musleabihf')
|
|
341
|
-
const bindingPackageVersion = require('@leonsilicon/remnem-linux-arm-musleabihf/package.json').version
|
|
342
|
-
if (bindingPackageVersion !== '0.1.8' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
343
|
-
throw new Error(`Native binding package version mismatch, expected 0.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
344
|
-
}
|
|
345
|
-
return binding
|
|
346
|
-
} catch (e) {
|
|
347
|
-
loadErrors.push(e)
|
|
348
|
-
}
|
|
349
|
-
} else {
|
|
350
|
-
try {
|
|
351
|
-
return require('./remnem.linux-arm-gnueabihf.node')
|
|
352
|
-
} catch (e) {
|
|
353
|
-
loadErrors.push(e)
|
|
354
|
-
}
|
|
355
|
-
try {
|
|
356
|
-
const binding = require('@leonsilicon/remnem-linux-arm-gnueabihf')
|
|
357
|
-
const bindingPackageVersion = require('@leonsilicon/remnem-linux-arm-gnueabihf/package.json').version
|
|
358
|
-
if (bindingPackageVersion !== '0.1.8' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
359
|
-
throw new Error(`Native binding package version mismatch, expected 0.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
360
|
-
}
|
|
361
|
-
return binding
|
|
362
|
-
} catch (e) {
|
|
363
|
-
loadErrors.push(e)
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
} else if (process.arch === 'loong64') {
|
|
367
|
-
if (isMusl()) {
|
|
368
|
-
try {
|
|
369
|
-
return require('./remnem.linux-loong64-musl.node')
|
|
370
|
-
} catch (e) {
|
|
371
|
-
loadErrors.push(e)
|
|
372
|
-
}
|
|
373
|
-
try {
|
|
374
|
-
const binding = require('@leonsilicon/remnem-linux-loong64-musl')
|
|
375
|
-
const bindingPackageVersion = require('@leonsilicon/remnem-linux-loong64-musl/package.json').version
|
|
376
|
-
if (bindingPackageVersion !== '0.1.8' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
377
|
-
throw new Error(`Native binding package version mismatch, expected 0.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
378
|
-
}
|
|
379
|
-
return binding
|
|
380
|
-
} catch (e) {
|
|
381
|
-
loadErrors.push(e)
|
|
382
|
-
}
|
|
383
|
-
} else {
|
|
384
|
-
try {
|
|
385
|
-
return require('./remnem.linux-loong64-gnu.node')
|
|
386
|
-
} catch (e) {
|
|
387
|
-
loadErrors.push(e)
|
|
388
|
-
}
|
|
389
|
-
try {
|
|
390
|
-
const binding = require('@leonsilicon/remnem-linux-loong64-gnu')
|
|
391
|
-
const bindingPackageVersion = require('@leonsilicon/remnem-linux-loong64-gnu/package.json').version
|
|
392
|
-
if (bindingPackageVersion !== '0.1.8' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
393
|
-
throw new Error(`Native binding package version mismatch, expected 0.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
394
|
-
}
|
|
395
|
-
return binding
|
|
396
|
-
} catch (e) {
|
|
397
|
-
loadErrors.push(e)
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
} else if (process.arch === 'riscv64') {
|
|
401
|
-
if (isMusl()) {
|
|
402
|
-
try {
|
|
403
|
-
return require('./remnem.linux-riscv64-musl.node')
|
|
404
|
-
} catch (e) {
|
|
405
|
-
loadErrors.push(e)
|
|
406
|
-
}
|
|
407
|
-
try {
|
|
408
|
-
const binding = require('@leonsilicon/remnem-linux-riscv64-musl')
|
|
409
|
-
const bindingPackageVersion = require('@leonsilicon/remnem-linux-riscv64-musl/package.json').version
|
|
410
|
-
if (bindingPackageVersion !== '0.1.8' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
411
|
-
throw new Error(`Native binding package version mismatch, expected 0.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
412
|
-
}
|
|
413
|
-
return binding
|
|
414
|
-
} catch (e) {
|
|
415
|
-
loadErrors.push(e)
|
|
416
|
-
}
|
|
417
|
-
} else {
|
|
418
|
-
try {
|
|
419
|
-
return require('./remnem.linux-riscv64-gnu.node')
|
|
420
|
-
} catch (e) {
|
|
421
|
-
loadErrors.push(e)
|
|
422
|
-
}
|
|
423
|
-
try {
|
|
424
|
-
const binding = require('@leonsilicon/remnem-linux-riscv64-gnu')
|
|
425
|
-
const bindingPackageVersion = require('@leonsilicon/remnem-linux-riscv64-gnu/package.json').version
|
|
426
|
-
if (bindingPackageVersion !== '0.1.8' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
427
|
-
throw new Error(`Native binding package version mismatch, expected 0.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
428
|
-
}
|
|
429
|
-
return binding
|
|
430
|
-
} catch (e) {
|
|
431
|
-
loadErrors.push(e)
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
} else if (process.arch === 'ppc64') {
|
|
435
|
-
try {
|
|
436
|
-
return require('./remnem.linux-ppc64-gnu.node')
|
|
437
|
-
} catch (e) {
|
|
438
|
-
loadErrors.push(e)
|
|
439
|
-
}
|
|
440
|
-
try {
|
|
441
|
-
const binding = require('@leonsilicon/remnem-linux-ppc64-gnu')
|
|
442
|
-
const bindingPackageVersion = require('@leonsilicon/remnem-linux-ppc64-gnu/package.json').version
|
|
443
|
-
if (bindingPackageVersion !== '0.1.8' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
444
|
-
throw new Error(`Native binding package version mismatch, expected 0.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
445
|
-
}
|
|
446
|
-
return binding
|
|
447
|
-
} catch (e) {
|
|
448
|
-
loadErrors.push(e)
|
|
449
|
-
}
|
|
450
|
-
} else if (process.arch === 's390x') {
|
|
451
|
-
try {
|
|
452
|
-
return require('./remnem.linux-s390x-gnu.node')
|
|
453
|
-
} catch (e) {
|
|
454
|
-
loadErrors.push(e)
|
|
455
|
-
}
|
|
456
|
-
try {
|
|
457
|
-
const binding = require('@leonsilicon/remnem-linux-s390x-gnu')
|
|
458
|
-
const bindingPackageVersion = require('@leonsilicon/remnem-linux-s390x-gnu/package.json').version
|
|
459
|
-
if (bindingPackageVersion !== '0.1.8' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
460
|
-
throw new Error(`Native binding package version mismatch, expected 0.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
461
|
-
}
|
|
462
|
-
return binding
|
|
463
|
-
} catch (e) {
|
|
464
|
-
loadErrors.push(e)
|
|
465
|
-
}
|
|
466
|
-
} else {
|
|
467
|
-
loadErrors.push(new Error(`Unsupported architecture on Linux: ${process.arch}`))
|
|
468
|
-
}
|
|
469
|
-
} else if (process.platform === 'openharmony') {
|
|
470
|
-
if (process.arch === 'arm64') {
|
|
471
|
-
try {
|
|
472
|
-
return require('./remnem.openharmony-arm64.node')
|
|
473
|
-
} catch (e) {
|
|
474
|
-
loadErrors.push(e)
|
|
475
|
-
}
|
|
476
|
-
try {
|
|
477
|
-
const binding = require('@leonsilicon/remnem-openharmony-arm64')
|
|
478
|
-
const bindingPackageVersion = require('@leonsilicon/remnem-openharmony-arm64/package.json').version
|
|
479
|
-
if (bindingPackageVersion !== '0.1.8' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
480
|
-
throw new Error(`Native binding package version mismatch, expected 0.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
481
|
-
}
|
|
482
|
-
return binding
|
|
483
|
-
} catch (e) {
|
|
484
|
-
loadErrors.push(e)
|
|
485
|
-
}
|
|
486
|
-
} else if (process.arch === 'x64') {
|
|
487
|
-
try {
|
|
488
|
-
return require('./remnem.openharmony-x64.node')
|
|
489
|
-
} catch (e) {
|
|
490
|
-
loadErrors.push(e)
|
|
491
|
-
}
|
|
492
|
-
try {
|
|
493
|
-
const binding = require('@leonsilicon/remnem-openharmony-x64')
|
|
494
|
-
const bindingPackageVersion = require('@leonsilicon/remnem-openharmony-x64/package.json').version
|
|
495
|
-
if (bindingPackageVersion !== '0.1.8' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
496
|
-
throw new Error(`Native binding package version mismatch, expected 0.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
497
|
-
}
|
|
498
|
-
return binding
|
|
499
|
-
} catch (e) {
|
|
500
|
-
loadErrors.push(e)
|
|
501
|
-
}
|
|
502
|
-
} else if (process.arch === 'arm') {
|
|
503
|
-
try {
|
|
504
|
-
return require('./remnem.openharmony-arm.node')
|
|
505
|
-
} catch (e) {
|
|
506
|
-
loadErrors.push(e)
|
|
507
|
-
}
|
|
508
|
-
try {
|
|
509
|
-
const binding = require('@leonsilicon/remnem-openharmony-arm')
|
|
510
|
-
const bindingPackageVersion = require('@leonsilicon/remnem-openharmony-arm/package.json').version
|
|
511
|
-
if (bindingPackageVersion !== '0.1.8' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
512
|
-
throw new Error(`Native binding package version mismatch, expected 0.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
513
|
-
}
|
|
514
|
-
return binding
|
|
515
|
-
} catch (e) {
|
|
516
|
-
loadErrors.push(e)
|
|
517
|
-
}
|
|
518
|
-
} else {
|
|
519
|
-
loadErrors.push(new Error(`Unsupported architecture on OpenHarmony: ${process.arch}`))
|
|
520
|
-
}
|
|
521
|
-
} else {
|
|
522
|
-
loadErrors.push(new Error(`Unsupported OS: ${process.platform}, architecture: ${process.arch}`))
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
nativeBinding = requireNative()
|
|
527
|
-
|
|
528
|
-
// NAPI_RS_FORCE_WASI is a tri-state flag:
|
|
529
|
-
// unset / any other value → native binding preferred, WASI is only a fallback
|
|
530
|
-
// 'true' → force WASI fallback even if native loaded
|
|
531
|
-
// 'error' → force WASI and throw if no WASI binding is found
|
|
532
|
-
// Treating any non-empty string as truthy (the historical behavior) meant
|
|
533
|
-
// NAPI_RS_FORCE_WASI=false, NAPI_RS_FORCE_WASI=0, etc. inadvertently triggered
|
|
534
|
-
// the WASI path, causing ENOENT for packages shipped without a .wasi.cjs file.
|
|
535
|
-
const forceWasi =
|
|
536
|
-
process.env.NAPI_RS_FORCE_WASI === 'true' || process.env.NAPI_RS_FORCE_WASI === 'error'
|
|
537
|
-
|
|
538
|
-
if (!nativeBinding || forceWasi) {
|
|
539
|
-
let wasiBinding = null
|
|
540
|
-
let wasiBindingError = null
|
|
541
|
-
try {
|
|
542
|
-
wasiBinding = require('./remnem.wasi.cjs')
|
|
543
|
-
nativeBinding = wasiBinding
|
|
544
|
-
} catch (err) {
|
|
545
|
-
if (forceWasi) {
|
|
546
|
-
wasiBindingError = err
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
if (!nativeBinding || forceWasi) {
|
|
550
|
-
try {
|
|
551
|
-
wasiBinding = require('@leonsilicon/remnem-wasm32-wasi')
|
|
552
|
-
nativeBinding = wasiBinding
|
|
553
|
-
} catch (err) {
|
|
554
|
-
if (forceWasi) {
|
|
555
|
-
if (!wasiBindingError) {
|
|
556
|
-
wasiBindingError = err
|
|
557
|
-
} else {
|
|
558
|
-
wasiBindingError.cause = err
|
|
559
|
-
}
|
|
560
|
-
loadErrors.push(err)
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
if (process.env.NAPI_RS_FORCE_WASI === 'error' && !wasiBinding) {
|
|
565
|
-
const error = new Error('WASI binding not found and NAPI_RS_FORCE_WASI is set to error')
|
|
566
|
-
error.cause = wasiBindingError
|
|
567
|
-
throw error
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
if (!nativeBinding) {
|
|
572
|
-
if (loadErrors.length > 0) {
|
|
573
|
-
const error = new Error(
|
|
574
|
-
`Cannot find native binding. ` +
|
|
575
|
-
`npm has a bug related to optional dependencies (https://github.com/npm/cli/issues/4828). ` +
|
|
576
|
-
'Please try `npm i` again after removing both package-lock.json and node_modules directory.',
|
|
577
|
-
)
|
|
578
|
-
// assign instead of the `new Error(message, { cause })` options form,
|
|
579
|
-
// which Node < 16.9 silently ignores
|
|
580
|
-
error.cause = loadErrors.reduce((err, cur) => {
|
|
581
|
-
cur.cause = err
|
|
582
|
-
return cur
|
|
583
|
-
})
|
|
584
|
-
throw error
|
|
585
|
-
}
|
|
586
|
-
throw new Error(`Failed to load native binding`)
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
module.exports = nativeBinding
|
|
590
|
-
module.exports.clean = nativeBinding.clean
|
|
591
|
-
module.exports.resolveWorkspace = nativeBinding.resolveWorkspace
|