stackbite 0.5.10 → 0.5.11

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 CHANGED
@@ -7,19 +7,31 @@ and Linux x64 with glibc; macOS, ARM and musl/Alpine builds are not supplied yet
7
7
  Python installation and compilation are unnecessary. Archive extraction requires
8
8
  `tar` (included in current Windows and common Linux distributions).
9
9
 
10
- ## Available without an npm account
10
+ ## Install without an account
11
+
12
+ The public npm package is available as `stackbite`:
13
+
14
+ ```sh
15
+ npx --yes stackbite
16
+ npm install --global stackbite
17
+ stackbite
18
+ ```
19
+
20
+ Update a registry installation with `npm install --global stackbite@latest`.
21
+
22
+ ## Direct GitHub package
11
23
 
12
24
  Run the package attached to the verified GitHub release:
13
25
 
14
26
  ```sh
15
- npx --yes https://github.com/Shinick-Han/stackbite/releases/download/v0.5.10/stackbite-0.5.10.tgz
27
+ npx --yes https://github.com/Shinick-Han/stackbite/releases/download/v0.5.11/stackbite-0.5.11.tgz
16
28
  ```
17
29
 
18
30
  Arguments go after the package URL, for example `--version` or `--status`. For a
19
31
  persistent command, install that same package globally:
20
32
 
21
33
  ```sh
22
- npm install --global https://github.com/Shinick-Han/stackbite/releases/download/v0.5.10/stackbite-0.5.10.tgz
34
+ npm install --global https://github.com/Shinick-Han/stackbite/releases/download/v0.5.11/stackbite-0.5.11.tgz
23
35
  stackbite
24
36
  ```
25
37
 
@@ -33,28 +45,17 @@ checksums and product identity, then reuses a persistent binary cache. There is
33
45
  postinstall download or provider installation. An offline cached launch is possible;
34
46
  the first launch needs access to GitHub release downloads.
35
47
 
36
- ## Short npm registry commands
37
-
38
- Once the package owner publishes `stackbite` to the public npm registry:
39
-
40
- ```sh
41
- npx --yes stackbite
42
- npm install --global stackbite
43
- stackbite
44
- ```
45
-
46
- These short commands require registry publication. Until that happens, use the
47
- verified GitHub package URL above rather than a similarly named external package.
48
- Update a registry installation with `npm install --global stackbite@latest`.
49
48
  For a GitHub URL installation, install the package URL from the newer release.
50
49
  Each npm package pins one native release; the portable app's own `stackbite update`
51
50
  does not change the npm package version.
52
51
 
53
52
  ## Existing data and processes
54
53
 
55
- `HELM_STATE_DIR` remains the explicit state override. Existing Windows installed
56
- configuration and Linux managed-launcher state are reused; otherwise state stays
57
- at `%LOCALAPPDATA%\Helm\state` or `${XDG_STATE_HOME:-~/.local/state}/helm`.
54
+ `STACKBITE_STATE_DIR` is the explicit state override. The bundled native runtime
55
+ owns state discovery and migration for both npm and direct launches. It reuses
56
+ existing configured state and keeps live databases, authentication and records
57
+ in place. New state uses `%LOCALAPPDATA%\Stackbite\state` or
58
+ `${XDG_STATE_HOME:-~/.local/state}/stackbite`.
58
59
  Rooms, Seats, authentication, provider configuration, journals and Work Stack
59
60
  contracts are not renamed or migrated. Binary cache data is separate from this
60
61
  state. Installing or launching the npm package does not stop an existing backend.
@@ -71,7 +72,7 @@ Build and verify both native platform archives first. Prepare the pinned manifes
71
72
  from their exact extracted bundles and archive bytes:
72
73
 
