posipaki 0.49.0 → 0.49.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-Df5v2zuv.js → actor-MIvmdVJD.js} +82 -81
- package/dist/actor-MIvmdVJD.js.map +1 -0
- package/dist/hooks-DO-efRM_.d.ts.map +1 -1
- package/dist/{index-DFqA3rI6.d.ts → index-ChSy_Vdu.d.ts} +13 -2
- package/dist/{index-DFqA3rI6.d.ts.map → index-ChSy_Vdu.d.ts.map} +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/port/index.d.ts +2 -2
- package/dist/port/index.js +3 -3
- package/dist/port/node.js +1 -1
- package/dist/{port-BR7f7BDY.js → port-0vYKSxBM.js} +21 -5
- package/dist/{port-BR7f7BDY.js.map → port-0vYKSxBM.js.map} +1 -1
- package/dist/remote/index.js +1 -1
- package/dist/remote/node.js +3 -3
- package/dist/{version-DyYl4K-F.js → version-DNJbW_di.js} +2 -2
- package/dist/{version-DyYl4K-F.js.map → version-DNJbW_di.js.map} +1 -1
- package/dist/{websocket-Ce4oq-7O.js → websocket-By6xlyLp.js} +2 -2
- package/dist/{websocket-Ce4oq-7O.js.map → websocket-By6xlyLp.js.map} +1 -1
- package/package.json +1 -1
- package/dist/actor-Df5v2zuv.js.map +0 -1
|
@@ -1,5 +1,67 @@
|
|
|
1
1
|
import { n as defineMessages, t as defineActor } from "./define-actor-DR1P1PA5.js";
|
|
2
2
|
import { StringDecoder } from "node:string_decoder";
|
|
3
|
+
//#region src/port/held.ts
|
|
4
|
+
/**
|
|
5
|
+
* `inner`, with the frames that arrive before anyone is subscribed kept for the readers that follow.
|
|
6
|
+
*
|
|
7
|
+
* The kept frames are not bounded, because a bound depends on what the far end may say before anyone listens,
|
|
8
|
+
* and that is not something this adapter can know.
|
|
9
|
+
*/
|
|
10
|
+
function held(inner) {
|
|
11
|
+
const readers = /* @__PURE__ */ new Set();
|
|
12
|
+
const closers = /* @__PURE__ */ new Set();
|
|
13
|
+
const failers = /* @__PURE__ */ new Set();
|
|
14
|
+
const kept = [];
|
|
15
|
+
let live = false;
|
|
16
|
+
const emit = (frame) => {
|
|
17
|
+
for (const reader of [...readers]) reader(frame);
|
|
18
|
+
};
|
|
19
|
+
inner.onFrame((frame) => {
|
|
20
|
+
if (live) {
|
|
21
|
+
emit(frame);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (readers.size === 0) {
|
|
25
|
+
kept.push(frame);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
live = true;
|
|
29
|
+
kept.length = 0;
|
|
30
|
+
emit(frame);
|
|
31
|
+
});
|
|
32
|
+
inner.onClose((reason) => {
|
|
33
|
+
for (const closer of [...closers]) closer(reason);
|
|
34
|
+
});
|
|
35
|
+
inner.onError((error) => {
|
|
36
|
+
for (const failer of [...failers]) failer(error);
|
|
37
|
+
});
|
|
38
|
+
return {
|
|
39
|
+
send: (frame) => inner.send(frame),
|
|
40
|
+
onFrame(handler) {
|
|
41
|
+
readers.add(handler);
|
|
42
|
+
for (const frame of kept) handler(frame);
|
|
43
|
+
return () => {
|
|
44
|
+
readers.delete(handler);
|
|
45
|
+
};
|
|
46
|
+
},
|
|
47
|
+
onClose(handler) {
|
|
48
|
+
closers.add(handler);
|
|
49
|
+
return () => {
|
|
50
|
+
closers.delete(handler);
|
|
51
|
+
};
|
|
52
|
+
},
|
|
53
|
+
onError(handler) {
|
|
54
|
+
failers.add(handler);
|
|
55
|
+
return () => {
|
|
56
|
+
failers.delete(handler);
|
|
57
|
+
};
|
|
58
|
+
},
|
|
59
|
+
close: (reason) => inner.close(reason),
|
|
60
|
+
info: inner.info,
|
|
61
|
+
control: (command) => inner.control(command)
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
//#endregion
|
|
3
65
|
//#region src/port/split.ts
|
|
4
66
|
const NL = 10;
|
|
5
67
|
const CR = 13;
|
|
@@ -81,27 +143,7 @@ function splitChannel(inner, announced = NOTHING) {
|
|
|
81
143
|
}
|
|
82
144
|
}
|
|
83
145
|
};
|
|
84
|
-
|
|
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 {
|
|
146
|
+
const parts = held({
|
|
105
147
|
send: async (part) => {
|
|
106
148
|
const head = Buffer.from(`${part.line}\n`, "utf8");
|
|
107
149
|
const body = part.bytes === null ? head : Buffer.concat([head, Buffer.from(part.bytes)]);
|
|
@@ -135,69 +177,28 @@ function splitChannel(inner, announced = NOTHING) {
|
|
|
135
177
|
},
|
|
136
178
|
info: inner.info,
|
|
137
179
|
control: (command) => inner.control(command)
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
//#endregion
|
|
141
|
-
//#region src/port/held.ts
|
|
142
|
-
/**
|
|
143
|
-
* `inner`, with the frames that arrive before anyone is subscribed kept for the readers that follow.
|
|
144
|
-
*
|
|
145
|
-
* The kept frames are not bounded, because a bound depends on what the far end may say before anyone listens,
|
|
146
|
-
* and that is not something this adapter can know.
|
|
147
|
-
*/
|
|
148
|
-
function held(inner) {
|
|
149
|
-
const readers = /* @__PURE__ */ new Set();
|
|
150
|
-
const closers = /* @__PURE__ */ new Set();
|
|
151
|
-
const failers = /* @__PURE__ */ new Set();
|
|
152
|
-
const kept = [];
|
|
153
|
-
let live = false;
|
|
154
|
-
const emit = (frame) => {
|
|
155
|
-
for (const reader of [...readers]) reader(frame);
|
|
156
|
-
};
|
|
157
|
-
inner.onFrame((frame) => {
|
|
158
|
-
if (live) {
|
|
159
|
-
emit(frame);
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
|
-
if (readers.size === 0) {
|
|
163
|
-
kept.push(frame);
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
live = true;
|
|
167
|
-
kept.length = 0;
|
|
168
|
-
emit(frame);
|
|
169
180
|
});
|
|
170
|
-
inner.
|
|
171
|
-
|
|
181
|
+
inner.onFrame((chunk) => {
|
|
182
|
+
if (ended) return;
|
|
183
|
+
buffered = buffered.length === 0 ? Buffer.from(chunk) : Buffer.concat([buffered, Buffer.from(chunk)]);
|
|
184
|
+
drain();
|
|
172
185
|
});
|
|
173
186
|
inner.onError((error) => {
|
|
174
187
|
for (const failer of [...failers]) failer(error);
|
|
175
188
|
});
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
};
|
|
190
|
-
},
|
|
191
|
-
onError(handler) {
|
|
192
|
-
failers.add(handler);
|
|
193
|
-
return () => {
|
|
194
|
-
failers.delete(handler);
|
|
195
|
-
};
|
|
196
|
-
},
|
|
197
|
-
close: (reason) => inner.close(reason),
|
|
198
|
-
info: inner.info,
|
|
199
|
-
control: (command) => inner.control(command)
|
|
200
|
-
};
|
|
189
|
+
inner.onClose((why) => {
|
|
190
|
+
if (ended) return;
|
|
191
|
+
if (pending === null && buffered.length > 0) {
|
|
192
|
+
const rest = buffered;
|
|
193
|
+
buffered = Buffer.alloc(0);
|
|
194
|
+
emit({
|
|
195
|
+
line: decoder.write(rest) + decoder.end(),
|
|
196
|
+
bytes: null
|
|
197
|
+
});
|
|
198
|
+
} else decoder.end();
|
|
199
|
+
close(why);
|
|
200
|
+
});
|
|
201
|
+
return parts;
|
|
201
202
|
}
|
|
202
203
|
//#endregion
|
|
203
204
|
//#region src/port/actor.ts
|
|
@@ -257,6 +258,6 @@ function portActor(spec) {
|
|
|
257
258
|
});
|
|
258
259
|
}
|
|
259
260
|
//#endregion
|
|
260
|
-
export {
|
|
261
|
+
export { splitChannel as n, held as r, portActor as t };
|
|
261
262
|
|
|
262
|
-
//# sourceMappingURL=actor-
|
|
263
|
+
//# sourceMappingURL=actor-MIvmdVJD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actor-MIvmdVJD.js","names":[],"sources":["../src/port/held.ts","../src/port/split.ts","../src/port/actor.ts"],"sourcesContent":["// ── 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 info: inner.info,\n control: (command) => inner.control(command),\n };\n}\n","// ── 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\";\nimport { held } from \"./held.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 // Built and wrapped before the inner channel is read: the medium may have kept frames for its first\n // reader, and subscribing drains them at once — a part produced then must be a reader's to find, not the\n // wire's to lose.\n const parts: Channel<Part, C> = held<Part, C>({\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 info: inner.info,\n control: (command) => inner.control(command),\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 parts;\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 in `setup`, which the runtime awaits, so an actor that is ready has a channel: a send is\n// never asked to wait for one, and a port that cannot open fails its start rather than looking alive. What a\n// channel is — a process, a socket, a pair in memory — is `open`'s business; the 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 /** What the medium knows about itself — a process its pid — as the channel reported it. */\n info: Record<string, unknown>;\n}\n\n/** What a medium's actor is handed: a name, and a way to open the channel it will own. */\nexport interface PortActorSpec<Args, F, C = string> {\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}\n\ntype PortState<F, C> = {\n public: PortPublic<C>;\n private: { channel: Channel<F, C>; args: unknown };\n};\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, through\n * the channel's own `control`; posipaki's `STOP` ends the actor, which closes the channel. Out `DATA {data}`\n * for every frame. The channel's ending is left in `state.end`, what the medium knows about itself in\n * `state.info`, and then the actor stops.\n */\nexport function portActor<Args, F, C = string>(\n spec: PortActorSpec<Args, F, C>,\n): ActorDefinition<Args, PortState<F, C>, PortIn<F>, PortOut<F>, {}> {\n return defineActor({\n name: spec.name,\n inMessages: defineMessages<PortIn<F>>(),\n outMessages: defineMessages<PortOut<F>>(),\n setup: async (args: Args): Promise<PortState<F, C>> => {\n const channel = await spec.open(args);\n return {\n public: { alive: true, end: null, info: channel.info },\n private: { channel, args },\n };\n },\n afterStart() {\n const { channel } = this.state.private;\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 async beforeEnd() {\n this.state.public.alive = false;\n await this.state.private.channel.close();\n },\n handlers: {\n async SEND(msg: SendMessage<F>) {\n await this.state.private.channel.send(msg.data);\n },\n SIGNAL(msg: SignalMessage) {\n this.state.private.channel.control({ signal: msg.signal });\n },\n },\n });\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks-DO-efRM_.d.ts","names":[],"sources":["../src/actor-types.
|
|
1
|
+
{"version":3,"file":"hooks-DO-efRM_.d.ts","names":[],"sources":["../src/actor-types.ts","../src/hooks.ts"],"mappings":";;KAmBY,cAAc,UAAU;EAClC,gBAAgB;;UAED;GACd,cAAc;;KAEL,UAAU,cAAc,YAClC,KAAK,OACL,QAAQ,sBACE;KACA,eAAe,cAAc,WAAW,QAE/C,KAAK,gBAAgB,UAAU,QAAQ;EAAS,MAAM;;;;;;;;;;;KAa/C,uBAAuB,kBAAkB;;;UAGpC;GACd,eAAe;;KAEN,OAAO,MAAM;EAAS,QAAQ;EAAK,SAAS;;KAC5C,YAAY,KAAK,UAAU,2BAA2B,cAAc;KAEpE,YAAY,UAAU,4CAChC,UAAU,sBAAsB,SAAS,SAAS,UAAU,UAAU,KAClE,aAAa,GAAG,YAAY,IAAI,IAAI,IAAI,IAAI;UAGjC,gBACf,MACA,eACA,cAAc,SACd,eAAe,SACf,0BAA0B;EAE1B,IAAI,eAAe,MAAM,YAAY,gBAAgB,OAAO;;EAE5D;;EAEA,gBAAgB,gBAAgB;;EAEhC,MACE,MAAM,MACN;IACE;IACA,YAAY,KAAK,QAAQ,MAAM;IAC/B,aAAa;IACb;IACA;;;IAGA,aAAa;;IAEb;MAED,QACD,aACE,MACA,YAAY,gBACZ,OACA,QACA,oBAAoB;;;;EAMxB,aACE,KAAK,UACL,MAAM,MACN;IACE;IACA,gBAAgB;IAChB,aAAa;MAEd,QACD,aACE,MACA,YAAY,gBACZ,OACA,QACA,oBAAoB;EAGxB,YAAY,cAAc;EAC1B,aAAa,cAAc;;;;;;;;;KASjB,YACV,MACA,eACA,cAAc,SACd,eAAe,SACf,gBAAgB,eAChB,iBAAiB,eAAe,QAChC,0BAA0B;;EAG1B;EACA,UAAU,gBAAgB;;;EAG1B,aAAa;;;;EAIb,kBAAkB;EAClB,cAAc,cAAc;EAC5B,aAAa,cAAc;;;;EAI3B,eACE,MAAM,aACJ,aAEA,OACA,QACA,eACA,UACA,oBAAoB,4BAEZ;;EAGZ,SACE,MAAM,aACJ,aAEA,OACA,QACA,eACA,UACA,oBAAoB,kBAEtB,MAAM,SACH,QAAQ,iBAAiB;EAE9B,0BAA0B;EAE1B,wBAAwB,aAAa,QAAQ;EAE7C,aAAa,qBAAqB,aAAa,QAAQ;;;;;;EAOvD,YAAY,qBAAqB,aAAa,QAAQ;EAEtD,WAAW,oBAAoB,aAAa,cAAc,QAAQ,aAAa;EAE/E,UAAU,KAAK,QAAQ,QAAQ,eAAe,aAAa,QAAQ;EAEnE,aAAa,KAAK,OAAO,QAAQ,eAAe,aAAa,QAAQ;EAErE,eAAe,KAAK,SAAS,QAAQ,sBAAsB;;;;EAK3D,eACE,cACA,MAAM,aACN,oBACG,aAAa,QAAQ;;;;;;EAO1B,YAAY,QAAQ,eAAe,wBAAwB,QAAQ;EAEnE,UAAU,WACR,SACE,aACE,MACA,eACA,OACA,QACA,SACA,UACA,oBAAoB;EAI1B,UAAU,UACR,SACE,aACE,MACA,eACA,OACA,QACA,SACA,UACA,oBAAoB;EAG1B,qBAAqB,oBACnB,SACE,aACE,MACA,eACA,OACA,QACA,SACA,UACA,kBAAkB;EAIxB,YAAY,QAAQ;IAClB,SACF,aAAa,MAAM,eAAe,OAAO,QAAQ,SAAS,UAAU,oBAAoB;KAE9E,YAAY,8BAGtB,SACA,SACA,eACA,eAAe,UACf;;cAMW;;cAGA,8BAA6B;;;;;;;;cAS7B;;cAGA,6BAA4B;;KAG7B,4BAA4B;;KAK5B,2BAA2B;;KAG3B;;KAIA,YAAY,IAAI,cAAc,QAAQ,MAAM,IAAI,QAAQ;;KAGxD,mBAAmB,eAAe,kBAAkB;KAEpD,aACV,MACA,eACA,cAAc,SACd,eAAe,SACf,gBAAgB,eAChB,iBAAiB,eAAe,QAChC,0BAA0B,qBACxB,UACF;EACE,OAAO;EACP;EACA;;;;;;EAMA,MAAM,aACJ,MACA,YAAY,gBACZ,OACA,QACA,oBAAoB;EAGtB,OAAO,KAAK;EACZ;EAEA,YAAY,SACV,aAAa,MAAM,eAAe,OAAO,QAAQ,SAAS,UAAU,sBAEpE;EACF,OAAO;EAEP,QAAQ,eAAe;EAEvB,KAAK,GAAG,GAAG,WAAW,SAAS,WAAW,OAAO,UAAU,mBACzD,OAAO,gBAAgB,GAAG,GAAG,IAAI,IAAI,IACrC,OAAO,GACP;IACE;IACA,aAAa;MAEd,QAAQ,aAAa,GAAG,YAAY,IAAI,IAAI,IAAI,IAAI;EAEvD,KAAK,WAAW,MAAM,YAAY,gBAAgB,OAAO;;;;;;KASjD,eAAe,KAAK,UAAU,kBAClC,YACA,qBACA,cAAc,eACd,eAAe,eACf,gBAAgB,qBAChB,gBACA,0BAA0B,qBAE9B,aACE,MACA,eACA,OACA,QACA,SACA,iBAAiB,eAAe,SAAS,WAAW,eAAe,QACnE,oBAAoB;;;;;;;;;;;;;;;UC3UT;;;UAGA,wBAAwB;;;;;;;;;;;;;;;iBAkBzB,UAAU,OAAO,yBAC/B,YAAY,MAAM,UAAU,MAAM,UAAU,aAAa,QAAQ,0BACjE,SAAS,MAAM,UAAU,MAAM,UAAU,aAAa,QAAQ,eAC5D,MAAM,UAAU,MAAM,UAAU,aAAa,QAAQ;;;;;;;;;;;;;;;;;;;iBA6BzC,aAAa,UAAU,WACrC,MAAM,GACN,SAAS,QAAQ,KAAK,SAAS,eAAe,MAC7C;KA0BS,KAAK,GAAG,qBAAqB,MAAM,MAAM,MAAM,MAAM,MAAM;iBAEjD,SAAS,GAAG,qBAAqB,GACrD,IAAI,KAAK,GAAG,GAAG,gBACf,MAAM,qCACN,SAAS,MACN,MAAM,IACR,QAAQ"}
|
|
@@ -93,6 +93,17 @@ interface FetchPortOptions {
|
|
|
93
93
|
* response. `close()` aborts the request, and the far side hears it.
|
|
94
94
|
*/
|
|
95
95
|
declare function fetchPort(url: string, options?: FetchPortOptions): Promise<Channel<Uint8Array, HttpEnd>>;
|
|
96
|
+
/** The response head, or a rejection that says why there is none. */
|
|
97
|
+
/**
|
|
98
|
+
* A response that is not a stream: the far end answered, and the answer was a refusal.
|
|
99
|
+
*
|
|
100
|
+
* The status is here as a fact and in the sentence, because a caller that decides what to do next wants the
|
|
101
|
+
* number and a caller reading a log wants the words.
|
|
102
|
+
*/
|
|
103
|
+
declare class HttpRefusal extends Error {
|
|
104
|
+
readonly status: number;
|
|
105
|
+
constructor(status: number, message: string);
|
|
106
|
+
}
|
|
96
107
|
//#endregion
|
|
97
108
|
//#region src/port/duplex.d.ts
|
|
98
109
|
/** A pair whose two sides carry the same frame type, read as one channel. */
|
|
@@ -101,5 +112,5 @@ declare function duplexChannel<F, C = void>(pair: {
|
|
|
101
112
|
readonly outbound: Channel<F, C>;
|
|
102
113
|
}): Channel<F, C>;
|
|
103
114
|
//#endregion
|
|
104
|
-
export {
|
|
105
|
-
//# sourceMappingURL=index-
|
|
115
|
+
export { memoryChannelPair as _, fetchPort as a, Sourced as c, StreamPair as d, streamChannel as f, MemoryEnd as g, ChannelPair as h, HttpRefusal as i, all as l, splitChannel as m, FetchPortOptions as n, held as o, Announcement as p, HttpEnd as r, Ended as s, duplexChannel as t, settled as u };
|
|
116
|
+
//# sourceMappingURL=index-ChSy_Vdu.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-
|
|
1
|
+
{"version":3,"file":"index-ChSy_Vdu.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;;;;KCVxC,gBAAgB;;;;;;;iBAUZ,aAAa,YAC3B,OAAO,QAAQ,YAAY,IAC3B,YAAW,eACV,QAAQ,MAAM;;;;UCpBA;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;;;;;;;iBAkEvF,QAAQ,kBAAkB,GAAG,GAC3C,SAAS,OAAO,GAAG,QAAQ,GAAG,MAC7B,QAAQ,QAAQ,GAAG,KAAK,MAAM,GAAG;;;;;;;;;iBCtFpB,KAAK,GAAG,GAAG,OAAO,QAAQ,GAAG,KAAK,QAAQ,GAAG;;;;UCR5C;;WAEN;;UAGM;;EAEf,OAAO;;EAEP;;;;;;;;iBASoB,UAAU,aAAa,UAAS,mBAAwB,QAAQ,QAAQ,YAAY;;;;;;;;cAmF7F,oBAAoB;WAEpB;EADX,YACW,gBACT;;;;;iBCtGY,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.49.
|
|
23
|
+
declare const LIB_VERSION = "0.49.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-DNJbW_di.js";
|
|
6
6
|
//#region src/process.ts
|
|
7
7
|
/** @deprecated Use {@link spawnAsync} instead. */
|
|
8
8
|
function spawn(fn, pname, tp) {
|
package/dist/port/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
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-4MaIKVnw.js";
|
|
2
|
-
import { a as
|
|
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 };
|
|
2
|
+
import { _ as memoryChannelPair, a as fetchPort, c as Sourced, d as StreamPair, f as streamChannel, g as MemoryEnd, h as ChannelPair, i as HttpRefusal, l as all, m as splitChannel, n as FetchPortOptions, o as held, p as Announcement, r as HttpEnd, s as Ended, t as duplexChannel, u as settled } from "../index-ChSy_Vdu.js";
|
|
3
|
+
export { type Announcement, type Channel, ChannelClosed, type ChannelPair, type DataMessage, type Ended, type FetchPortOptions, type HttpEnd, HttpRefusal, 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 };
|
package/dist/port/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
import { n as
|
|
3
|
-
export { ChannelClosed, all, duplexChannel, fetchPort, held, memoryChannelPair, portActor, portReactor, settled, splitChannel, streamChannel };
|
|
1
|
+
import { a as all, c as memoryChannelPair, i as fetchPort, l as ChannelClosed, n as portReactor, o as settled, r as HttpRefusal, s as streamChannel, t as duplexChannel } from "../port-0vYKSxBM.js";
|
|
2
|
+
import { n as splitChannel, r as held, t as portActor } from "../actor-MIvmdVJD.js";
|
|
3
|
+
export { ChannelClosed, HttpRefusal, all, duplexChannel, fetchPort, held, memoryChannelPair, portActor, portReactor, settled, splitChannel, streamChannel };
|
package/dist/port/node.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as
|
|
1
|
+
import { n as splitChannel, r as held, t as portActor } from "../actor-MIvmdVJD.js";
|
|
2
2
|
import { spawn } from "node:child_process";
|
|
3
3
|
//#region src/port/node/spawn.ts
|
|
4
4
|
const DEFAULT_KILL_AFTER_MS = 5e3;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { r as held } from "./actor-MIvmdVJD.js";
|
|
2
2
|
//#region src/port/channel.ts
|
|
3
3
|
/** What is thrown when a frame is sent on a channel that is over. */
|
|
4
4
|
var ChannelClosed = class extends Error {
|
|
@@ -393,7 +393,10 @@ async function fetchPort(url, options = {}) {
|
|
|
393
393
|
controller.abort();
|
|
394
394
|
await reader?.cancel().catch(() => void 0);
|
|
395
395
|
},
|
|
396
|
-
info: {
|
|
396
|
+
info: {
|
|
397
|
+
url,
|
|
398
|
+
status: response.status
|
|
399
|
+
},
|
|
397
400
|
control: () => {}
|
|
398
401
|
};
|
|
399
402
|
const reader = response.body?.getReader();
|
|
@@ -421,12 +424,25 @@ async function fetchPort(url, options = {}) {
|
|
|
421
424
|
return port;
|
|
422
425
|
}
|
|
423
426
|
/** The response head, or a rejection that says why there is none. */
|
|
427
|
+
/**
|
|
428
|
+
* A response that is not a stream: the far end answered, and the answer was a refusal.
|
|
429
|
+
*
|
|
430
|
+
* The status is here as a fact and in the sentence, because a caller that decides what to do next wants the
|
|
431
|
+
* number and a caller reading a log wants the words.
|
|
432
|
+
*/
|
|
433
|
+
var HttpRefusal = class extends Error {
|
|
434
|
+
constructor(status, message) {
|
|
435
|
+
super(message);
|
|
436
|
+
this.status = status;
|
|
437
|
+
this.name = "HttpRefusal";
|
|
438
|
+
}
|
|
439
|
+
};
|
|
424
440
|
async function answered(url, init, connectMs) {
|
|
425
441
|
const attempt = fetch(url, init).catch((error) => Promise.reject(named(url, error)));
|
|
426
442
|
const response = connectMs === void 0 ? await attempt : await Promise.race([attempt, new Promise((_resolve, reject) => setTimeout(() => reject(/* @__PURE__ */ new Error(`fetchPort: ${url} answered nothing within ${connectMs}ms`)), connectMs))]);
|
|
427
443
|
if (!response.ok) {
|
|
428
444
|
const body = await response.text().catch(() => "");
|
|
429
|
-
throw new
|
|
445
|
+
throw new HttpRefusal(response.status, `fetchPort: ${url} answered ${response.status}${body === "" ? "" : `: ${body.slice(0, 200)}`}`);
|
|
430
446
|
}
|
|
431
447
|
return response;
|
|
432
448
|
}
|
|
@@ -503,6 +519,6 @@ function duplexChannel(pair) {
|
|
|
503
519
|
};
|
|
504
520
|
}
|
|
505
521
|
//#endregion
|
|
506
|
-
export {
|
|
522
|
+
export { all as a, memoryChannelPair as c, fetchPort as i, ChannelClosed as l, portReactor as n, settled as o, HttpRefusal as r, streamChannel as s, duplexChannel as t };
|
|
507
523
|
|
|
508
|
-
//# sourceMappingURL=port-
|
|
524
|
+
//# sourceMappingURL=port-0vYKSxBM.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"port-BR7f7BDY.js","names":[],"sources":["../src/port/channel.ts","../src/port/memory.ts","../src/port/stream.ts","../src/port/combine.ts","../src/port/fetch.ts","../src/port/reactor.ts","../src/port/duplex.ts"],"sourcesContent":["// ── A channel ───────────────────────────────────────────────────────────────\n//\n// Carries values of one type between two ends. The type parameter is what crosses: bytes, a line and the\n// octets it announced, a decoded frame. A medium produces one; a protocol adapter wraps one into another.\n//\n// It ends one of three ways, and each has its own callback:\n//\n// close() this side ends it; the far end hears a close, this side's callers hear nothing\n// onClose the far end is gone, with the reason it gave\n// onError the wire failed; once, and always before onClose\n//\n// `close()` is idempotent. `send()` rejects once the channel is over, from either side.\n\n/**\n * A line of a channel that carries lines, and the octets it announced.\n *\n * A line may announce octets after it, as a stream chunk does on the remote seam, so a part is the line and\n * what it announced. A medium that moves whole messages, a websocket for instance, produces parts with no\n * octets. A byte medium produces none until the splitter has run.\n */\nexport interface Part {\n /** One line, without its terminator. */\n line: string;\n /** The octets the line announced, when it announced any. */\n bytes: Uint8Array | null;\n}\n\n/**\n * Values of one type, between two ends.\n *\n * `C` is what the far end says when it closes — a sentence for a medium, or whatever the medium has to say for\n * itself: a spawned process ends with an exit status, and that is the fact worth having. `close()` takes a\n * sentence from this side, because the close we ask for is ours.\n */\nexport interface Channel<F, C = string> {\n /**\n * Put a frame on it.\n *\n * Rejects when the channel is over, from either side: there is no reader left, and a resolved promise\n * would say the frame had been taken.\n */\n send(frame: F): Promise<void>;\n /** A frame arrived. The returned function stops this reader and no other. */\n onFrame(handler: (frame: F) => void): () => void;\n /** The far end closed, and this is what it said. Once, after any frames already read. */\n onClose(handler: (reason: C) => void): () => void;\n /** The wire failed. Once, and always followed by a close. */\n onError(handler: (error: unknown) => void): () => void;\n /**\n * Close it from this side.\n *\n * Idempotent: a second call does nothing. The far end hears a close; the callers on this side do not,\n * because they are the ones who asked.\n */\n close(reason?: string): Promise<void>;\n /** What the medium knows about itself: a process its pid, a socket its peer. Empty when it knows nothing. */\n readonly info: Record<string, unknown>;\n /**\n * Ask the medium to act on what is behind the channel — signal a process, resize a terminal.\n *\n * A medium with nothing behind it does nothing. The command is the medium's own vocabulary; the channel\n * only carries it.\n */\n control(command: Record<string, unknown>): void;\n}\n\n/** What is thrown when a frame is sent on a channel that is over. */\nexport class ChannelClosed extends Error {\n constructor(reason: string) {\n super(`the channel is closed: ${reason}`);\n this.name = \"ChannelClosed\";\n }\n}\n","// ── A channel with no medium ────────────────────────────────────────────────\n//\n// Two ends over nothing: what one sends, the other reads. For testing an adapter or a protocol without a\n// socket, a child or a file, and for exercising the endings without faking one.\n//\n// No buffer: a frame reaches the other end before `send` settles.\n\nimport { ChannelClosed, type Channel } from \"./channel.js\";\n\n/** One end of a pair. `fail` is the hook this double adds: it breaks the wire the way a socket would. */\nexport interface MemoryEnd<F> extends Channel<F> {\n /** Break the wire: the far end hears an error, and then a close. */\n fail(error: unknown): void;\n}\n\nexport interface ChannelPair<F> {\n near: MemoryEnd<F>;\n far: MemoryEnd<F>;\n}\n\ntype Side = \"near\" | \"far\";\n\ninterface End<F> {\n frames: Set<(frame: F) => void>;\n closes: Set<(reason: string) => void>;\n errors: Set<(error: unknown) => void>;\n}\n\nfunction end<F>(): End<F> {\n return { frames: new Set(), closes: new Set(), errors: new Set() };\n}\n\n/** The two halves of one channel. */\nexport function memoryChannelPair<F>(): ChannelPair<F> {\n const near = end<F>();\n const far = end<F>();\n const closed: Record<Side, string | null> = { near: null, far: null };\n const other = (side: Side): Side => (side === \"near\" ? \"far\" : \"near\");\n\n /** One side's own state and the other side's, which is all a channel is. */\n const make = (side: Side): MemoryEnd<F> => {\n const mine = side === \"near\" ? near : far;\n const theirs = side === \"near\" ? far : near;\n return {\n send: async (frame: F) => {\n const ended = closed[side] ?? closed[other(side)];\n if (ended !== null) throw new ChannelClosed(ended);\n for (const handler of [...theirs.frames]) handler(frame);\n },\n onFrame: (handler) => {\n mine.frames.add(handler);\n return () => {\n mine.frames.delete(handler);\n };\n },\n onClose: (handler) => {\n mine.closes.add(handler);\n return () => {\n mine.closes.delete(handler);\n };\n },\n onError: (handler) => {\n mine.errors.add(handler);\n return () => {\n mine.errors.delete(handler);\n };\n },\n close: async (reason = \"closed here\") => {\n if (closed[side] !== null) return;\n const peer = other(side);\n closed[side] = reason;\n if (closed[peer] !== null) return;\n closed[peer] = reason;\n for (const handler of [...theirs.closes]) handler(reason);\n },\n info: {},\n control: () => {},\n fail: (error: unknown) => {\n if (closed[side] !== null) return;\n const peer = other(side);\n if (closed[peer] !== null) return;\n for (const handler of [...theirs.errors]) handler(error);\n for (const handler of [...theirs.closes]) handler(\"the wire failed\");\n closed[side] = \"the wire failed\";\n closed[peer] = \"the wire failed\";\n },\n };\n };\n\n return { near: make(\"near\"), far: make(\"far\") };\n}\n","// ── a stream pair as a channel of bytes ────────────────────────────────\n//\n// Chunks out as they arrive, chunks in as they are written, and an ending. Framing, splitting and the meaning\n// of a frame compose on top of this.\n//\n// A send settles when the stream has flushed the chunk, not when it has accepted it into a buffer, so a writer\n// cannot run ahead of the pipe without waiting.\n//\n// Two of the three endings are discovered here rather than declared: a read side that ends is a peer that\n// closed, and a broken stream is a wire that failed.\n\nimport type { Readable, Writable } from \"node:stream\";\n\nimport { ChannelClosed, type Channel } from \"./channel.js\";\n\n/** What the channel talks over: something to read from, something to write to. */\nexport interface StreamPair {\n read: Readable;\n write: Writable;\n}\n\n/** A write error that means the peer has already hung up. */\nfunction peerGone(code: unknown): boolean {\n return (\n code === \"EPIPE\" ||\n code === \"ERR_STREAM_DESTROYED\" ||\n code === \"ERR_STREAM_WRITE_AFTER_END\" ||\n code === \"ERR_STREAM_ALREADY_FINISHED\"\n );\n}\n\nfunction asBytes(chunk: Buffer | string): Uint8Array {\n if (typeof chunk === \"string\") return new Uint8Array(Buffer.from(chunk, \"utf8\"));\n return new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength);\n}\n\n/**\n * A channel of bytes over a stream pair.\n *\n * `close()` ends the write side, so the far end hears an end of stream, and destroys the read side, so no\n * more chunks arrive after this side has said it is done. A peer that goes away is a close of this side's\n * own readers, and the reason says which of the two it was.\n */\nexport function streamChannel(pair: StreamPair): Channel<Uint8Array> {\n const frames = new Set<(frame: Uint8Array) => void>();\n const closers = new Set<(reason: string) => void>();\n const failers = new Set<(error: unknown) => void>();\n /** What this side's readers were told, and null while they have been told nothing. */\n let reported: string | null = null;\n let ended = false;\n\n const release = (): void => {\n // Best effort: a stream whose peer is gone throws from `destroy` and from `end`, and teardown is not\n // the place to find out.\n try {\n pair.read.destroy();\n } catch {\n /* already gone */\n }\n try {\n if (!pair.write.writableEnded) pair.write.end();\n } catch {\n /* already gone */\n }\n };\n\n /** End it from this side: the far end hears it, and this side's readers do not — they asked. */\n const shut = (): void => {\n if (ended) return;\n ended = true;\n release();\n };\n\n /** The far end is gone, and this side's readers hear it. */\n const finish = (reason: string): void => {\n if (ended) return;\n ended = true;\n reported = reason;\n release();\n for (const closer of [...closers]) closer(reason);\n };\n\n /** The wire failed: this side hears the error once, and then a close. */\n const fail = (error: unknown): void => {\n if (ended) return;\n ended = true;\n reported = \"the wire failed\";\n release();\n for (const failer of [...failers]) failer(error);\n for (const closer of [...closers]) closer(\"the wire failed\");\n };\n\n pair.read.on(\"data\", (chunk: Buffer | string) => {\n if (ended) return;\n const bytes = asBytes(chunk);\n for (const reader of [...frames]) reader(bytes);\n });\n pair.read.on(\"end\", () => finish(\"the far end closed\"));\n // A stream destroyed without an end — a socket whose peer vanished — says so only here.\n pair.read.on(\"close\", () => finish(\"the far end closed\"));\n pair.read.on(\"error\", (error: Error) => fail(error));\n pair.write.on(\"error\", (error: Error) => fail(error));\n\n const send = (frame: Uint8Array): Promise<void> =>\n new Promise<void>((resolve, reject) => {\n if (ended) {\n reject(new ChannelClosed(reported ?? \"closed here\"));\n return;\n }\n const done = (err?: Error | null): void => {\n if (err === undefined || err === null) {\n resolve();\n return;\n }\n if (peerGone((err as { code?: unknown }).code)) {\n finish(\"the peer is gone\");\n reject(new ChannelClosed(\"the peer is gone\"));\n return;\n }\n fail(err);\n reject(err);\n };\n try {\n pair.write.write(frame, done);\n } catch (err) {\n fail(err);\n reject(err);\n }\n });\n\n return {\n send,\n onFrame: (handler) => {\n frames.add(handler);\n return () => {\n frames.delete(handler);\n };\n },\n onClose: (handler) => {\n if (reported !== null) {\n handler(reported);\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: () => {\n shut();\n return Promise.resolve();\n },\n info: {},\n control: () => {},\n };\n}\n","// ── several channels as one ─────────────────────────────────────────────────\n//\n// Two combinators, named after the promise pair because the choice is the same one: do you stop at the first\n// ending, or do you wait for every channel to say how it ended?\n//\n// `all` is the first: a frame from any source arrives tagged with the source, and the first ending ends the\n// combined channel with that source's reason. `settled` is the second: every ending arrives as a frame of its\n// own, tagged the same way, and the combined channel closes once all of them have.\n//\n// Neither sends. A combined channel is made of others, so a frame put on it has no destination; `send`\n// rejects and says so, and `close` closes every source.\n\nimport type { Channel } from \"./channel.js\";\n\n/** A frame, and which of the combined channels it arrived on. */\nexport interface Sourced<T, F> {\n readonly source: T;\n readonly frame: F;\n}\n\n/** An ending, and which of the combined channels ended. */\nexport interface Ended<T, C> {\n readonly source: T;\n readonly ending: C;\n}\n\nfunction sendRefusal<T>(sources: T[]): Error {\n return new Error(`this channel is made of ${sources.length}: send on one of them, not on the combination`);\n}\n\n/**\n * Every frame from every source, tagged; the first ending ends it.\n *\n * The ending is the first one to arrive, and the others are ignored afterwards. This is what a process wants\n * by default: its stdout ending means the process is gone, and that is the news.\n */\nexport function all<T extends string, F, C>(sources: Record<T, Channel<F, C>>): Channel<Sourced<T, F>, C> {\n const names = Object.keys(sources) as T[];\n const readers = new Set<(frame: Sourced<T, F>) => void>();\n const closers = new Set<(reason: C) => void>();\n const failers = new Set<(error: unknown) => void>();\n let ended = false;\n /** What the first ending said, for a reader that subscribes after it. */\n let ending: C | undefined;\n\n const end = (reason: C): void => {\n if (ended) return;\n ended = true;\n ending = reason;\n for (const closer of [...closers]) closer(reason);\n };\n\n for (const name of names) {\n const source = sources[name];\n source.onFrame((frame) => {\n for (const reader of [...readers]) reader({ source: name, frame });\n });\n source.onClose(end);\n source.onError((error) => {\n for (const failer of [...failers]) failer(error);\n });\n }\n\n return {\n send: () => Promise.reject(sendRefusal(names)),\n onFrame(handler) {\n readers.add(handler);\n return () => {\n readers.delete(handler);\n };\n },\n onClose(handler) {\n if (ending !== undefined) {\n handler(ending);\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 async close(reason?: string) {\n ended = true;\n await Promise.all(names.map((name) => sources[name].close(reason)));\n },\n info: {},\n control: () => {},\n };\n}\n\n/**\n * Every frame from every source, tagged, and every ending as a frame of its own.\n *\n * It closes once all of them have ended, and that close carries nothing: the endings already arrived as frames,\n * each one saying which source it belongs to.\n */\nexport function settled<T extends string, F, C>(\n sources: Record<T, Channel<F, C>>,\n): Channel<Sourced<T, F> | Ended<T, C>, void> {\n const names = Object.keys(sources) as T[];\n const readers = new Set<(frame: Sourced<T, F> | Ended<T, C>) => void>();\n const closers = new Set<(reason: void) => void>();\n const failers = new Set<(error: unknown) => void>();\n let remaining = names.length;\n let ended = false;\n\n const emit = (frame: Sourced<T, F> | Ended<T, C>): void => {\n for (const reader of [...readers]) reader(frame);\n };\n\n const end = (): void => {\n if (ended) return;\n ended = true;\n for (const closer of [...closers]) closer(undefined);\n };\n\n for (const name of names) {\n const source = sources[name];\n source.onFrame((frame) => emit({ source: name, frame }));\n source.onClose((ending) => {\n emit({ source: name, ending });\n remaining -= 1;\n if (remaining === 0) end();\n });\n source.onError((error) => {\n for (const failer of [...failers]) failer(error);\n });\n }\n\n return {\n send: () => Promise.reject(sendRefusal(names)),\n onFrame(handler) {\n readers.add(handler);\n return () => {\n readers.delete(handler);\n };\n },\n onClose(handler) {\n if (ended) {\n handler(undefined);\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 async close(reason?: string) {\n ended = true;\n await Promise.all(names.map((name) => sources[name].close(reason)));\n },\n info: {},\n control: () => {},\n };\n}\n","// ── an HTTP request as a port ───────────────────────────────────────────────\n//\n// The response body is the channel's frames, `close()` aborts the request, and the ending is what the response\n// said about itself. A request that never got a response is a rejection, the way a spawner that cannot connect\n// is: a non-2xx, a refused connection, a promise that never settles.\n\nimport type { Channel } from \"./channel.js\";\nimport { held } from \"./held.js\";\n\n/** What a response said when its body was over. */\nexport interface HttpEnd {\n /** The status the far end answered with. The frames that came before it are its body. */\n readonly status: number;\n}\n\nexport interface FetchPortOptions {\n /** Passed to `fetch`: method, headers, body. The request's own signal is not read; `close()` aborts. */\n init?: RequestInit;\n /** How long to wait for the response head. No bound by default: a stream may be long. */\n connectMs?: number;\n}\n\n/**\n * A URL as a channel of the body it answers with.\n *\n * Frames are the chunks of the body as they arrive, so a caller reads a stream rather than waiting for a whole\n * response. `close()` aborts the request, and the far side hears it.\n */\nexport async function fetchPort(url: string, options: FetchPortOptions = {}): Promise<Channel<Uint8Array, HttpEnd>> {\n const controller = new AbortController();\n const response = await answered(url, { ...options.init, signal: controller.signal }, options.connectMs);\n\n const readers = new Set<(frame: Uint8Array) => void>();\n const closers = new Set<(reason: HttpEnd) => void>();\n const failers = new Set<(error: unknown) => void>();\n const ending: HttpEnd = { status: response.status };\n let ended = false;\n\n const end = (): void => {\n if (ended) return;\n ended = true;\n for (const closer of [...closers]) closer(ending);\n };\n\n const frames: Channel<Uint8Array, HttpEnd> = {\n send: () => Promise.reject(new Error(\"a response body has no input; send on the request instead\")),\n onFrame(handler) {\n readers.add(handler);\n return () => {\n readers.delete(handler);\n };\n },\n onClose(handler) {\n if (ended) {\n handler(ending);\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 async close() {\n controller.abort();\n await reader?.cancel().catch(() => undefined);\n },\n info: { url },\n control: () => {},\n };\n\n const reader = response.body?.getReader();\n // Wrapped before the first read: a body can deliver a chunk in the same turn the port is handed over.\n const port = held(frames);\n\n const pump = async (): Promise<void> => {\n if (reader === undefined) {\n end();\n return;\n }\n try {\n for (;;) {\n const chunk = await reader.read();\n if (chunk.done) {\n end();\n return;\n }\n for (const target of [...readers]) target(chunk.value);\n }\n } catch (error) {\n for (const failer of [...failers]) failer(error);\n end();\n }\n };\n void pump();\n\n return port;\n}\n\n/** The response head, or a rejection that says why there is none. */\nasync function answered(url: string, init: RequestInit, connectMs: number | undefined): Promise<Response> {\n const attempt = fetch(url, init).catch((error: unknown) => Promise.reject(named(url, error)));\n const response =\n connectMs === undefined\n ? await attempt\n : await Promise.race([\n attempt,\n new Promise<never>((_resolve, reject) =>\n setTimeout(() => reject(new Error(`fetchPort: ${url} answered nothing within ${connectMs}ms`)), connectMs),\n ),\n ]);\n\n if (!response.ok) {\n const body = await response.text().catch(() => \"\");\n throw new Error(`fetchPort: ${url} answered ${response.status}${body === \"\" ? \"\" : `: ${body.slice(0, 200)}`}`);\n }\n return response;\n}\n\nfunction named(url: string, error: unknown): Error {\n return new Error(`fetchPort: ${url}: ${error instanceof Error ? error.message : String(error)}`);\n}\n","// ── the loop, at the port level ─────────────────────────────────────────────\n//\n// A listener yields a pair of ports per accept, and one handler runs on that pair. The same loop the connection\n// reactor runs, one level down: there the unit is a connection that speaks a protocol, here it is a pair of\n// channels and nothing above them.\n\nimport type { Channel } from \"./channel.js\";\n\n/** One accepted exchange: what the far side sends, and what we send back. */\nexport interface PortPair<In, Out, Meta = unknown, C = void> {\n readonly inbound: Channel<In, C>;\n readonly outbound: Channel<Out, C>;\n /** Whatever the listener resolved about the caller: admission, a path, a token's subject. */\n readonly meta: Meta;\n}\n\n/** Where pairs arrive. The listener owns the medium and its admission. */\nexport interface PortListener<In, Out, Meta = unknown, C = void> {\n accept(): Promise<PortPair<In, Out, Meta, C>>;\n close(): Promise<void>;\n}\n\nexport interface PortReactorOptions<In, Out, Meta, C = void> {\n /** Called once a pair has been accepted and its handler has been given it. */\n onSession?(pair: PortPair<In, Out, Meta, C>): void;\n /** Called when a session is over, with whatever the handler threw. */\n onClosed?(pair: PortPair<In, Out, Meta, C>, error: unknown): void;\n /** A handler that throws is reported here, and the loop goes on. */\n onError?(error: unknown): void;\n}\n\nexport interface PortReactor {\n /** How many handlers are running now. */\n readonly live: number;\n /** Close the listener, stop accepting, and wait for the handlers to finish. */\n stop(): Promise<void>;\n}\n\n/**\n * One handler per accepted pair, in arrival order.\n *\n * The loop ends when the listener's `accept()` rejects, which a closed listener does. A handler that throws is\n * reported and its session ends; the loop carries on with the next pair.\n */\nexport function portReactor<In, Out, Meta, C = void>(\n listener: PortListener<In, Out, Meta, C>,\n handle: (pair: PortPair<In, Out, Meta, C>) => void | Promise<void>,\n options: PortReactorOptions<In, Out, Meta, C> = {},\n): PortReactor {\n const running = new Set<Promise<void>>();\n let stopped = false;\n\n const serve = (pair: PortPair<In, Out, Meta, C>): void => {\n const session = (async () => {\n options.onSession?.(pair);\n try {\n await handle(pair);\n } catch (error) {\n options.onError?.(error);\n options.onClosed?.(pair, error);\n return;\n }\n options.onClosed?.(pair, undefined);\n })();\n running.add(session);\n void session.finally(() => running.delete(session));\n };\n\n const loop = (async () => {\n for (;;) {\n let pair: PortPair<In, Out, Meta, C>;\n try {\n pair = await listener.accept();\n } catch {\n return;\n }\n if (stopped) return;\n serve(pair);\n }\n })();\n\n return {\n get live() {\n return running.size;\n },\n async stop() {\n stopped = true;\n await listener.close();\n await loop;\n await Promise.all([...running]);\n },\n };\n}\n","// ── a pair of channels as one ───────────────────────────────────────────────\n//\n// A medium that has an inbound side and an outbound side — a request and its answer, a socket's reader and its\n// writer — arrives as two channels. A channel has one frame type, so this is only for a pair whose two sides\n// carry the same one: frames arrive from the inbound side, `send` writes to the outbound side, `close()` ends it.\n//\n// The ending is the inbound side's: when the far side has sent everything, this channel closes with whatever that\n// side said. Closing it here closes the outbound side, which is how an answer is finished.\n\nimport type { Channel } from \"./channel.js\";\n\n/** A pair whose two sides carry the same frame type, read as one channel. */\nexport function duplexChannel<F, C = void>(pair: {\n readonly inbound: Channel<F, C>;\n readonly outbound: Channel<F, C>;\n}): Channel<F, C> {\n return {\n send: (frame) => pair.outbound.send(frame),\n onFrame: (handler) => pair.inbound.onFrame(handler),\n onClose: (handler) => pair.inbound.onClose(handler),\n onError: (handler) => pair.inbound.onError(handler),\n close: async (reason) => {\n await pair.outbound.close(reason);\n },\n info: { ...pair.inbound.info, ...pair.outbound.info },\n control: (command) => pair.inbound.control(command),\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"port-0vYKSxBM.js","names":[],"sources":["../src/port/channel.ts","../src/port/memory.ts","../src/port/stream.ts","../src/port/combine.ts","../src/port/fetch.ts","../src/port/reactor.ts","../src/port/duplex.ts"],"sourcesContent":["// ── A channel ───────────────────────────────────────────────────────────────\n//\n// Carries values of one type between two ends. The type parameter is what crosses: bytes, a line and the\n// octets it announced, a decoded frame. A medium produces one; a protocol adapter wraps one into another.\n//\n// It ends one of three ways, and each has its own callback:\n//\n// close() this side ends it; the far end hears a close, this side's callers hear nothing\n// onClose the far end is gone, with the reason it gave\n// onError the wire failed; once, and always before onClose\n//\n// `close()` is idempotent. `send()` rejects once the channel is over, from either side.\n\n/**\n * A line of a channel that carries lines, and the octets it announced.\n *\n * A line may announce octets after it, as a stream chunk does on the remote seam, so a part is the line and\n * what it announced. A medium that moves whole messages, a websocket for instance, produces parts with no\n * octets. A byte medium produces none until the splitter has run.\n */\nexport interface Part {\n /** One line, without its terminator. */\n line: string;\n /** The octets the line announced, when it announced any. */\n bytes: Uint8Array | null;\n}\n\n/**\n * Values of one type, between two ends.\n *\n * `C` is what the far end says when it closes — a sentence for a medium, or whatever the medium has to say for\n * itself: a spawned process ends with an exit status, and that is the fact worth having. `close()` takes a\n * sentence from this side, because the close we ask for is ours.\n */\nexport interface Channel<F, C = string> {\n /**\n * Put a frame on it.\n *\n * Rejects when the channel is over, from either side: there is no reader left, and a resolved promise\n * would say the frame had been taken.\n */\n send(frame: F): Promise<void>;\n /** A frame arrived. The returned function stops this reader and no other. */\n onFrame(handler: (frame: F) => void): () => void;\n /** The far end closed, and this is what it said. Once, after any frames already read. */\n onClose(handler: (reason: C) => void): () => void;\n /** The wire failed. Once, and always followed by a close. */\n onError(handler: (error: unknown) => void): () => void;\n /**\n * Close it from this side.\n *\n * Idempotent: a second call does nothing. The far end hears a close; the callers on this side do not,\n * because they are the ones who asked.\n */\n close(reason?: string): Promise<void>;\n /** What the medium knows about itself: a process its pid, a socket its peer. Empty when it knows nothing. */\n readonly info: Record<string, unknown>;\n /**\n * Ask the medium to act on what is behind the channel — signal a process, resize a terminal.\n *\n * A medium with nothing behind it does nothing. The command is the medium's own vocabulary; the channel\n * only carries it.\n */\n control(command: Record<string, unknown>): void;\n}\n\n/** What is thrown when a frame is sent on a channel that is over. */\nexport class ChannelClosed extends Error {\n constructor(reason: string) {\n super(`the channel is closed: ${reason}`);\n this.name = \"ChannelClosed\";\n }\n}\n","// ── A channel with no medium ────────────────────────────────────────────────\n//\n// Two ends over nothing: what one sends, the other reads. For testing an adapter or a protocol without a\n// socket, a child or a file, and for exercising the endings without faking one.\n//\n// No buffer: a frame reaches the other end before `send` settles.\n\nimport { ChannelClosed, type Channel } from \"./channel.js\";\n\n/** One end of a pair. `fail` is the hook this double adds: it breaks the wire the way a socket would. */\nexport interface MemoryEnd<F> extends Channel<F> {\n /** Break the wire: the far end hears an error, and then a close. */\n fail(error: unknown): void;\n}\n\nexport interface ChannelPair<F> {\n near: MemoryEnd<F>;\n far: MemoryEnd<F>;\n}\n\ntype Side = \"near\" | \"far\";\n\ninterface End<F> {\n frames: Set<(frame: F) => void>;\n closes: Set<(reason: string) => void>;\n errors: Set<(error: unknown) => void>;\n}\n\nfunction end<F>(): End<F> {\n return { frames: new Set(), closes: new Set(), errors: new Set() };\n}\n\n/** The two halves of one channel. */\nexport function memoryChannelPair<F>(): ChannelPair<F> {\n const near = end<F>();\n const far = end<F>();\n const closed: Record<Side, string | null> = { near: null, far: null };\n const other = (side: Side): Side => (side === \"near\" ? \"far\" : \"near\");\n\n /** One side's own state and the other side's, which is all a channel is. */\n const make = (side: Side): MemoryEnd<F> => {\n const mine = side === \"near\" ? near : far;\n const theirs = side === \"near\" ? far : near;\n return {\n send: async (frame: F) => {\n const ended = closed[side] ?? closed[other(side)];\n if (ended !== null) throw new ChannelClosed(ended);\n for (const handler of [...theirs.frames]) handler(frame);\n },\n onFrame: (handler) => {\n mine.frames.add(handler);\n return () => {\n mine.frames.delete(handler);\n };\n },\n onClose: (handler) => {\n mine.closes.add(handler);\n return () => {\n mine.closes.delete(handler);\n };\n },\n onError: (handler) => {\n mine.errors.add(handler);\n return () => {\n mine.errors.delete(handler);\n };\n },\n close: async (reason = \"closed here\") => {\n if (closed[side] !== null) return;\n const peer = other(side);\n closed[side] = reason;\n if (closed[peer] !== null) return;\n closed[peer] = reason;\n for (const handler of [...theirs.closes]) handler(reason);\n },\n info: {},\n control: () => {},\n fail: (error: unknown) => {\n if (closed[side] !== null) return;\n const peer = other(side);\n if (closed[peer] !== null) return;\n for (const handler of [...theirs.errors]) handler(error);\n for (const handler of [...theirs.closes]) handler(\"the wire failed\");\n closed[side] = \"the wire failed\";\n closed[peer] = \"the wire failed\";\n },\n };\n };\n\n return { near: make(\"near\"), far: make(\"far\") };\n}\n","// ── a stream pair as a channel of bytes ────────────────────────────────\n//\n// Chunks out as they arrive, chunks in as they are written, and an ending. Framing, splitting and the meaning\n// of a frame compose on top of this.\n//\n// A send settles when the stream has flushed the chunk, not when it has accepted it into a buffer, so a writer\n// cannot run ahead of the pipe without waiting.\n//\n// Two of the three endings are discovered here rather than declared: a read side that ends is a peer that\n// closed, and a broken stream is a wire that failed.\n\nimport type { Readable, Writable } from \"node:stream\";\n\nimport { ChannelClosed, type Channel } from \"./channel.js\";\n\n/** What the channel talks over: something to read from, something to write to. */\nexport interface StreamPair {\n read: Readable;\n write: Writable;\n}\n\n/** A write error that means the peer has already hung up. */\nfunction peerGone(code: unknown): boolean {\n return (\n code === \"EPIPE\" ||\n code === \"ERR_STREAM_DESTROYED\" ||\n code === \"ERR_STREAM_WRITE_AFTER_END\" ||\n code === \"ERR_STREAM_ALREADY_FINISHED\"\n );\n}\n\nfunction asBytes(chunk: Buffer | string): Uint8Array {\n if (typeof chunk === \"string\") return new Uint8Array(Buffer.from(chunk, \"utf8\"));\n return new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength);\n}\n\n/**\n * A channel of bytes over a stream pair.\n *\n * `close()` ends the write side, so the far end hears an end of stream, and destroys the read side, so no\n * more chunks arrive after this side has said it is done. A peer that goes away is a close of this side's\n * own readers, and the reason says which of the two it was.\n */\nexport function streamChannel(pair: StreamPair): Channel<Uint8Array> {\n const frames = new Set<(frame: Uint8Array) => void>();\n const closers = new Set<(reason: string) => void>();\n const failers = new Set<(error: unknown) => void>();\n /** What this side's readers were told, and null while they have been told nothing. */\n let reported: string | null = null;\n let ended = false;\n\n const release = (): void => {\n // Best effort: a stream whose peer is gone throws from `destroy` and from `end`, and teardown is not\n // the place to find out.\n try {\n pair.read.destroy();\n } catch {\n /* already gone */\n }\n try {\n if (!pair.write.writableEnded) pair.write.end();\n } catch {\n /* already gone */\n }\n };\n\n /** End it from this side: the far end hears it, and this side's readers do not — they asked. */\n const shut = (): void => {\n if (ended) return;\n ended = true;\n release();\n };\n\n /** The far end is gone, and this side's readers hear it. */\n const finish = (reason: string): void => {\n if (ended) return;\n ended = true;\n reported = reason;\n release();\n for (const closer of [...closers]) closer(reason);\n };\n\n /** The wire failed: this side hears the error once, and then a close. */\n const fail = (error: unknown): void => {\n if (ended) return;\n ended = true;\n reported = \"the wire failed\";\n release();\n for (const failer of [...failers]) failer(error);\n for (const closer of [...closers]) closer(\"the wire failed\");\n };\n\n pair.read.on(\"data\", (chunk: Buffer | string) => {\n if (ended) return;\n const bytes = asBytes(chunk);\n for (const reader of [...frames]) reader(bytes);\n });\n pair.read.on(\"end\", () => finish(\"the far end closed\"));\n // A stream destroyed without an end — a socket whose peer vanished — says so only here.\n pair.read.on(\"close\", () => finish(\"the far end closed\"));\n pair.read.on(\"error\", (error: Error) => fail(error));\n pair.write.on(\"error\", (error: Error) => fail(error));\n\n const send = (frame: Uint8Array): Promise<void> =>\n new Promise<void>((resolve, reject) => {\n if (ended) {\n reject(new ChannelClosed(reported ?? \"closed here\"));\n return;\n }\n const done = (err?: Error | null): void => {\n if (err === undefined || err === null) {\n resolve();\n return;\n }\n if (peerGone((err as { code?: unknown }).code)) {\n finish(\"the peer is gone\");\n reject(new ChannelClosed(\"the peer is gone\"));\n return;\n }\n fail(err);\n reject(err);\n };\n try {\n pair.write.write(frame, done);\n } catch (err) {\n fail(err);\n reject(err);\n }\n });\n\n return {\n send,\n onFrame: (handler) => {\n frames.add(handler);\n return () => {\n frames.delete(handler);\n };\n },\n onClose: (handler) => {\n if (reported !== null) {\n handler(reported);\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: () => {\n shut();\n return Promise.resolve();\n },\n info: {},\n control: () => {},\n };\n}\n","// ── several channels as one ─────────────────────────────────────────────────\n//\n// Two combinators, named after the promise pair because the choice is the same one: do you stop at the first\n// ending, or do you wait for every channel to say how it ended?\n//\n// `all` is the first: a frame from any source arrives tagged with the source, and the first ending ends the\n// combined channel with that source's reason. `settled` is the second: every ending arrives as a frame of its\n// own, tagged the same way, and the combined channel closes once all of them have.\n//\n// Neither sends. A combined channel is made of others, so a frame put on it has no destination; `send`\n// rejects and says so, and `close` closes every source.\n\nimport type { Channel } from \"./channel.js\";\n\n/** A frame, and which of the combined channels it arrived on. */\nexport interface Sourced<T, F> {\n readonly source: T;\n readonly frame: F;\n}\n\n/** An ending, and which of the combined channels ended. */\nexport interface Ended<T, C> {\n readonly source: T;\n readonly ending: C;\n}\n\nfunction sendRefusal<T>(sources: T[]): Error {\n return new Error(`this channel is made of ${sources.length}: send on one of them, not on the combination`);\n}\n\n/**\n * Every frame from every source, tagged; the first ending ends it.\n *\n * The ending is the first one to arrive, and the others are ignored afterwards. This is what a process wants\n * by default: its stdout ending means the process is gone, and that is the news.\n */\nexport function all<T extends string, F, C>(sources: Record<T, Channel<F, C>>): Channel<Sourced<T, F>, C> {\n const names = Object.keys(sources) as T[];\n const readers = new Set<(frame: Sourced<T, F>) => void>();\n const closers = new Set<(reason: C) => void>();\n const failers = new Set<(error: unknown) => void>();\n let ended = false;\n /** What the first ending said, for a reader that subscribes after it. */\n let ending: C | undefined;\n\n const end = (reason: C): void => {\n if (ended) return;\n ended = true;\n ending = reason;\n for (const closer of [...closers]) closer(reason);\n };\n\n for (const name of names) {\n const source = sources[name];\n source.onFrame((frame) => {\n for (const reader of [...readers]) reader({ source: name, frame });\n });\n source.onClose(end);\n source.onError((error) => {\n for (const failer of [...failers]) failer(error);\n });\n }\n\n return {\n send: () => Promise.reject(sendRefusal(names)),\n onFrame(handler) {\n readers.add(handler);\n return () => {\n readers.delete(handler);\n };\n },\n onClose(handler) {\n if (ending !== undefined) {\n handler(ending);\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 async close(reason?: string) {\n ended = true;\n await Promise.all(names.map((name) => sources[name].close(reason)));\n },\n info: {},\n control: () => {},\n };\n}\n\n/**\n * Every frame from every source, tagged, and every ending as a frame of its own.\n *\n * It closes once all of them have ended, and that close carries nothing: the endings already arrived as frames,\n * each one saying which source it belongs to.\n */\nexport function settled<T extends string, F, C>(\n sources: Record<T, Channel<F, C>>,\n): Channel<Sourced<T, F> | Ended<T, C>, void> {\n const names = Object.keys(sources) as T[];\n const readers = new Set<(frame: Sourced<T, F> | Ended<T, C>) => void>();\n const closers = new Set<(reason: void) => void>();\n const failers = new Set<(error: unknown) => void>();\n let remaining = names.length;\n let ended = false;\n\n const emit = (frame: Sourced<T, F> | Ended<T, C>): void => {\n for (const reader of [...readers]) reader(frame);\n };\n\n const end = (): void => {\n if (ended) return;\n ended = true;\n for (const closer of [...closers]) closer(undefined);\n };\n\n for (const name of names) {\n const source = sources[name];\n source.onFrame((frame) => emit({ source: name, frame }));\n source.onClose((ending) => {\n emit({ source: name, ending });\n remaining -= 1;\n if (remaining === 0) end();\n });\n source.onError((error) => {\n for (const failer of [...failers]) failer(error);\n });\n }\n\n return {\n send: () => Promise.reject(sendRefusal(names)),\n onFrame(handler) {\n readers.add(handler);\n return () => {\n readers.delete(handler);\n };\n },\n onClose(handler) {\n if (ended) {\n handler(undefined);\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 async close(reason?: string) {\n ended = true;\n await Promise.all(names.map((name) => sources[name].close(reason)));\n },\n info: {},\n control: () => {},\n };\n}\n","// ── an HTTP request as a port ───────────────────────────────────────────────\n//\n// The response body is the channel's frames, `close()` aborts the request, and the ending is what the response\n// said about itself. A request that never got a response is a rejection, the way a spawner that cannot connect\n// is: a non-2xx, a refused connection, a promise that never settles.\n\nimport type { Channel } from \"./channel.js\";\nimport { held } from \"./held.js\";\n\n/** What a response said when its body was over. */\nexport interface HttpEnd {\n /** The status the far end answered with. The frames that came before it are its body. */\n readonly status: number;\n}\n\nexport interface FetchPortOptions {\n /** Passed to `fetch`: method, headers, body. The request's own signal is not read; `close()` aborts. */\n init?: RequestInit;\n /** How long to wait for the response head. No bound by default: a stream may be long. */\n connectMs?: number;\n}\n\n/**\n * A URL as a channel of the body it answers with.\n *\n * Frames are the chunks of the body as they arrive, so a caller reads a stream rather than waiting for a whole\n * response. `close()` aborts the request, and the far side hears it.\n */\nexport async function fetchPort(url: string, options: FetchPortOptions = {}): Promise<Channel<Uint8Array, HttpEnd>> {\n const controller = new AbortController();\n const response = await answered(url, { ...options.init, signal: controller.signal }, options.connectMs);\n\n const readers = new Set<(frame: Uint8Array) => void>();\n const closers = new Set<(reason: HttpEnd) => void>();\n const failers = new Set<(error: unknown) => void>();\n const ending: HttpEnd = { status: response.status };\n let ended = false;\n\n const end = (): void => {\n if (ended) return;\n ended = true;\n for (const closer of [...closers]) closer(ending);\n };\n\n const frames: Channel<Uint8Array, HttpEnd> = {\n send: () => Promise.reject(new Error(\"a response body has no input; send on the request instead\")),\n onFrame(handler) {\n readers.add(handler);\n return () => {\n readers.delete(handler);\n };\n },\n onClose(handler) {\n if (ended) {\n handler(ending);\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 async close() {\n controller.abort();\n await reader?.cancel().catch(() => undefined);\n },\n info: { url, status: response.status },\n control: () => {},\n };\n\n const reader = response.body?.getReader();\n // Wrapped before the first read: a body can deliver a chunk in the same turn the port is handed over.\n const port = held(frames);\n\n const pump = async (): Promise<void> => {\n if (reader === undefined) {\n end();\n return;\n }\n try {\n for (;;) {\n const chunk = await reader.read();\n if (chunk.done) {\n end();\n return;\n }\n for (const target of [...readers]) target(chunk.value);\n }\n } catch (error) {\n for (const failer of [...failers]) failer(error);\n end();\n }\n };\n void pump();\n\n return port;\n}\n\n/** The response head, or a rejection that says why there is none. */\n/**\n * A response that is not a stream: the far end answered, and the answer was a refusal.\n *\n * The status is here as a fact and in the sentence, because a caller that decides what to do next wants the\n * number and a caller reading a log wants the words.\n */\nexport class HttpRefusal extends Error {\n constructor(\n readonly status: number,\n message: string,\n ) {\n super(message);\n this.name = \"HttpRefusal\";\n }\n}\n\nasync function answered(url: string, init: RequestInit, connectMs: number | undefined): Promise<Response> {\n const attempt = fetch(url, init).catch((error: unknown) => Promise.reject(named(url, error)));\n const response =\n connectMs === undefined\n ? await attempt\n : await Promise.race([\n attempt,\n new Promise<never>((_resolve, reject) =>\n setTimeout(() => reject(new Error(`fetchPort: ${url} answered nothing within ${connectMs}ms`)), connectMs),\n ),\n ]);\n\n if (!response.ok) {\n const body = await response.text().catch(() => \"\");\n throw new HttpRefusal(\n response.status,\n `fetchPort: ${url} answered ${response.status}${body === \"\" ? \"\" : `: ${body.slice(0, 200)}`}`,\n );\n }\n return response;\n}\n\nfunction named(url: string, error: unknown): Error {\n return new Error(`fetchPort: ${url}: ${error instanceof Error ? error.message : String(error)}`);\n}\n","// ── the loop, at the port level ─────────────────────────────────────────────\n//\n// A listener yields a pair of ports per accept, and one handler runs on that pair. The same loop the connection\n// reactor runs, one level down: there the unit is a connection that speaks a protocol, here it is a pair of\n// channels and nothing above them.\n\nimport type { Channel } from \"./channel.js\";\n\n/** One accepted exchange: what the far side sends, and what we send back. */\nexport interface PortPair<In, Out, Meta = unknown, C = void> {\n readonly inbound: Channel<In, C>;\n readonly outbound: Channel<Out, C>;\n /** Whatever the listener resolved about the caller: admission, a path, a token's subject. */\n readonly meta: Meta;\n}\n\n/** Where pairs arrive. The listener owns the medium and its admission. */\nexport interface PortListener<In, Out, Meta = unknown, C = void> {\n accept(): Promise<PortPair<In, Out, Meta, C>>;\n close(): Promise<void>;\n}\n\nexport interface PortReactorOptions<In, Out, Meta, C = void> {\n /** Called once a pair has been accepted and its handler has been given it. */\n onSession?(pair: PortPair<In, Out, Meta, C>): void;\n /** Called when a session is over, with whatever the handler threw. */\n onClosed?(pair: PortPair<In, Out, Meta, C>, error: unknown): void;\n /** A handler that throws is reported here, and the loop goes on. */\n onError?(error: unknown): void;\n}\n\nexport interface PortReactor {\n /** How many handlers are running now. */\n readonly live: number;\n /** Close the listener, stop accepting, and wait for the handlers to finish. */\n stop(): Promise<void>;\n}\n\n/**\n * One handler per accepted pair, in arrival order.\n *\n * The loop ends when the listener's `accept()` rejects, which a closed listener does. A handler that throws is\n * reported and its session ends; the loop carries on with the next pair.\n */\nexport function portReactor<In, Out, Meta, C = void>(\n listener: PortListener<In, Out, Meta, C>,\n handle: (pair: PortPair<In, Out, Meta, C>) => void | Promise<void>,\n options: PortReactorOptions<In, Out, Meta, C> = {},\n): PortReactor {\n const running = new Set<Promise<void>>();\n let stopped = false;\n\n const serve = (pair: PortPair<In, Out, Meta, C>): void => {\n const session = (async () => {\n options.onSession?.(pair);\n try {\n await handle(pair);\n } catch (error) {\n options.onError?.(error);\n options.onClosed?.(pair, error);\n return;\n }\n options.onClosed?.(pair, undefined);\n })();\n running.add(session);\n void session.finally(() => running.delete(session));\n };\n\n const loop = (async () => {\n for (;;) {\n let pair: PortPair<In, Out, Meta, C>;\n try {\n pair = await listener.accept();\n } catch {\n return;\n }\n if (stopped) return;\n serve(pair);\n }\n })();\n\n return {\n get live() {\n return running.size;\n },\n async stop() {\n stopped = true;\n await listener.close();\n await loop;\n await Promise.all([...running]);\n },\n };\n}\n","// ── a pair of channels as one ───────────────────────────────────────────────\n//\n// A medium that has an inbound side and an outbound side — a request and its answer, a socket's reader and its\n// writer — arrives as two channels. A channel has one frame type, so this is only for a pair whose two sides\n// carry the same one: frames arrive from the inbound side, `send` writes to the outbound side, `close()` ends it.\n//\n// The ending is the inbound side's: when the far side has sent everything, this channel closes with whatever that\n// side said. Closing it here closes the outbound side, which is how an answer is finished.\n\nimport type { Channel } from \"./channel.js\";\n\n/** A pair whose two sides carry the same frame type, read as one channel. */\nexport function duplexChannel<F, C = void>(pair: {\n readonly inbound: Channel<F, C>;\n readonly outbound: Channel<F, C>;\n}): Channel<F, C> {\n return {\n send: (frame) => pair.outbound.send(frame),\n onFrame: (handler) => pair.inbound.onFrame(handler),\n onClose: (handler) => pair.inbound.onClose(handler),\n onError: (handler) => pair.inbound.onError(handler),\n close: async (reason) => {\n await pair.outbound.close(reason);\n },\n info: { ...pair.inbound.info, ...pair.outbound.info },\n control: (command) => pair.inbound.control(command),\n };\n}\n"],"mappings":"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"}
|
package/dist/remote/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as readFrame, B as isRelease, C as RemoteStream, D as isStreamRef, E as isBytesRef, F as isExit, G as VERSION, H as isState, I as isInit, J as decode, K as badFrame, L as isMsg, M as errorReason, N as frameReaders, O as makeSender, P as isError, Q as json1Channel, R as isPause, S as RemoteBlob, T as isBlobRef, U as isStop, V as isResume, W as BAD_PREFIX_LIMIT, X as isBad, Y as encode, Z as json1, _ as HandshakeError, a as remoteClient, b as protoFrame, c as oneConnection, d as frameChannel, et as PROCESS_REF, f as jsonSeam, g as HANDSHAKE_TIMEOUT_MS, h as seamOf, i as CHANNEL_LOST, j as errorFrame, k as RemoteProcess, l as reactor, m as seamAnnounced, n as WebSocketTransport, o as pumpOutput, p as jsonSeamParts, q as badReason, rt as rootIdFor, s as stderrSink, t as WS_OPEN, tt as isRemoteProcess, u as serveRemoteActor, v as PROTO_KEY, w as StreamStore, x as protoVersion, y as handshake, z as isProto } from "../websocket-
|
|
1
|
+
import { $ as readFrame, B as isRelease, C as RemoteStream, D as isStreamRef, E as isBytesRef, F as isExit, G as VERSION, H as isState, I as isInit, J as decode, K as badFrame, L as isMsg, M as errorReason, N as frameReaders, O as makeSender, P as isError, Q as json1Channel, R as isPause, S as RemoteBlob, T as isBlobRef, U as isStop, V as isResume, W as BAD_PREFIX_LIMIT, X as isBad, Y as encode, Z as json1, _ as HandshakeError, a as remoteClient, b as protoFrame, c as oneConnection, d as frameChannel, et as PROCESS_REF, f as jsonSeam, g as HANDSHAKE_TIMEOUT_MS, h as seamOf, i as CHANNEL_LOST, j as errorFrame, k as RemoteProcess, l as reactor, m as seamAnnounced, n as WebSocketTransport, o as pumpOutput, p as jsonSeamParts, q as badReason, rt as rootIdFor, s as stderrSink, t as WS_OPEN, tt as isRemoteProcess, u as serveRemoteActor, v as PROTO_KEY, w as StreamStore, x as protoVersion, y as handshake, z as isProto } from "../websocket-By6xlyLp.js";
|
|
2
2
|
//#region src/remote/transports/worker.ts
|
|
3
3
|
/** The worker encoding: native structured clone (no JSON). */
|
|
4
4
|
const WORKER_VERSION = "clone.v1";
|
package/dist/remote/node.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { t as LIB_VERSION } from "../version-
|
|
2
|
-
import {
|
|
3
|
-
import { A as channelThrough, G as VERSION, M as errorReason$1, Q as json1Channel, a as remoteClient, f as jsonSeam, h as seamOf, j as errorFrame$1, n as WebSocketTransport, nt as lowBand, o as pumpOutput, r as readParts, s as stderrSink, u as serveRemoteActor, w as StreamStore, z as isProto } from "../websocket-
|
|
1
|
+
import { t as LIB_VERSION } from "../version-DNJbW_di.js";
|
|
2
|
+
import { s as streamChannel } from "../port-0vYKSxBM.js";
|
|
3
|
+
import { A as channelThrough, G as VERSION, M as errorReason$1, Q as json1Channel, a as remoteClient, f as jsonSeam, h as seamOf, j as errorFrame$1, n as WebSocketTransport, nt as lowBand, o as pumpOutput, r as readParts, s as stderrSink, u as serveRemoteActor, w as StreamStore, z as isProto } from "../websocket-By6xlyLp.js";
|
|
4
4
|
import { execFile, spawn } from "node:child_process";
|
|
5
5
|
import { chmod, mkdir, mkdtemp, open, readFile, rm, stat, unlink } from "node:fs/promises";
|
|
6
6
|
import { createHash, randomUUID } from "node:crypto";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
//#region src/version.ts
|
|
2
2
|
/** posipaki's release version. Must equal package.json's `version`. */
|
|
3
|
-
const LIB_VERSION = "0.49.
|
|
3
|
+
const LIB_VERSION = "0.49.1";
|
|
4
4
|
//#endregion
|
|
5
5
|
export { LIB_VERSION as t };
|
|
6
6
|
|
|
7
|
-
//# sourceMappingURL=version-
|
|
7
|
+
//# sourceMappingURL=version-DNJbW_di.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version-
|
|
1
|
+
{"version":3,"file":"version-DNJbW_di.js","names":[],"sources":["../src/version.ts"],"sourcesContent":["// ── Library identity ───────────────────────────────────────────────────────\n//\n// posipaki's own release version, as a plain inlined string. A consumer that\n// stages artifacts onto a host it knows nothing about has to name those\n// artifacts after which posipaki they speak, and the bundle that runs there has\n// no node_modules and no posipaki on disk — it can never read a file to find out.\n//\n// It is not the protocol version: that is `VERSION` in ./remote (`json.v1`), and\n// it does not move between releases. The two answer different questions.\n//\n// version.test.ts pins this to package.json, so a release that forgets to bump it\n// fails the suite rather than shipping a lie.\n\n/** posipaki's release version. Must equal package.json's `version`. */\nexport const LIB_VERSION = \"0.49.1\";\n"],"mappings":";;AAcA,MAAa,cAAc"}
|