@fnndsc/calypso 0.3.7 → 0.4.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.
@@ -0,0 +1,148 @@
1
+ /**
2
+ * The advertised location of one running daemon, keyed by CUBE identity.
3
+ *
4
+ * @property identity - The normalised `<user>@<url>` this daemon hosts; stored
5
+ * so a resolve can verify an exact match rather than trust the filename hash
6
+ * alone.
7
+ * @property url - The daemon's WebSocket address (e.g. `ws://127.0.0.1:54321`).
8
+ * @property token - The attach token gating the daemon's handshake.
9
+ */
10
+ export interface Berth {
11
+ identity: string;
12
+ url: string;
13
+ token: string;
14
+ }
15
+ /**
16
+ * Normalises a `<user>@<url>` identity lexically — no DNS, no network.
17
+ *
18
+ * The URL scheme and host are lowercased; the trailing slash CUBE requires is
19
+ * preserved; the port and the user's case are kept exactly. Host aliases (a
20
+ * short hostname versus its FQDN) are deliberately *not* merged: that is DNS
21
+ * resolution, not string rewriting, and a key that depends on DNS breaks under
22
+ * load balancers and split-horizon resolution. The rule is "same string, same
23
+ * daemon" — operators adopt one canonical URL per CUBE by convention.
24
+ *
25
+ * @param user - The CUBE username, used with exact case.
26
+ * @param cubeUrl - The CUBE API URL as the user typed it (scheme included).
27
+ * @returns The normalised identity string used as the berth key input.
28
+ */
29
+ export declare function identity_normalise(user: string, cubeUrl: string): string;
30
+ /** The reserved identity for a daemon started with no restored CUBE session. */
31
+ export declare const DISCONNECTED_IDENTITY: string;
32
+ /**
33
+ * Derives the berth identity for a session, falling back to the reserved
34
+ * disconnected identity when there is no restored user/URL. Both the daemon
35
+ * (writing its berth) and a surface (guarding against a duplicate, or attaching)
36
+ * key on this so they always agree.
37
+ *
38
+ * @param user - The connected CUBE username, or null/undefined when disconnected.
39
+ * @param cubeUrl - The connected CUBE URL, or null/undefined when disconnected.
40
+ * @returns The normalised identity, or {@link DISCONNECTED_IDENTITY}.
41
+ */
42
+ export declare function identity_forSession(user: string | null | undefined, cubeUrl: string | null | undefined): string;
43
+ /**
44
+ * Computes the short, filesystem-safe key for a normalised identity.
45
+ *
46
+ * @param identity - A normalised identity from {@link identity_normalise}.
47
+ * @returns The first 16 hex characters of the identity's SHA-256 digest.
48
+ */
49
+ export declare function berthKey_compute(identity: string): string;
50
+ /**
51
+ * The directory berths live in: `$XDG_RUNTIME_DIR/calypso` when the runtime
52
+ * directory is set (Linux, per-user `0700`, cleared on logout), else the system
53
+ * temp directory (macOS `TMPDIR` is already per-user-private; Linux `/tmp`).
54
+ *
55
+ * @returns The absolute berth directory path (not guaranteed to exist yet).
56
+ */
57
+ export declare function berthDir_path(): string;
58
+ /**
59
+ * The absolute path of one identity's berth file.
60
+ *
61
+ * @param identity - A normalised identity from {@link identity_normalise}.
62
+ * @returns The berth file path (may not exist).
63
+ */
64
+ export declare function berth_path(identity: string): string;
65
+ /**
66
+ * Writes a berth to its identity-keyed file, readable only by the current user.
67
+ *
68
+ * @param berth - The berth to advertise; its `identity` must be normalised.
69
+ */
70
+ export declare function berth_write(berth: Berth): void;
71
+ /**
72
+ * Reads one identity's berth from disk, verifying the stored identity matches
73
+ * exactly (so a hash collision can never mis-route).
74
+ *
75
+ * @param identity - A normalised identity from {@link identity_normalise}.
76
+ * @returns The berth, or null when none is advertised or it is malformed.
77
+ */
78
+ export declare function berth_read(identity: string): Berth | null;
79
+ /**
80
+ * Reads every advertised berth in the berth directory.
81
+ *
82
+ * @returns All well-formed berths; an empty array when the directory is absent
83
+ * or holds none.
84
+ */
85
+ export declare function berthAll_read(): Berth[];
86
+ /**
87
+ * Removes an identity's berth file if present (used to reap a berth whose
88
+ * daemon a liveness probe found dead).
89
+ *
90
+ * @param identity - A normalised identity from {@link identity_normalise}.
91
+ */
92
+ export declare function berth_remove(identity: string): void;
93
+ /**
94
+ * Reports whether something is listening at a berth's WebSocket address, by a
95
+ * plain TCP connect — no WebSocket handshake, so this stays within the daemon
96
+ * package (which has no client). It is the liveness check `daemon_launch` uses
97
+ * to refuse starting a rival for an identity that is already hosted; a surface's
98
+ * resolver uses a stronger handshake probe for attach.
99
+ *
100
+ * @param url - A `ws://host:port` berth URL.
101
+ * @param timeoutMs - How long to wait for the TCP connect (default 500 ms).
102
+ * @returns True when the port accepts a connection.
103
+ */
104
+ export declare function berthUrl_isAlive(url: string, timeoutMs?: number): Promise<boolean>;
105
+ /**
106
+ * A probe that reports whether a berth's daemon is actually reachable. The
107
+ * surface supplies one backed by its attach client; the local resolver uses it
108
+ * to reap dead berths on read.
109
+ */
110
+ export type BerthLivenessProbe = (berth: Berth) => Promise<boolean>;
111
+ /**
112
+ * The berth lookup seam. Tier 1 ships {@link LocalBerthResolver} over the local
113
+ * files; a future tier-2 `PorterBerthResolver` will implement the same contract
114
+ * over the network. Every surface depends only on this interface.
115
+ */
116
+ export interface BerthResolver {
117
+ /**
118
+ * Resolves one identity to a live berth.
119
+ *
120
+ * @param identity - A normalised identity from {@link identity_normalise}.
121
+ * @returns The live berth, or null when none is advertised or it is dead.
122
+ */
123
+ resolve(identity: string): Promise<Berth | null>;
124
+ /**
125
+ * Lists every live berth (for a bare `--remote` with several daemons).
126
+ *
127
+ * @returns The live berths, dead ones reaped.
128
+ */
129
+ list(): Promise<Berth[]>;
130
+ }
131
+ /**
132
+ * The tier-1 resolver: reads identity-keyed berth files and, when given a
133
+ * liveness probe, reaps any berth whose daemon has gone (passive cleanup — the
134
+ * next read of a stale berth removes it). Without a probe it returns berths as
135
+ * recorded, trusting the caller's own attach to surface a dead one.
136
+ */
137
+ export declare class LocalBerthResolver implements BerthResolver {
138
+ private readonly liveness_probe?;
139
+ /**
140
+ * @param liveness_probe - Optional reachability probe; when present, dead
141
+ * berths are reaped and never returned.
142
+ */
143
+ constructor(liveness_probe?: BerthLivenessProbe | undefined);
144
+ /** @inheritdoc */
145
+ resolve(identity: string): Promise<Berth | null>;
146
+ /** @inheritdoc */
147
+ list(): Promise<Berth[]>;
148
+ }
@@ -0,0 +1,288 @@
1
+ /**
2
+ * @file Identity-keyed daemon berths.
3
+ *
4
+ * A *berth* is the advertised location of one running CALYPSO daemon, keyed by
5
+ * the CUBE identity it hosts. It supersedes the single per-OS-user discovery
6
+ * file: several daemons — one per `<user>@<url>` identity — can now advertise on
7
+ * one machine, each in its own file, and a surface resolves the one it wants by
8
+ * identity.
9
+ *
10
+ * The berth records the daemon's WebSocket address and attach token. Files live
11
+ * in the user's runtime directory (`$XDG_RUNTIME_DIR`, else the system temp dir)
12
+ * under an owned `calypso/` subdirectory, `0700` on the directory and `0600` on
13
+ * each file — the same same-user perimeter the single-file discovery used, now
14
+ * multiplied by identity. See docs/session-supervisor.adoc for the design.
15
+ *
16
+ * All berth lookup goes through the {@link BerthResolver} seam so a future
17
+ * network `PorterBerthResolver` can replace the local one without any surface
18
+ * change. Liveness (is the daemon still there?) is supplied to the local
19
+ * resolver as an injected probe, keeping this server-side package free of a
20
+ * WebSocket client: the surface injects a probe backed by its own attach client.
21
+ *
22
+ * @module
23
+ */
24
+ import { writeFileSync, readFileSync, existsSync, mkdirSync, readdirSync, unlinkSync } from 'fs';
25
+ import { join } from 'path';
26
+ import { tmpdir } from 'os';
27
+ import { createHash } from 'node:crypto';
28
+ import { connect as net_connect } from 'node:net';
29
+ /** The prefix of every berth filename, so a directory scan finds only berths. */
30
+ const BERTH_FILE_PREFIX = 'berth-';
31
+ /** The owned subdirectory berths live under, inside the runtime directory. */
32
+ const BERTH_SUBDIR = 'calypso';
33
+ /**
34
+ * Normalises a `<user>@<url>` identity lexically — no DNS, no network.
35
+ *
36
+ * The URL scheme and host are lowercased; the trailing slash CUBE requires is
37
+ * preserved; the port and the user's case are kept exactly. Host aliases (a
38
+ * short hostname versus its FQDN) are deliberately *not* merged: that is DNS
39
+ * resolution, not string rewriting, and a key that depends on DNS breaks under
40
+ * load balancers and split-horizon resolution. The rule is "same string, same
41
+ * daemon" — operators adopt one canonical URL per CUBE by convention.
42
+ *
43
+ * @param user - The CUBE username, used with exact case.
44
+ * @param cubeUrl - The CUBE API URL as the user typed it (scheme included).
45
+ * @returns The normalised identity string used as the berth key input.
46
+ */
47
+ export function identity_normalise(user, cubeUrl) {
48
+ const schemeSplit = cubeUrl.indexOf('://');
49
+ let normalisedUrl;
50
+ if (schemeSplit === -1) {
51
+ normalisedUrl = cubeUrl;
52
+ }
53
+ else {
54
+ const scheme = cubeUrl.slice(0, schemeSplit).toLowerCase();
55
+ const rest = cubeUrl.slice(schemeSplit + 3);
56
+ // Lowercase only the authority (host[:port]); leave the path exactly as
57
+ // written, including the trailing slash CUBE requires.
58
+ const pathStart = rest.indexOf('/');
59
+ const authority = pathStart === -1 ? rest : rest.slice(0, pathStart);
60
+ const path = pathStart === -1 ? '' : rest.slice(pathStart);
61
+ normalisedUrl = `${scheme}://${authority.toLowerCase()}${path}`;
62
+ }
63
+ return `${user}@${normalisedUrl}`;
64
+ }
65
+ /** The reserved identity for a daemon started with no restored CUBE session. */
66
+ export const DISCONNECTED_IDENTITY = 'disconnected@no-cube';
67
+ /**
68
+ * Derives the berth identity for a session, falling back to the reserved
69
+ * disconnected identity when there is no restored user/URL. Both the daemon
70
+ * (writing its berth) and a surface (guarding against a duplicate, or attaching)
71
+ * key on this so they always agree.
72
+ *
73
+ * @param user - The connected CUBE username, or null/undefined when disconnected.
74
+ * @param cubeUrl - The connected CUBE URL, or null/undefined when disconnected.
75
+ * @returns The normalised identity, or {@link DISCONNECTED_IDENTITY}.
76
+ */
77
+ export function identity_forSession(user, cubeUrl) {
78
+ return user && cubeUrl ? identity_normalise(user, cubeUrl) : DISCONNECTED_IDENTITY;
79
+ }
80
+ /**
81
+ * Computes the short, filesystem-safe key for a normalised identity.
82
+ *
83
+ * @param identity - A normalised identity from {@link identity_normalise}.
84
+ * @returns The first 16 hex characters of the identity's SHA-256 digest.
85
+ */
86
+ export function berthKey_compute(identity) {
87
+ return createHash('sha256').update(identity).digest('hex').slice(0, 16);
88
+ }
89
+ /**
90
+ * The directory berths live in: `$XDG_RUNTIME_DIR/calypso` when the runtime
91
+ * directory is set (Linux, per-user `0700`, cleared on logout), else the system
92
+ * temp directory (macOS `TMPDIR` is already per-user-private; Linux `/tmp`).
93
+ *
94
+ * @returns The absolute berth directory path (not guaranteed to exist yet).
95
+ */
96
+ export function berthDir_path() {
97
+ const runtimeDir = process.env.XDG_RUNTIME_DIR || tmpdir();
98
+ return join(runtimeDir, BERTH_SUBDIR);
99
+ }
100
+ /**
101
+ * Ensures the berth directory exists, owner-only (`0700`).
102
+ */
103
+ function berthDir_ensure() {
104
+ mkdirSync(berthDir_path(), { recursive: true, mode: 0o700 });
105
+ }
106
+ /**
107
+ * The absolute path of one identity's berth file.
108
+ *
109
+ * @param identity - A normalised identity from {@link identity_normalise}.
110
+ * @returns The berth file path (may not exist).
111
+ */
112
+ export function berth_path(identity) {
113
+ return join(berthDir_path(), `${BERTH_FILE_PREFIX}${berthKey_compute(identity)}.json`);
114
+ }
115
+ /**
116
+ * Writes a berth to its identity-keyed file, readable only by the current user.
117
+ *
118
+ * @param berth - The berth to advertise; its `identity` must be normalised.
119
+ */
120
+ export function berth_write(berth) {
121
+ berthDir_ensure();
122
+ writeFileSync(berth_path(berth.identity), JSON.stringify(berth), { mode: 0o600 });
123
+ }
124
+ /**
125
+ * Validates that an unknown parsed value is a well-formed {@link Berth}.
126
+ *
127
+ * @param parsed - The value read from a berth file.
128
+ * @returns The value as a Berth, or null when it is malformed.
129
+ */
130
+ function berth_validate(parsed) {
131
+ if (typeof parsed === 'object' && parsed !== null &&
132
+ typeof parsed.identity === 'string' &&
133
+ typeof parsed.url === 'string' &&
134
+ typeof parsed.token === 'string') {
135
+ return parsed;
136
+ }
137
+ return null;
138
+ }
139
+ /**
140
+ * Reads one identity's berth from disk, verifying the stored identity matches
141
+ * exactly (so a hash collision can never mis-route).
142
+ *
143
+ * @param identity - A normalised identity from {@link identity_normalise}.
144
+ * @returns The berth, or null when none is advertised or it is malformed.
145
+ */
146
+ export function berth_read(identity) {
147
+ const path = berth_path(identity);
148
+ if (!existsSync(path)) {
149
+ return null;
150
+ }
151
+ try {
152
+ const berth = berth_validate(JSON.parse(readFileSync(path, 'utf-8')));
153
+ return berth && berth.identity === identity ? berth : null;
154
+ }
155
+ catch {
156
+ return null;
157
+ }
158
+ }
159
+ /**
160
+ * Reads every advertised berth in the berth directory.
161
+ *
162
+ * @returns All well-formed berths; an empty array when the directory is absent
163
+ * or holds none.
164
+ */
165
+ export function berthAll_read() {
166
+ const dir = berthDir_path();
167
+ if (!existsSync(dir)) {
168
+ return [];
169
+ }
170
+ const berths = [];
171
+ for (const name of readdirSync(dir)) {
172
+ if (!name.startsWith(BERTH_FILE_PREFIX) || !name.endsWith('.json')) {
173
+ continue;
174
+ }
175
+ try {
176
+ const berth = berth_validate(JSON.parse(readFileSync(join(dir, name), 'utf-8')));
177
+ if (berth) {
178
+ berths.push(berth);
179
+ }
180
+ }
181
+ catch {
182
+ // A malformed or vanished file is simply skipped.
183
+ }
184
+ }
185
+ return berths;
186
+ }
187
+ /**
188
+ * Removes an identity's berth file if present (used to reap a berth whose
189
+ * daemon a liveness probe found dead).
190
+ *
191
+ * @param identity - A normalised identity from {@link identity_normalise}.
192
+ */
193
+ export function berth_remove(identity) {
194
+ const path = berth_path(identity);
195
+ if (existsSync(path)) {
196
+ try {
197
+ unlinkSync(path);
198
+ }
199
+ catch {
200
+ // Already gone: the reap is a best-effort convenience.
201
+ }
202
+ }
203
+ }
204
+ /**
205
+ * Reports whether something is listening at a berth's WebSocket address, by a
206
+ * plain TCP connect — no WebSocket handshake, so this stays within the daemon
207
+ * package (which has no client). It is the liveness check `daemon_launch` uses
208
+ * to refuse starting a rival for an identity that is already hosted; a surface's
209
+ * resolver uses a stronger handshake probe for attach.
210
+ *
211
+ * @param url - A `ws://host:port` berth URL.
212
+ * @param timeoutMs - How long to wait for the TCP connect (default 500 ms).
213
+ * @returns True when the port accepts a connection.
214
+ */
215
+ export function berthUrl_isAlive(url, timeoutMs = 500) {
216
+ return new Promise((resolve) => {
217
+ let host;
218
+ let port;
219
+ try {
220
+ const parsed = new URL(url);
221
+ host = parsed.hostname;
222
+ port = Number(parsed.port);
223
+ }
224
+ catch {
225
+ resolve(false);
226
+ return;
227
+ }
228
+ if (!port) {
229
+ resolve(false);
230
+ return;
231
+ }
232
+ const socket = net_connect({ host, port });
233
+ const settle = (alive) => {
234
+ socket.destroy();
235
+ resolve(alive);
236
+ };
237
+ socket.setTimeout(timeoutMs);
238
+ socket.once('connect', () => settle(true));
239
+ socket.once('timeout', () => settle(false));
240
+ socket.once('error', () => settle(false));
241
+ });
242
+ }
243
+ /**
244
+ * The tier-1 resolver: reads identity-keyed berth files and, when given a
245
+ * liveness probe, reaps any berth whose daemon has gone (passive cleanup — the
246
+ * next read of a stale berth removes it). Without a probe it returns berths as
247
+ * recorded, trusting the caller's own attach to surface a dead one.
248
+ */
249
+ export class LocalBerthResolver {
250
+ liveness_probe;
251
+ /**
252
+ * @param liveness_probe - Optional reachability probe; when present, dead
253
+ * berths are reaped and never returned.
254
+ */
255
+ constructor(liveness_probe) {
256
+ this.liveness_probe = liveness_probe;
257
+ }
258
+ /** @inheritdoc */
259
+ async resolve(identity) {
260
+ const berth = berth_read(identity);
261
+ if (!berth) {
262
+ return null;
263
+ }
264
+ if (this.liveness_probe && !(await this.liveness_probe(berth))) {
265
+ berth_remove(berth.identity);
266
+ return null;
267
+ }
268
+ return berth;
269
+ }
270
+ /** @inheritdoc */
271
+ async list() {
272
+ const berths = berthAll_read();
273
+ if (!this.liveness_probe) {
274
+ return berths;
275
+ }
276
+ const live = [];
277
+ for (const berth of berths) {
278
+ if (await this.liveness_probe(berth)) {
279
+ live.push(berth);
280
+ }
281
+ else {
282
+ berth_remove(berth.identity);
283
+ }
284
+ }
285
+ return live;
286
+ }
287
+ }
288
+ //# sourceMappingURL=berth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"berth.js","sourceRoot":"","sources":["../../src/daemon/berth.ts"],"names":[],"mappings":"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"}
@@ -17,7 +17,8 @@ import { token_generate } from './token.js';
17
17
  import { sink_set } from '@fnndsc/brasa';
