stackbite 0.5.61 → 0.5.63

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stackbite",
3
- "version": "0.5.61",
3
+ "version": "0.5.63",
4
4
  "description": "Verified native Stackbite CLI bootstrapper",
5
5
  "license": "UNLICENSED",
6
6
  "engines": {
@@ -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
- return launchNative(installed.executable, argv, { ...environment,
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
- {
2
- "schema": 1,
3
- "version": "0.5.61",
4
- "commit": "5a243ed8845e8cdc2dd199a78008fe3d3217f0fd",
5
- "repository": "Shinick-Han/stackbite",
6
- "platforms": {
7
- "win32-x64": {
8
- "asset": "stackbite-0.5.61-windows-x64-5a243ed8845e.zip",
9
- "url": "https://github.com/Shinick-Han/stackbite/releases/download/v0.5.61/stackbite-0.5.61-windows-x64-5a243ed8845e.zip",
10
- "sha256": "b0c7b9439c00a31ff37297b862b6bb59660eec57d9de33ea77abc8362191c3a0",
11
- "size": 89484988,
12
- "root": "stackbite-0.5.61-windows-x64-5a243ed8845e",
13
- "manifestSha256": "4838f1247f11825c4d83e83ba52e4e3fbd939e505f6377ef950179406eb80b6a",
14
- "metadataSha256": "65175a5a289ca8397829843ab3b239bf8ad6820fbe53902c65ca3efc5904f8ac"
15
- },
16
- "linux-x64": {
17
- "asset": "stackbite-0.5.61-linux-x86_64-5a243ed8845e.tar.gz",
18
- "url": "https://github.com/Shinick-Han/stackbite/releases/download/v0.5.61/stackbite-0.5.61-linux-x86_64-5a243ed8845e.tar.gz",
19
- "sha256": "11accac9280ed3f2dad40a86205b6117b0891bdbb2410d19fc6303f2858fc267",
20
- "size": 70946763,
21
- "root": "stackbite-0.5.61-linux-x86_64-5a243ed8845e",
22
- "manifestSha256": "2769d060e2eb90216abbdb5dbfe58c18a3e8ebfc1506d5872a5dbbedcbe73a0e",
23
- "metadataSha256": "5faf2b13ba3c77a1573482795fdca4999fc05923b9003338e8bf3bb0d3d83fd3"
24
- }
25
- }
26
- }
1
+ {
2
+ "schema": 1,
3
+ "version": "0.5.63",
4
+ "commit": "a84f43aadeb7d63807de633186607acdaa1a08ec",
5
+ "repository": "Shinick-Han/stackbite",
6
+ "platforms": {
7
+ "win32-x64": {
8
+ "asset": "stackbite-0.5.63-windows-x64-a84f43aadeb7.zip",
9
+ "url": "https://github.com/Shinick-Han/stackbite/releases/download/v0.5.63/stackbite-0.5.63-windows-x64-a84f43aadeb7.zip",
10
+ "sha256": "1204e569fab0cd18f7d1877c2e18fe2db3ec0d8c03a18bbfc2d16a61d6ce1cc7",
11
+ "size": 89517115,
12
+ "root": "stackbite-0.5.63-windows-x64-a84f43aadeb7",
13
+ "manifestSha256": "99ee8519853c5a76dc6ad8ed2ce2f16f3da8d80d3474422f991cb0e2903c4b23",
14
+ "metadataSha256": "da36339045769b38184dda09de010d1f4ecc91788341167ee6ff805296f81c3d"
15
+ },
16
+ "linux-x64": {
17
+ "asset": "stackbite-0.5.63-linux-x86_64-a84f43aadeb7.tar.gz",
18
+ "url": "https://github.com/Shinick-Han/stackbite/releases/download/v0.5.63/stackbite-0.5.63-linux-x86_64-a84f43aadeb7.tar.gz",
19
+ "sha256": "63375ec11ecbfe4b234a66233602928c94f09d58b4d99032a5f5354e5a531eb5",
20
+ "size": 70977528,
21
+ "root": "stackbite-0.5.63-linux-x86_64-a84f43aadeb7",
22
+ "manifestSha256": "c95795c21cefc8b8e4394fe2842e60686cd4de5ce0a21aeae7978f747dbba25b",
23
+ "metadataSha256": "e2fa02381a93f7a5cf7d032ae0b8322f64476f5727963236f31790f2d1c7ba7c"
24
+ }
25
+ }
26
+ }