73
74
  ```sh
74
- python scripts/prepare_npm_release.py --version 0.5.10
75
+ python scripts/prepare_npm_release.py --version 0.5.11
75
76
  npm test
76
77
  npm pack
77
78
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stackbite",
3
- "version": "0.5.10",
3
+ "version": "0.5.11",
4
4
  "description": "Verified native Stackbite CLI bootstrapper",
5
5
  "license": "UNLICENSED",
6
6
  "engines": { "node": ">=20" },
@@ -6,7 +6,7 @@ const { createHash } = require('node:crypto');
6
6
  const { LIMITS, fail, memberPath, inside, hashFile, readSmall, exists, safeDirectory } = require('./common');
7
7
  const { download } = require('./download');
8
8
  const { extractArchive } = require('./archive');
9
- const { stateDirectory, cacheDirectory } = require('./state');
9
+ const { cacheDirectory } = require('./cache');
10
10
  const packageVersion = require('../../../package.json').version;
11
11
 
12
12
  function releaseSpec(manifest, platform = process.platform, arch = process.arch, runtime = {}) {
@@ -142,9 +142,9 @@ async function main(argv = process.argv.slice(2), options = {}) {
142
142
  const platform = options.platform || process.platform;
143
143
  const environment = options.environment || process.env;
144
144
  const spec = releaseSpec(manifest, platform, options.arch || process.arch, options);
145
- const state = await stateDirectory(environment, platform);
146
145
  const installed = await ensureBinary(spec, { ...options, cache: options.cache || cacheDirectory(environment, platform) });
147
- return launchNative(installed.executable, argv, { ...environment, HELM_HOME: path.resolve(installed.home),
148
- HELM_STATE_DIR: state }, options);
146
+ // The bundled runtime owns state discovery and migration for every entrypoint.
147
+ return launchNative(installed.executable, argv, { ...environment,
148
+ STACKBITE_HOME: path.resolve(installed.home) }, options);
149
149
  }
150
150
  module.exports = { releaseSpec, validatePayload, ensureBinary, launchNative, main };
@@ -0,0 +1,10 @@
1
+ 'use strict';
2
+ const path = require('node:path');
3
+ const os = require('node:os');
4
+
5
+ function cacheDirectory(environment = process.env, platform = process.platform, home = os.homedir()) {
6
+ return platform === 'win32'
7
+ ? path.resolve(environment.LOCALAPPDATA || path.join(home, 'AppData', 'Local'), 'Stackbite', 'cache')
8
+ : path.resolve(environment.XDG_CACHE_HOME || path.join(environment.HOME || home, '.cache'), 'stackbite');
9
+ }
10
+ module.exports = { cacheDirectory };
@@ -1,26 +1,26 @@
1
1
  {
2
2
  "schema": 1,
3
- "version": "0.5.10",
4
- "commit": "5af83c540e88354a05caa789bb64a663580d5a50",
3
+ "version": "0.5.11",
4
+ "commit": "572562d1755f055d2ec343ec431876a2d2838eec",
5
5
  "repository": "Shinick-Han/stackbite",
6
6
  "platforms": {
7
7
  "win32-x64": {
8
- "asset": "stackbite-0.5.10-windows-x64-5af83c540e88.zip",
9
- "url": "https://github.com/Shinick-Han/stackbite/releases/download/v0.5.10/stackbite-0.5.10-windows-x64-5af83c540e88.zip",
10
- "sha256": "39308402c837ab602266c3dad0d335c85b0c704773ffcd76c84e0c298d3501d7",
11
- "size": 43596699,
12
- "root": "stackbite-0.5.10-windows-x64-5af83c540e88",
13
- "manifestSha256": "0da0c2d439ae7f4e1d783eb6ebfb19046cbf572b11d31b2e79911b93a85b1fb3",
14
- "metadataSha256": "376b458296be12e979c7548bf60bf51aa15c21229f4821889096161c05e31d50"
8
+ "asset": "stackbite-0.5.11-windows-x64-572562d1755f.zip",
9
+ "url": "https://github.com/Shinick-Han/stackbite/releases/download/v0.5.11/stackbite-0.5.11-windows-x64-572562d1755f.zip",
10
+ "sha256": "757619ad45c8f20b76e6c2b67e061415d7894e8d8e1cb9ce215a427dcc5c1b8f",
11
+ "size": 35311793,
12
+ "root": "stackbite-0.5.11-windows-x64-572562d1755f",
13
+ "manifestSha256": "179ced3cf7c7cd8aebc9fec5244baa978152730da8d894812e7b4587630e264b",
14
+ "metadataSha256": "d783e1f17dd31a43521b9b78b62a7c13f3e0193fe07e23b27e078038596a9589"
15
15
  },
16
16
  "linux-x64": {
17
- "asset": "stackbite-0.5.10-linux-x86_64-5af83c540e88.tar.gz",
18
- "url": "https://github.com/Shinick-Han/stackbite/releases/download/v0.5.10/stackbite-0.5.10-linux-x86_64-5af83c540e88.tar.gz",
19
- "sha256": "f997ee78358e5d6ce114fc74a57dc24d0ed65a62a2fd50235eb7de6fdad0f259",
20
- "size": 23795505,
21
- "root": "stackbite-0.5.10-linux-x86_64-5af83c540e88",
22
- "manifestSha256": "fe1f7db461651d825a051e34eea4be85decf30e3daa3d74bb18553b4b7f0e36a",
23
- "metadataSha256": "d095f1dbec1b42f0df933f7d1f5c5b98d517b13754dfd5cd552034f47ffc98d1"
17
+ "asset": "stackbite-0.5.11-linux-x86_64-572562d1755f.tar.gz",
18
+ "url": "https://github.com/Shinick-Han/stackbite/releases/download/v0.5.11/stackbite-0.5.11-linux-x86_64-572562d1755f.tar.gz",
19
+ "sha256": "500927a33edb6ec567b7b0d20ff40ad9f24646b52d33eebeb23f550907554f6c",
20
+ "size": 18475500,
21
+ "root": "stackbite-0.5.11-linux-x86_64-572562d1755f",
22
+ "manifestSha256": "7b8487f4f29b36d9d584d981dc57dc96da991c2951bd808c67fb158ae1239eba",
23
+ "metadataSha256": "0490bde5afb5279516b254eb43b25bf228def181cfd4a83cc2c4251993718c8b"
24
24
  }
25
25
  }
26
26
  }
@@ -1,87 +0,0 @@
1
- 'use strict';
2
- const path = require('node:path');
3
- const os = require('node:os');
4
- const fs = require('node:fs/promises');
5
- const { readSmall, fail } = require('./common');
6
-
7
- function shellLiteral(value) {
8
- if (!value.startsWith("'") || !value.endsWith("'")) return null;
9
- const parts = value.slice(1, -1).split("'\\''");
10
- if (parts.some(part => /['\r\n\0]/.test(part))) return null;
11
- return parts.join("'");
12
- }
13
- function managedState(content) {
14
- const lines = content.split('\n');
15
- if (lines.length !== 8 || lines[0] !== '#!/bin/sh' || !/^# (Helm|Stackbite) managed launcher$/.test(lines[1])
16
- || lines[2] !== 'if [ -z "${HELM_STATE_DIR:-}" ]; then' || lines[4] !== ' export HELM_STATE_DIR'
17
- || lines[5] !== 'fi' || lines[7] !== '' || !lines[3].startsWith(' HELM_STATE_DIR=')
18
- || !lines[6].startsWith('exec ') || !lines[6].endsWith(' "$@"')) return null;
19
- const state = shellLiteral(lines[3].slice(' HELM_STATE_DIR='.length));
20
- const image = shellLiteral(lines[6].slice(5, -5));
21
- if (!state || !path.isAbsolute(state) || !image || !path.isAbsolute(image)
22
- || !['stackbite', 'helm'].includes(path.basename(image))) return null;
23
- return state;
24
- }
25
- function windowsManagedState(content, appRoot) {
26
- // Exact portable-installer grammar, including the original unmarked Helm
27
- // launcher. Values are read literally; no CMD expansion or execution occurs.
28
- const match = /^@echo off\r?\n(?:rem Stackbite managed launcher\r?\n)?setlocal\r?\nset "HELM_HOME=(?<home>[^"%\r\n\0]+)"\r?\nset "HELM_STATE_DIR=(?<state>[^"%\r\n\0]+)"\r?\n"\k<home>\\(?:stackbite|helm)\.exe" %\*\r?\nexit \/b %errorlevel%\r?\n$/.exec(content);
29
- if (!match || !path.win32.isAbsolute(match.groups.home) || !path.win32.isAbsolute(match.groups.state)) return null;
30
- const relative = path.win32.relative(appRoot.toLowerCase(), path.win32.normalize(match.groups.home).toLowerCase());
31
- if (!relative || relative === '..' || relative.startsWith('..\\') || path.win32.isAbsolute(relative)) return null;
32
- return match.groups.state;
33
- }
34
- async function launcherText(filename) {
35
- try {
36
- const info = await fs.lstat(filename);
37
- if (!info.isFile() || info.isSymbolicLink() || info.size > 16384) return null;
38
- const bytes = await readSmall(filename, 16384);
39
- const content = bytes.toString('utf8');
40
- if (content.includes('\uFFFD') && /^@echo off\r?\n(?:rem Stackbite managed launcher\r?\n)?setlocal\r?\nset "HELM_HOME=/.test(content)) {
41
- fail('Existing managed Windows launcher is not UTF-8; set HELM_STATE_DIR explicitly to preserve its state.');
42
- }
43
- return content;
44
- } catch (error) { if (error.code === 'ENOENT') return null; throw error; }
45
- }
46
- async function stateDirectory(environment = process.env, platform = process.platform, home = os.homedir()) {
47
- if (environment.HELM_STATE_DIR) return path.resolve(environment.HELM_STATE_DIR);
48
- if (platform === 'win32') {
49
- const local = environment.LOCALAPPDATA || path.join(home, 'AppData', 'Local');
50
- for (const name of ['default-install.json', 'install.json']) {
51
- let bytes;
52
- try { bytes = await readSmall(path.join(local, 'Helm', name), 16384); }
53
- catch (error) { if (error.code === 'ENOENT') continue; throw error; }
54
- let config;
55
- try { config = JSON.parse(bytes.toString('utf8').replace(/^\uFEFF/, '')); } catch { fail('Existing Helm install configuration is invalid'); }
56
- if (config && typeof config.state === 'string' && config.state && !/[\0\r\n]/.test(config.state)) return path.resolve(config.state);
57
- }
58
- const profile = environment.USERPROFILE || home;
59
- const appRoot = path.resolve(local, 'Helm', 'app');
60
- for (const name of ['stackbite.cmd', 'stackbite-portable.cmd', 'helm.cmd', 'helm-portable.cmd']) {
61
- const content = await launcherText(path.join(profile, '.local', 'bin', name));
62
- const state = content === null ? null : windowsManagedState(content, appRoot);
63
- if (state) return path.resolve(state);
64
- }
65
- return path.resolve(local, 'Helm', 'state');
66
- }
67
- const userHome = environment.HOME || home;
68
- for (const name of ['stackbite', 'helm']) {
69
- let bytes;
70
- try {
71
- const launcher = path.join(userHome, '.local', 'bin', name);
72
- const info = await fs.lstat(launcher);
73
- if (!info.isFile() || info.isSymbolicLink() || info.size > 16384) continue;
74
- bytes = await readSmall(launcher, 16384);
75
- }
76
- catch (error) { if (error.code === 'ENOENT') continue; throw error; }
77
- const state = managedState(bytes.toString('utf8'));
78
- if (state) return path.resolve(state);
79
- }
80
- return path.resolve(environment.XDG_STATE_HOME || path.join(userHome, '.local', 'state'), 'helm');
81
- }
82
- function cacheDirectory(environment = process.env, platform = process.platform, home = os.homedir()) {
83
- return platform === 'win32'
84
- ? path.resolve(environment.LOCALAPPDATA || path.join(home, 'AppData', 'Local'), 'Stackbite', 'cache')
85
- : path.resolve(environment.XDG_CACHE_HOME || path.join(environment.HOME || home, '.cache'), 'stackbite');
86
- }
87
- module.exports = { shellLiteral, managedState, windowsManagedState, stateDirectory, cacheDirectory };