sunnah 1.1.2 → 1.1.4
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.
Potentially problematic release.
This version of sunnah might be problematic. Click here for more details.
- package/bin/index.js +43 -11
- package/package.json +1 -1
package/bin/index.js
CHANGED
|
@@ -12,6 +12,10 @@ const pkg = JSON.parse(
|
|
|
12
12
|
fs.readFileSync(path.join(__dirname, "..", "package.json"), "utf8"),
|
|
13
13
|
);
|
|
14
14
|
|
|
15
|
+
// ── Windows compatibility ─────────────────────────────────────────────────────
|
|
16
|
+
const isWin = process.platform === "win32";
|
|
17
|
+
const NPM = isWin ? "npm.cmd" : "npm";
|
|
18
|
+
|
|
15
19
|
// ── Colors ────────────────────────────────────────────────────────────────────
|
|
16
20
|
const c = {
|
|
17
21
|
reset: "\x1b[0m",
|
|
@@ -117,7 +121,6 @@ function animateInstall(pkgName) {
|
|
|
117
121
|
let stageIdx = 0;
|
|
118
122
|
let npmDone = false;
|
|
119
123
|
|
|
120
|
-
// Print initial bar on its own line
|
|
121
124
|
process.stdout.write(drawBar(stages[0].label, 0) + "\n");
|
|
122
125
|
|
|
123
126
|
const tick = () => {
|
|
@@ -128,14 +131,12 @@ function animateInstall(pkgName) {
|
|
|
128
131
|
const step = (stage.end - prevEnd) / 22;
|
|
129
132
|
percent = Math.min(percent + step, stage.end);
|
|
130
133
|
|
|
131
|
-
// Overwrite the bar line
|
|
132
134
|
process.stdout.write("\r\x1b[K");
|
|
133
135
|
process.stdout.write(drawBar(stage.label, percent));
|
|
134
136
|
|
|
135
137
|
if (percent >= stage.end) {
|
|
136
138
|
stageIdx++;
|
|
137
139
|
if (stageIdx >= stages.length) {
|
|
138
|
-
// All visual stages done — wait for npm
|
|
139
140
|
const poll = setInterval(() => {
|
|
140
141
|
if (npmDone) {
|
|
141
142
|
clearInterval(poll);
|
|
@@ -154,26 +155,48 @@ function animateInstall(pkgName) {
|
|
|
154
155
|
|
|
155
156
|
setTimeout(tick, stages[0].ms);
|
|
156
157
|
|
|
157
|
-
//
|
|
158
|
-
const proc = spawn(
|
|
158
|
+
// spawn npm.cmd on Windows, npm on Unix
|
|
159
|
+
const proc = spawn(NPM, ["install", "-g", pkgName], {
|
|
159
160
|
stdio: ["ignore", "pipe", "pipe"],
|
|
161
|
+
shell: isWin,
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
proc.on("error", () => {
|
|
165
|
+
// resolve anyway so the UI doesn't hang on spawn failure
|
|
166
|
+
npmDone = true;
|
|
160
167
|
});
|
|
168
|
+
|
|
161
169
|
proc.on("close", () => {
|
|
162
170
|
npmDone = true;
|
|
163
171
|
});
|
|
164
172
|
});
|
|
165
173
|
}
|
|
166
174
|
|
|
167
|
-
// ── Check
|
|
168
|
-
|
|
175
|
+
// ── Check installed status ONCE at startup, cache forever ───────────────────
|
|
176
|
+
// Calling npm on every render was freezing the terminal. We run one
|
|
177
|
+
// 'npm list -g' at startup, parse the output, and never shell out again.
|
|
178
|
+
function buildInstalledCache() {
|
|
179
|
+
const cache = new Map();
|
|
180
|
+
let out = "";
|
|
169
181
|
try {
|
|
170
|
-
execSync(
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
182
|
+
out = execSync(`${NPM} list -g --depth=0`, {
|
|
183
|
+
encoding: "utf8",
|
|
184
|
+
shell: isWin,
|
|
185
|
+
timeout: 8000,
|
|
186
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
187
|
+
});
|
|
188
|
+
} catch (e) {
|
|
189
|
+
out = e.stdout || "";
|
|
174
190
|
}
|
|
191
|
+
for (const p of PACKAGES) {
|
|
192
|
+
cache.set(p.name, out.includes(p.name));
|
|
193
|
+
}
|
|
194
|
+
return cache;
|
|
175
195
|
}
|
|
176
196
|
|
|
197
|
+
let installedCache = new Map();
|
|
198
|
+
const isInstalled = (name) => installedCache.get(name) ?? false;
|
|
199
|
+
|
|
177
200
|
// ── Render the interactive list ───────────────────────────────────────────────
|
|
178
201
|
const DIV_W = () => Math.min(W() - 2, 70);
|
|
179
202
|
|
|
@@ -315,6 +338,7 @@ async function main() {
|
|
|
315
338
|
|
|
316
339
|
// --list
|
|
317
340
|
if (flags.some((f) => f === "--list" || f === "-l")) {
|
|
341
|
+
installedCache = buildInstalledCache();
|
|
318
342
|
const div = gray("─".repeat(60));
|
|
319
343
|
console.log("");
|
|
320
344
|
console.log(div);
|
|
@@ -342,6 +366,13 @@ async function main() {
|
|
|
342
366
|
process.exit(1);
|
|
343
367
|
}
|
|
344
368
|
|
|
369
|
+
// Build installed cache once — never call npm during rendering
|
|
370
|
+
process.stdout.write(
|
|
371
|
+
"\n " + "\x1b[90m" + "Checking installed packages…" + "\x1b[0m",
|
|
372
|
+
);
|
|
373
|
+
installedCache = buildInstalledCache();
|
|
374
|
+
process.stdout.write("\r\x1b[K");
|
|
375
|
+
|
|
345
376
|
readline.emitKeypressEvents(process.stdin);
|
|
346
377
|
process.stdin.setRawMode(true);
|
|
347
378
|
hideCursor();
|
|
@@ -443,6 +474,7 @@ async function main() {
|
|
|
443
474
|
console.log("");
|
|
444
475
|
|
|
445
476
|
await animateInstall(p.name);
|
|
477
|
+
installedCache.set(p.name, true); // update cache
|
|
446
478
|
|
|
447
479
|
console.log(
|
|
448
480
|
` ${green("✓")} ${bold(green(p.label))} installed successfully`,
|