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 +21 -20
- package/package.json +1 -1
- package/packaging/npm/lib/bootstrap.js +4 -4
- package/packaging/npm/lib/cache.js +10 -0
- package/packaging/npm/release.json +16 -16
- package/packaging/npm/lib/state.js +0 -87
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
|
-
##
|
|
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.
|
|
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.
|
|
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
|
-
`
|
|
56
|
-
|
|
57
|
-
|
|
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.
|
|
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
|
@@ -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 {
|
|
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
|
-
|
|
148
|
-
|
|
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.
|
|
4
|
-
"commit": "
|
|
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.
|
|
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.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.
|
|
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.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 };
|