posipaki 0.38.0 → 0.40.0
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/{client-Cg_MlE0m.d.ts → client-PWS8gJ0-.d.ts} +14 -4
- package/dist/{client-Cg_MlE0m.d.ts.map → client-PWS8gJ0-.d.ts.map} +1 -1
- package/dist/{define-actor-CCJy7LDp.js → define-actor-D7c9vn6S.js} +42 -34
- package/dist/define-actor-D7c9vn6S.js.map +1 -0
- package/dist/hooks-CgXhmY4r.js.map +1 -1
- package/dist/{hooks-gmAsdJBN.d.ts → hooks-D1QaP6Vv.d.ts} +13 -4
- package/dist/hooks-D1QaP6Vv.d.ts.map +1 -0
- package/dist/hooks.d.ts +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/{json1-DZ8N0TuZ.js → json1-B-oUZzI_.js} +18 -4
- package/dist/{json1-DZ8N0TuZ.js.map → json1-B-oUZzI_.js.map} +1 -1
- package/dist/plugins/debug-logger.d.ts +2 -2
- package/dist/plugins/tree-introspection.d.ts +2 -2
- package/dist/plugins/tree-introspection.js +1 -1
- package/dist/{process-DjRQSZef.d.ts → process-BVwU7TQo.d.ts} +2 -2
- package/dist/{process-DjRQSZef.d.ts.map → process-BVwU7TQo.d.ts.map} +1 -1
- package/dist/{process.async-CdQ_zpKp.js → process.async-C_-NpMFX.js} +3 -1
- package/dist/process.async-C_-NpMFX.js.map +1 -0
- package/dist/remote/index.d.ts +4 -4
- package/dist/remote/index.js +2 -2
- package/dist/remote/node.d.ts +3 -3
- package/dist/remote/node.js +2 -2
- package/dist/testing/index.d.ts +2 -2
- package/dist/{types-DDc-stle.d.ts → types-DYd-DDFB.d.ts} +40 -3
- package/dist/{types-DDc-stle.d.ts.map → types-DYd-DDFB.d.ts.map} +1 -1
- package/dist/{version-BnBkASor.js → version-D4C9wBG0.js} +2 -2
- package/dist/{version-BnBkASor.js.map → version-D4C9wBG0.js.map} +1 -1
- package/dist/xfetch.d.ts +2 -2
- package/package.json +1 -1
- package/dist/define-actor-CCJy7LDp.js.map +0 -1
- package/dist/hooks-gmAsdJBN.d.ts.map +0 -1
- package/dist/process.async-CdQ_zpKp.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { h as MethodOptions, l as ActorDefinition, p as HandlerOptions, v as ReflectionOptions } from "./hooks-
|
|
1
|
+
import { i as Message } from "./types-DYd-DDFB.js";
|
|
2
|
+
import { h as MethodOptions, l as ActorDefinition, p as HandlerOptions, v as ReflectionOptions } from "./hooks-D1QaP6Vv.js";
|
|
3
3
|
//#region src/remote/channel.d.ts
|
|
4
4
|
interface StringTransport {
|
|
5
5
|
send(frame: string): void | Promise<void>;
|
|
@@ -54,7 +54,17 @@ declare function isRelease(msg: Record<string, unknown>): msg is {
|
|
|
54
54
|
//#endregion
|
|
55
55
|
//#region src/remote/client.d.ts
|
|
56
56
|
type ClientSpawner<Args> = (args: Args) => Promise<Channel>;
|
|
57
|
+
/**
|
|
58
|
+
* Why a proxy ends when the wire under it goes.
|
|
59
|
+
*
|
|
60
|
+
* The far side is *unreachable*, which is not the same as ended: the handles that came across are
|
|
61
|
+
* still here and still readable, and what the far process left behind is still what it left behind.
|
|
62
|
+
* But nothing it says can arrive and nothing here can reach it, and that is news of its own — so the
|
|
63
|
+
* proxy ends with this reason rather than sitting there silent. Whoever forked the proxy hears it
|
|
64
|
+
* where it hears everything else about a child, in `onChildExit`.
|
|
65
|
+
*/
|
|
66
|
+
declare const CHANNEL_LOST = "channel-lost";
|
|
57
67
|
declare function remoteClient<Args, State, InMsg extends Message, OutMsg extends Message, Methods extends MethodOptions = MethodOptions, Handlers extends HandlerOptions<InMsg> = HandlerOptions<InMsg>, R extends ReflectionOptions = ReflectionOptions>(name: string, spawner: ClientSpawner<Args>): ActorDefinition<Args, State, InMsg, OutMsg, R>;
|
|
58
68
|
//#endregion
|
|
59
|
-
export {
|
|
60
|
-
//# sourceMappingURL=client-
|
|
69
|
+
export { StreamKind as a, isInit as c, isProto as d, isRelease as f, isStop as h, Channel as i, isMsg as l, isState as m, ClientSpawner as n, StringTransport as o, isResume as p, remoteClient as r, isExit as s, CHANNEL_LOST as t, isPause as u };
|
|
70
|
+
//# sourceMappingURL=client-PWS8gJ0-.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-
|
|
1
|
+
{"version":3,"file":"client-PWS8gJ0-.d.ts","names":[],"sources":["../src/remote/channel.ts","../src/remote/client.ts"],"mappings":";;;UAgBiB;EACf,KAAK,uBAAuB;EAC5B,UAAU,UAAU;EACpB;;EAEA,QAAQ;EACR,SAAS;;UAGM;EACf,KAAK,OAAO,iCAAiC;EAC7C,UAAU,UAAU,OAAO;EAC3B;;EAEA,QAAQ;EACR,SAAS;;iBA6CK,QAAQ,KAAK,0BAA0B;EAAS;;iBAGhD,OAAO,KAAK,0BAA0B;EAAS,OAAO;;iBAGtD,QAAQ,KAAK,0BAA0B;EAAS,QAAQ;;iBAGxD,MACd,KAAK,0BACJ;EAAS;IAAQ;IAAkB,MAAM;;;iBAG5B,OACd,KAAK,0BACJ;EAAS;IAAS;IAAc;;;KAavB;iBA+BI,OAAO,KAAK,0BAA0B;EAAS,OAAO;;iBAGtD,QAAQ,KAAK,0BAA0B;EAAS,QAAQ;;iBAGxD,SAAS,KAAK,0BAA0B;EAAS,SAAS;;iBAG1D,UAAU,KAAK,0BAA0B;EAAS,UAAU;;;;KCtGhE,cAAc,SAAS,MAAM,SAAS,QAAQ;;;;;;;;;;cAY7C;iBAEG,aACd,MACA,OACA,cAAc,SACd,eAAe,SACf,gBAAgB,gBAAgB,eAChC,iBAAiB,eAAe,SAAS,eAAe,QACxD,UAAU,oBAAoB,mBAE9B,cACA,SAAS,cAAc,QACtB,gBAAgB,MAAM,OAAO,OAAO,QAAQ"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as spawnAsync, i as runDispatchAsync } from "./process.async-
|
|
1
|
+
import { a as spawnAsync, i as runDispatchAsync } from "./process.async-C_-NpMFX.js";
|
|
2
2
|
import { a as STOP_SENTINEL, i as PROPAGATE_SENTINEL, t as callHook } from "./hooks-CgXhmY4r.js";
|
|
3
3
|
//#region src/define-actor.ts
|
|
4
4
|
function defineMessages() {}
|
|
@@ -39,9 +39,23 @@ function defineActor(config) {
|
|
|
39
39
|
let done = false;
|
|
40
40
|
let exitReason;
|
|
41
41
|
let rawState = void 0;
|
|
42
|
+
/**
|
|
43
|
+
* End this actor, and write the reason down twice: the hooks (`beforeEnd`, `afterEnd`) read
|
|
44
|
+
* the local copy, and the EXIT the parent receives carries it as well. An exit that says
|
|
45
|
+
* only *that* something ended leaves the parent to guess — and a stop that was agreed to, a
|
|
46
|
+
* wire that closed (`CHANNEL_LOST`) and a child that finished are three different things to
|
|
47
|
+
* whoever has to react.
|
|
48
|
+
*/
|
|
49
|
+
const endWith = (reason, wake = false) => {
|
|
50
|
+
exitReason = reason;
|
|
51
|
+
ctx.exitReason = reason;
|
|
52
|
+
done = true;
|
|
53
|
+
if (wake) ctx.wake();
|
|
54
|
+
};
|
|
42
55
|
const decorated = /* @__PURE__ */ new Map();
|
|
43
|
-
const
|
|
56
|
+
const actorCtx = {
|
|
44
57
|
ctx,
|
|
58
|
+
self: ctx.self,
|
|
45
59
|
...assembly.methods || {},
|
|
46
60
|
...assembly.$decorate || {},
|
|
47
61
|
reflection: {},
|
|
@@ -49,26 +63,23 @@ function defineActor(config) {
|
|
|
49
63
|
name: ctx.pname,
|
|
50
64
|
id: ctx.id,
|
|
51
65
|
async emit(msg) {
|
|
52
|
-
await callHook(assembly.onEmit, void 0,
|
|
66
|
+
await callHook(assembly.onEmit, void 0, actorCtx, msg, {
|
|
53
67
|
fromName: ctx.pname,
|
|
54
68
|
fromId: ctx.id
|
|
55
69
|
});
|
|
56
70
|
ctx.toParent(msg);
|
|
57
71
|
},
|
|
58
72
|
agreeToStop() {
|
|
59
|
-
|
|
60
|
-
done = true;
|
|
73
|
+
endWith("stopped");
|
|
61
74
|
},
|
|
62
75
|
exit(reason) {
|
|
63
|
-
|
|
64
|
-
done = true;
|
|
65
|
-
ctx.wake();
|
|
76
|
+
endWith(reason, true);
|
|
66
77
|
},
|
|
67
78
|
$child: {},
|
|
68
79
|
decorators: {},
|
|
69
80
|
fork: async (childActor, childArgs, forkOpts) => {
|
|
70
81
|
let child;
|
|
71
|
-
const childName = forkOpts?.name ?? childActor?.name ?? `child-${Object.keys(
|
|
82
|
+
const childName = forkOpts?.name ?? childActor?.name ?? `child-${Object.keys(actorCtx.$child).length}`;
|
|
72
83
|
const treeName = `${ctx.pname}:${childName}`;
|
|
73
84
|
const childAddPlugins = [...assembly.addPlugins || [], ...forkOpts?.addPlugins || []];
|
|
74
85
|
child = await childActor.spawnAsChild(ctx, childArgs, {
|
|
@@ -76,11 +87,11 @@ function defineActor(config) {
|
|
|
76
87
|
parentPlugins: assembly.resolvedPlugins || [],
|
|
77
88
|
...childAddPlugins.length ? { addPlugins: childAddPlugins } : {}
|
|
78
89
|
});
|
|
79
|
-
|
|
90
|
+
actorCtx.$child[child.pname] = child;
|
|
80
91
|
return child;
|
|
81
92
|
}
|
|
82
93
|
};
|
|
83
|
-
actorCtxMap.set(ctx.id,
|
|
94
|
+
actorCtxMap.set(ctx.id, actorCtx);
|
|
84
95
|
/**
|
|
85
96
|
* Lifecycle hooks are the actor's own control flow: if one throws, the
|
|
86
97
|
* state machine is half-applied, so the error is fatal — `onError` still
|
|
@@ -96,43 +107,40 @@ function defineActor(config) {
|
|
|
96
107
|
*/
|
|
97
108
|
const hookErrorHandler = async (e) => {
|
|
98
109
|
try {
|
|
99
|
-
await assembly.onError?.call(
|
|
110
|
+
await assembly.onError?.call(actorCtx, e);
|
|
100
111
|
} catch {}
|
|
101
112
|
return PROPAGATE_SENTINEL;
|
|
102
113
|
};
|
|
103
114
|
ctx.afterExit = async () => {
|
|
104
|
-
await callHook(assembly.afterEnd, hookErrorHandler,
|
|
115
|
+
await callHook(assembly.afterEnd, hookErrorHandler, actorCtx, exitReason);
|
|
105
116
|
};
|
|
106
|
-
for (const [k, v] of decorated)
|
|
107
|
-
await callHook(assembly.beforeStart, hookErrorHandler,
|
|
108
|
-
if (assembly.setup) rawState = await assembly.setup.call(
|
|
117
|
+
for (const [k, v] of decorated) actorCtx[k] = v;
|
|
118
|
+
await callHook(assembly.beforeStart, hookErrorHandler, actorCtx);
|
|
119
|
+
if (assembly.setup) rawState = await assembly.setup.call(actorCtx, args);
|
|
109
120
|
else rawState = null;
|
|
110
|
-
|
|
121
|
+
actorCtx.state = rawState;
|
|
111
122
|
yield hidePrivate(rawState);
|
|
112
|
-
await callHook(assembly.afterStart, hookErrorHandler,
|
|
123
|
+
await callHook(assembly.afterStart, hookErrorHandler, actorCtx);
|
|
113
124
|
yield* runDispatchAsync(ctx.pname, async (stamped) => {
|
|
114
125
|
const [msg, sender] = stamped;
|
|
115
126
|
if (msg.type === "__ADVANCE__") return;
|
|
116
127
|
if (msg.type === "STOP") {
|
|
117
|
-
if (assembly.onStopRequested) await callHook(assembly.onStopRequested, hookErrorHandler,
|
|
118
|
-
else
|
|
119
|
-
exitReason = "stopped";
|
|
120
|
-
done = true;
|
|
121
|
-
}
|
|
128
|
+
if (assembly.onStopRequested) await callHook(assembly.onStopRequested, hookErrorHandler, actorCtx);
|
|
129
|
+
else endWith("stopped");
|
|
122
130
|
return;
|
|
123
131
|
}
|
|
124
132
|
if (msg.type === "EXIT") {
|
|
125
133
|
const childName = sender.fromName;
|
|
126
|
-
if (childName &&
|
|
127
|
-
await callHook(assembly.onChildExit, hookErrorHandler,
|
|
134
|
+
if (childName && actorCtx.$child[childName]) delete actorCtx.$child[childName];
|
|
135
|
+
await callHook(assembly.onChildExit, hookErrorHandler, actorCtx, childName, msg, msg.reason);
|
|
128
136
|
const orphans = msg.orphans;
|
|
129
137
|
if (orphans && orphans.length > 0) for (const orphan of orphans) {
|
|
130
|
-
const decision = assembly.onOrphan ? await callHook(assembly.onOrphan, hookErrorHandler,
|
|
138
|
+
const decision = assembly.onOrphan ? await callHook(assembly.onOrphan, hookErrorHandler, actorCtx, orphan) : "force-stop";
|
|
131
139
|
if (decision === "adopt") {
|
|
132
140
|
ctx.adopt(orphan);
|
|
133
141
|
const idx = ctx.orphans.indexOf(orphan);
|
|
134
142
|
if (idx >= 0) ctx.orphans.splice(idx, 1);
|
|
135
|
-
|
|
143
|
+
actorCtx.$child[orphan.pname] = orphan;
|
|
136
144
|
} else if (decision === "force-stop") {
|
|
137
145
|
orphan.forceStop({ cascade: true });
|
|
138
146
|
const idx = ctx.orphans.indexOf(orphan);
|
|
@@ -142,23 +150,23 @@ function defineActor(config) {
|
|
|
142
150
|
}
|
|
143
151
|
let hookStopped = false;
|
|
144
152
|
if (msg.type !== "STOP" && msg.type !== "EXIT" && assembly.onMessage) {
|
|
145
|
-
if (await callHook(assembly.onMessage, assembly.onError,
|
|
153
|
+
if (await callHook(assembly.onMessage, assembly.onError, actorCtx, msg, sender) === STOP_SENTINEL) hookStopped = true;
|
|
146
154
|
}
|
|
147
155
|
if (msg.type !== "STOP" && !hookStopped) {
|
|
148
156
|
const handler = (assembly.handlers || {})[msg.type] || assembly.onUnhandled;
|
|
149
|
-
await callHook(handler, assembly.onError,
|
|
157
|
+
await callHook(handler, assembly.onError, actorCtx, msg, sender);
|
|
150
158
|
}
|
|
151
159
|
}, () => done);
|
|
152
|
-
await callHook(assembly.beforeEnd, hookErrorHandler,
|
|
160
|
+
await callHook(assembly.beforeEnd, hookErrorHandler, actorCtx, exitReason);
|
|
153
161
|
};
|
|
154
162
|
}
|
|
155
163
|
function attachReflection(proc, reflectionMethods) {
|
|
156
|
-
const
|
|
157
|
-
if (
|
|
164
|
+
const actorCtx = actorCtxMap.get(proc.id);
|
|
165
|
+
if (actorCtx) proc.$reflection = actorCtx.reflection;
|
|
158
166
|
if (!reflectionMethods) return;
|
|
159
167
|
const refl = proc.$reflection;
|
|
160
168
|
const written = Object.entries(reflectionMethods);
|
|
161
|
-
for (const [k, m] of written) refl[k] = async (...args) => await m.apply(
|
|
169
|
+
for (const [k, m] of written) refl[k] = async (...args) => await m.apply(actorCtx, args);
|
|
162
170
|
}
|
|
163
171
|
return {
|
|
164
172
|
fn: makeRuntime(config),
|
|
@@ -186,4 +194,4 @@ function defineActor(config) {
|
|
|
186
194
|
//#endregion
|
|
187
195
|
export { defineMessages as n, defineActor as t };
|
|
188
196
|
|
|
189
|
-
//# sourceMappingURL=define-actor-
|
|
197
|
+
//# sourceMappingURL=define-actor-D7c9vn6S.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-actor-D7c9vn6S.js","names":[],"sources":["../src/define-actor.ts"],"sourcesContent":["// ── defineActor — high-level actor wrapper ───────────────────────────────────\n//\n// Compiles a declarative config into an AsyncProcessFn. Built on top of\n// the existing runDispatchAsync / spawnAsync primitives.\n//\nimport {\n type AsyncProcess,\n runDispatchAsync,\n spawnAsync,\n AnyProcess,\n INTERNAL_ADVANCE,\n} from \"./process.async.js\";\nimport type {\n WithSender,\n SenderInfo,\n AsyncProcessFn,\n Message,\n ExitMessage,\n ForkSite,\n ProcessCtx,\n} from \"./types.js\";\nimport type {\n ActorDefinition,\n ActorConfig,\n ActorContext,\n MethodOptions,\n ActorMessages,\n HandlerOptions,\n HandlerFn,\n ReflectionOptions,\n AnyConfig,\n HidePrivate,\n} from \"./actor-types.js\";\nimport { STOP_SENTINEL, PROPAGATE_SENTINEL } from \"./actor-types.js\";\nimport { ActorDecorated, type ActorPlugin, ActorReflection, callHook } from \"./hooks.js\";\n\nexport function defineMessages<OutMsg extends Message = Message>(): ActorMessages<OutMsg> {\n return undefined as unknown as ActorMessages<OutMsg>;\n}\n\nfunction hidePrivate<T>(value: T): HidePrivate<T> {\n if (value && typeof value === \"object\" && \"private\" in value && \"public\" in value) {\n return value.public as HidePrivate<T>;\n }\n return value as HidePrivate<T>;\n}\n\nfunction resolvePlugins(\n raw: ActorPlugin[] | ((parents: ActorPlugin[]) => ActorPlugin[]) | undefined,\n parentPlugins?: ActorPlugin[],\n addPlugins?: ActorPlugin[],\n): ActorPlugin[] {\n const resolved = !raw\n ? parentPlugins\n ? [...parentPlugins]\n : []\n : Array.isArray(raw)\n ? [...raw]\n : raw(parentPlugins ?? []);\n\n const combined = addPlugins ? [...resolved, ...addPlugins] : resolved;\n\n // Deduplicate by function name\n const seen = new Set<string>();\n return combined.filter((p) => {\n const name = p.name;\n if (!name) {\n console.warn(\"posipaki: plugin has no name, dedup won't work\");\n return true;\n }\n if (seen.has(name)) return false;\n seen.add(name);\n return true;\n });\n}\n\nasync function assembleActor<C>(\n config: C,\n plugins: ActorPlugin[],\n addPlugins?: ActorPlugin[],\n): Promise<C> {\n // Work with the default ActorPlugin type internally, cast back on return\n let cur = config as AnyConfig;\n for (const p of plugins) {\n try {\n cur = await p(cur);\n } catch (e: unknown) {\n console.error(`[assembleActor] plugin \"${p.name || \"?\"}\" failed:`, e);\n }\n }\n cur.resolvedPlugins = plugins;\n if (addPlugins) cur.addPlugins = addPlugins;\n return cur as C;\n}\n\nexport function defineActor<\n Args,\n InternalState,\n InMsg extends Message,\n OutMsg extends Message,\n Methods extends MethodOptions,\n Handlers extends HandlerOptions<InMsg>,\n ReflectionMethods extends ReflectionOptions,\n>(\n config: ActorConfig<Args, InternalState, InMsg, OutMsg, Methods, Handlers, ReflectionMethods>,\n): ActorDefinition<Args, InternalState, InMsg, OutMsg, ReflectionMethods> {\n const actorCtxMap = new Map<\n symbol,\n ActorContext<Args, InternalState, InMsg, OutMsg, Methods, Handlers, ReflectionMethods>\n >();\n\n function makeRuntime(\n assembly: ActorConfig<Args, InternalState, InMsg, OutMsg, Methods, Handlers, ReflectionMethods>,\n ): AsyncProcessFn<Args, HidePrivate<InternalState>, InMsg, OutMsg> {\n return async function* (\n ctx,\n args,\n ): AsyncGenerator<HidePrivate<InternalState | null>, void, WithSender<InMsg>> {\n let done = false;\n let exitReason: unknown;\n let rawState: InternalState = undefined as unknown as InternalState;\n\n /**\n * End this actor, and write the reason down twice: the hooks (`beforeEnd`, `afterEnd`) read\n * the local copy, and the EXIT the parent receives carries it as well. An exit that says\n * only *that* something ended leaves the parent to guess — and a stop that was agreed to, a\n * wire that closed (`CHANNEL_LOST`) and a child that finished are three different things to\n * whoever has to react.\n */\n const endWith = (reason: unknown, wake = false): void => {\n exitReason = reason;\n ctx.exitReason = reason;\n done = true;\n // The loop only re-reads `done` when it is resumed: an idle actor is\n // parked at its dispatch yield and would sit there forever.\n if (wake) ctx.wake();\n };\n\n const decorated = new Map();\n const actorCtx: ActorContext<\n Args,\n InternalState,\n InMsg,\n OutMsg,\n Methods,\n Handlers,\n ReflectionMethods & ActorReflection\n > = {\n ctx,\n // The process itself, as the ctx knows it: the same object this actor is being\n // run as, handed out by an actor that wants to be reached rather than named.\n self: ctx.self as unknown as ActorContext<\n Args,\n InternalState,\n InMsg,\n OutMsg,\n Methods,\n Handlers,\n ReflectionMethods & ActorReflection\n >['self'],\n ...((assembly.methods || {}) as Methods),\n ...((assembly.$decorate || {}) as ActorDecorated),\n reflection: {} as ReflectionMethods & ActorReflection,\n state: rawState,\n name: ctx.pname,\n id: ctx.id,\n async emit(msg: OutMsg) {\n await callHook(assembly.onEmit, undefined, actorCtx, msg, {\n fromName: ctx.pname,\n fromId: ctx.id,\n });\n ctx.toParent(msg);\n },\n agreeToStop() {\n endWith(\"stopped\");\n },\n exit(reason: unknown) {\n endWith(reason, true);\n },\n $child: {} as Record<string, AnyProcess>,\n decorators: {},\n fork: async <A, S, IM extends Message, OM extends InMsg, R extends ReflectionOptions>(\n childActor: ActorDefinition<A, S, IM, OM, R>,\n childArgs?: A,\n forkOpts?: { name?: string; addPlugins?: ActorPlugin[] },\n ): Promise<AsyncProcess<A, HidePrivate<S>, IM, OM, R & ActorReflection>> => {\n let child: AsyncProcess<A, HidePrivate<S>, IM, OM, R & ActorReflection>;\n const childName =\n forkOpts?.name ?? childActor?.name ?? `child-${Object.keys(actorCtx.$child).length}`;\n const treeName = `${ctx.pname}:${childName}`;\n const childAddPlugins = [...(assembly.addPlugins || []), ...(forkOpts?.addPlugins || [])];\n child = await childActor.spawnAsChild(ctx, childArgs!, {\n name: treeName,\n parentPlugins: assembly.resolvedPlugins || [],\n ...(childAddPlugins.length ? { addPlugins: childAddPlugins } : {}),\n });\n actorCtx.$child[child.pname] = child as unknown as AnyProcess;\n return child;\n },\n };\n actorCtxMap.set(ctx.id, actorCtx);\n /**\n * Lifecycle hooks are the actor's own control flow: if one throws, the\n * state machine is half-applied, so the error is fatal — `onError` still\n * observes it (a logger logs it), but it cannot absorb it. The actor goes\n * down and its parent still gets the EXIT, instead of staying up with\n * nothing left to do.\n *\n * Message hooks and handlers are not forced either way: they are called\n * with `onError` itself, and its *return value* decides — nothing means\n * \"handled, carry on\" (the default, and what an observing logger\n * returns), `propagateError()` means \"not handled\", and the actor goes\n * down with the same EXIT.\n */\n const hookErrorHandler = async (e: unknown): Promise<unknown> => {\n try {\n await assembly.onError?.call(actorCtx, e);\n } catch {\n // An error in the error handler must not mask the original one.\n }\n return PROPAGATE_SENTINEL;\n };\n ctx.afterExit = async () => {\n await callHook(assembly.afterEnd, hookErrorHandler, actorCtx, exitReason);\n };\n\n for (const [k, v] of decorated) {\n (actorCtx as Record<string, unknown>)[k] = v;\n }\n\n await callHook(\n assembly.beforeStart,\n hookErrorHandler,\n actorCtx as ActorContext<\n Args,\n never, // state not set yet\n InMsg,\n OutMsg,\n Methods,\n Handlers,\n ReflectionMethods & ActorReflection\n >,\n );\n\n if (assembly.setup) {\n rawState = await assembly.setup.call(\n actorCtx as ActorContext<\n Args,\n never, // break inference cycle here\n InMsg,\n OutMsg,\n Methods,\n Handlers,\n ReflectionMethods & ActorReflection\n >,\n args,\n );\n } else {\n rawState = null as InternalState;\n }\n actorCtx.state = rawState;\n yield hidePrivate(rawState);\n await callHook(assembly.afterStart, hookErrorHandler, actorCtx);\n\n yield* runDispatchAsync<WithSender<InMsg | ExitMessage>>(\n ctx.pname,\n async (stamped) => {\n const [msg, sender] = stamped;\n if (msg.type === INTERNAL_ADVANCE) return; // framework traffic, not a message\n if (msg.type === \"STOP\") {\n if (assembly.onStopRequested) {\n await callHook(assembly.onStopRequested, hookErrorHandler, actorCtx);\n // Hook may call agreeToStop(). If not, actor keeps running.\n } else {\n endWith(\"stopped\");\n }\n return;\n }\n if (msg.type === \"EXIT\") {\n // FIXME: process name are user-specified\n // and should not be used for indexing so\n // we don't get into name conflicts\n const childName = sender.fromName;\n if (childName && actorCtx.$child[childName]) {\n delete actorCtx.$child[childName];\n }\n await callHook(\n assembly.onChildExit,\n hookErrorHandler,\n actorCtx,\n childName,\n msg as ExitMessage,\n (msg as ExitMessage).reason,\n );\n // Orphan policy: a child that exits may leave still-running\n // grandchildren behind (see ctx-orphans / orphan-policy).\n const orphans = (msg as ExitMessage).orphans;\n if (orphans && orphans.length > 0) {\n for (const orphan of orphans) {\n // Default when no hook is defined: hard-kill the orphan.\n const decision = assembly.onOrphan\n ? await callHook(assembly.onOrphan, hookErrorHandler, actorCtx, orphan)\n : \"force-stop\";\n if (decision === \"adopt\") {\n ctx.adopt(orphan);\n const idx = ctx.orphans.indexOf(orphan);\n if (idx >= 0) ctx.orphans.splice(idx, 1);\n actorCtx.$child[orphan.pname] = orphan;\n } else if (decision === \"force-stop\") {\n orphan.forceStop({ cascade: true });\n const idx = ctx.orphans.indexOf(orphan);\n if (idx >= 0) ctx.orphans.splice(idx, 1);\n } else if (decision === \"unparent\") {\n orphan.unparent();\n }\n // 'leave' (or undefined) → do nothing; it propagates on exit.\n }\n }\n }\n let hookStopped = false;\n if (msg.type !== \"STOP\" && msg.type !== \"EXIT\" && assembly.onMessage) {\n const result = await callHook(\n assembly.onMessage,\n assembly.onError,\n actorCtx,\n msg as InMsg,\n sender,\n );\n if (result === STOP_SENTINEL) hookStopped = true;\n }\n if (msg.type !== \"STOP\" && !hookStopped) {\n const handler =\n ((assembly.handlers || ({} as Handlers))[\n msg.type as keyof Handlers\n ] as HandlerFn<InMsg>) || assembly.onUnhandled;\n\n await callHook(handler, assembly.onError, actorCtx, msg as InMsg, sender);\n }\n },\n () => done,\n );\n\n await callHook(assembly.beforeEnd, hookErrorHandler, actorCtx, exitReason);\n };\n }\n\n type ReflectableProcess = {\n id: symbol;\n $reflection: Record<string, Function>;\n };\n function attachReflection(\n proc: ReflectableProcess,\n reflectionMethods: ReflectionMethods | undefined,\n ): void {\n const actorCtx = actorCtxMap.get(proc.id);\n if (actorCtx) {\n // One object under two names: the surface the handle exposes as\n // `$reflection` and the one the actor's own hooks see as `reflection`.\n // Handing the same object to both is what lets a method be added after\n // assembly — the first caller that needs that is a remote peer saying\n // which methods it can answer.\n proc.$reflection = actorCtx.reflection as unknown as Record<string, Function>;\n }\n if (!reflectionMethods) return;\n const refl = proc.$reflection as Record<string, Function>;\n // The declared contract is `ReflectionMethod`, whose parameters are `never`\n // because nothing is called through it; this is the one place that calls\n // what it describes.\n const written = Object.entries(reflectionMethods) as Array<\n [string, (...args: unknown[]) => unknown]\n >;\n for (const [k, m] of written) {\n // A promise whatever the method was written as, so a caller reads the same\n // call the same way whether the actor is here or behind a wire.\n refl[k] = async (...args: unknown[]) => await m.apply(actorCtx, args);\n }\n }\n\n return {\n fn: makeRuntime(config),\n name: config.name,\n pvtPluginsRaw: config.plugins,\n inMessages: config.inMessages,\n outMessages: config.outMessages,\n async spawn(\n args: Args,\n opts?: {\n name?: string;\n toParent?: (msg: OutMsg, from: SenderInfo) => void;\n addPlugins?: ActorPlugin[];\n parentName?: string | null;\n parentId?: symbol | null;\n /**\n * Resolve only once the initial state is available. Default `true`:\n * a spawned process is safe to send to when `spawn()` returns. Pass\n * `false` for the raw handle — the caller then has to `await\n * proc.ready()` itself before sending anything it wants handled.\n */\n awaitReady?: boolean;\n },\n ): Promise<\n AsyncProcess<\n Args,\n HidePrivate<InternalState>,\n InMsg,\n OutMsg,\n ReflectionMethods & ActorReflection\n >\n > {\n const plugs = resolvePlugins(config.plugins, undefined, opts?.addPlugins);\n const assembly = await assembleActor(config, plugs, opts?.addPlugins);\n const runtime = makeRuntime(assembly);\n const proc = spawnAsync(\n runtime,\n opts?.name ?? assembly.name ?? \"actor\",\n opts?.toParent,\n opts?.parentName,\n opts?.parentId,\n )(args);\n attachReflection(proc, assembly.$reflectionMethods as ReflectionMethods);\n if (opts?.awaitReady !== false) await proc.ready();\n return proc as AsyncProcess<\n Args,\n HidePrivate<InternalState>,\n InMsg,\n OutMsg,\n ReflectionMethods & ActorReflection\n >;\n },\n async spawnAsChild(\n ctx: ForkSite,\n args: Args,\n opts?: {\n name?: string;\n parentPlugins?: ActorPlugin[];\n addPlugins?: ActorPlugin[];\n },\n ) {\n const plugs = resolvePlugins(config.plugins, opts?.parentPlugins, opts?.addPlugins);\n const assembly = await assembleActor(config, plugs, opts?.addPlugins);\n const runtime = makeRuntime(assembly);\n const proc = ctx.fork(runtime, opts?.name ?? assembly.name ?? \"child\")(args);\n attachReflection(proc, assembly.$reflectionMethods as ReflectionMethods);\n return proc as AsyncProcess<\n Args,\n HidePrivate<InternalState>,\n InMsg,\n OutMsg,\n ReflectionMethods & ActorReflection\n >;\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks-CgXhmY4r.js","names":[],"sources":["../src/actor-types.ts","../src/hooks.ts"],"sourcesContent":["// ── defineActor types ────────────────────────────────────────────────────────\n//\n// Shared between define-actor.ts (implementation) and consumers that want\n// to reference the config/context/definition shapes without importing the\n// implementation module directly.\n\nimport type { SenderInfo, AsyncProcessFn, Message, ProcessCtx, ExitMessage } from \"./types.js\";\nimport type { ActorDecorated, ActorReflection } from \"./hooks.js\";\nimport type { AnyProcess, AsyncProcess } from \"./process.async.js\";\n\n// Internal marker do not use\nexport type ActorMessages<M extends Message> = {\n __tag_messages: M;\n};\nexport interface MethodOptions {\n [key: string]: Function;\n}\nexport type HandlerFn<InMsg extends Message> = (\n msg: InMsg,\n sender: SenderInfo,\n) => void | Promise<void>;\nexport type HandlerOptions<InMsg extends Message> = Omit<\n {\n [K in InMsg[\"type\"]]: HandlerFn<Extract<InMsg, { type: K }>>;\n },\n \"STOP\"\n>;\n/**\n * A reflection method, async by contract: it answers with a promise, even when\n * it has the answer already. The same call has to read the same way whether the\n * actor is here or behind a wire, and a caller that had to know which of the two\n * it was holding would be reading the shape of the deployment, not the answer.\n *\n * The parameters are `never` because nothing is called through this type — it is\n * the contract every declared method is checked against.\n */\nexport type ReflectionMethod = (...args: never[]) => Promise<unknown>;\n/** The reflection surface a process exposes: named methods, each of them async\n * by {@link ReflectionMethod}'s contract. */\nexport interface ReflectionOptions {\n [name: string]: ReflectionMethod;\n}\nexport type Paired<Priv, Pub> = { public: Pub; private: Priv };\nexport type HidePrivate<T> = T extends Paired<unknown, unknown> ? T[\"public\"] : T;\n\nexport type SpawnedFrom<T extends ActorDefinition<any, any, any, any, any>> =\n T extends ActorDefinition<infer A, infer S, infer IM, infer OM, infer R>\n ? AsyncProcess<A, HidePrivate<S>, IM, OM, R & ActorReflection>\n : never;\n\nexport interface ActorDefinition<\n Args,\n InternalState,\n InMsg extends Message,\n OutMsg extends Message,\n ReflectionMethods extends ReflectionOptions,\n> {\n fn: AsyncProcessFn<Args, HidePrivate<InternalState>, InMsg, OutMsg>;\n /** Preferred process name (from config.name). */\n name?: string;\n /** Raw plugin config (array or transform). Resolved at fork time. @internal */\n pvtPluginsRaw?: ActorPlugin[] | PluginTransform;\n /** Spawn this actor as a standalone process. */\n spawn(\n args: Args,\n opts?: {\n name?: string;\n toParent?: (msg: OutMsg, from: SenderInfo) => void;\n addPlugins?: ActorPlugin[];\n parentName?: string | null;\n parentId?: symbol | null;\n /** Wait for the initial state before resolving. Default `true`. */\n awaitReady?: boolean;\n },\n ): Promise<\n AsyncProcess<\n Args,\n HidePrivate<InternalState>,\n InMsg,\n OutMsg,\n ReflectionMethods & ActorReflection\n >\n >;\n /** Spawn this actor as a child of the calling process.\n * `ctx` must be able to fork children that emit `OutMsg` — i.e. the\n * parent's in-message is a supertype of this actor's out-message. */\n spawnAsChild<PMO extends Message>(\n ctx: ProcessCtx<unknown, unknown, OutMsg, PMO>,\n args: Args,\n opts?: {\n name?: string;\n parentPlugins?: ActorPlugin[];\n addPlugins?: ActorPlugin[];\n },\n ): Promise<\n AsyncProcess<\n Args,\n HidePrivate<InternalState>,\n InMsg,\n OutMsg,\n ReflectionMethods & ActorReflection\n >\n >;\n inMessages: ActorMessages<InMsg> | undefined;\n outMessages: ActorMessages<OutMsg> | undefined;\n}\n/**\n * The config object as a user writes it.\n *\n * Hooks take their `this` from the `ThisType` at the end of this type: a per-hook\n * annotation erases the inferred methods surface. `beforeStart` and `setup` keep\n * one, for the state.\n */\nexport type ActorConfig<\n Args,\n InternalState,\n InMsg extends Message,\n OutMsg extends Message,\n Methods extends MethodOptions,\n Handlers extends HandlerOptions<InMsg>,\n ReflectionMethods extends ReflectionOptions,\n> = {\n /** Preferred process name. Used by ctx.fork() when no explicit name is given. */\n name?: string;\n plugins?: ActorPlugin[] | PluginTransform;\n /** Non-overridable plugins added at spawn time (spawn/fork opts).\n * Set by the framework during assembly, not by user config. @internal */\n addPlugins?: ActorPlugin[];\n /** Resolved plugin chain (raw config transformed against parent plugins).\n * Set by the framework during assembly, replacing `plugins` (the raw form).\n * @internal */\n resolvedPlugins?: ActorPlugin[];\n outMessages?: ActorMessages<OutMsg>;\n inMessages?: ActorMessages<InMsg>;\n /** Fires once `self` is built, before `setup`. State is not yet set\n * (`this.state` is `never`). Use for registering the process/ctx before\n * any child is forked in `setup`. */\n beforeStart?: (\n this: ActorContext<\n Args,\n never,\n InMsg,\n OutMsg,\n MethodOptions,\n Handlers,\n ReflectionMethods & ActorReflection\n >,\n ) => void | Promise<void>;\n\n /** `this.state` is `never`: the returned value is the state. */\n setup?: (\n this: ActorContext<\n Args,\n never,\n InMsg,\n OutMsg,\n MethodOptions,\n Handlers,\n ReflectionMethods & ActorReflection\n >,\n args: Args,\n ) => Promise<InternalState> | InternalState;\n\n afterStart?: () => void | Promise<void>;\n\n onStopRequested?: () => HookResult | Promise<HookResult>;\n\n beforeEnd?: (reason?: unknown) => HookResult | Promise<HookResult>;\n\n /**\n * Runs once the actor has ended — after its EXIT. It is *not* called when the\n * actor never started (`setup()` or a pre-start hook threw): the state is\n * typed as present here, and an actor that never got one has nothing to end.\n */\n afterEnd?: (reason?: unknown) => HookResult | Promise<HookResult>;\n\n onError?: (error?: unknown) => HookResult | ErrorResult | Promise<HookResult | ErrorResult>;\n\n onEmit?: (msg: OutMsg, sender: SenderInfo) => HookResult | Promise<HookResult>;\n\n onMessage?: (msg: InMsg, sender: SenderInfo) => HookResult | Promise<HookResult>;\n\n onUnhandled?: (msg: Message, sender: SenderInfo) => void | Promise<void>;\n\n onChildExit?: (name: string, reason: ExitMessage) => HookResult | Promise<HookResult>;\n\n /** Fires for each orphan a child leaves behind (in its EXIT). Return the\n * policy: `'adopt'` (promote to a child, draining its buffer), `'force-stop'`\n * (hard-kill), `'unparent'` (drop its buffer, keep it running in `orphans`),\n * or `'leave'` (keep buffering, propagate up on my exit). When no `onOrphan`\n * is defined, the default is `'force-stop'`. */\n onOrphan?: (orphan: AnyProcess) => OrphanDecision | void | Promise<OrphanDecision | void>;\n\n handlers: Handlers &\n ThisType<\n ActorContext<\n Args,\n InternalState,\n InMsg,\n OutMsg,\n Methods,\n Handlers,\n ReflectionMethods & ActorReflection\n >\n >;\n\n methods?: Methods &\n ThisType<\n ActorContext<\n Args,\n InternalState,\n InMsg,\n OutMsg,\n Methods,\n Handlers,\n ReflectionMethods & ActorReflection\n >\n >;\n $reflectionMethods?: ReflectionMethods &\n ThisType<\n ActorContext<\n Args,\n InternalState,\n InMsg,\n OutMsg,\n Methods,\n Handlers,\n ActorReflection & ActorReflection\n >\n >;\n // for plugin use only\n $decorate?: Partial<ActorDecorated>;\n} & ThisType<\n ActorContext<Args, InternalState, InMsg, OutMsg, Methods, Handlers, ReflectionMethods & ActorReflection>\n>;\nexport type AnyConfig = ActorConfig<\n unknown,\n unknown,\n Message,\n Message,\n MethodOptions,\n HandlerOptions<Message>,\n ReflectionOptions\n>;\n\n// ── stop propagation sentinel ────────────────────────────────────────────\n\n/** Returned by onMessage hooks to prevent further dispatch. */\nexport const STOP_SENTINEL = Symbol(\"posipaki.stopPropagation\");\n\n/** Type-safe sentinel for short-circuiting onMessage hooks. */\nexport const stopPropagation = (): typeof STOP_SENTINEL => STOP_SENTINEL;\n\n/**\n * Returned by an `onError` handler that only *observed* the error — logged it,\n * counted it — and did not handle it. The framework then lets the error\n * propagate: the actor still goes down and its parent still gets the EXIT.\n * Without this an observing handler (the bundled debug logger is one) silently\n * turns a broken lifecycle hook into a survivor with nothing left to do.\n */\nexport const PROPAGATE_SENTINEL = Symbol(\"posipaki.propagateError\");\n\n/** Type-safe sentinel for an onError handler that did not handle the error. */\nexport const propagateError = (): typeof PROPAGATE_SENTINEL => PROPAGATE_SENTINEL;\n\n/** Return type of onError handlers: void (handled) or sentinel (not handled). */\nexport type ErrorResult = void | typeof PROPAGATE_SENTINEL;\n\n// ── hook function types ──────────────────────────────────────────────────\n\n/** Return type of onMessage hooks: void (continue) or sentinel (stop). */\nexport type HookResult = void | typeof STOP_SENTINEL;\n\n/** Decision returned by `onOrphan` for how to handle an inherited orphan. */\nexport type OrphanDecision = \"adopt\" | \"force-stop\" | \"unparent\" | \"leave\";\n// ── plugin types ─────────────────────────────────────────────────────────\n\n/** A reusable unit of actor behaviour. */\nexport type ActorPlugin<C = AnyConfig> = (config: C) => C | Promise<C>;\n\n/** Transform parent plugins into child plugins. */\nexport type PluginTransform = (parentPlugins: ActorPlugin[]) => ActorPlugin[];\n\nexport type ActorContext<\n Args,\n InternalState,\n InMsg extends Message,\n OutMsg extends Message,\n Methods extends MethodOptions,\n Handlers extends HandlerOptions<InMsg>,\n ReflectionMethods extends ReflectionOptions,\n> = Methods &\n ActorDecorated & {\n state: InternalState;\n name: string;\n id: symbol;\n\n emit: (msg: OutMsg) => void;\n agreeToStop: () => void;\n\n reflection: ThisType<\n ActorContext<Args, InternalState, InMsg, OutMsg, Methods, Handlers, ReflectionMethods>\n > &\n ReflectionMethods;\n exit: (reason?: unknown) => void;\n\n $child: Record<string, AnyProcess>;\n\n fork<A, S, IM extends Message, OM extends InMsg, R extends ReflectionOptions>(\n actor: ActorDefinition<A, S, IM, OM, R>,\n args?: A,\n opts?: {\n name?: string;\n addPlugins?: ActorPlugin[];\n },\n ): Promise<AsyncProcess<A, HidePrivate<S>, IM, OM, R & ActorReflection>>;\n\n ctx: ProcessCtx<Args, HidePrivate<InternalState>, InMsg, OutMsg>;\n };\n\n\n\n/**\n * The context a config's hooks are typed against, for a `Partial<>` overlay:\n * a mapped type drops the marker `ActorConfig` carries.\n */\nexport type ActorContextOf<C> = C extends ActorConfig<\n infer Args,\n infer InternalState,\n infer InMsg extends Message,\n infer OutMsg extends Message,\n infer Methods extends MethodOptions,\n infer Handlers,\n infer ReflectionMethods extends ReflectionOptions\n>\n ? ActorContext<\n Args,\n InternalState,\n InMsg,\n OutMsg,\n Methods,\n Handlers extends HandlerOptions<InMsg> ? Handlers : HandlerOptions<InMsg>,\n ReflectionMethods & ActorReflection\n >\n : never;\n","// ── Lifecycle Hooks ──────────────────────────────────────────────────────\n//\n// Extends ProcessCtx and defineActor with observable lifecycle hooks.\n// Hooks are additive — multiple callbacks can register for the same hook\n// point, and they fire in registration order.\n\nimport {\n STOP_SENTINEL,\n stopPropagation,\n PROPAGATE_SENTINEL,\n propagateError,\n} from \"./actor-types.js\";\nimport type {\n HookResult,\n ActorPlugin,\n PluginTransform,\n AnyConfig,\n ActorContextOf,\n ReflectionOptions,\n} from \"./actor-types.js\";\n\n// ── stop propagation sentinel ────────────────────────────────────────────\n\n// Re-exports from actor-types.ts (backward compatibility)\nexport { STOP_SENTINEL, stopPropagation, PROPAGATE_SENTINEL, propagateError };\nexport type { HookResult, ActorPlugin, PluginTransform };\n\n// ── type augmentation (Fastify-style) ────────────────────────────────────\n\n/**\n * Interface that plugins can augment via declaration merging.\n * Plugins ship a .d.ts that adds properties to this interface,\n * making them available on `this` in handlers and methods.\n *\n * Example (in a plugin's .d.ts):\n * declare module 'posipaki' {\n * interface ActorDecorated {\n * log: Logger;\n * }\n * }\n */\nexport interface ActorDecorated {}\n/** Reflection methods plugins and the framework add to every actor. Merged by\n * declaration, and held to {@link ReflectionOptions}' contract: async. */\nexport interface ActorReflection extends ReflectionOptions {}\n\n// ── chainHook ────────────────────────────────────────────────────────────\n\n/**\n * Compose two lifecycle hooks so that `plugin` fires first.\n *\n * If `plugin` returns the STOP_SENTINEL (via stopPropagation()),\n * `existing` is skipped entirely and the sentinel propagates.\n * Otherwise `existing` fires and its return value is used.\n *\n * Typical use in a plugin:\n * (cfg) => ({ ...cfg, onStart: chainHook(cfg.onStart, myOnStart) })\n *\n * @param existing - the current hook on the config (may be undefined)\n * @param plugin - the new hook to prepend\n * @returns a composed hook suitable for ActorConfig\n */\nexport function chainHook<TThis, TArgs extends unknown[]>(\n existing: ((this: TThis, ...args: TArgs) => HookResult | Promise<HookResult>) | undefined,\n plugin: (this: TThis, ...args: TArgs) => HookResult | Promise<HookResult>,\n): (this: TThis, ...args: TArgs) => HookResult | Promise<HookResult> {\n if (!existing) return plugin;\n return async function (this: TThis, ...args: TArgs): Promise<HookResult> {\n const result = await plugin.call(this, ...args);\n if (result === STOP_SENTINEL) return result;\n return await existing.call(this, ...args);\n } as (this: TThis, ...args: TArgs) => HookResult | Promise<HookResult>;\n}\n\n// ── mergeConfigs ─────────────────────────────────────────────────────────\n\n/**\n * Merge an overlay config into a base config, auto-chaining every on* hook.\n *\n * Each key in `overlay` that starts with \"on\" followed by an uppercase\n * letter (onStart, onMessage, onEmit, etc.) is composed via chainHook()\n * so that the overlay hook fires before the base hook, and stopPropagation\n * is respected.\n *\n * Typical use in a plugin:\n * return mergeConfigs(cfg, {\n * onStart() { this.log.info('starting'); },\n * beforeEnd() { this.log.info('stopping'); },\n * });\n *\n * @param base - the existing config (ActorConfig)\n * @param overlay - new hook implementations to prepend\n * @returns a new config with hooks chained\n */\nexport function mergeConfigs<C extends AnyConfig>(\n base: C,\n overlay: Partial<C> & ThisType<ActorContextOf<C>>,\n): C {\n const result = { ...base } as Record<string, unknown>;\n for (const key of Object.keys(overlay as Record<string, unknown>)) {\n const val = (overlay as Record<string, unknown>)[key];\n if (typeof val === \"function\" && /^(on|after|before)[A-Z]/.test(key)) {\n result[key] = chainHook(\n (base as Record<string, unknown>)[key] as (\n this: unknown,\n ...args: unknown[]\n ) => HookResult | Promise<HookResult>,\n val as (this: unknown, ...args: unknown[]) => HookResult | Promise<HookResult>,\n );\n } else {\n result[key] = val;\n }\n }\n result.$reflectionMethods = {};\n Object.assign(\n result.$reflectionMethods as object,\n \"$reflectionMethods\" in base ? base.$reflectionMethods : {},\n \"$reflectionMethods\" in overlay ? overlay.$reflectionMethods : {},\n );\n\n return result as unknown as C;\n}\n\nexport type Hook<T, I extends unknown[], O> = (this: T, ...args: I) => O;\n\nexport async function callHook<T, I extends unknown[], O>(\n fn: Hook<T, I, O> | undefined,\n eh: ((e: unknown) => unknown) | undefined,\n thisArg: T,\n ...args: I\n): Promise<O | undefined> {\n if (fn) {\n try {\n return await fn.call(thisArg, ...args);\n } catch (e) {\n if (eh) {\n let decision: unknown;\n try {\n decision = await eh(e);\n } catch {\n // An error inside the error handler must not mask the original one.\n }\n // An observing handler says so by returning the sentinel: the error it\n // did not handle keeps propagating, so the actor still goes down.\n if (decision === PROPAGATE_SENTINEL) throw e;\n } else {\n throw e;\n }\n }\n }\n return undefined;\n}\n"],"mappings":";;AAwPA,MAAa,gBAAgB,OAAO,0BAA0B;;AAG9D,MAAa,wBAA8C;;;;;;;;AAS3D,MAAa,qBAAqB,OAAO,yBAAyB;;AAGlE,MAAa,uBAAkD;;;;;;;;;;;;;;;;;ACzM/D,SAAgB,UACd,UACA,QACmE;CACnE,IAAI,CAAC,UAAU,OAAO;CACtB,OAAO,eAA6B,GAAG,MAAkC;EACvE,MAAM,SAAS,MAAM,OAAO,KAAK,MAAM,GAAG,IAAI;EAC9C,IAAI,WAAW,eAAe,OAAO;EACrC,OAAO,MAAM,SAAS,KAAK,MAAM,GAAG,IAAI;CAC1C;AACF;;;;;;;;;;;;;;;;;;;AAsBA,SAAgB,aACd,MACA,SACG;CACH,MAAM,SAAS,EAAE,GAAG,KAAK;CACzB,KAAK,MAAM,OAAO,OAAO,KAAK,OAAkC,GAAG;EACjE,MAAM,MAAO,QAAoC;EACjD,IAAI,OAAO,QAAQ,cAAc,0BAA0B,KAAK,GAAG,GACjE,OAAO,OAAO,UACX,KAAiC,MAIlC,GACF;OAEA,OAAO,OAAO;CAElB;CACA,OAAO,qBAAqB,CAAC;CAC7B,OAAO,OACL,OAAO,oBACP,wBAAwB,OAAO,KAAK,qBAAqB,CAAC,GAC1D,wBAAwB,UAAU,QAAQ,qBAAqB,CAAC,CAClE;CAEA,OAAO;AACT;AAIA,eAAsB,SACpB,IACA,IACA,SACA,GAAG,MACqB;CACxB,IAAI,IACF,IAAI;EACF,OAAO,MAAM,GAAG,KAAK,SAAS,GAAG,IAAI;CACvC,SAAS,GAAG;EACV,IAAI,IAAI;GACN,IAAI;GACJ,IAAI;IACF,WAAW,MAAM,GAAG,CAAC;GACvB,QAAQ,CAER;GAGA,IAAI,aAAa,oBAAoB,MAAM;EAC7C,OACE,MAAM;CAEV;AAGJ"}
|
|
1
|
+
{"version":3,"file":"hooks-CgXhmY4r.js","names":[],"sources":["../src/actor-types.ts","../src/hooks.ts"],"sourcesContent":["// ── defineActor types ────────────────────────────────────────────────────────\n//\n// Shared between define-actor.ts (implementation) and consumers that want\n// to reference the config/context/definition shapes without importing the\n// implementation module directly.\n\nimport type { SenderInfo, AsyncProcessFn, Message, ProcessCtx, ExitMessage, ForkSite } from \"./types.js\";\nimport type { ActorDecorated, ActorReflection } from \"./hooks.js\";\nimport type { AnyProcess, AsyncProcess } from \"./process.async.js\";\n\n// Internal marker do not use\nexport type ActorMessages<M extends Message> = {\n __tag_messages: M;\n};\nexport interface MethodOptions {\n [key: string]: Function;\n}\nexport type HandlerFn<InMsg extends Message> = (\n msg: InMsg,\n sender: SenderInfo,\n) => void | Promise<void>;\nexport type HandlerOptions<InMsg extends Message> = Omit<\n {\n [K in InMsg[\"type\"]]: HandlerFn<Extract<InMsg, { type: K }>>;\n },\n \"STOP\"\n>;\n/**\n * A reflection method, async by contract: it answers with a promise, even when\n * it has the answer already. The same call has to read the same way whether the\n * actor is here or behind a wire, and a caller that had to know which of the two\n * it was holding would be reading the shape of the deployment, not the answer.\n *\n * The parameters are `never` because nothing is called through this type — it is\n * the contract every declared method is checked against.\n */\nexport type ReflectionMethod = (...args: never[]) => Promise<unknown>;\n/** The reflection surface a process exposes: named methods, each of them async\n * by {@link ReflectionMethod}'s contract. */\nexport interface ReflectionOptions {\n [name: string]: ReflectionMethod;\n}\nexport type Paired<Priv, Pub> = { public: Pub; private: Priv };\nexport type HidePrivate<T> = T extends Paired<unknown, unknown> ? T[\"public\"] : T;\n\nexport type SpawnedFrom<T extends ActorDefinition<any, any, any, any, any>> =\n T extends ActorDefinition<infer A, infer S, infer IM, infer OM, infer R>\n ? AsyncProcess<A, HidePrivate<S>, IM, OM, R & ActorReflection>\n : never;\n\nexport interface ActorDefinition<\n Args,\n InternalState,\n InMsg extends Message,\n OutMsg extends Message,\n ReflectionMethods extends ReflectionOptions,\n> {\n fn: AsyncProcessFn<Args, HidePrivate<InternalState>, InMsg, OutMsg>;\n /** Preferred process name (from config.name). */\n name?: string;\n /** Raw plugin config (array or transform). Resolved at fork time. @internal */\n pvtPluginsRaw?: ActorPlugin[] | PluginTransform;\n /** Spawn this actor as a standalone process. */\n spawn(\n args: Args,\n opts?: {\n name?: string;\n toParent?: (msg: OutMsg, from: SenderInfo) => void;\n addPlugins?: ActorPlugin[];\n parentName?: string | null;\n parentId?: symbol | null;\n /** Wait for the initial state before resolving. Default `true`. */\n awaitReady?: boolean;\n },\n ): Promise<\n AsyncProcess<\n Args,\n HidePrivate<InternalState>,\n InMsg,\n OutMsg,\n ReflectionMethods & ActorReflection\n >\n >;\n /** Spawn this actor as a child of the calling process.\n * `ctx` must be able to fork children that emit `OutMsg` — i.e. the\n * parent's in-message is a supertype of this actor's out-message. */\n spawnAsChild(\n ctx: ForkSite,\n args: Args,\n opts?: {\n name?: string;\n parentPlugins?: ActorPlugin[];\n addPlugins?: ActorPlugin[];\n },\n ): Promise<\n AsyncProcess<\n Args,\n HidePrivate<InternalState>,\n InMsg,\n OutMsg,\n ReflectionMethods & ActorReflection\n >\n >;\n inMessages: ActorMessages<InMsg> | undefined;\n outMessages: ActorMessages<OutMsg> | undefined;\n}\n/**\n * The config object as a user writes it.\n *\n * Hooks take their `this` from the `ThisType` at the end of this type: a per-hook\n * annotation erases the inferred methods surface. `beforeStart` and `setup` keep\n * one, for the state.\n */\nexport type ActorConfig<\n Args,\n InternalState,\n InMsg extends Message,\n OutMsg extends Message,\n Methods extends MethodOptions,\n Handlers extends HandlerOptions<InMsg>,\n ReflectionMethods extends ReflectionOptions,\n> = {\n /** Preferred process name. Used by ctx.fork() when no explicit name is given. */\n name?: string;\n plugins?: ActorPlugin[] | PluginTransform;\n /** Non-overridable plugins added at spawn time (spawn/fork opts).\n * Set by the framework during assembly, not by user config. @internal */\n addPlugins?: ActorPlugin[];\n /** Resolved plugin chain (raw config transformed against parent plugins).\n * Set by the framework during assembly, replacing `plugins` (the raw form).\n * @internal */\n resolvedPlugins?: ActorPlugin[];\n outMessages?: ActorMessages<OutMsg>;\n inMessages?: ActorMessages<InMsg>;\n /** Fires once `self` is built, before `setup`. State is not yet set\n * (`this.state` is `never`). Use for registering the process/ctx before\n * any child is forked in `setup`. */\n beforeStart?: (\n this: ActorContext<\n Args,\n never,\n InMsg,\n OutMsg,\n MethodOptions,\n Handlers,\n ReflectionMethods & ActorReflection\n >,\n ) => void | Promise<void>;\n\n /** `this.state` is `never`: the returned value is the state. */\n setup?: (\n this: ActorContext<\n Args,\n never,\n InMsg,\n OutMsg,\n MethodOptions,\n Handlers,\n ReflectionMethods & ActorReflection\n >,\n args: Args,\n ) => Promise<InternalState> | InternalState;\n\n afterStart?: () => void | Promise<void>;\n\n onStopRequested?: () => HookResult | Promise<HookResult>;\n\n beforeEnd?: (reason?: unknown) => HookResult | Promise<HookResult>;\n\n /**\n * Runs once the actor has ended — after its EXIT. It is *not* called when the\n * actor never started (`setup()` or a pre-start hook threw): the state is\n * typed as present here, and an actor that never got one has nothing to end.\n */\n afterEnd?: (reason?: unknown) => HookResult | Promise<HookResult>;\n\n onError?: (error?: unknown) => HookResult | ErrorResult | Promise<HookResult | ErrorResult>;\n\n onEmit?: (msg: OutMsg, sender: SenderInfo) => HookResult | Promise<HookResult>;\n\n onMessage?: (msg: InMsg, sender: SenderInfo) => HookResult | Promise<HookResult>;\n\n onUnhandled?: (msg: Message, sender: SenderInfo) => void | Promise<void>;\n\n /** A child ended. `exit` is what it sent — its orphans travel there — and `reason` is what it\n * ended *for*: the value `exit(reason)` was given, `\"stopped\"` for a stop that was agreed to,\n * `CHANNEL_LOST` when the wire under a proxy went, or undefined when nobody asked. */\n onChildExit?: (\n name: string,\n exit: ExitMessage,\n reason: unknown,\n ) => HookResult | Promise<HookResult>;\n\n /** Fires for each orphan a child leaves behind (in its EXIT). Return the\n * policy: `'adopt'` (promote to a child, draining its buffer), `'force-stop'`\n * (hard-kill), `'unparent'` (drop its buffer, keep it running in `orphans`),\n * or `'leave'` (keep buffering, propagate up on my exit). When no `onOrphan`\n * is defined, the default is `'force-stop'`. */\n onOrphan?: (orphan: AnyProcess) => OrphanDecision | void | Promise<OrphanDecision | void>;\n\n handlers: Handlers &\n ThisType<\n ActorContext<\n Args,\n InternalState,\n InMsg,\n OutMsg,\n Methods,\n Handlers,\n ReflectionMethods & ActorReflection\n >\n >;\n\n methods?: Methods &\n ThisType<\n ActorContext<\n Args,\n InternalState,\n InMsg,\n OutMsg,\n Methods,\n Handlers,\n ReflectionMethods & ActorReflection\n >\n >;\n $reflectionMethods?: ReflectionMethods &\n ThisType<\n ActorContext<\n Args,\n InternalState,\n InMsg,\n OutMsg,\n Methods,\n Handlers,\n ActorReflection & ActorReflection\n >\n >;\n // for plugin use only\n $decorate?: Partial<ActorDecorated>;\n} & ThisType<\n ActorContext<Args, InternalState, InMsg, OutMsg, Methods, Handlers, ReflectionMethods & ActorReflection>\n>;\nexport type AnyConfig = ActorConfig<\n unknown,\n unknown,\n Message,\n Message,\n MethodOptions,\n HandlerOptions<Message>,\n ReflectionOptions\n>;\n\n// ── stop propagation sentinel ────────────────────────────────────────────\n\n/** Returned by onMessage hooks to prevent further dispatch. */\nexport const STOP_SENTINEL = Symbol(\"posipaki.stopPropagation\");\n\n/** Type-safe sentinel for short-circuiting onMessage hooks. */\nexport const stopPropagation = (): typeof STOP_SENTINEL => STOP_SENTINEL;\n\n/**\n * Returned by an `onError` handler that only *observed* the error — logged it,\n * counted it — and did not handle it. The framework then lets the error\n * propagate: the actor still goes down and its parent still gets the EXIT.\n * Without this an observing handler (the bundled debug logger is one) silently\n * turns a broken lifecycle hook into a survivor with nothing left to do.\n */\nexport const PROPAGATE_SENTINEL = Symbol(\"posipaki.propagateError\");\n\n/** Type-safe sentinel for an onError handler that did not handle the error. */\nexport const propagateError = (): typeof PROPAGATE_SENTINEL => PROPAGATE_SENTINEL;\n\n/** Return type of onError handlers: void (handled) or sentinel (not handled). */\nexport type ErrorResult = void | typeof PROPAGATE_SENTINEL;\n\n// ── hook function types ──────────────────────────────────────────────────\n\n/** Return type of onMessage hooks: void (continue) or sentinel (stop). */\nexport type HookResult = void | typeof STOP_SENTINEL;\n\n/** Decision returned by `onOrphan` for how to handle an inherited orphan. */\nexport type OrphanDecision = \"adopt\" | \"force-stop\" | \"unparent\" | \"leave\";\n// ── plugin types ─────────────────────────────────────────────────────────\n\n/** A reusable unit of actor behaviour. */\nexport type ActorPlugin<C = AnyConfig> = (config: C) => C | Promise<C>;\n\n/** Transform parent plugins into child plugins. */\nexport type PluginTransform = (parentPlugins: ActorPlugin[]) => ActorPlugin[];\n\nexport type ActorContext<\n Args,\n InternalState,\n InMsg extends Message,\n OutMsg extends Message,\n Methods extends MethodOptions,\n Handlers extends HandlerOptions<InMsg>,\n ReflectionMethods extends ReflectionOptions,\n> = Methods &\n ActorDecorated & {\n state: InternalState;\n name: string;\n id: symbol;\n /** This actor as a process: the handle another process can be given so that it can\n * send here. There is no other way to obtain one — a process is reachable because\n * somebody holds it, and this is how it hands itself over. The same object as\n * `ctx.self`, and as the one a spawner, a parent or a remote handle stands for.\n * Erased, like every handle that leaves: whoever receives it declares what it is. */\n self: AsyncProcess<\n Args,\n HidePrivate<InternalState>,\n InMsg,\n OutMsg,\n ReflectionMethods & ActorReflection\n >;\n\n emit: (msg: OutMsg) => void;\n agreeToStop: () => void;\n\n reflection: ThisType<\n ActorContext<Args, InternalState, InMsg, OutMsg, Methods, Handlers, ReflectionMethods>\n > &\n ReflectionMethods;\n exit: (reason?: unknown) => void;\n\n $child: Record<string, AnyProcess>;\n\n fork<A, S, IM extends Message, OM extends InMsg, R extends ReflectionOptions>(\n actor: ActorDefinition<A, S, IM, OM, R>,\n args?: A,\n opts?: {\n name?: string;\n addPlugins?: ActorPlugin[];\n },\n ): Promise<AsyncProcess<A, HidePrivate<S>, IM, OM, R & ActorReflection>>;\n\n ctx: ProcessCtx<Args, HidePrivate<InternalState>, InMsg, OutMsg>;\n };\n\n\n\n/**\n * The context a config's hooks are typed against, for a `Partial<>` overlay:\n * a mapped type drops the marker `ActorConfig` carries.\n */\nexport type ActorContextOf<C> = C extends ActorConfig<\n infer Args,\n infer InternalState,\n infer InMsg extends Message,\n infer OutMsg extends Message,\n infer Methods extends MethodOptions,\n infer Handlers,\n infer ReflectionMethods extends ReflectionOptions\n>\n ? ActorContext<\n Args,\n InternalState,\n InMsg,\n OutMsg,\n Methods,\n Handlers extends HandlerOptions<InMsg> ? Handlers : HandlerOptions<InMsg>,\n ReflectionMethods & ActorReflection\n >\n : never;\n","// ── Lifecycle Hooks ──────────────────────────────────────────────────────\n//\n// Extends ProcessCtx and defineActor with observable lifecycle hooks.\n// Hooks are additive — multiple callbacks can register for the same hook\n// point, and they fire in registration order.\n\nimport {\n STOP_SENTINEL,\n stopPropagation,\n PROPAGATE_SENTINEL,\n propagateError,\n} from \"./actor-types.js\";\nimport type {\n HookResult,\n ActorPlugin,\n PluginTransform,\n AnyConfig,\n ActorContextOf,\n ReflectionOptions,\n} from \"./actor-types.js\";\n\n// ── stop propagation sentinel ────────────────────────────────────────────\n\n// Re-exports from actor-types.ts (backward compatibility)\nexport { STOP_SENTINEL, stopPropagation, PROPAGATE_SENTINEL, propagateError };\nexport type { HookResult, ActorPlugin, PluginTransform };\n\n// ── type augmentation (Fastify-style) ────────────────────────────────────\n\n/**\n * Interface that plugins can augment via declaration merging.\n * Plugins ship a .d.ts that adds properties to this interface,\n * making them available on `this` in handlers and methods.\n *\n * Example (in a plugin's .d.ts):\n * declare module 'posipaki' {\n * interface ActorDecorated {\n * log: Logger;\n * }\n * }\n */\nexport interface ActorDecorated {}\n/** Reflection methods plugins and the framework add to every actor. Merged by\n * declaration, and held to {@link ReflectionOptions}' contract: async. */\nexport interface ActorReflection extends ReflectionOptions {}\n\n// ── chainHook ────────────────────────────────────────────────────────────\n\n/**\n * Compose two lifecycle hooks so that `plugin` fires first.\n *\n * If `plugin` returns the STOP_SENTINEL (via stopPropagation()),\n * `existing` is skipped entirely and the sentinel propagates.\n * Otherwise `existing` fires and its return value is used.\n *\n * Typical use in a plugin:\n * (cfg) => ({ ...cfg, onStart: chainHook(cfg.onStart, myOnStart) })\n *\n * @param existing - the current hook on the config (may be undefined)\n * @param plugin - the new hook to prepend\n * @returns a composed hook suitable for ActorConfig\n */\nexport function chainHook<TThis, TArgs extends unknown[]>(\n existing: ((this: TThis, ...args: TArgs) => HookResult | Promise<HookResult>) | undefined,\n plugin: (this: TThis, ...args: TArgs) => HookResult | Promise<HookResult>,\n): (this: TThis, ...args: TArgs) => HookResult | Promise<HookResult> {\n if (!existing) return plugin;\n return async function (this: TThis, ...args: TArgs): Promise<HookResult> {\n const result = await plugin.call(this, ...args);\n if (result === STOP_SENTINEL) return result;\n return await existing.call(this, ...args);\n } as (this: TThis, ...args: TArgs) => HookResult | Promise<HookResult>;\n}\n\n// ── mergeConfigs ─────────────────────────────────────────────────────────\n\n/**\n * Merge an overlay config into a base config, auto-chaining every on* hook.\n *\n * Each key in `overlay` that starts with \"on\" followed by an uppercase\n * letter (onStart, onMessage, onEmit, etc.) is composed via chainHook()\n * so that the overlay hook fires before the base hook, and stopPropagation\n * is respected.\n *\n * Typical use in a plugin:\n * return mergeConfigs(cfg, {\n * onStart() { this.log.info('starting'); },\n * beforeEnd() { this.log.info('stopping'); },\n * });\n *\n * @param base - the existing config (ActorConfig)\n * @param overlay - new hook implementations to prepend\n * @returns a new config with hooks chained\n */\nexport function mergeConfigs<C extends AnyConfig>(\n base: C,\n overlay: Partial<C> & ThisType<ActorContextOf<C>>,\n): C {\n const result = { ...base } as Record<string, unknown>;\n for (const key of Object.keys(overlay as Record<string, unknown>)) {\n const val = (overlay as Record<string, unknown>)[key];\n if (typeof val === \"function\" && /^(on|after|before)[A-Z]/.test(key)) {\n result[key] = chainHook(\n (base as Record<string, unknown>)[key] as (\n this: unknown,\n ...args: unknown[]\n ) => HookResult | Promise<HookResult>,\n val as (this: unknown, ...args: unknown[]) => HookResult | Promise<HookResult>,\n );\n } else {\n result[key] = val;\n }\n }\n result.$reflectionMethods = {};\n Object.assign(\n result.$reflectionMethods as object,\n \"$reflectionMethods\" in base ? base.$reflectionMethods : {},\n \"$reflectionMethods\" in overlay ? overlay.$reflectionMethods : {},\n );\n\n return result as unknown as C;\n}\n\nexport type Hook<T, I extends unknown[], O> = (this: T, ...args: I) => O;\n\nexport async function callHook<T, I extends unknown[], O>(\n fn: Hook<T, I, O> | undefined,\n eh: ((e: unknown) => unknown) | undefined,\n thisArg: T,\n ...args: I\n): Promise<O | undefined> {\n if (fn) {\n try {\n return await fn.call(thisArg, ...args);\n } catch (e) {\n if (eh) {\n let decision: unknown;\n try {\n decision = await eh(e);\n } catch {\n // An error inside the error handler must not mask the original one.\n }\n // An observing handler says so by returning the sentinel: the error it\n // did not handle keeps propagating, so the actor still goes down.\n if (decision === PROPAGATE_SENTINEL) throw e;\n } else {\n throw e;\n }\n }\n }\n return undefined;\n}\n"],"mappings":";;AA+PA,MAAa,gBAAgB,OAAO,0BAA0B;;AAG9D,MAAa,wBAA8C;;;;;;;;AAS3D,MAAa,qBAAqB,OAAO,yBAAyB;;AAGlE,MAAa,uBAAkD;;;;;;;;;;;;;;;;;AChN/D,SAAgB,UACd,UACA,QACmE;CACnE,IAAI,CAAC,UAAU,OAAO;CACtB,OAAO,eAA6B,GAAG,MAAkC;EACvE,MAAM,SAAS,MAAM,OAAO,KAAK,MAAM,GAAG,IAAI;EAC9C,IAAI,WAAW,eAAe,OAAO;EACrC,OAAO,MAAM,SAAS,KAAK,MAAM,GAAG,IAAI;CAC1C;AACF;;;;;;;;;;;;;;;;;;;AAsBA,SAAgB,aACd,MACA,SACG;CACH,MAAM,SAAS,EAAE,GAAG,KAAK;CACzB,KAAK,MAAM,OAAO,OAAO,KAAK,OAAkC,GAAG;EACjE,MAAM,MAAO,QAAoC;EACjD,IAAI,OAAO,QAAQ,cAAc,0BAA0B,KAAK,GAAG,GACjE,OAAO,OAAO,UACX,KAAiC,MAIlC,GACF;OAEA,OAAO,OAAO;CAElB;CACA,OAAO,qBAAqB,CAAC;CAC7B,OAAO,OACL,OAAO,oBACP,wBAAwB,OAAO,KAAK,qBAAqB,CAAC,GAC1D,wBAAwB,UAAU,QAAQ,qBAAqB,CAAC,CAClE;CAEA,OAAO;AACT;AAIA,eAAsB,SACpB,IACA,IACA,SACA,GAAG,MACqB;CACxB,IAAI,IACF,IAAI;EACF,OAAO,MAAM,GAAG,KAAK,SAAS,GAAG,IAAI;CACvC,SAAS,GAAG;EACV,IAAI,IAAI;GACN,IAAI;GACJ,IAAI;IACF,WAAW,MAAM,GAAG,CAAC;GACvB,QAAQ,CAER;GAGA,IAAI,aAAa,oBAAoB,MAAM;EAC7C,OACE,MAAM;CAEV;AAGJ"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as ProcessCtx, f as AnyProcess, i as Message, n as ExitMessage, p as AsyncProcess, r as ForkSite, s as SenderInfo, t as AsyncProcessFn } from "./types-DYd-DDFB.js";
|
|
2
2
|
//#region src/actor-types.d.ts
|
|
3
3
|
type ActorMessages<M extends Message> = {
|
|
4
4
|
__tag_messages: M;
|
|
@@ -50,7 +50,7 @@ interface ActorDefinition<Args, InternalState, InMsg extends Message, OutMsg ext
|
|
|
50
50
|
/** Spawn this actor as a child of the calling process.
|
|
51
51
|
* `ctx` must be able to fork children that emit `OutMsg` — i.e. the
|
|
52
52
|
* parent's in-message is a supertype of this actor's out-message. */
|
|
53
|
-
spawnAsChild
|
|
53
|
+
spawnAsChild(ctx: ForkSite, args: Args, opts?: {
|
|
54
54
|
name?: string;
|
|
55
55
|
parentPlugins?: ActorPlugin[];
|
|
56
56
|
addPlugins?: ActorPlugin[];
|
|
@@ -97,7 +97,10 @@ type ActorConfig<Args, InternalState, InMsg extends Message, OutMsg extends Mess
|
|
|
97
97
|
onEmit?: (msg: OutMsg, sender: SenderInfo) => HookResult | Promise<HookResult>;
|
|
98
98
|
onMessage?: (msg: InMsg, sender: SenderInfo) => HookResult | Promise<HookResult>;
|
|
99
99
|
onUnhandled?: (msg: Message, sender: SenderInfo) => void | Promise<void>;
|
|
100
|
-
|
|
100
|
+
/** A child ended. `exit` is what it sent — its orphans travel there — and `reason` is what it
|
|
101
|
+
* ended *for*: the value `exit(reason)` was given, `"stopped"` for a stop that was agreed to,
|
|
102
|
+
* `CHANNEL_LOST` when the wire under a proxy went, or undefined when nobody asked. */
|
|
103
|
+
onChildExit?: (name: string, exit: ExitMessage, reason: unknown) => HookResult | Promise<HookResult>;
|
|
101
104
|
/** Fires for each orphan a child leaves behind (in its EXIT). Return the
|
|
102
105
|
* policy: `'adopt'` (promote to a child, draining its buffer), `'force-stop'`
|
|
103
106
|
* (hard-kill), `'unparent'` (drop its buffer, keep it running in `orphans`),
|
|
@@ -138,6 +141,12 @@ type ActorContext<Args, InternalState, InMsg extends Message, OutMsg extends Mes
|
|
|
138
141
|
state: InternalState;
|
|
139
142
|
name: string;
|
|
140
143
|
id: symbol;
|
|
144
|
+
/** This actor as a process: the handle another process can be given so that it can
|
|
145
|
+
* send here. There is no other way to obtain one — a process is reachable because
|
|
146
|
+
* somebody holds it, and this is how it hands itself over. The same object as
|
|
147
|
+
* `ctx.self`, and as the one a spawner, a parent or a remote handle stands for.
|
|
148
|
+
* Erased, like every handle that leaves: whoever receives it declares what it is. */
|
|
149
|
+
self: AsyncProcess<Args, HidePrivate<InternalState>, InMsg, OutMsg, ReflectionMethods & ActorReflection>;
|
|
141
150
|
emit: (msg: OutMsg) => void;
|
|
142
151
|
agreeToStop: () => void;
|
|
143
152
|
reflection: ThisType<ActorContext<Args, InternalState, InMsg, OutMsg, Methods, Handlers, ReflectionMethods>> & ReflectionMethods;
|
|
@@ -210,4 +219,4 @@ type Hook<T, I extends unknown[], O> = (this: T, ...args: I) => O;
|
|
|
210
219
|
declare function callHook<T, I extends unknown[], O>(fn: Hook<T, I, O> | undefined, eh: ((e: unknown) => unknown) | undefined, thisArg: T, ...args: I): Promise<O | undefined>;
|
|
211
220
|
//#endregion
|
|
212
221
|
export { stopPropagation as S, PluginTransform as _, chainHook as a, SpawnedFrom as b, ActorContext as c, ActorPlugin as d, HandlerFn as f, PROPAGATE_SENTINEL as g, MethodOptions as h, callHook as i, ActorDefinition as l, HookResult as m, ActorReflection as n, mergeConfigs as o, HandlerOptions as p, Hook as r, ActorConfig as s, ActorDecorated as t, ActorMessages as u, ReflectionOptions as v, propagateError as x, STOP_SENTINEL as y };
|
|
213
|
-
//# sourceMappingURL=hooks-
|
|
222
|
+
//# sourceMappingURL=hooks-D1QaP6Vv.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks-D1QaP6Vv.d.ts","names":[],"sources":["../src/actor-types.ts","../src/hooks.ts"],"mappings":"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"}
|
package/dist/hooks.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { S as stopPropagation, _ as PluginTransform, a as chainHook, d as ActorPlugin, g as PROPAGATE_SENTINEL, i as callHook, m as HookResult, n as ActorReflection, o as mergeConfigs, r as Hook, t as ActorDecorated, x as propagateError, y as STOP_SENTINEL } from "./hooks-
|
|
1
|
+
import { S as stopPropagation, _ as PluginTransform, a as chainHook, d as ActorPlugin, g as PROPAGATE_SENTINEL, i as callHook, m as HookResult, n as ActorReflection, o as mergeConfigs, r as Hook, t as ActorDecorated, x as propagateError, y as STOP_SENTINEL } from "./hooks-D1QaP6Vv.js";
|
|
2
2
|
export { ActorDecorated, type ActorPlugin, ActorReflection, Hook, type HookResult, PROPAGATE_SENTINEL, type PluginTransform, STOP_SENTINEL, callHook, chainHook, mergeConfigs, propagateError, stopPropagation };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
import { S as stopPropagation, _ as PluginTransform, a as chainHook, b as SpawnedFrom, c as ActorContext, d as ActorPlugin, f as HandlerFn, h as MethodOptions, i as callHook, l as ActorDefinition, m as HookResult, n as ActorReflection, o as mergeConfigs, p as HandlerOptions, s as ActorConfig, t as ActorDecorated, u as ActorMessages, v as ReflectionOptions, x as propagateError } from "./hooks-
|
|
3
|
-
import { n as spawn, t as Process } from "./process-
|
|
1
|
+
import { a as ProcessCtx, c as SenderOrigin, d as WithoutSender, f as AnyProcess, h as spawnAsync, i as Message, l as StopMessage, m as runDispatchAsync, n as ExitMessage, o as ProcessFn, p as AsyncProcess, s as SenderInfo, t as AsyncProcessFn, u as WithSender } from "./types-DYd-DDFB.js";
|
|
2
|
+
import { S as stopPropagation, _ as PluginTransform, a as chainHook, b as SpawnedFrom, c as ActorContext, d as ActorPlugin, f as HandlerFn, h as MethodOptions, i as callHook, l as ActorDefinition, m as HookResult, n as ActorReflection, o as mergeConfigs, p as HandlerOptions, s as ActorConfig, t as ActorDecorated, u as ActorMessages, v as ReflectionOptions, x as propagateError } from "./hooks-D1QaP6Vv.js";
|
|
3
|
+
import { n as spawn, t as Process } from "./process-BVwU7TQo.js";
|
|
4
4
|
//#region src/util.d.ts
|
|
5
5
|
type ReducerClosure<M> = (msg: M) => void;
|
|
6
6
|
type ReadyFn = () => boolean;
|
|
@@ -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.40.0";
|
|
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.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/util.ts","../src/adapters.ts","../src/define-actor.ts","../src/version.ts"],"mappings":";;;;KAOK,eAAe,MAAM,KAAK;KAC1B;;;;;;iBASK,YAAY,GACpB,cACA,IAAI,eAAe,IACnB,UAAS,SACT,uBACC,sBAAsB;;;iBCpBT,SAAS,GAAG,GAAG,WAAW,SAAS,WAAW,SAC5D,IAAI,UAAU,GAAG,GAAG,IAAI,MACvB,eAAe,GAAG,GAAG,IAAI;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/util.ts","../src/adapters.ts","../src/define-actor.ts","../src/version.ts"],"mappings":";;;;KAOK,eAAe,MAAM,KAAK;KAC1B;;;;;;iBASK,YAAY,GACpB,cACA,IAAI,eAAe,IACnB,UAAS,SACT,uBACC,sBAAsB;;;iBCpBT,SAAS,GAAG,GAAG,WAAW,SAAS,WAAW,SAC5D,IAAI,UAAU,GAAG,GAAG,IAAI,MACvB,eAAe,GAAG,GAAG,IAAI;;;iBCgCZ,eAAe,eAAe,UAAU,YAAY,cAAc;iBA2DlE,YACd,MACA,eACA,cAAc,SACd,eAAe,SACf,gBAAgB,eAChB,iBAAiB,eAAe,QAChC,0BAA0B,mBAE1B,QAAQ,YAAY,MAAM,eAAe,OAAO,QAAQ,SAAS,UAAU,qBAC1E,gBAAgB,MAAM,eAAe,OAAO,QAAQ;;;;cC3F1C"}
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { i as runDispatch } from "./util-Brtfgv68.js";
|
|
2
|
-
import { a as spawnAsync, i as runDispatchAsync, o as asyncify, t as AsyncProcess } from "./process.async-
|
|
2
|
+
import { a as spawnAsync, i as runDispatchAsync, o as asyncify, t as AsyncProcess } from "./process.async-C_-NpMFX.js";
|
|
3
3
|
import { n as chainHook, o as propagateError, r as mergeConfigs, s as stopPropagation, t as callHook } from "./hooks-CgXhmY4r.js";
|
|
4
|
-
import { n as defineMessages, t as defineActor } from "./define-actor-
|
|
5
|
-
import { t as LIB_VERSION } from "./version-
|
|
4
|
+
import { n as defineMessages, t as defineActor } from "./define-actor-D7c9vn6S.js";
|
|
5
|
+
import { t as LIB_VERSION } from "./version-D4C9wBG0.js";
|
|
6
6
|
//#region src/process.ts
|
|
7
7
|
/** @deprecated Use {@link spawnAsync} instead. */
|
|
8
8
|
function spawn(fn, pname, tp) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { r as makeWaiter } from "./util-Brtfgv68.js";
|
|
2
|
-
import { r as isProcess } from "./process.async-
|
|
2
|
+
import { r as isProcess } from "./process.async-C_-NpMFX.js";
|
|
3
3
|
import { s as stopPropagation } from "./hooks-CgXhmY4r.js";
|
|
4
|
-
import { t as defineActor } from "./define-actor-
|
|
4
|
+
import { t as defineActor } from "./define-actor-D7c9vn6S.js";
|
|
5
5
|
//#region src/remote/process-ref.ts
|
|
6
6
|
/** The key that marks a process reference inside an otherwise JSON value. */
|
|
7
7
|
const PROCESS_REF = "$p";
|
|
@@ -1037,6 +1037,9 @@ async function serveRemoteActor(actor, spawner) {
|
|
|
1037
1037
|
await proc.ready();
|
|
1038
1038
|
streams.crossed(proc, table.rootId());
|
|
1039
1039
|
streams.flush();
|
|
1040
|
+
channel.onClose(() => {
|
|
1041
|
+
proc.stop();
|
|
1042
|
+
});
|
|
1040
1043
|
function dispatch(raw) {
|
|
1041
1044
|
const frame = decodeFrame(raw, handleFor);
|
|
1042
1045
|
if (calls.settle(frame)) return;
|
|
@@ -1105,6 +1108,16 @@ async function serveRemoteActor(actor, spawner) {
|
|
|
1105
1108
|
}
|
|
1106
1109
|
//#endregion
|
|
1107
1110
|
//#region src/remote/client.ts
|
|
1111
|
+
/**
|
|
1112
|
+
* Why a proxy ends when the wire under it goes.
|
|
1113
|
+
*
|
|
1114
|
+
* The far side is *unreachable*, which is not the same as ended: the handles that came across are
|
|
1115
|
+
* still here and still readable, and what the far process left behind is still what it left behind.
|
|
1116
|
+
* But nothing it says can arrive and nothing here can reach it, and that is news of its own — so the
|
|
1117
|
+
* proxy ends with this reason rather than sitting there silent. Whoever forked the proxy hears it
|
|
1118
|
+
* where it hears everything else about a child, in `onChildExit`.
|
|
1119
|
+
*/
|
|
1120
|
+
const CHANNEL_LOST = "channel-lost";
|
|
1108
1121
|
function remoteClient(name, spawner) {
|
|
1109
1122
|
return defineActor({
|
|
1110
1123
|
name,
|
|
@@ -1247,6 +1260,7 @@ function remoteClient(name, spawner) {
|
|
|
1247
1260
|
calls.rejectAll();
|
|
1248
1261
|
for (const held of table.handles()) if (isRemoteProcess(held)) held.disconnect();
|
|
1249
1262
|
streams.stopAll();
|
|
1263
|
+
this.exit(CHANNEL_LOST);
|
|
1250
1264
|
});
|
|
1251
1265
|
await start;
|
|
1252
1266
|
return {
|
|
@@ -1305,6 +1319,6 @@ function json1Channel(transport) {
|
|
|
1305
1319
|
};
|
|
1306
1320
|
}
|
|
1307
1321
|
//#endregion
|
|
1308
|
-
export {
|
|
1322
|
+
export { isState as _, CHANNEL_LOST as a, isRemoteProcess as b, makeSender as c, isInit as d, isMsg as f, isResume as g, isRelease as h, json1Channel as i, RemoteProcess as l, isProto as m, decode as n, remoteClient as o, isPause as p, encode as r, serveRemoteActor as s, VERSION as t, isExit as u, isStop as v, rootIdFor as x, PROCESS_REF as y };
|
|
1309
1323
|
|
|
1310
|
-
//# sourceMappingURL=json1-
|
|
1324
|
+
//# sourceMappingURL=json1-B-oUZzI_.js.map
|