@fnndsc/chell 5.7.0 → 5.7.1
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.
|
@@ -1,88 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
*
|
|
5
|
-
* A Linux boot ends at a login. A daemon boot ended at a resting face — a
|
|
6
|
-
* brain animation and a status line, with the boot log a keypress away —
|
|
7
|
-
* that was a screensaver where a session belonged. The identity is already
|
|
8
|
-
* resolved by the time the engine is ready, so the login is the attach: an
|
|
9
|
-
* ordinary `chell --remote` surface is put on the daemon's own terminal.
|
|
10
|
-
*
|
|
11
|
-
* It is a child process on the wire, not an in-process shortcut. The daemon
|
|
12
|
-
* process holds one output sink and one interaction surface for every
|
|
13
|
-
* attached session; a REPL started inside it would take those over and
|
|
14
|
-
* every other surface would go quiet. A child pays one loopback hop, which
|
|
15
|
-
* is what every surface pays, and shares nothing else.
|
|
16
|
-
*
|
|
17
|
-
* `exit` in the console detaches; the daemon stays up, its terminal idle.
|
|
18
|
-
* Enter attaches again. Ctrl-C at that idle terminal stops the daemon, as
|
|
19
|
-
* it always did. While the console holds the terminal, whatever the daemon
|
|
20
|
-
* itself writes — a roster row, a late warm-up settling — is held and
|
|
21
|
-
* handed back on detach, so it lands after the surface's last line and
|
|
22
|
-
* never across its prompt.
|
|
23
|
-
*
|
|
24
|
-
* @module
|
|
25
|
-
*/
|
|
26
|
-
import { type ChildProcess } from 'node:child_process';
|
|
27
|
-
import type { EventEmitter } from 'node:events';
|
|
28
|
-
/** What the console needs to know about the daemon it attaches to. */
|
|
29
|
-
export interface DaemonConsoleTarget {
|
|
30
|
-
identity: string;
|
|
31
|
-
url: string;
|
|
32
|
-
token: string;
|
|
33
|
-
}
|
|
34
|
-
/** The running attached surface: settles with its exit code. */
|
|
35
|
-
export interface ConsoleChild {
|
|
36
|
-
exited: Promise<number>;
|
|
37
|
-
}
|
|
38
|
-
/** The seams the console loop runs on, replaceable under test. */
|
|
39
|
-
export interface DaemonConsoleDeps {
|
|
40
|
-
/** Starts a `chell --remote` surface on this terminal. */
|
|
41
|
-
attach: (target: DaemonConsoleTarget) => ConsoleChild;
|
|
42
|
-
/** Holds the daemon's own console writes. */
|
|
43
|
-
cage_start: () => void;
|
|
44
|
-
/** Hands back what was held. */
|
|
45
|
-
cage_stop: () => string[];
|
|
46
|
-
/** Resolves true on Enter, false when the terminal's input ends. */
|
|
47
|
-
enter_wait: () => Promise<boolean>;
|
|
48
|
-
/** The terminal's own line writer. */
|
|
49
|
-
log: (line: string) => void;
|
|
50
|
-
}
|
|
51
|
-
/** The chell entry this module was built beside: the surface to spawn. */
|
|
1
|
+
import { type DaemonConsoleTarget } from '@fnndsc/calypso';
|
|
2
|
+
export type { DaemonConsoleTarget };
|
|
3
|
+
/** This chell build's own entry, spawned as the console surface. */
|
|
52
4
|
export declare const CHELL_ENTRY: string;
|
|
53
|
-
/** What the spawner needs of a child: its exit and error events. */
|
|
54
|
-
export type SpawnedChild = Pick<ChildProcess, 'once'>;
|
|
55
|
-
/** A process spawner with the shape of `child_process.spawn`. */
|
|
56
|
-
export type Spawn = (command: string, args: string[], options: {
|
|
57
|
-
stdio: 'inherit';
|
|
58
|
-
env: NodeJS.ProcessEnv;
|
|
59
|
-
}) => SpawnedChild;
|
|
60
|
-
/** What the Enter wait needs of the terminal's input. */
|
|
61
|
-
export type ConsoleInput = Pick<EventEmitter, 'on' | 'once' | 'off'> & {
|
|
62
|
-
resume(): unknown;
|
|
63
|
-
pause(): unknown;
|
|
64
|
-
};
|
|
65
|
-
/**
|
|
66
|
-
* Starts a remote chell surface on this terminal, attached by address.
|
|
67
|
-
*
|
|
68
|
-
* @param target - The daemon's wire address and token.
|
|
69
|
-
* @param spawn - The process spawner; `child_process.spawn` by default.
|
|
70
|
-
* @returns The child, settling with its exit code when the operator detaches.
|
|
71
|
-
*/
|
|
72
|
-
export declare function surface_spawn(target: DaemonConsoleTarget, spawn?: Spawn): ConsoleChild;
|
|
73
|
-
/**
|
|
74
|
-
* Waits for the operator to press Enter at the idle daemon terminal.
|
|
75
|
-
*
|
|
76
|
-
* @param input - The terminal's input; `process.stdin` by default.
|
|
77
|
-
* @returns True on a line of input; false when the input ends.
|
|
78
|
-
*/
|
|
79
|
-
export declare function enter_await(input?: ConsoleInput): Promise<boolean>;
|
|
80
5
|
/**
|
|
81
|
-
* Runs the daemon console
|
|
82
|
-
*
|
|
6
|
+
* Runs the daemon console on chell's own terminal, spawning this chell as
|
|
7
|
+
* the surface.
|
|
83
8
|
*
|
|
84
9
|
* @param target - The daemon to attach to.
|
|
85
|
-
* @param deps - The seams; the live ones by default.
|
|
86
10
|
* @returns Resolves when the operator will not attach again.
|
|
87
11
|
*/
|
|
88
|
-
export declare function daemonConsole_run(target: DaemonConsoleTarget
|
|
12
|
+
export declare function daemonConsole_run(target: DaemonConsoleTarget): Promise<void>;
|
|
@@ -1,130 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @file
|
|
3
|
-
*
|
|
2
|
+
* @file chell's daemon-console entry, over the console the daemon package
|
|
3
|
+
* owns.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* It is a child process on the wire, not an in-process shortcut. The daemon
|
|
12
|
-
* process holds one output sink and one interaction surface for every
|
|
13
|
-
* attached session; a REPL started inside it would take those over and
|
|
14
|
-
* every other surface would go quiet. A child pays one loopback hop, which
|
|
15
|
-
* is what every surface pays, and shares nothing else.
|
|
16
|
-
*
|
|
17
|
-
* `exit` in the console detaches; the daemon stays up, its terminal idle.
|
|
18
|
-
* Enter attaches again. Ctrl-C at that idle terminal stops the daemon, as
|
|
19
|
-
* it always did. While the console holds the terminal, whatever the daemon
|
|
20
|
-
* itself writes — a roster row, a late warm-up settling — is held and
|
|
21
|
-
* handed back on detach, so it lands after the surface's last line and
|
|
22
|
-
* never across its prompt.
|
|
5
|
+
* The console loop, the cage and the reattach grammar live in calypso, since
|
|
6
|
+
* both the standalone `calypso` binary and `chell --daemon` end their boot
|
|
7
|
+
* this way. chell's one difference is the surface it launches: it spawns
|
|
8
|
+
* itself — this build, at this path — rather than whatever `chell` the path
|
|
9
|
+
* happens to resolve, so the console is never a different chell than the
|
|
10
|
+
* daemon it sits on.
|
|
23
11
|
*
|
|
24
12
|
* @module
|
|
25
13
|
*/
|
|
26
|
-
import { spawn as childSpawn } from 'node:child_process';
|
|
27
14
|
import { fileURLToPath } from 'node:url';
|
|
28
|
-
import
|
|
29
|
-
|
|
30
|
-
/** The chell entry this module was built beside: the surface to spawn. */
|
|
15
|
+
import { daemonConsole_run as consoleSession_run, consoleDeps_live, } from '@fnndsc/calypso';
|
|
16
|
+
/** This chell build's own entry, spawned as the console surface. */
|
|
31
17
|
export const CHELL_ENTRY = fileURLToPath(new URL('../index.js', import.meta.url));
|
|
18
|
+
/** Launch the surface as this very chell, not one resolved from the path. */
|
|
19
|
+
const CHELL_LAUNCH = { exec: process.execPath, prefixArgs: [CHELL_ENTRY] };
|
|
32
20
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* @param target - The daemon's wire address and token.
|
|
36
|
-
* @param spawn - The process spawner; `child_process.spawn` by default.
|
|
37
|
-
* @returns The child, settling with its exit code when the operator detaches.
|
|
38
|
-
*/
|
|
39
|
-
export function surface_spawn(target, spawn = childSpawn) {
|
|
40
|
-
// The identity rides along so the surface greets with it, not with the
|
|
41
|
-
// address twice; the environment mark tells it whose terminal it is on,
|
|
42
|
-
// so it skips the greeting the daemon's banner already gave.
|
|
43
|
-
const child = spawn(process.execPath, [CHELL_ENTRY, '--remote', target.identity, '--attach', target.url, '--token', target.token], { stdio: 'inherit', env: { ...process.env, CHELL_CONSOLE: '1' } });
|
|
44
|
-
const exited = new Promise((resolve) => {
|
|
45
|
-
child.once('exit', (code) => { resolve(code ?? 0); });
|
|
46
|
-
child.once('error', () => { resolve(1); });
|
|
47
|
-
});
|
|
48
|
-
return { exited };
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Waits for the operator to press Enter at the idle daemon terminal.
|
|
52
|
-
*
|
|
53
|
-
* @param input - The terminal's input; `process.stdin` by default.
|
|
54
|
-
* @returns True on a line of input; false when the input ends.
|
|
55
|
-
*/
|
|
56
|
-
export function enter_await(input = process.stdin) {
|
|
57
|
-
return new Promise((resolve) => {
|
|
58
|
-
const cleanup = () => {
|
|
59
|
-
input.off('data', onData);
|
|
60
|
-
input.off('end', onEnd);
|
|
61
|
-
input.pause();
|
|
62
|
-
};
|
|
63
|
-
const onData = () => { cleanup(); resolve(true); };
|
|
64
|
-
const onEnd = () => { cleanup(); resolve(false); };
|
|
65
|
-
input.on('data', onData);
|
|
66
|
-
input.once('end', onEnd);
|
|
67
|
-
input.resume();
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
/** The live seams: a real child on the wire, the real cage, the real terminal. */
|
|
71
|
-
const LIVE_DEPS = {
|
|
72
|
-
attach: (target) => surface_spawn(target),
|
|
73
|
-
cage_start: consoleCage_start,
|
|
74
|
-
cage_stop: consoleCage_stop,
|
|
75
|
-
enter_wait: () => enter_await(),
|
|
76
|
-
log: (line) => { console.log(line); },
|
|
77
|
-
};
|
|
78
|
-
/**
|
|
79
|
-
* Holds the terminal's interrupt while a surface has it.
|
|
80
|
-
*
|
|
81
|
-
* The surface's readline owns Ctrl-C while attached (it clears the typed
|
|
82
|
-
* line, as chell always has); the daemon's own stop-on-interrupt is put
|
|
83
|
-
* back once the surface detaches, so Ctrl-C at the idle terminal stops
|
|
84
|
-
* the daemon as before.
|
|
85
|
-
*
|
|
86
|
-
* @returns A restore function.
|
|
87
|
-
*/
|
|
88
|
-
function interrupt_hold() {
|
|
89
|
-
const held = process.listeners('SIGINT');
|
|
90
|
-
process.removeAllListeners('SIGINT');
|
|
91
|
-
const ignore = () => { };
|
|
92
|
-
process.on('SIGINT', ignore);
|
|
93
|
-
return () => {
|
|
94
|
-
process.off('SIGINT', ignore);
|
|
95
|
-
for (const listener of held)
|
|
96
|
-
process.on('SIGINT', listener);
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Runs the daemon console until the operator leaves the terminal idle for
|
|
101
|
-
* good: attach, detach on `exit`, attach again on Enter, until stdin ends.
|
|
21
|
+
* Runs the daemon console on chell's own terminal, spawning this chell as
|
|
22
|
+
* the surface.
|
|
102
23
|
*
|
|
103
24
|
* @param target - The daemon to attach to.
|
|
104
|
-
* @param deps - The seams; the live ones by default.
|
|
105
25
|
* @returns Resolves when the operator will not attach again.
|
|
106
26
|
*/
|
|
107
|
-
export async function daemonConsole_run(target
|
|
108
|
-
|
|
109
|
-
deps.log(chalk.green(`[+] Console attached to ${target.identity} — 'exit' detaches, Enter attaches again, Ctrl-C then stops the daemon`));
|
|
110
|
-
deps.cage_start();
|
|
111
|
-
const restore = interrupt_hold();
|
|
112
|
-
let held;
|
|
113
|
-
try {
|
|
114
|
-
await deps.attach(target).exited;
|
|
115
|
-
}
|
|
116
|
-
finally {
|
|
117
|
-
restore();
|
|
118
|
-
held = deps.cage_stop();
|
|
119
|
-
}
|
|
120
|
-
if (held.length > 0) {
|
|
121
|
-
deps.log(chalk.gray('[+] While the console was attached:'));
|
|
122
|
-
for (const line of held)
|
|
123
|
-
deps.log(line);
|
|
124
|
-
}
|
|
125
|
-
deps.log(chalk.green('[+] Console detached; the daemon is still running. Enter attaches again, Ctrl-C stops the daemon.'));
|
|
126
|
-
if (!(await deps.enter_wait()))
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
27
|
+
export async function daemonConsole_run(target) {
|
|
28
|
+
return consoleSession_run(target, consoleDeps_live(CHELL_LAUNCH));
|
|
129
29
|
}
|
|
130
30
|
//# sourceMappingURL=daemonConsole.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"daemonConsole.js","sourceRoot":"","sources":["../../src/core/daemonConsole.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"daemonConsole.js","sourceRoot":"","sources":["../../src/core/daemonConsole.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EACL,iBAAiB,IAAI,kBAAkB,EACvC,gBAAgB,GAGjB,MAAM,iBAAiB,CAAC;AAIzB,oEAAoE;AACpE,MAAM,CAAC,MAAM,WAAW,GAAW,aAAa,CAAC,IAAI,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE1F,6EAA6E;AAC7E,MAAM,YAAY,GAAkB,EAAE,IAAI,EAAE,OAAO,CAAC,QAAQ,EAAE,UAAU,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC;AAE1F;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,MAA2B;IACjE,OAAO,kBAAkB,CAAC,MAAM,EAAE,gBAAgB,CAAC,YAAY,CAAC,CAAC,CAAC;AACpE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fnndsc/chell",
|
|
3
|
-
"version": "5.7.
|
|
3
|
+
"version": "5.7.1",
|
|
4
4
|
"description": "ChELL Executes Layered Logic - Interactive ChRIS REPL Shell",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"license": "MIT",
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"@fnndsc/brasa": "^0.20.0",
|
|
42
|
-
"@fnndsc/calypso": "^0.
|
|
42
|
+
"@fnndsc/calypso": "^0.13.0",
|
|
43
43
|
"@fnndsc/chili": "^3.6.6",
|
|
44
44
|
"@fnndsc/cumin": "^3.21.0",
|
|
45
45
|
"@fnndsc/salsa": "^3.15.0",
|