@anhlp/alp 0.0.1-beta.6 → 0.0.1-beta.8

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
@@ -1,22 +1,19 @@
1
1
  # @anhlp/alp
2
2
 
3
- The `alp` command of [ALP](https://github.com/phucanh08/alp). This package is a small launcher:
4
- npm installs the ALP executable for your machine as one optional dependency,
5
- `@anhlp/alp-<os>-<arch>` (darwin-arm64, darwin-x64, linux-x64, linux-arm64 (glibc), win32-x64),
6
- and `alp` runs it with your arguments. Nothing is downloaded after install.
3
+ The `alp` command of [ALP](https://github.com/phucanh08/alp) for npm users. This package is a
4
+ thin wrapper: it depends on `@anhlp/alp-cli` (pinned to the same version) and its `alp` runs that
5
+ CLI on your Node (22.12 or later). Nothing is downloaded after install.
7
6
 
8
7
  ```sh
9
8
  npm install -g @anhlp/alp@beta
10
9
  alp --version
11
10
  ```
12
11
 
13
- If `alp` says the executable for this machine is not installed, npm skipped optional
14
- dependencies (`--omit=optional`): reinstall with `--include=optional`, or install the executable
15
- directly from [GitHub Releases](https://github.com/phucanh08/alp/releases) with `install.sh`
16
- (`install.ps1` on Windows). Update an npm install with npm (`npm install -g @anhlp/alp@beta`);
17
- `alp update` updates only an executable installed from GitHub Releases.
12
+ Update an npm install with npm (`npm install -g @anhlp/alp@beta`); `alp update` updates only the
13
+ ALP bundle installed from [GitHub Releases](https://github.com/phucanh08/alp/releases) with
14
+ `install.sh` (`install.ps1` on Windows), which brings its own Node.
18
15
 
19
16
  The libraries (`@anhlp/alp-core`, `-protocol`, `-runtime`, `-client`, `-daemon`, `-cli`) and the
20
- Paseo plugin (`@anhlp/alp-paseo`) stay JavaScript packages.
17
+ Paseo plugin (`@anhlp/alp-paseo`) are JavaScript packages too.
21
18
 
22
19
  Apache-2.0; see LICENSE and NOTICE.
package/bin/alp.js CHANGED
@@ -1,5 +1,3 @@
1
1
  #!/usr/bin/env node
2
- // @anhlp/alp's `alp`: runs the ALP executable from @anhlp/alp-<os>-<arch> (lib/launcher.js).
3
- import { main } from '../lib/launcher.js';
4
-
5
- await main();
2
+ // @anhlp/alp's `alp` (t-1807): runs the CLI of its one dependency, @anhlp/alp-cli, on this Node.
3
+ import '@anhlp/alp-cli/cli';
package/package.json CHANGED
@@ -1,27 +1,22 @@
1
1
  {
2
2
  "name": "@anhlp/alp",
3
- "version": "0.0.1-beta.6",
4
- "description": "ALP command line: installs the ALP executable for this machine (@anhlp/alp-<os>-<arch>) and runs it",
3
+ "version": "0.0.1-beta.8",
4
+ "description": "ALP command line for npm: runs the CLI of @anhlp/alp-cli on your Node (22.12 or later)",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "alp": "bin/alp.js"
8
8
  },
9
9
  "files": [
10
10
  "bin/alp.js",
11
- "lib/launcher.js",
12
11
  "README.md",
13
12
  "LICENSE",
14
13
  "NOTICE"
15
14
  ],
16
15
  "engines": {
17
- "node": ">=18"
16
+ "node": ">=22.12"
18
17
  },
19
- "optionalDependencies": {
20
- "@anhlp/alp-darwin-arm64": "0.0.1-beta.6",
21
- "@anhlp/alp-darwin-x64": "0.0.1-beta.6",
22
- "@anhlp/alp-linux-x64": "0.0.1-beta.6",
23
- "@anhlp/alp-linux-arm64": "0.0.1-beta.6",
24
- "@anhlp/alp-win32-x64": "0.0.1-beta.6"
18
+ "dependencies": {
19
+ "@anhlp/alp-cli": "0.0.1-beta.8"
25
20
  },
26
21
  "license": "Apache-2.0",
27
22
  "repository": {
package/lib/launcher.js DELETED
@@ -1,136 +0,0 @@
1
- // The `alp` command of the npm package @anhlp/alp (t-cd7f): a launcher, not ALP itself. npm installs
2
- // the ALP executable for this machine as one optional dependency, @anhlp/alp-<os>-<arch>; this file
3
- // finds it and runs it with the same arguments, stdio, exit code and signal. Plain Node, no
4
- // dependencies, no postinstall download.
5
- import { spawn } from 'node:child_process';
6
- import { existsSync } from 'node:fs';
7
- import { createRequire } from 'node:module';
8
- import path from 'node:path';
9
-
10
- export const RELEASES_URL = 'https://github.com/phucanh08/alp/releases';
11
- export const INSTALL_SH = 'curl -fsSL https://github.com/phucanh08/alp/releases/latest/download/install.sh | sh';
12
-
13
- /** The platform packages, keyed by `${process.platform}-${process.arch}`. Linux builds are glibc only. */
14
- export const PLATFORM_PACKAGES = Object.freeze({
15
- 'darwin-arm64': '@anhlp/alp-darwin-arm64',
16
- 'darwin-x64': '@anhlp/alp-darwin-x64',
17
- 'linux-x64': '@anhlp/alp-linux-x64',
18
- 'linux-arm64': '@anhlp/alp-linux-arm64',
19
- 'win32-x64': '@anhlp/alp-win32-x64',
20
- });
21
-
22
- /** Whether this Linux runs glibc (Node reports its runtime glibc version; musl reports none). */
23
- export function isGlibc(report = () => process.report?.getReport?.()) {
24
- try { return Boolean(/** @type {any} */ (report())?.header?.glibcVersionRuntime); } catch { return false; }
25
- }
26
-
27
- /**
28
- * The platform package for a machine, or why there is none.
29
- * @param {{ platform?: string, arch?: string, glibc?: () => boolean }} [machine]
30
- * @returns {{ name: string, executable: string } | { error: string }}
31
- */
32
- export function platformPackage({ platform = process.platform, arch = process.arch, glibc = isGlibc } = {}) {
33
- const key = `${platform}-${arch}`;
34
- const name = PLATFORM_PACKAGES[key];
35
- if (!name) return { error: `ALP has no build for ${key}; supported: ${Object.keys(PLATFORM_PACKAGES).join(', ')}.` };
36
- if (platform === 'linux' && !glibc()) return { error: `ALP's Linux builds need glibc; this ${key} system uses another C library (musl, as on Alpine).` };
37
- return { name, executable: platform === 'win32' ? 'alp.exe' : 'alp' };
38
- }
39
-
40
- /**
41
- * The ALP executable installed beside this package, or an error message for the user.
42
- * @param {{ platform?: string, arch?: string, glibc?: () => boolean, resolve?: (request: string) => string, exists?: (file: string) => boolean }} [options]
43
- * @returns {{ binary: string, name: string } | { error: string }}
44
- */
45
- export function findBinary({ resolve = createRequire(import.meta.url).resolve, exists = existsSync, ...machine } = {}) {
46
- const wanted = platformPackage(machine);
47
- // No executable exists for this machine: only the JavaScript CLI can run here.
48
- if ('error' in wanted) return { error: `alp: ${wanted.error}\nRun the JavaScript CLI instead (Node 22.12 or later; it also provides \`alp\`): npm uninstall -g @anhlp/alp && npm install -g @anhlp/alp-cli@beta\n(${RELEASES_URL})` };
49
- let manifest;
50
- try { manifest = resolve(`${wanted.name}/package.json`); } catch {
51
- return { error: missingMessage(`${wanted.name}, the ALP executable for this machine, is not installed (npm skips optional dependencies with --omit=optional or --no-optional).`) };
52
- }
53
- const binary = path.join(path.dirname(manifest), 'bin', wanted.executable);
54
- if (!exists(binary)) return { error: missingMessage(`${wanted.name} is installed but has no ${path.join('bin', wanted.executable)}; reinstall it.`) };
55
- return { binary, name: wanted.name };
56
- }
57
-
58
- /** @param {string} reason */
59
- export function missingMessage(reason) {
60
- return [
61
- `alp: ${reason}`,
62
- 'Reinstall with optional dependencies: npm install -g @anhlp/alp@beta --include=optional',
63
- `Or install the ALP executable directly: ${INSTALL_SH}`,
64
- `(Windows: install.ps1; every build: ${RELEASES_URL})`,
65
- ].join('\n');
66
- }
67
-
68
- /** Whether a terminal is attached (any of stdin, stdout, stderr): its keyboard signals reach the whole foreground group. */
69
- export const onTerminal = (proc = process) => Boolean(proc.stdin?.isTTY || proc.stdout?.isTTY || proc.stderr?.isTTY);
70
-
71
- /** Signals the launcher outlives so the executable decides what they mean. */
72
- const HANDLED = ['SIGINT', 'SIGTERM', 'SIGHUP', 'SIGQUIT', 'SIGBREAK', 'SIGUSR1', 'SIGUSR2'];
73
- /** The terminal's keyboard signals: a terminal sends them to the whole foreground process group, the executable included. */
74
- const KEYBOARD = new Set(['SIGINT', 'SIGQUIT', 'SIGBREAK']);
75
-
76
- /**
77
- * Whether a signal the launcher received must be passed on. Signals sent to the launcher alone
78
- * (kill <pid>, a supervisor) are. The terminal's Ctrl-C/Ctrl-\ already reached the executable, so
79
- * passing it on would deliver it twice. On Windows the console delivers Ctrl-C/Ctrl-Break to every
80
- * process attached to it, and kill() there only terminates, so nothing is passed on.
81
- */
82
- export function forwards(signal, { platform = process.platform, tty = onTerminal() } = {}) {
83
- if (platform === 'win32') return false;
84
- return !(KEYBOARD.has(signal) && tty);
85
- }
86
-
87
- /**
88
- * Runs `binary` with `args` and inherited stdio. Resolves with how it ended: `{ code }` or `{ signal }`.
89
- * The launcher stays alive on the signals it handles and passes them on as `forwards` says; the
90
- * executable decides what they mean, and the launcher only reports how it ended.
91
- * @param {string} binary @param {string[]} args
92
- * @param {{ spawn?: typeof spawn, process?: NodeJS.Process, platform?: string, tty?: boolean }} [options]
93
- * @returns {Promise<{ code: number } | { signal: NodeJS.Signals }>}
94
- */
95
- export function run(binary, args, { spawn: start = spawn, process: proc = process, platform = process.platform, tty = onTerminal() } = {}) {
96
- return new Promise(resolve => {
97
- const child = start(binary, args, { stdio: 'inherit', windowsHide: false });
98
- let started = false;
99
- child.once('spawn', () => { started = true; });
100
- const handlers = new Map();
101
- const release = () => { for (const [signal, handler] of handlers) proc.removeListener(signal, handler); };
102
- for (const signal of HANDLED) {
103
- const handler = () => { if (forwards(signal, { platform, tty })) try { child.kill(signal); } catch {} };
104
- try { proc.on(signal, handler); handlers.set(signal, handler); } catch {}
105
- }
106
- child.on('error', error => {
107
- // After the executable started, an error (a failed kill) changes nothing: its exit decides.
108
- if (started) return;
109
- release();
110
- proc.stderr.write(`alp: could not run ${binary}: ${error.message}\n${missingMessage('the ALP executable could not start.')}\n`);
111
- resolve({ code: 1 });
112
- });
113
- child.once('exit', (code, signal) => {
114
- release();
115
- resolve(signal ? { signal } : { code: code ?? 1 });
116
- });
117
- });
118
- }
119
-
120
- /** The launcher's main: find the executable, run it, end as it ended. */
121
- export async function main(args = process.argv.slice(2)) {
122
- const found = findBinary();
123
- if ('error' in found) {
124
- process.stderr.write(`${found.error}\n`);
125
- process.exitCode = 1;
126
- return;
127
- }
128
- const end = await run(found.binary, args);
129
- if ('signal' in end) {
130
- // End by the same signal, so a shell sees what the child saw; exit 128+n if it does not kill us.
131
- try { process.kill(process.pid, end.signal); } catch {}
132
- const number = (await import('node:os')).constants.signals[end.signal] ?? 0;
133
- process.exit(128 + number);
134
- }
135
- process.exit(end.code);
136
- }