18
18
  import { surface_set } from '@fnndsc/brasa';
19
19
  import { sessionPromptContext_build } from '@fnndsc/brasa';
20
- import { discovery_write, discovery_path } from './discovery.js';
20
+ import { chrisContext } from '@fnndsc/cumin';
21
+ import { identity_forSession, berth_write, berth_read, berth_path, berthUrl_isAlive, DISCONNECTED_IDENTITY } from './berth.js';
21
22
  /** The daemon sink forwards live command output to the executing surface. */
22
23
  class DaemonSink {
23
24
  daemon;
@@ -49,6 +50,24 @@ export async function daemon_launch(engine) {
49
50
  if (chalk.level < 1) {
50
51
  chalk.level = 3;
51
52
  }
53
+ // Key the berth by the CUBE identity this daemon hosts, so several daemons —
54
+ // one per identity — can advertise on one machine. A daemon with no restored
55
+ // session (disconnected standalone start) falls back to a sentinel identity,
56
+ // matching the disconnected prompt context, so it stays discoverable.
57
+ const cubeUrl = await chrisContext.ChRISURL_get();
58
+ const cubeUser = await chrisContext.ChRISuser_get();
59
+ const identity = identity_forSession(cubeUser, cubeUrl);
60
+ // Guard against a split-brain second daemon for this identity: if one is
61
+ // already live, point the operator at it and refuse rather than host a rival
62
+ // and orphan the running one's berth. This covers both launch paths (chell
63
+ // --daemon and the standalone calypso binary), since both land here.
64
+ const existing = berth_read(identity);
65
+ if (existing && (await berthUrl_isAlive(existing.url))) {
66
+ const attachHint = identity === DISCONNECTED_IDENTITY ? '' : ` ${identity}`;
67
+ console.error(chalk.red(`[!] A CALYPSO daemon for ${identity} is already running at ${existing.url}`));
68
+ console.error(chalk.gray(` attach with: chell --remote${attachHint}`));
69
+ process.exit(1);
70
+ }
52
71
  const token = token_generate();
53
72
  const daemon = new CalypsoDaemon({
54
73
  engine,
@@ -73,10 +92,13 @@ export async function daemon_launch(engine) {
73
92
  surface_set(surface);
74
93
  const port = await daemon.start();
75
94
  const url = `ws://127.0.0.1:${port}`;
76
- discovery_write({ url, token });
95
+ const berth = { identity, url, token };
96
+ berth_write(berth);
97
+ const attachHint = identity === DISCONNECTED_IDENTITY ? '' : ` ${identity}`;
77
98
  console.log(chalk.green(`[+] CALYPSO daemon listening on ${url}`));
99
+ console.log(chalk.gray(` identity: ${identity}`));
78
100
  console.log(chalk.gray(` token: ${token}`));
79
- console.log(chalk.gray(` discovery: ${discovery_path()}`));
80
- console.log(chalk.gray(' attach a surface with: chell --remote'));
101
+ console.log(chalk.gray(` berth: ${berth_path(identity)}`));
102
+ console.log(chalk.gray(` attach a surface with: chell --remote${attachHint}`));
81
103
  }
82
104
  //# sourceMappingURL=launch.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"launch.js","sourceRoot":"","sources":["../../src/daemon/launch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"launch.js","sourceRoot":"","sources":["../../src/daemon/launch.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -19,3 +19,4 @@ export { token_generate, token_writeFile, token_matches } from './daemon/token.j
19
19
  export { CalypsoDaemon, type DaemonOptions, type EditOutcome } from './daemon/server.js';
20
20
  export { daemon_launch } from './daemon/launch.js';
21
21
  export { discovery_read, discovery_write, discovery_path, type Discovery } from './daemon/discovery.js';
22
+ export { identity_normalise, identity_forSession, DISCONNECTED_IDENTITY, berthKey_compute, berthDir_path, berth_path, berth_write, berth_read, berthAll_read, berth_remove, berthUrl_isAlive, LocalBerthResolver, type Berth, type BerthResolver, type BerthLivenessProbe, } from './daemon/berth.js';
package/dist/index.js CHANGED
@@ -18,4 +18,5 @@ export { token_generate, token_writeFile, token_matches } from './daemon/token.j
18
18
  export { CalypsoDaemon } from './daemon/server.js';
19
19
  export { daemon_launch } from './daemon/launch.js';
20
20
  export { discovery_read, discovery_write, discovery_path } from './daemon/discovery.js';
21
+ export { identity_normalise, identity_forSession, DISCONNECTED_IDENTITY, berthKey_compute, berthDir_path, berth_path, berth_write, berth_read, berthAll_read, berth_remove, berthUrl_isAlive, LocalBerthResolver, } from './daemon/berth.js';
21
22
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,qBAAqB,GAEtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,EACrB,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,uBAAuB,EACvB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,qBAAqB,EACrB,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,GAIpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,sBAAsB,EACtB,YAAY,GAEb,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACnF,OAAO,EAAE,aAAa,EAAwC,MAAM,oBAAoB,CAAC;AACzF,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAkB,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,qBAAqB,GAEtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,EACrB,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,uBAAuB,EACvB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,qBAAqB,EACrB,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,GAIpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,sBAAsB,EACtB,YAAY,GAEb,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACnF,OAAO,EAAE,aAAa,EAAwC,MAAM,oBAAoB,CAAC;AACzF,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAkB,MAAM,uBAAuB,CAAC;AACxG,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,gBAAgB,EAChB,aAAa,EACb,UAAU,EACV,WAAW,EACX,UAAU,EACV,aAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,GAInB,MAAM,mBAAmB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fnndsc/calypso",
3
- "version": "0.3.7",
3
+ "version": "0.4.1",
4
4
  "description": "The CALYPSO wire contract: typed protocol schemas and boundary validation for the ChRIS session daemon",
5
5
  "repository": {
6
6
  "type": "git",
@@ -51,8 +51,8 @@
51
51
  "typescript": "^5.0.0"
52
52
  },
53
53
  "dependencies": {
54
- "@fnndsc/brasa": "^0.8.0",
55
- "@fnndsc/cumin": "^3.7.0",
54
+ "@fnndsc/brasa": "^0.9.0",
55
+ "@fnndsc/cumin": "^3.8.0",
56
56
  "chalk": "^4.1.2",
57
57
  "ws": "^8.18.0",
58
58
  "zod": "^3.23.8"