posipaki 0.47.0 → 0.48.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.
- package/dist/actor-C8DzeQeT.js +258 -0
- package/dist/actor-C8DzeQeT.js.map +1 -0
- package/dist/index-B3FcBNz7.d.ts +105 -0
- package/dist/index-B3FcBNz7.d.ts.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/port/index.d.ts +3 -0
- package/dist/port/index.js +3 -0
- package/dist/port/node.d.ts +73 -0
- package/dist/port/node.d.ts.map +1 -0
- package/dist/port/node.js +353 -0
- package/dist/port/node.js.map +1 -0
- package/dist/port-DowG9tgl.js +493 -0
- package/dist/port-DowG9tgl.js.map +1 -0
- package/dist/reactor-CWPBP7qN.d.ts +135 -0
- package/dist/reactor-CWPBP7qN.d.ts.map +1 -0
- package/dist/remote/gateway-cli.js +74 -55
- package/dist/remote/gateway-cli.js.map +1 -1
- package/dist/remote/index.d.ts +71 -13
- package/dist/remote/index.d.ts.map +1 -1
- package/dist/remote/index.js +15 -19
- package/dist/remote/index.js.map +1 -1
- package/dist/remote/node.d.ts +17 -10
- package/dist/remote/node.d.ts.map +1 -1
- package/dist/remote/node.js +73 -47
- package/dist/remote/node.js.map +1 -1
- package/dist/{version-DRbb_jh2.js → version-CjO8pCPA.js} +2 -2
- package/dist/{version-DRbb_jh2.js.map → version-CjO8pCPA.js.map} +1 -1
- package/dist/{websocket-GFSUt3YC.d.ts → websocket-AU2aygxx.d.ts} +49 -24
- package/dist/websocket-AU2aygxx.d.ts.map +1 -0
- package/dist/{websocket-Dnorztuc.js → websocket-Ddmd6p1n.js} +529 -134
- package/dist/websocket-Ddmd6p1n.js.map +1 -0
- package/package.json +9 -1
- package/dist/websocket-Dnorztuc.js.map +0 -1
- package/dist/websocket-GFSUt3YC.d.ts.map +0 -1
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import { n as defineMessages, t as defineActor } from "./define-actor-DR1P1PA5.js";
|
|
2
|
+
import { StringDecoder } from "node:string_decoder";
|
|
3
|
+
//#region src/port/split.ts
|
|
4
|
+
const NL = 10;
|
|
5
|
+
const CR = 13;
|
|
6
|
+
const NOTHING = () => null;
|
|
7
|
+
/**
|
|
8
|
+
* One byte channel in, one channel of parts out.
|
|
9
|
+
*
|
|
10
|
+
* The returned channel's `send` is the same rule backwards: a part becomes its line, a terminator, and the
|
|
11
|
+
* octets it carried.
|
|
12
|
+
*/
|
|
13
|
+
function splitChannel(inner, announced = NOTHING) {
|
|
14
|
+
const readers = /* @__PURE__ */ new Set();
|
|
15
|
+
const closers = /* @__PURE__ */ new Set();
|
|
16
|
+
const failers = /* @__PURE__ */ new Set();
|
|
17
|
+
const decoder = new StringDecoder("utf8");
|
|
18
|
+
/** Bytes that are not yet a frame: a line, or the octets a line announced. */
|
|
19
|
+
let buffered = Buffer.alloc(0);
|
|
20
|
+
/** The line whose announced octets are still arriving. */
|
|
21
|
+
let pending = null;
|
|
22
|
+
let ended = false;
|
|
23
|
+
let reason = null;
|
|
24
|
+
const emit = (part) => {
|
|
25
|
+
for (const reader of [...readers]) reader(part);
|
|
26
|
+
};
|
|
27
|
+
/** The far end is gone: our own readers hear it. */
|
|
28
|
+
const close = (why) => {
|
|
29
|
+
if (ended) return;
|
|
30
|
+
ended = true;
|
|
31
|
+
reason = why;
|
|
32
|
+
for (const closer of [...closers]) closer(why);
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* End it here: the far end hears a close, our own readers do not, because we are the one who asked. The
|
|
36
|
+
* reason stays null: a sentence from this side is not `C`, which is what the other end had to say.
|
|
37
|
+
*/
|
|
38
|
+
const shut = () => {
|
|
39
|
+
if (ended) return;
|
|
40
|
+
ended = true;
|
|
41
|
+
};
|
|
42
|
+
/** Hand over what the buffer holds, as far as the framing allows. */
|
|
43
|
+
const drain = () => {
|
|
44
|
+
while (!ended) {
|
|
45
|
+
if (pending !== null) {
|
|
46
|
+
if (buffered.length < pending.bytes) return;
|
|
47
|
+
const bytes = buffered.subarray(0, pending.bytes);
|
|
48
|
+
buffered = buffered.subarray(pending.bytes);
|
|
49
|
+
const line = pending.line;
|
|
50
|
+
pending = null;
|
|
51
|
+
emit({
|
|
52
|
+
line,
|
|
53
|
+
bytes: new Uint8Array(bytes)
|
|
54
|
+
});
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const cut = buffered.indexOf(NL);
|
|
58
|
+
if (cut === -1) return;
|
|
59
|
+
const raw = buffered.subarray(0, cut);
|
|
60
|
+
buffered = buffered.subarray(cut + 1);
|
|
61
|
+
const line = raw.length > 0 && raw[raw.length - 1] === CR ? raw.subarray(0, raw.length - 1) : raw;
|
|
62
|
+
const text = decoder.write(line);
|
|
63
|
+
const count = announced(text);
|
|
64
|
+
if (count === null) {
|
|
65
|
+
emit({
|
|
66
|
+
line: text,
|
|
67
|
+
bytes: null
|
|
68
|
+
});
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
pending = {
|
|
72
|
+
line: text,
|
|
73
|
+
bytes: count
|
|
74
|
+
};
|
|
75
|
+
if (count === 0) {
|
|
76
|
+
pending = null;
|
|
77
|
+
emit({
|
|
78
|
+
line: text,
|
|
79
|
+
bytes: /* @__PURE__ */ new Uint8Array(0)
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
inner.onFrame((chunk) => {
|
|
85
|
+
if (ended) return;
|
|
86
|
+
buffered = buffered.length === 0 ? Buffer.from(chunk) : Buffer.concat([buffered, Buffer.from(chunk)]);
|
|
87
|
+
drain();
|
|
88
|
+
});
|
|
89
|
+
inner.onError((error) => {
|
|
90
|
+
for (const failer of [...failers]) failer(error);
|
|
91
|
+
});
|
|
92
|
+
inner.onClose((why) => {
|
|
93
|
+
if (ended) return;
|
|
94
|
+
if (pending === null && buffered.length > 0) {
|
|
95
|
+
const rest = buffered;
|
|
96
|
+
buffered = Buffer.alloc(0);
|
|
97
|
+
emit({
|
|
98
|
+
line: decoder.write(rest) + decoder.end(),
|
|
99
|
+
bytes: null
|
|
100
|
+
});
|
|
101
|
+
} else decoder.end();
|
|
102
|
+
close(why);
|
|
103
|
+
});
|
|
104
|
+
return {
|
|
105
|
+
send: async (part) => {
|
|
106
|
+
const head = Buffer.from(`${part.line}\n`, "utf8");
|
|
107
|
+
const body = part.bytes === null ? head : Buffer.concat([head, Buffer.from(part.bytes)]);
|
|
108
|
+
await inner.send(new Uint8Array(body));
|
|
109
|
+
},
|
|
110
|
+
onFrame: (handler) => {
|
|
111
|
+
readers.add(handler);
|
|
112
|
+
return () => {
|
|
113
|
+
readers.delete(handler);
|
|
114
|
+
};
|
|
115
|
+
},
|
|
116
|
+
onClose: (handler) => {
|
|
117
|
+
if (ended && reason !== null) {
|
|
118
|
+
handler(reason);
|
|
119
|
+
return () => {};
|
|
120
|
+
}
|
|
121
|
+
closers.add(handler);
|
|
122
|
+
return () => {
|
|
123
|
+
closers.delete(handler);
|
|
124
|
+
};
|
|
125
|
+
},
|
|
126
|
+
onError: (handler) => {
|
|
127
|
+
failers.add(handler);
|
|
128
|
+
return () => {
|
|
129
|
+
failers.delete(handler);
|
|
130
|
+
};
|
|
131
|
+
},
|
|
132
|
+
close: async (why = "closed here") => {
|
|
133
|
+
shut();
|
|
134
|
+
await inner.close(why);
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
//#endregion
|
|
139
|
+
//#region src/port/held.ts
|
|
140
|
+
/**
|
|
141
|
+
* `inner`, with the frames that arrive before anyone is subscribed kept for the readers that follow.
|
|
142
|
+
*
|
|
143
|
+
* The kept frames are not bounded, because a bound depends on what the far end may say before anyone listens,
|
|
144
|
+
* and that is not something this adapter can know.
|
|
145
|
+
*/
|
|
146
|
+
function held(inner) {
|
|
147
|
+
const readers = /* @__PURE__ */ new Set();
|
|
148
|
+
const closers = /* @__PURE__ */ new Set();
|
|
149
|
+
const failers = /* @__PURE__ */ new Set();
|
|
150
|
+
const kept = [];
|
|
151
|
+
let live = false;
|
|
152
|
+
const emit = (frame) => {
|
|
153
|
+
for (const reader of [...readers]) reader(frame);
|
|
154
|
+
};
|
|
155
|
+
inner.onFrame((frame) => {
|
|
156
|
+
if (live) {
|
|
157
|
+
emit(frame);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
if (readers.size === 0) {
|
|
161
|
+
kept.push(frame);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
live = true;
|
|
165
|
+
kept.length = 0;
|
|
166
|
+
emit(frame);
|
|
167
|
+
});
|
|
168
|
+
inner.onClose((reason) => {
|
|
169
|
+
for (const closer of [...closers]) closer(reason);
|
|
170
|
+
});
|
|
171
|
+
inner.onError((error) => {
|
|
172
|
+
for (const failer of [...failers]) failer(error);
|
|
173
|
+
});
|
|
174
|
+
return {
|
|
175
|
+
send: (frame) => inner.send(frame),
|
|
176
|
+
onFrame(handler) {
|
|
177
|
+
readers.add(handler);
|
|
178
|
+
for (const frame of kept) handler(frame);
|
|
179
|
+
return () => {
|
|
180
|
+
readers.delete(handler);
|
|
181
|
+
};
|
|
182
|
+
},
|
|
183
|
+
onClose(handler) {
|
|
184
|
+
closers.add(handler);
|
|
185
|
+
return () => {
|
|
186
|
+
closers.delete(handler);
|
|
187
|
+
};
|
|
188
|
+
},
|
|
189
|
+
onError(handler) {
|
|
190
|
+
failers.add(handler);
|
|
191
|
+
return () => {
|
|
192
|
+
failers.delete(handler);
|
|
193
|
+
};
|
|
194
|
+
},
|
|
195
|
+
close: (reason) => inner.close(reason)
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
//#endregion
|
|
199
|
+
//#region src/port/actor.ts
|
|
200
|
+
/**
|
|
201
|
+
* An actor over one channel.
|
|
202
|
+
*
|
|
203
|
+
* In `SEND {data}` writes to it and `SIGNAL {signal}` asks the medium to act on what is behind it; posipaki's
|
|
204
|
+
* `STOP` ends the actor, which closes the channel. Out `DATA {data}` for every frame. The channel's ending is
|
|
205
|
+
* left in `state.end` and the actor stops.
|
|
206
|
+
*/
|
|
207
|
+
function portActor(spec) {
|
|
208
|
+
return defineActor({
|
|
209
|
+
name: spec.name,
|
|
210
|
+
inMessages: /* @__PURE__ */ defineMessages(),
|
|
211
|
+
outMessages: /* @__PURE__ */ defineMessages(),
|
|
212
|
+
setup: (args) => ({
|
|
213
|
+
public: {
|
|
214
|
+
alive: false,
|
|
215
|
+
end: null
|
|
216
|
+
},
|
|
217
|
+
private: {
|
|
218
|
+
channel: null,
|
|
219
|
+
args
|
|
220
|
+
}
|
|
221
|
+
}),
|
|
222
|
+
afterStart() {
|
|
223
|
+
const { args } = this.state.private;
|
|
224
|
+
spec.open(args).then((channel) => {
|
|
225
|
+
this.state.private.channel = channel;
|
|
226
|
+
this.state.public.alive = true;
|
|
227
|
+
channel.onFrame((data) => {
|
|
228
|
+
this.emit({
|
|
229
|
+
type: "DATA",
|
|
230
|
+
data
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
channel.onClose((reason) => {
|
|
234
|
+
this.state.public.alive = false;
|
|
235
|
+
this.state.public.end = reason;
|
|
236
|
+
this.exit();
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
},
|
|
240
|
+
async beforeEnd() {
|
|
241
|
+
this.state.public.alive = false;
|
|
242
|
+
await this.state.private.channel?.close();
|
|
243
|
+
},
|
|
244
|
+
handlers: {
|
|
245
|
+
async SEND(msg) {
|
|
246
|
+
await this.state.private.channel?.send(msg.data);
|
|
247
|
+
},
|
|
248
|
+
SIGNAL(msg) {
|
|
249
|
+
const channel = this.state.private.channel;
|
|
250
|
+
if (channel !== null) spec.signal?.(channel, msg.signal);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
//#endregion
|
|
256
|
+
export { held as n, splitChannel as r, portActor as t };
|
|
257
|
+
|
|
258
|
+
//# sourceMappingURL=actor-C8DzeQeT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actor-C8DzeQeT.js","names":[],"sources":["../src/port/split.ts","../src/port/held.ts","../src/port/actor.ts"],"sourcesContent":["// ── bytes into parts: the splitter ──────────────────────────────────────────\n//\n// Cuts a stream of bytes on 0x0a; what lies between two cuts is a line. Every byte medium does this: a stdio pair,\n// a socket, an HTTP body.\n\n// Splitting on the byte is safe for UTF-8: a continuation byte is never 0x0a, so a character cannot be cut in\n// half. A character that straddles two chunks waits in the buffer until the rest arrives.\n//\n// Text is decoded by a StringDecoder for the same reason: half a character waits rather than becoming two\n// replacement marks.\n//\n// A line may announce octets after it. The splitter does not know that rule, so it is passed in: given a line,\n// how many raw octets follow it? The seam answers with `$chunk`; a medium with no such thing answers none.\n\nimport { StringDecoder } from \"node:string_decoder\";\n\nimport type { Channel, Part } from \"./channel.js\";\n\nconst NL = 0x0a;\nconst CR = 0x0d;\n\n/** Given a line, how many raw octets follow it. Default: none, this is a plain line. */\nexport type Announcement = (line: string) => number | null;\n\nconst NOTHING: Announcement = () => null;\n\n/**\n * One byte channel in, one channel of parts out.\n *\n * The returned channel's `send` is the same rule backwards: a part becomes its line, a terminator, and the\n * octets it carried.\n */\nexport function splitChannel<C = string>(\n inner: Channel<Uint8Array, C>,\n announced: Announcement = NOTHING,\n): Channel<Part, C> {\n const readers = new Set<(part: Part) => void>();\n const closers = new Set<(reason: C) => void>();\n const failers = new Set<(error: unknown) => void>();\n const decoder = new StringDecoder(\"utf8\");\n /** Bytes that are not yet a frame: a line, or the octets a line announced. */\n let buffered = Buffer.alloc(0);\n /** The line whose announced octets are still arriving. */\n let pending: { line: string; bytes: number } | null = null;\n let ended = false;\n let reason: C | null = null;\n\n const emit = (part: Part): void => {\n for (const reader of [...readers]) reader(part);\n };\n\n /** The far end is gone: our own readers hear it. */\n const close = (why: C): void => {\n if (ended) return;\n ended = true;\n reason = why;\n for (const closer of [...closers]) closer(why);\n };\n\n /**\n * End it here: the far end hears a close, our own readers do not, because we are the one who asked. The\n * reason stays null: a sentence from this side is not `C`, which is what the other end had to say.\n */\n const shut = (): void => {\n if (ended) return;\n ended = true;\n };\n\n /** Hand over what the buffer holds, as far as the framing allows. */\n const drain = (): void => {\n while (!ended) {\n if (pending !== null) {\n if (buffered.length < pending.bytes) return;\n const bytes = buffered.subarray(0, pending.bytes);\n buffered = buffered.subarray(pending.bytes);\n const line = pending.line;\n pending = null;\n emit({ line, bytes: new Uint8Array(bytes) });\n continue;\n }\n const cut = buffered.indexOf(NL);\n if (cut === -1) return;\n const raw = buffered.subarray(0, cut);\n buffered = buffered.subarray(cut + 1);\n const line = raw.length > 0 && raw[raw.length - 1] === CR ? raw.subarray(0, raw.length - 1) : raw;\n const text = decoder.write(line);\n const count = announced(text);\n if (count === null) {\n emit({ line: text, bytes: null });\n continue;\n }\n pending = { line: text, bytes: count };\n if (count === 0) {\n pending = null;\n emit({ line: text, bytes: new Uint8Array(0) });\n }\n }\n };\n\n inner.onFrame((chunk) => {\n if (ended) return;\n buffered = buffered.length === 0 ? Buffer.from(chunk) : Buffer.concat([buffered, Buffer.from(chunk)]);\n drain();\n });\n inner.onError((error) => {\n for (const failer of [...failers]) failer(error);\n });\n inner.onClose((why) => {\n if (ended) return;\n // Whatever is left without a terminator is still a line: a peer that hangs up after writing has said\n // something, and dropping it would be the framing deciding to lose the last word.\n if (pending === null && buffered.length > 0) {\n const rest = buffered;\n buffered = Buffer.alloc(0);\n emit({ line: decoder.write(rest) + decoder.end(), bytes: null });\n } else {\n decoder.end();\n }\n close(why);\n });\n\n return {\n send: async (part: Part) => {\n const head = Buffer.from(`${part.line}\\n`, \"utf8\");\n const body = part.bytes === null ? head : Buffer.concat([head, Buffer.from(part.bytes)]);\n await inner.send(new Uint8Array(body));\n },\n onFrame: (handler) => {\n readers.add(handler);\n return () => {\n readers.delete(handler);\n };\n },\n onClose: (handler) => {\n if (ended && reason !== null) {\n handler(reason);\n return () => {};\n }\n closers.add(handler);\n return () => {\n closers.delete(handler);\n };\n },\n onError: (handler) => {\n failers.add(handler);\n return () => {\n failers.delete(handler);\n };\n },\n close: async (why = \"closed here\") => {\n shut();\n await inner.close(why);\n },\n };\n}\n","// ── a channel that keeps what nobody was reading yet ────────────────────────\n//\n// A medium can deliver a frame in the same turn a reader is being installed, and a channel with no subscriber\n// drops it. This wraps a channel so nothing is dropped for want of a listener: what arrives while nobody is\n// subscribed is kept, and every subscriber that arrives before the first frame is delivered is given it.\n//\n// The window ends at the first delivery. After that the channel is live, and a subscriber that comes later has\n// missed what went before it — which is what any live channel means, and the alternative would be an unbounded\n// copy of everything ever said.\n\nimport type { Channel } from \"./channel.js\";\n\n/**\n * `inner`, with the frames that arrive before anyone is subscribed kept for the readers that follow.\n *\n * The kept frames are not bounded, because a bound depends on what the far end may say before anyone listens,\n * and that is not something this adapter can know.\n */\nexport function held<F, C>(inner: Channel<F, C>): Channel<F, C> {\n const readers = new Set<(frame: F) => void>();\n const closers = new Set<(reason: C) => void>();\n const failers = new Set<(error: unknown) => void>();\n const kept: F[] = [];\n let live = false;\n\n const emit = (frame: F): void => {\n for (const reader of [...readers]) reader(frame);\n };\n\n inner.onFrame((frame) => {\n if (live) {\n emit(frame);\n return;\n }\n if (readers.size === 0) {\n kept.push(frame);\n return;\n }\n // Somebody is reading: from here the channel is live, and what was kept has been taken.\n live = true;\n kept.length = 0;\n emit(frame);\n });\n inner.onClose((reason) => {\n for (const closer of [...closers]) closer(reason);\n });\n inner.onError((error) => {\n for (const failer of [...failers]) failer(error);\n });\n\n return {\n send: (frame) => inner.send(frame),\n onFrame(handler) {\n readers.add(handler);\n // Handed to every subscriber that arrives before the first delivery, not only to the first.\n for (const frame of kept) handler(frame);\n return () => {\n readers.delete(handler);\n };\n },\n onClose(handler) {\n closers.add(handler);\n return () => {\n closers.delete(handler);\n };\n },\n onError(handler) {\n failers.add(handler);\n return () => {\n failers.delete(handler);\n };\n },\n close: (reason) => inner.close(reason),\n };\n}\n","// ── a port as an actor ──────────────────────────────────────────────────────\n//\n// One actor that owns one channel and speaks for it: what it is told to send goes in, what the channel delivers\n// comes out as DATA, and the way the channel ended is left in the actor's state, where a parent reads anyway.\n//\n// The channel is opened when the actor starts and closed when it ends, so the actor's life and the channel's\n// are the same one. What a channel is — a process, a socket, a pair in memory — is the opener's business; the\n// actor knows only that it has one.\n\nimport type { ActorDefinition } from \"../actor-types.js\";\nimport { defineActor, defineMessages } from \"../define-actor.js\";\nimport type { Message } from \"../types.js\";\nimport type { Channel } from \"./channel.js\";\n\n/** Write this to the channel. */\nexport interface SendMessage<F> extends Message {\n type: \"SEND\";\n data: F;\n}\n\n/** Ask the channel's own world to act on what is behind it; a medium without one ignores it. */\nexport interface SignalMessage extends Message {\n type: \"SIGNAL\";\n signal: string;\n}\n\n/** A frame the channel delivered. */\nexport interface DataMessage<F> extends Message {\n type: \"DATA\";\n data: F;\n}\n\nexport type PortIn<F> = SendMessage<F> | SignalMessage;\nexport type PortOut<F> = DataMessage<F>;\n\n/** What a parent may read of a port. The ending is here because it is state, not news. */\nexport interface PortPublic<C> {\n /** The channel is open. False before it opens and after it has ended. */\n alive: boolean;\n /** How it ended, or null while it has not. */\n end: C | null;\n}\n\nexport interface PortActorSpec<Args, F, C> {\n name: string;\n /** Opens the channel this actor owns. Called once, when the actor starts. */\n open(args: Args): Promise<Channel<F, C>>;\n /** How a signal reaches the medium. A process sends it; a connection with no process behind it has none. */\n signal?(channel: Channel<F, C>, signal: string): void;\n}\n\ntype PortState<C> = { public: PortPublic<C>; private: { channel: Channel<unknown, C> | null; args: unknown } };\n\n/**\n * An actor over one channel.\n *\n * In `SEND {data}` writes to it and `SIGNAL {signal}` asks the medium to act on what is behind it; posipaki's\n * `STOP` ends the actor, which closes the channel. Out `DATA {data}` for every frame. The channel's ending is\n * left in `state.end` and the actor stops.\n */\nexport function portActor<Args, F, C>(\n spec: PortActorSpec<Args, F, C>,\n): ActorDefinition<Args, PortState<C>, PortIn<F>, PortOut<F>, {}> {\n return defineActor({\n name: spec.name,\n inMessages: defineMessages<PortIn<F>>(),\n outMessages: defineMessages<PortOut<F>>(),\n setup: (args: Args) => ({\n public: { alive: false as boolean, end: null as C | null },\n private: { channel: null as Channel<unknown, C> | null, args },\n }),\n afterStart() {\n const { args } = this.state.private;\n void spec.open(args).then((channel) => {\n this.state.private.channel = channel;\n this.state.public.alive = true;\n channel.onFrame((data) => {\n this.emit({ type: \"DATA\", data });\n });\n channel.onClose((reason) => {\n this.state.public.alive = false;\n this.state.public.end = reason;\n this.exit();\n });\n });\n },\n async beforeEnd() {\n this.state.public.alive = false;\n await (this.state.private.channel as Channel<F, C> | null)?.close();\n },\n handlers: {\n async SEND(msg: SendMessage<F>) {\n await (this.state.private.channel as Channel<F, C> | null)?.send(msg.data);\n },\n SIGNAL(msg: SignalMessage) {\n const channel = this.state.private.channel as Channel<F, C> | null;\n if (channel !== null) spec.signal?.(channel, msg.signal);\n },\n },\n });\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { g as Part, m as Channel } from "./reactor-CWPBP7qN.js";
|
|
2
|
+
import { Readable, Writable } from "node:stream";
|
|
3
|
+
//#region src/port/memory.d.ts
|
|
4
|
+
/** One end of a pair. `fail` is the hook this double adds: it breaks the wire the way a socket would. */
|
|
5
|
+
interface MemoryEnd<F> extends Channel<F> {
|
|
6
|
+
/** Break the wire: the far end hears an error, and then a close. */
|
|
7
|
+
fail(error: unknown): void;
|
|
8
|
+
}
|
|
9
|
+
interface ChannelPair<F> {
|
|
10
|
+
near: MemoryEnd<F>;
|
|
11
|
+
far: MemoryEnd<F>;
|
|
12
|
+
}
|
|
13
|
+
/** The two halves of one channel. */
|
|
14
|
+
declare function memoryChannelPair<F>(): ChannelPair<F>;
|
|
15
|
+
//#endregion
|
|
16
|
+
//#region src/port/split.d.ts
|
|
17
|
+
/** Given a line, how many raw octets follow it. Default: none, this is a plain line. */
|
|
18
|
+
type Announcement = (line: string) => number | null;
|
|
19
|
+
/**
|
|
20
|
+
* One byte channel in, one channel of parts out.
|
|
21
|
+
*
|
|
22
|
+
* The returned channel's `send` is the same rule backwards: a part becomes its line, a terminator, and the
|
|
23
|
+
* octets it carried.
|
|
24
|
+
*/
|
|
25
|
+
declare function splitChannel<C = string>(inner: Channel<Uint8Array, C>, announced?: Announcement): Channel<Part, C>;
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region src/port/stream.d.ts
|
|
28
|
+
/** What the channel talks over: something to read from, something to write to. */
|
|
29
|
+
interface StreamPair {
|
|
30
|
+
read: Readable;
|
|
31
|
+
write: Writable;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* A channel of bytes over a stream pair.
|
|
35
|
+
*
|
|
36
|
+
* `close()` ends the write side, so the far end hears an end of stream, and destroys the read side, so no
|
|
37
|
+
* more chunks arrive after this side has said it is done. A peer that goes away is a close of this side's
|
|
38
|
+
* own readers, and the reason says which of the two it was.
|
|
39
|
+
*/
|
|
40
|
+
declare function streamChannel(pair: StreamPair): Channel<Uint8Array>;
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/port/combine.d.ts
|
|
43
|
+
/** A frame, and which of the combined channels it arrived on. */
|
|
44
|
+
interface Sourced<T, F> {
|
|
45
|
+
readonly source: T;
|
|
46
|
+
readonly frame: F;
|
|
47
|
+
}
|
|
48
|
+
/** An ending, and which of the combined channels ended. */
|
|
49
|
+
interface Ended<T, C> {
|
|
50
|
+
readonly source: T;
|
|
51
|
+
readonly ending: C;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Every frame from every source, tagged; the first ending ends it.
|
|
55
|
+
*
|
|
56
|
+
* The ending is the first one to arrive, and the others are ignored afterwards. This is what a process wants
|
|
57
|
+
* by default: its stdout ending means the process is gone, and that is the news.
|
|
58
|
+
*/
|
|
59
|
+
declare function all<T extends string, F, C>(sources: Record<T, Channel<F, C>>): Channel<Sourced<T, F>, C>;
|
|
60
|
+
/**
|
|
61
|
+
* Every frame from every source, tagged, and every ending as a frame of its own.
|
|
62
|
+
*
|
|
63
|
+
* It closes once all of them have ended, and that close carries nothing: the endings already arrived as frames,
|
|
64
|
+
* each one saying which source it belongs to.
|
|
65
|
+
*/
|
|
66
|
+
declare function settled<T extends string, F, C>(sources: Record<T, Channel<F, C>>): Channel<Sourced<T, F> | Ended<T, C>, void>;
|
|
67
|
+
//#endregion
|
|
68
|
+
//#region src/port/held.d.ts
|
|
69
|
+
/**
|
|
70
|
+
* `inner`, with the frames that arrive before anyone is subscribed kept for the readers that follow.
|
|
71
|
+
*
|
|
72
|
+
* The kept frames are not bounded, because a bound depends on what the far end may say before anyone listens,
|
|
73
|
+
* and that is not something this adapter can know.
|
|
74
|
+
*/
|
|
75
|
+
declare function held<F, C>(inner: Channel<F, C>): Channel<F, C>;
|
|
76
|
+
//#endregion
|
|
77
|
+
//#region src/port/fetch.d.ts
|
|
78
|
+
/** What a response said when its body was over. */
|
|
79
|
+
interface HttpEnd {
|
|
80
|
+
/** The status the far end answered with. The frames that came before it are its body. */
|
|
81
|
+
readonly status: number;
|
|
82
|
+
}
|
|
83
|
+
interface FetchPortOptions {
|
|
84
|
+
/** Passed to `fetch`: method, headers, body. The request's own signal is not read; `close()` aborts. */
|
|
85
|
+
init?: RequestInit;
|
|
86
|
+
/** How long to wait for the response head. No bound by default: a stream may be long. */
|
|
87
|
+
connectMs?: number;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* A URL as a channel of the body it answers with.
|
|
91
|
+
*
|
|
92
|
+
* Frames are the chunks of the body as they arrive, so a caller reads a stream rather than waiting for a whole
|
|
93
|
+
* response. `close()` aborts the request, and the far side hears it.
|
|
94
|
+
*/
|
|
95
|
+
declare function fetchPort(url: string, options?: FetchPortOptions): Promise<Channel<Uint8Array, HttpEnd>>;
|
|
96
|
+
//#endregion
|
|
97
|
+
//#region src/port/duplex.d.ts
|
|
98
|
+
/** A pair whose two sides carry the same frame type, read as one channel. */
|
|
99
|
+
declare function duplexChannel<F, C = void>(pair: {
|
|
100
|
+
readonly inbound: Channel<F, C>;
|
|
101
|
+
readonly outbound: Channel<F, C>;
|
|
102
|
+
}): Channel<F, C>;
|
|
103
|
+
//#endregion
|
|
104
|
+
export { held as a, all as c, streamChannel as d, Announcement as f, memoryChannelPair as g, MemoryEnd as h, fetchPort as i, settled as l, ChannelPair as m, FetchPortOptions as n, Ended as o, splitChannel as p, HttpEnd as r, Sourced as s, duplexChannel as t, StreamPair as u };
|
|
105
|
+
//# sourceMappingURL=index-B3FcBNz7.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-B3FcBNz7.d.ts","names":[],"sources":["../src/port/memory.ts","../src/port/split.ts","../src/port/stream.ts","../src/port/combine.ts","../src/port/held.ts","../src/port/fetch.ts","../src/port/duplex.ts"],"mappings":";;;;UAUiB,UAAU,WAAW,QAAQ;;EAE5C,KAAK;;UAGU,YAAY;EAC3B,MAAM,UAAU;EAChB,KAAK,UAAU;;;iBAgBD,kBAAkB,MAAM,YAAY;;;;KCXxC,gBAAgB;;;;;;;iBAUZ,aAAa,YAC3B,OAAO,QAAQ,YAAY,IAC3B,YAAW,eACV,QAAQ,MAAM;;;;UCnBA;EACf,MAAM;EACN,OAAO;;;;;;;;;iBAyBO,cAAc,MAAM,aAAa,QAAQ;;;;UC5BxC,QAAQ,GAAG;WACjB,QAAQ;WACR,OAAO;;;UAID,MAAM,GAAG;WACf,QAAQ;WACR,QAAQ;;;;;;;;iBAaH,IAAI,kBAAkB,GAAG,GAAG,SAAS,OAAO,GAAG,QAAQ,GAAG,MAAM,QAAQ,QAAQ,GAAG,IAAI;;;;;;;iBAgEvF,QAAQ,kBAAkB,GAAG,GAC3C,SAAS,OAAO,GAAG,QAAQ,GAAG,MAC7B,QAAQ,QAAQ,GAAG,KAAK,MAAM,GAAG;;;;;;;;;iBCpFpB,KAAK,GAAG,GAAG,OAAO,QAAQ,GAAG,KAAK,QAAQ,GAAG;;;;UCR5C;;WAEN;;UAGM;;EAEf,OAAO;;EAEP;;;;;;;;iBASoB,UAAU,aAAa,UAAS,mBAAwB,QAAQ,QAAQ,YAAY;;;;iBChB1F,cAAc,GAAG,UAAU;WAChC,SAAS,QAAQ,GAAG;WACpB,UAAU,QAAQ,GAAG;IAC5B,QAAQ,GAAG"}
|
package/dist/index.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ declare function defineActor<Args, InternalState, InMsg extends Message, OutMsg
|
|
|
20
20
|
//#endregion
|
|
21
21
|
//#region src/version.d.ts
|
|
22
22
|
/** posipaki's release version. Must equal package.json's `version`. */
|
|
23
|
-
declare const LIB_VERSION = "0.
|
|
23
|
+
declare const LIB_VERSION = "0.48.1";
|
|
24
24
|
//#endregion
|
|
25
25
|
export { type ActorConfig, type ActorContext, type ActorDecorated, type ActorDefinition, type ActorPlugin, type ActorReflection, type AnyProcess, AsyncProcess, type AsyncProcessFn, type ExitMessage, type HandlerFn, type HandlerOptions, type HookResult, LIB_VERSION, type Message, type MethodOptions, type PluginTransform, Process, type ProcessCtx, type ProcessFn, type SenderInfo, type SenderOrigin, type SpawnedFrom, type StopMessage, type WithSender, type WithoutSender, asyncify, callHook, chainHook, defineActor, defineMessages, mergeConfigs, propagateError, runDispatch, runDispatchAsync, spawn, spawnAsync, stopPropagation };
|
|
26
26
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { i as runDispatch } from "./util-Brtfgv68.js";
|
|
|
2
2
|
import { a as spawnAsync, i as runDispatchAsync, o as asyncify, t as AsyncProcess } from "./process.async-B1FqZyD1.js";
|
|
3
3
|
import { n as chainHook, o as propagateError, r as mergeConfigs, s as stopPropagation, t as callHook } from "./hooks-CgXhmY4r.js";
|
|
4
4
|
import { n as defineMessages, t as defineActor } from "./define-actor-DR1P1PA5.js";
|
|
5
|
-
import { t as LIB_VERSION } from "./version-
|
|
5
|
+
import { t as LIB_VERSION } from "./version-CjO8pCPA.js";
|
|
6
6
|
//#region src/process.ts
|
|
7
7
|
/** @deprecated Use {@link spawnAsync} instead. */
|
|
8
8
|
function spawn(fn, pname, tp) {
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { a as portReactor, c as PortIn, d as SendMessage, f as SignalMessage, g as Part, h as ChannelClosed, i as PortReactorOptions, l as PortOut, m as Channel, n as PortPair, o as DataMessage, p as portActor, r as PortReactor, s as PortActorSpec, t as PortListener, u as PortPublic } from "../reactor-CWPBP7qN.js";
|
|
2
|
+
import { a as held, c as all, d as streamChannel, f as Announcement, g as memoryChannelPair, h as MemoryEnd, i as fetchPort, l as settled, m as ChannelPair, n as FetchPortOptions, o as Ended, p as splitChannel, r as HttpEnd, s as Sourced, t as duplexChannel, u as StreamPair } from "../index-B3FcBNz7.js";
|
|
3
|
+
export { type Announcement, type Channel, ChannelClosed, type ChannelPair, type DataMessage, type Ended, type FetchPortOptions, type HttpEnd, type MemoryEnd, type Part, type PortActorSpec, type PortIn, type PortListener, type PortOut, type PortPair, type PortPublic, type PortReactor, type PortReactorOptions, type SendMessage, type SignalMessage, type Sourced, type StreamPair, all, duplexChannel, fetchPort, held, memoryChannelPair, portActor, portReactor, settled, splitChannel, streamChannel };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { a as settled, c as ChannelClosed, i as all, n as portReactor, o as streamChannel, r as fetchPort, s as memoryChannelPair, t as duplexChannel } from "../port-DowG9tgl.js";
|
|
2
|
+
import { n as held, r as splitChannel, t as portActor } from "../actor-C8DzeQeT.js";
|
|
3
|
+
export { ChannelClosed, all, duplexChannel, fetchPort, held, memoryChannelPair, portActor, portReactor, settled, splitChannel, streamChannel };
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { l as ActorDefinition } from "../hooks-DO-efRM_.js";
|
|
2
|
+
import { c as PortIn, l as PortOut, m as Channel, t as PortListener, u as PortPublic } from "../reactor-CWPBP7qN.js";
|
|
3
|
+
//#region src/port/node/spawn.d.ts
|
|
4
|
+
/** How a process ended: it exited with a code, or a signal terminated it. */
|
|
5
|
+
type ProcessEnd = {
|
|
6
|
+
readonly kind: "exit";
|
|
7
|
+
readonly code: number;
|
|
8
|
+
} | {
|
|
9
|
+
readonly kind: "signal";
|
|
10
|
+
readonly signal: string;
|
|
11
|
+
};
|
|
12
|
+
interface SpawnPortOptions {
|
|
13
|
+
cwd?: string;
|
|
14
|
+
env?: NodeJS.ProcessEnv;
|
|
15
|
+
/** How long the process may live after its stdin is closed. Default 5000 ms, then SIGKILL. */
|
|
16
|
+
killAfterMs?: number;
|
|
17
|
+
}
|
|
18
|
+
interface ProcessPorts {
|
|
19
|
+
readonly stdout: Channel<Uint8Array, ProcessEnd>;
|
|
20
|
+
readonly stderr: Channel<Uint8Array, ProcessEnd>;
|
|
21
|
+
}
|
|
22
|
+
/** A command as a channel of bytes: stdout in, stdin out, and its exit when it closes. */
|
|
23
|
+
declare function spawnPort(command: string[], options?: SpawnPortOptions): Promise<Channel<Uint8Array, ProcessEnd>>;
|
|
24
|
+
/** One process, its stdout and its stderr, each a channel that ends with the same exit. */
|
|
25
|
+
declare function spawnPorts(command: string[], options?: SpawnPortOptions): Promise<ProcessPorts>;
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region src/port/node/process.d.ts
|
|
28
|
+
/** How a process port is started. */
|
|
29
|
+
interface ProcessPortArgs {
|
|
30
|
+
command: string[];
|
|
31
|
+
cwd?: string;
|
|
32
|
+
env?: NodeJS.ProcessEnv;
|
|
33
|
+
/** How long the process may live after its stdin is closed. Default 5000 ms, then SIGKILL. */
|
|
34
|
+
killAfterMs?: number;
|
|
35
|
+
}
|
|
36
|
+
/** The child's octets, frame for frame. */
|
|
37
|
+
declare const BinaryPort: ActorDefinition<ProcessPortArgs, {
|
|
38
|
+
public: PortPublic<ProcessEnd>;
|
|
39
|
+
private: {
|
|
40
|
+
channel: Channel<unknown, ProcessEnd> | null;
|
|
41
|
+
args: unknown;
|
|
42
|
+
};
|
|
43
|
+
}, PortIn<Uint8Array<ArrayBufferLike>>, PortOut<Uint8Array<ArrayBufferLike>>, {}>;
|
|
44
|
+
/** The same child, cut into lines. */
|
|
45
|
+
declare const Utf8Port: ActorDefinition<ProcessPortArgs, {
|
|
46
|
+
public: PortPublic<ProcessEnd>;
|
|
47
|
+
private: {
|
|
48
|
+
channel: Channel<unknown, ProcessEnd> | null;
|
|
49
|
+
args: unknown;
|
|
50
|
+
};
|
|
51
|
+
}, PortIn<string>, PortOut<string>, {}>;
|
|
52
|
+
//#endregion
|
|
53
|
+
//#region src/port/node/listener.d.ts
|
|
54
|
+
interface HttpListenerOptions<Meta> {
|
|
55
|
+
port?: number;
|
|
56
|
+
hostname?: string;
|
|
57
|
+
/** Admission before a body is made: what it returns is the pair's meta; throwing refuses the request. */
|
|
58
|
+
identify?(request: Request): Meta | Promise<Meta>;
|
|
59
|
+
}
|
|
60
|
+
/** A port listener that is also an HTTP server: the port it bound, and the pairs it hands out. */
|
|
61
|
+
interface HttpListener<Meta> extends PortListener<Uint8Array, Uint8Array, Meta> {
|
|
62
|
+
readonly port: number;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* A server whose requests arrive as pairs of ports.
|
|
66
|
+
*
|
|
67
|
+
* `identify` runs before a pair exists, so a refused request costs no stream and the caller reads a status with
|
|
68
|
+
* the reason in it. The request body is the inbound port; the response body is the outbound one.
|
|
69
|
+
*/
|
|
70
|
+
declare function httpListener<Meta = unknown>(options?: HttpListenerOptions<Meta>): HttpListener<Meta>;
|
|
71
|
+
//#endregion
|
|
72
|
+
export { BinaryPort, type HttpListener, type HttpListenerOptions, type ProcessEnd, type ProcessPortArgs, type ProcessPorts, type SpawnPortOptions, Utf8Port, httpListener, spawnPort, spawnPorts };
|
|
73
|
+
//# sourceMappingURL=node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node.d.ts","names":[],"sources":["../../src/port/node/spawn.ts","../../src/port/node/process.ts","../../src/port/node/listener.ts"],"mappings":";;;;KAcY;WACG;WAAuB;;WACvB;WAAyB;;UACvB;EACf;EACA,MAAM,OAAO;;EAEb;;UAEe;WACN,QAAQ,QAAQ,YAAY;WAC5B,QAAQ,QAAQ,YAAY;;;iBAIvB,UACd,mBACA,UAAS,mBACR,QAAQ,QAAQ,YAAY;;iBAIT,WACpB,mBACA,UAAS,mBACR,QAAQ;;;;UC3BM;EACf;EACA;EACA,MAAM,OAAO;;EAEb;;;cA8CW,YAGX,gBAHqB;;;;;;GAGrB,OAAA,WAAA,mBAAA,QAAA,WAAA;;cAGW,UAGX,gBAHmB;;;;;;mBAGnB;;;UC3De,oBAAoB;EACnC;EACA;;EAEA,UAAU,SAAS,UAAU,OAAO,QAAQ;;;UAI7B,aAAa,cAAc,aAAa,YAAY,YAAY;WACtE;;;;;;;;iBAuBK,aAAa,gBAAgB,UAAS,oBAAoB,QAAa,aAAa"}
|