stackbite 0.5.60 → 0.5.62
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/package.json
CHANGED
|
@@ -223,6 +223,7 @@ async function launchNative(executable, argv, environment, { spawnImpl = spawn,
|
|
|
223
223
|
}
|
|
224
224
|
async function main(argv = process.argv.slice(2), options = {}) {
|
|
225
225
|
const setup = parseSetup(argv);
|
|
226
|
+
const removing = ['uninstall', 'delete'].includes(argv[0]);
|
|
226
227
|
const manifest = options.manifest || require('../release.json');
|
|
227
228
|
const platform = options.platform || process.platform;
|
|
228
229
|
const environment = options.environment || process.env;
|
|
@@ -230,12 +231,15 @@ async function main(argv = process.argv.slice(2), options = {}) {
|
|
|
230
231
|
// Every launch still verifies the full pinned payload; timing only observes it.
|
|
231
232
|
const installed = await timing.phase(environment, 'launcher.ensure', () => ensureBinary(spec, { ...options,
|
|
232
233
|
cache: options.cache || cacheDirectory(environment, platform),
|
|
233
|
-
checkOnly: setup?.checkOnly || false, reportCached: Boolean(setup),
|
|
234
|
+
checkOnly: removing || setup?.checkOnly || false, reportCached: Boolean(setup),
|
|
234
235
|
progress: options.progress || stageReporter(options.stderr || process.stderr) }));
|
|
235
236
|
if (setup) return { code: 0, signal: null };
|
|
236
237
|
timing.mark(environment, 'launcher.exec');
|
|
237
238
|
// The bundled runtime owns state discovery and migration for every entrypoint.
|
|
238
|
-
|
|
239
|
+
const result = await launchNative(installed.executable, argv, { ...environment,
|
|
239
240
|
STACKBITE_HOME: path.resolve(installed.home) }, options);
|
|
241
|
+
if (!removing) return result;
|
|
242
|
+
const { removeRegistration } = require('./uninstall-registration');
|
|
243
|
+
return removeRegistration(argv, result, environment, launchNative, options);
|
|
240
244
|
}
|
|
241
245
|
module.exports = { releaseSpec, validatePayload, ensureBinary, launchNative, main };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
// Let npm remove only this exact global registration. Never delete a shared prefix.
|
|
3
|
+
const fs = require('node:fs/promises');
|
|
4
|
+
const path = require('node:path');
|
|
5
|
+
|
|
6
|
+
async function registration(packageRoot, platform = process.platform) {
|
|
7
|
+
const root = path.resolve(packageRoot);
|
|
8
|
+
const modules = path.dirname(root);
|
|
9
|
+
if (path.basename(root) !== 'stackbite' || path.basename(modules) !== 'node_modules') return null;
|
|
10
|
+
const info = await fs.lstat(root);
|
|
11
|
+
if (!info.isDirectory() || info.isSymbolicLink() || await fs.realpath(root) !== root) {
|
|
12
|
+
throw new Error('Linked npm registration preserved; remove it through its original package manager');
|
|
13
|
+
}
|
|
14
|
+
const metadata = JSON.parse(await fs.readFile(path.join(root, 'package.json'), 'utf8'));
|
|
15
|
+
if (metadata.name !== 'stackbite') throw new Error('Foreign npm package registration preserved');
|
|
16
|
+
// npx owns its own cache, which is not a global registration.
|
|
17
|
+
const prefix = globalPrefix(modules, platform);
|
|
18
|
+
if (prefix === null || await projectLocal(prefix)) return null;
|
|
19
|
+
return prefix;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function globalPrefix(modules, platform) {
|
|
23
|
+
const prefix = path.dirname(modules);
|
|
24
|
+
if (prefix.split(path.sep).includes('_npx')) return null;
|
|
25
|
+
if (platform === 'win32') return prefix;
|
|
26
|
+
return path.basename(prefix) === 'lib' ? path.dirname(prefix) : null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function projectLocal(prefix) {
|
|
30
|
+
// A project-local node_modules tree is source, even when its package name matches.
|
|
31
|
+
for (const name of ['package.json', '.git']) {
|
|
32
|
+
try { await fs.lstat(path.join(prefix, name)); return true; }
|
|
33
|
+
catch (error) { if (error.code !== 'ENOENT') throw error; }
|
|
34
|
+
}
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function npmProgram(packageRoot, nodeExecutable, resolve = require.resolve) {
|
|
39
|
+
const metadata = resolve('npm/package.json', { paths: [packageRoot, path.dirname(nodeExecutable)] });
|
|
40
|
+
return path.join(path.dirname(metadata), 'bin', 'npm-cli.js');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function removeRegistration(argv, result, environment, launch, options = {}) {
|
|
44
|
+
if (!acceptedRemoval(argv, result)) return result;
|
|
45
|
+
const root = options.packageRoot || path.resolve(__dirname, '../../..');
|
|
46
|
+
const prefix = await registration(root, options.platform || process.platform);
|
|
47
|
+
if (prefix === null) return result;
|
|
48
|
+
const node = options.nodeExecutable || process.execPath;
|
|
49
|
+
const cli = options.npmCli || npmProgram(root, node);
|
|
50
|
+
const removed = await launch(node, [cli, 'uninstall', '--global', '--prefix', prefix,
|
|
51
|
+
'stackbite', '--ignore-scripts', '--offline', '--no-audit', '--no-fund'],
|
|
52
|
+
{ ...environment, npm_config_update_notifier: 'false' }, options);
|
|
53
|
+
if (removed.code !== 0 || removed.signal) throw new Error('Product removal was accepted; npm registration removal failed');
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function acceptedRemoval(argv, result) {
|
|
58
|
+
return explicitApply(argv) && !result.signal && [0, 2].includes(result.code);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function explicitApply(argv) {
|
|
62
|
+
const choices = new Set(['--all', '--keep-data', '--resume']);
|
|
63
|
+
return argv.length === 3 && ['uninstall', 'delete'].includes(argv[0])
|
|
64
|
+
&& argv.slice(1).includes('--apply') && argv.slice(1).some(arg => choices.has(arg));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
module.exports = { registration, npmProgram, removeRegistration, explicitApply };
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": 1,
|
|
3
|
-
"version": "0.5.
|
|
4
|
-
"commit": "
|
|
3
|
+
"version": "0.5.62",
|
|
4
|
+
"commit": "260b221b2c12353b0ceb783b895ee31a00efc7f6",
|
|
5
5
|
"repository": "Shinick-Han/stackbite",
|
|
6
6
|
"platforms": {
|
|
7
7
|
"win32-x64": {
|
|
8
|
-
"asset": "stackbite-0.5.
|
|
9
|
-
"url": "https://github.com/Shinick-Han/stackbite/releases/download/v0.5.
|
|
10
|
-
"sha256": "
|
|
11
|
-
"size":
|
|
12
|
-
"root": "stackbite-0.5.
|
|
13
|
-
"manifestSha256": "
|
|
14
|
-
"metadataSha256": "
|
|
8
|
+
"asset": "stackbite-0.5.62-windows-x64-260b221b2c12.zip",
|
|
9
|
+
"url": "https://github.com/Shinick-Han/stackbite/releases/download/v0.5.62/stackbite-0.5.62-windows-x64-260b221b2c12.zip",
|
|
10
|
+
"sha256": "7b7b98fb6051344ef1314b44b472d78e94d8f682d616d7dd33ec620f6d5f96b4",
|
|
11
|
+
"size": 89516359,
|
|
12
|
+
"root": "stackbite-0.5.62-windows-x64-260b221b2c12",
|
|
13
|
+
"manifestSha256": "9aa0a9d09ed360b4306c6c0d5ca6923b468e2fd55197c2b2a5a3d66cdf00b709",
|
|
14
|
+
"metadataSha256": "74f38d2b1f13a9464cc669a3fa7b1ef2f139d1194fdd36256483cb38e673befb"
|
|
15
15
|
},
|
|
16
16
|
"linux-x64": {
|
|
17
|
-
"asset": "stackbite-0.5.
|
|
18
|
-
"url": "https://github.com/Shinick-Han/stackbite/releases/download/v0.5.
|
|
19
|
-
"sha256": "
|
|
20
|
-
"size":
|
|
21
|
-
"root": "stackbite-0.5.
|
|
22
|
-
"manifestSha256": "
|
|
23
|
-
"metadataSha256": "
|
|
17
|
+
"asset": "stackbite-0.5.62-linux-x86_64-260b221b2c12.tar.gz",
|
|
18
|
+
"url": "https://github.com/Shinick-Han/stackbite/releases/download/v0.5.62/stackbite-0.5.62-linux-x86_64-260b221b2c12.tar.gz",
|
|
19
|
+
"sha256": "7c39e638e6d0b8ed0b0018fb78e705615246d7d64eda7085169bc83d6f6fec5b",
|
|
20
|
+
"size": 70976395,
|
|
21
|
+
"root": "stackbite-0.5.62-linux-x86_64-260b221b2c12",
|
|
22
|
+
"manifestSha256": "a11b098846f4bafc49101c976acf30ce95bec366150a9489b0d19f4cf63d6991",
|
|
23
|
+
"metadataSha256": "291e27e2251ad99173c5aacc0decdac4efab00b4804131d3d45d7db926a1fd11"
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
}
|