@mcp-b/do-runtime 0.1.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.
Files changed (52) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/LICENSE +110 -0
  3. package/LICENSE.workerd +176 -0
  4. package/NOTICE +7 -0
  5. package/README.md +282 -0
  6. package/dist/backends/node-sqlite.d.ts +38 -0
  7. package/dist/backends/node-sqlite.js +335 -0
  8. package/dist/backends/node-sqlite.js.map +1 -0
  9. package/dist/backends/sqlite-wasm.d.ts +130 -0
  10. package/dist/backends/sqlite-wasm.js +259 -0
  11. package/dist/backends/sqlite-wasm.js.map +1 -0
  12. package/dist/chunks/sqlite-DFg92Tgt.js +498 -0
  13. package/dist/chunks/sqlite-DFg92Tgt.js.map +1 -0
  14. package/dist/cloudflare-workers.js +351 -0
  15. package/dist/cloudflare-workers.js.map +1 -0
  16. package/dist/conformance/host.d.ts +58 -0
  17. package/dist/conformance.js +18 -0
  18. package/dist/conformance.js.map +1 -0
  19. package/dist/index.js +7184 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/server/alarm-scheduler.js +513 -0
  22. package/dist/server/alarm-scheduler.js.map +1 -0
  23. package/dist/src/api/actor-state.d.ts +396 -0
  24. package/dist/src/api/actor.d.ts +306 -0
  25. package/dist/src/api/cloudflare-workers.d.ts +259 -0
  26. package/dist/src/api/export-loopback.d.ts +264 -0
  27. package/dist/src/api/global-scope.d.ts +262 -0
  28. package/dist/src/api/http.d.ts +52 -0
  29. package/dist/src/api/sql.d.ts +188 -0
  30. package/dist/src/api/sync-kv.d.ts +51 -0
  31. package/dist/src/api/web-socket.d.ts +93 -0
  32. package/dist/src/api/worker-loader.d.ts +354 -0
  33. package/dist/src/index.d.ts +130 -0
  34. package/dist/src/io/actor-cache.d.ts +203 -0
  35. package/dist/src/io/actor-id.d.ts +74 -0
  36. package/dist/src/io/actor-sqlite.d.ts +298 -0
  37. package/dist/src/io/io-channels.d.ts +191 -0
  38. package/dist/src/io/io-context.d.ts +451 -0
  39. package/dist/src/io/io-gate.d.ts +298 -0
  40. package/dist/src/io/worker-source.d.ts +108 -0
  41. package/dist/src/io/worker.d.ts +88 -0
  42. package/dist/src/server/actor-container.d.ts +525 -0
  43. package/dist/src/server/actor-id-impl.d.ts +118 -0
  44. package/dist/src/server/alarm-scheduler.d.ts +201 -0
  45. package/dist/src/server/facet-deletion.d.ts +156 -0
  46. package/dist/src/server/facet-tree-index.d.ts +94 -0
  47. package/dist/src/server/sha256.d.ts +39 -0
  48. package/dist/src/transport/rpc-session.d.ts +34 -0
  49. package/dist/src/util/sqlite-kv.d.ts +98 -0
  50. package/dist/src/util/sqlite-metadata.d.ts +46 -0
  51. package/dist/src/util/sqlite.d.ts +291 -0
  52. package/package.json +111 -0
@@ -0,0 +1,298 @@
1
+ /**
2
+ * ← workerd `src/workerd/io/io-gate.{h,c++}`
3
+ *
4
+ * An I/O gate allows someone to "lock" a type of I/O so that other concurrent tasks trying to
5
+ * perform that type of I/O are blocked until the lock is released.
6
+ *
7
+ * I/O gates are used in actors to implement consistency guarantees, allowing in-memory state and
8
+ * storage to be synchronized.
9
+ *
10
+ * Each Actor has two main gates:
11
+ * - Input gate: While locked, blocks all incoming I/O events of any type from being delivered to
12
+ * the actor, other than the specific event or events that hold the lock. This includes
13
+ * blocking responses to subrequests, timer events, input streams, etc. Used when storage
14
+ * operations are outstanding, so that awaiting a storage operation does not risk allowing
15
+ * concurrent events that render the state inconsistent.
16
+ * - Output gate: While locked, blocks all outgoing messages from an actor that would allow the
17
+ * rest of the world to observe the actor's state. Held while writes that have been confirmed
18
+ * to the application are still being flushed to disk. If the flush fails, these messages will
19
+ * never be sent, so that the rest of the world cannot observe a prematurely-confirmed write.
20
+ *
21
+ * Three things kj gives for free and JS does not, resolved the same way at every site:
22
+ *
23
+ * 1. **Destructors.** `~Lock` releases and `~CriticalSection` diagnoses a dropped section as
24
+ * deadlock. Both become explicit: `Lock.release()` and `CriticalSection.drop()`. A `Lock`
25
+ * released twice throws rather than corrupting the refcount.
26
+ * 2. **Cancel-by-drop.** Dropping a `kj::Promise` unwinds its waiter. Every such site takes an
27
+ * `AbortSignal`, the convention `Timer.afterDelay` already set in `io-context.ts`. Aborting a
28
+ * `wait()` rejects it with `CanceledError`; a never-settling promise would be an invisible
29
+ * hang, which is what this repo's fail-closed tenet exists to prevent.
30
+ * 3. **`kj::ForkedPromise` holding an exception with no branches.** JS reports that as an
31
+ * unhandled rejection, so every promise this module stores keeps a no-op `catch` of its own
32
+ * and hands observers a separate view.
33
+ *
34
+ * Error strings are copied verbatim from upstream; users and upstream tests match on them.
35
+ *
36
+ * Not ported: `SpanParent`/`SpanBuilder` tracing, since there is no `trace.h` here and upstream's
37
+ * own tests pass `nullptr` at every call site; and the `~InputGate` assertion that no locks
38
+ * outlive the gate, which guards against dangling references GC makes impossible.
39
+ *
40
+ * Spec: §1.1, §1.2, §1.5, decisions 3, 5 and 13 in
41
+ * docs/decisions.md.
42
+ */
43
+ /**
44
+ * Raised when a `wait()` is cancelled through its `AbortSignal`.
45
+ *
46
+ * kj has no equivalent, because a cancelled continuation simply never runs. It is deliberately
47
+ * NOT a gate failure: a cancelled waiter leaves the gate exactly as it found it, so
48
+ * `CriticalSection.wait()` rethrows this one without calling `setBroken()`.
49
+ */
50
+ export declare class CanceledError extends Error {
51
+ readonly name = "CanceledError";
52
+ }
53
+ /**
54
+ * ← `kj::OneOf<kj::Own<kj::PromiseFulfiller<void>>, kj::Exception> brokenState`.
55
+ *
56
+ * `InputGate` starts in `fulfiller` — it builds its promise in the constructor — while
57
+ * `OutputGate` starts in `none` and only makes one when `onBroken()` is first called.
58
+ */
59
+ type BrokenState = {
60
+ readonly kind: "none";
61
+ } | {
62
+ readonly kind: "fulfiller";
63
+ readonly reject: (exception: unknown) => void;
64
+ } | {
65
+ readonly kind: "exception";
66
+ readonly exception: unknown;
67
+ };
68
+ /**
69
+ * Hooks that can be used to customize InputGate behavior.
70
+ *
71
+ * Technically, everything implemented here could be accomplished by a class that wraps
72
+ * InputGate, but the part of the code that wants to implement these hooks is far away from the
73
+ * part of the code that calls into the InputGate, and so it was more convenient to give the
74
+ * caller a way to inject behavior into InputGate.
75
+ */
76
+ export interface InputGateHooks {
77
+ inputGateLocked(): void;
78
+ inputGateReleased(): void;
79
+ inputGateWaiterAdded(): void;
80
+ inputGateWaiterRemoved(): void;
81
+ }
82
+ /** ← `InputGate::Hooks::DEFAULT`. */
83
+ export declare const DEFAULT_INPUT_GATE_HOOKS: InputGateHooks;
84
+ /** ← `InputGate::Waiter`: a `kj::List` node plus the adapted promise's fulfiller. */
85
+ declare class Waiter {
86
+ #private;
87
+ /** Rewritten by `CriticalSection.succeeded()` when a straggler is reparented. */
88
+ gate: InputGate;
89
+ readonly isChildWaiter: boolean;
90
+ /** ← `link.isLinked()`. */
91
+ linked: boolean;
92
+ constructor(gate: InputGate, isChildWaiter: boolean, resolve: (lock: Lock) => void, reject: (exception: unknown) => void);
93
+ unlink(): void;
94
+ fulfill(lock: Lock): void;
95
+ reject(exception: unknown): void;
96
+ }
97
+ /**
98
+ * An InputGate blocks incoming events from being delivered to an actor while the lock is held.
99
+ *
100
+ * Upstream marks the state below `private` and befriends `Lock` and `CriticalSection`.
101
+ * TypeScript has no friendship, and `protected` would not let `CriticalSection` reach these
102
+ * members on its *parent* gate, which `succeeded()` does. The boundary that actually holds is
103
+ * the package facade in `src/index.ts`, which exports none of these types.
104
+ */
105
+ export declare class InputGate {
106
+ #private;
107
+ readonly hooks: InputGateHooks;
108
+ /**
109
+ * How many instances of `Lock` currently exist? When this reaches zero, we'll release some
110
+ * waiters.
111
+ *
112
+ * Upstream also carries a `bool isCriticalSection`, because `CriticalSection` inherits
113
+ * `InputGate` privately and has to `static_cast` back. `instanceof` is the same test with no
114
+ * cast and no field that can disagree with the object it describes.
115
+ */
116
+ lockCount: number;
117
+ readonly waiters: Waiter[];
118
+ /**
119
+ * Waiters representing CriticalSections that are ready to start. These take priority over other
120
+ * waiters.
121
+ */
122
+ readonly waitingChildren: Waiter[];
123
+ /** A fulfiller for onBroken(), or an exception if already broken. */
124
+ brokenState: BrokenState;
125
+ constructor(hooks?: InputGateHooks);
126
+ /** Wait until there are no `Lock`s, then create a new one and return it. */
127
+ wait(signal?: AbortSignal): Promise<Lock>;
128
+ /**
129
+ * Rejects if and when calls to `wait()` become broken due to a failed critical section. The
130
+ * actor should be shut down in this case. This promise never resolves, only rejects.
131
+ */
132
+ onBroken(): Promise<never>;
133
+ /** ← `kj::newAdaptedPromise<Lock, Waiter>(gate, isChildWaiter, span)`. */
134
+ newWaiterPromise(isChildWaiter: boolean, signal?: AbortSignal): Promise<Lock>;
135
+ releaseLock(): void;
136
+ /** Called when a critical section fails. All future waiters will throw this exception. */
137
+ setBroken(exception: unknown): void;
138
+ }
139
+ /** ← `InputGate::Lock`. A lock that blocks all new events from being delivered while it exists. */
140
+ export declare class Lock {
141
+ #private;
142
+ constructor(gate: InputGate);
143
+ /** ← `~Lock`. */
144
+ release(): void;
145
+ /**
146
+ * Increments the lock's refcount, returning a duplicate `Lock`. All `Lock`s must be released
147
+ * before the gate is unlocked.
148
+ */
149
+ addRef(): Lock;
150
+ /**
151
+ * Start a new critical section from this lock. After `wait()` has been called on the returned
152
+ * critical section for the first time, no further Locks will be handed out by
153
+ * InputGate::wait() until the CriticalSection has been dropped.
154
+ *
155
+ * CriticalSections can be nested. If this Lock is itself part of a CriticalSection, the new
156
+ * CriticalSection will be nested within it and the outer CriticalSection's wait() won't
157
+ * produce a Lock again until the inner CriticalSection is dropped.
158
+ */
159
+ startCriticalSection(): CriticalSection;
160
+ /** If this lock was taken in a CriticalSection, return it. */
161
+ getCriticalSection(): CriticalSection | undefined;
162
+ isFor(otherGate: InputGate): boolean;
163
+ /** ← `operator==`. */
164
+ equals(other: Lock): boolean;
165
+ }
166
+ /** ← `InputGate::CriticalSection::State`. */
167
+ type CriticalSectionState =
168
+ /** wait() hasn't been called. */
169
+ "NOT_STARTED"
170
+ /** wait() has been called once, and that wait hasn't finished yet. */
171
+ | "INITIAL_WAIT"
172
+ /** First lock has been obtained, waiting for success() or failed(). */
173
+ | "RUNNING"
174
+ /** success() or failed() has been called. */
175
+ | "REPARENTED";
176
+ /**
177
+ * A CriticalSection is a procedure that must not be interrupted by anything "external".
178
+ * While a CriticalSection is running, all events that were not initiated by the
179
+ * CriticalSection itself will be blocked from being delivered.
180
+ *
181
+ * The difference between a Lock and a CriticalSection is that a critical section may succeed
182
+ * or fail. A failed critical section permanently breaks the input gate. Locks, on the other
183
+ * hand, are simply released when dropped.
184
+ *
185
+ * A CriticalSection itself holds a Lock, which blocks the "parent scope" from continuing
186
+ * execution until the critical section is done. Meanwhile, the code running inside the critical
187
+ * section obtains nested Locks. These nested locks control concurrency of the operations
188
+ * initiated within the critical section in the same way that input locks normally do at the
189
+ * top-level scope. E.g., if a critical section initiates a storage read and a fetch() at the
190
+ * same time, the fetch() is prevented from returning until after the storage read has returned.
191
+ */
192
+ export declare class CriticalSection extends InputGate {
193
+ #private;
194
+ state: CriticalSectionState;
195
+ constructor(parent: InputGate);
196
+ /**
197
+ * Wait for a nested lock in order to continue this CriticalSection.
198
+ *
199
+ * The first call to wait() begins the CriticalSection. After that wait completes, until the
200
+ * CriticalSection is done and dropped, no other locks will be allowed on this InputGate, except
201
+ * locks requested by calling wait() on this CriticalSection -- or one of its children.
202
+ *
203
+ * Everything before the first `await` runs in the caller's synchronous slice, which is what
204
+ * lets the NOT_STARTED path take its parent lock before any other event can queue behind it.
205
+ */
206
+ wait(signal?: AbortSignal): Promise<Lock>;
207
+ /**
208
+ * Call when the critical section has completed successfully. If this is not called before the
209
+ * CriticalSection is dropped, then failed() is called implicitly.
210
+ *
211
+ * Returns the input lock that was held on the parent critical section. This can be used to
212
+ * continue execution in the parent before any other input arrives.
213
+ */
214
+ succeeded(): Lock;
215
+ /**
216
+ * Call to indicate the CriticalSection has failed with the given exception. This immediately
217
+ * breaks the InputGate.
218
+ */
219
+ failed(exception: unknown): void;
220
+ /** ← `~CriticalSection`. */
221
+ drop(): void;
222
+ /** Return a reference for the parent scope, skipping any reparented CriticalSections */
223
+ parentAsInputGate(): InputGate;
224
+ }
225
+ /**
226
+ * ← the gate half of `IoContext::makeReentryCallback()` (`io-context.h:1507`), which is
227
+ * `ctx.run(func, cs)` with the critical section captured here rather than looked up later.
228
+ *
229
+ * Upstream, on why the critical section travels with the callback at all:
230
+ *
231
+ * > "What if the call was made within blockConcurrencyWhile()? The callback will be blocked until
232
+ * > the critical section ends, which could lead to deadlock if the critical section code is
233
+ * > waiting on it? ... The callback is allowed to run within the critical section
234
+ * > (blockConcurrencyWhile()) from which it was called."
235
+ *
236
+ * `criticalSection` must come from the capturing lock's `getCriticalSection()`, at the moment of
237
+ * capture. It cannot be recovered from gate state on invocation: a *new* external event that
238
+ * inherited the running section would skip the queue, and `blockConcurrencyWhile` would silently
239
+ * block nothing (Part 4).
240
+ *
241
+ * The lock covers the callback's synchronous slice and is released when the callback returns
242
+ * control — decision 1, and the reason a callback that awaits something does not wedge the gate.
243
+ * A callback needing the lock across an await takes `lock.addRef()`, which is upstream's
244
+ * `awaitIoWithInputLock` in the one shape io-gate can express (§1.2).
245
+ *
246
+ * The returned function can be called multiple times.
247
+ */
248
+ export declare function makeReentryCallback<Args extends unknown[], Result>(gate: InputGate, criticalSection: CriticalSection | undefined, func: (lock: Lock, ...args: Args) => Result | PromiseLike<Result>): (...args: Args) => Promise<Result>;
249
+ /**
250
+ * Hooks that can be used to customize OutputGate behavior. See `InputGateHooks` for why these
251
+ * are injected rather than wrapped.
252
+ */
253
+ export interface OutputGateHooks {
254
+ /**
255
+ * Optionally make a promise which should be raced with the lock promise to implement a
256
+ * timeout. The returned promise should be something that throws an exception after some
257
+ * timeout has expired.
258
+ */
259
+ makeTimeoutPromise(): Promise<never>;
260
+ outputGateLocked(): void;
261
+ outputGateReleased(): void;
262
+ outputGateWaiterAdded(): void;
263
+ outputGateWaiterRemoved(): void;
264
+ }
265
+ /** ← `OutputGate::Hooks::DEFAULT`. */
266
+ export declare const DEFAULT_OUTPUT_GATE_HOOKS: OutputGateHooks;
267
+ /**
268
+ * An OutputGate blocks outgoing messages from an Actor until writes which they might depend on
269
+ * are confirmed.
270
+ *
271
+ * A promise chain, not a counter (§1.1): each `lockWhile` joins a new link onto the chain and
272
+ * re-forks it, so a `wait()` is bound to exactly the locks outstanding when it was taken and is
273
+ * unaffected by any later `lockWhile`.
274
+ */
275
+ export declare class OutputGate {
276
+ #private;
277
+ constructor(hooks?: OutputGateHooks);
278
+ /**
279
+ * Block all future `wait()` calls until `promise` completes. Returns a wrapper around
280
+ * `promise`. If `promise` rejects, the exception will propagate to all future `wait()`s. If the
281
+ * returned promise is canceled before completion, all future `wait()`s will also throw.
282
+ */
283
+ lockWhile<T>(promise: Promise<T>, signal?: AbortSignal): Promise<T>;
284
+ /**
285
+ * Wait until all preceding locks are released. The wait will not be affected by any future
286
+ * call to `lockWhile()`.
287
+ */
288
+ wait(): Promise<void>;
289
+ /**
290
+ * Rejects if and when calls to `wait()` become broken due to a failed lockWhile(). The actor
291
+ * should be shut down in this case. This promise never resolves, only rejects.
292
+ *
293
+ * This method can only be called once.
294
+ */
295
+ onBroken(): Promise<never>;
296
+ isBroken(): boolean;
297
+ }
298
+ export {};
@@ -0,0 +1,108 @@
1
+ /**
2
+ * ← workerd `src/workerd/io/worker-source.h` — the `ModulesSource` arm.
3
+ *
4
+ * "Represents the source code for a Worker … WorkerSource is a data structure
5
+ * that can be constructed from either representation -- as well as from
6
+ * non-capnp-based sources, like the dynamic worker loader API." That last clause
7
+ * is why this file exists at all: `api/worker-loader.ts`'s `extractSource`
8
+ * produces one of these, and `io/io-channels.ts`'s `DynamicWorkerSource` carries
9
+ * it, so it has to live in `io/` where both can see it.
10
+ *
11
+ * **A partial port, in the shape `io/io-channels.ts` already established.** Three
12
+ * things upstream has here have nothing to port onto:
13
+ *
14
+ * - **The `ScriptSource` arm** — Service Workers syntax, one file plus injected
15
+ * globals. It arrives from a worker *configuration*, and configuration
16
+ * compilation (`server/workerd-api.c++`'s `compileScript`) has no port here.
17
+ * `WorkerLoader::extractSource` provably cannot produce one either: its single
18
+ * `return` is a `ModulesSource` (`api/worker-loader.c++:271-275`). So
19
+ * `WorkerSource.variant` is declared with the one arm this package can reach,
20
+ * and stays a tagged union so the other is additive rather than a reshape.
21
+ * - **`capnpSchemas`, `pythonMemorySnapshot`, `CapnpModule` and
22
+ * `dynamicEnvBuilder`** — capnp readers and an edge-runtime `env` hack, none of
23
+ * which has a schema or a reader here.
24
+ * - **`clone()`** — upstream deep-copies because a `WorkerSource` holds
25
+ * `StringPtr`s into a buffer someone else owns and `loadIsolate`'s callback
26
+ * "technically may be called any number of times" (`api/worker-loader.c++:90`).
27
+ * A JS value has no such lifetime: the same frozen object is handed back on
28
+ * every call, which is what `clone()` was reproducing. `ownContent` and
29
+ * `ownContentIsRpcResponse` on `DynamicWorkerSource` are the other half of the
30
+ * same kj bookkeeping and are absent for the same reason.
31
+ *
32
+ * **A `kj::OneOf` is tagged by its C++ type; a JS union needs the tag in the
33
+ * value.** Every variant here carries a `type` naming upstream's struct, so
34
+ * `content.is<Worker::Script::EsModule>()` becomes `content.type === "esModule"`.
35
+ * That is the same substitution `util/sqlite.ts` makes for statement kinds and
36
+ * the reason it is stated once, here.
37
+ *
38
+ * Spec: §1.11, decision 15 in docs/decisions.md.
39
+ */
40
+ /** ← `WorkerSource::EsModule`. `ownBody` is a Rust transpiler artifact with no port. */
41
+ export type EsModule = {
42
+ readonly type: "esModule";
43
+ readonly body: string;
44
+ };
45
+ /** ← `WorkerSource::CommonJsModule`. */
46
+ export type CommonJsModule = {
47
+ readonly type: "commonJsModule";
48
+ readonly body: string;
49
+ /** Upstream's field. `WorkerLoader::extractSource` never fills it. */
50
+ readonly namedExports?: readonly string[];
51
+ };
52
+ /** ← `WorkerSource::TextModule`. "text blob, imports as a string". */
53
+ export type TextModule = {
54
+ readonly type: "textModule";
55
+ readonly body: string;
56
+ };
57
+ /** ← `WorkerSource::DataModule`. "byte blob, imports as ArrayBuffer". */
58
+ export type DataModule = {
59
+ readonly type: "dataModule";
60
+ readonly body: Uint8Array;
61
+ };
62
+ /** ← `WorkerSource::WasmModule`. "Compiled .wasm file content." */
63
+ export type WasmModule = {
64
+ readonly type: "wasmModule";
65
+ readonly body: Uint8Array;
66
+ };
67
+ /**
68
+ * ← `WorkerSource::JsonModule`. "JSON-encoded content; will be parsed
69
+ * automatically when imported."
70
+ */
71
+ export type JsonModule = {
72
+ readonly type: "jsonModule";
73
+ readonly body: string;
74
+ };
75
+ /** ← `WorkerSource::PythonModule`. */
76
+ export type PythonModule = {
77
+ readonly type: "pythonModule";
78
+ readonly body: string;
79
+ };
80
+ /**
81
+ * ← `WorkerSource::ModuleContent`, minus the two arms no ported caller can
82
+ * produce: `PythonRequirement` (a system-provided package, named by a
83
+ * configuration this package does not compile) and `CapnpModule` (a type id into
84
+ * a schema bundle with no reader).
85
+ */
86
+ export type ModuleContent = EsModule | CommonJsModule | TextModule | DataModule | WasmModule | JsonModule | PythonModule;
87
+ /** ← `WorkerSource::Module`. */
88
+ export type Module = {
89
+ readonly name: string;
90
+ readonly content: ModuleContent;
91
+ /** ← "Hack for tests: register this as an internal module. Not allowed in production." */
92
+ readonly treatAsInternalForTest?: boolean;
93
+ };
94
+ /** ← `WorkerSource::ModulesSource`. "source code for a worker using ES Modules syntax." */
95
+ export type ModulesSource = {
96
+ readonly type: "modulesSource";
97
+ /** "Path to the main module, which can be looked up in the module registry." */
98
+ readonly mainModule: string;
99
+ /** "All the Worker's modules." */
100
+ readonly modules: readonly Module[];
101
+ readonly isPython: boolean;
102
+ };
103
+ /** ← `WorkerSource::variant`, whose `ScriptSource` arm is a boundary — see the header. */
104
+ export type WorkerSourceVariant = ModulesSource;
105
+ /** ← `WorkerSource`. */
106
+ export type WorkerSource = {
107
+ readonly variant: WorkerSourceVariant;
108
+ };
@@ -0,0 +1,88 @@
1
+ /**
2
+ * ← workerd `src/workerd/io/worker.h` — `Worker::Actor::FacetManager` only
3
+ * (`io/worker.h:901`).
4
+ *
5
+ * This file exists to settle a layering question the scaffolding got backwards.
6
+ * The facet surface `api/actor-state.ts` consumes was declared in
7
+ * `server/actor-container.ts`, which would give `api/` → `server/` a dependency
8
+ * upstream does not have: `api/actor-state.c++` includes from `api/`, `io/` and
9
+ * `jsg/` and from `server/` never, and the manager it reaches for is a nested
10
+ * class of `Worker::Actor` in `io/worker.h`. Per the README's rule for a
11
+ * legitimate upstream include crossing a wall, the reference widens to match
12
+ * upstream rather than the files being reshuffled to avoid it.
13
+ *
14
+ * `FacetManager` is not the same interface as `server/actor-container.ts`'s
15
+ * `FacetHost`, and conflating them is what produced the inverted dependency.
16
+ * `FacetHost` is the substrate PLACEMENT port — where a facet runs, the callable
17
+ * stub across that placement, and physical storage deletion — and it has no
18
+ * upstream twin, because workerd's facets are in-process. `FacetManager` is the
19
+ * package-owned layer above it that owns naming, ids, the limits, receipts and
20
+ * `clone()` orchestration, and it is the only facet thing `api/` may see.
21
+ * `server/` implements it on top of `FacetHost`.
22
+ *
23
+ * The rest of `worker.h` — `Worker`, `Worker::Isolate`, `Worker::Lock`,
24
+ * `Worker::Actor` itself — is isolate machinery with no port. The three
25
+ * `Worker::Actor` members `io/io-context.ts` reaches for are declared there, as
26
+ * that file's own comment explains; `assertCanSetAlarm()` joins them because
27
+ * `api/actor-state.c++` reaches for it through
28
+ * `IoContext::current().getActorOrThrow()`.
29
+ *
30
+ * Spec: §1.10, decision 14 in docs/decisions.md.
31
+ */
32
+ import type { ActorClassChannel } from "./io-channels.js";
33
+ /**
34
+ * ← `Worker::Actor::FacetManager::StartInfo`.
35
+ *
36
+ * `actorClass` is upstream's own type — a resolved
37
+ * `IoChannelFactory::ActorClassChannel`, which `io/io-channels.ts` ports and
38
+ * `DurableObjectClass.getChannel()` produces. An earlier revision typed it as
39
+ * `DurableObjectClass`, the `@cloudflare/workers-types` interface, which is
40
+ * declared `interface DurableObjectClass<_T> {}` and therefore accepts any
41
+ * object at all: it was `unknown` with a name, and it left `server/` with
42
+ * nothing to resolve a class against. Upstream resolves it one step earlier —
43
+ * `DurableObjectFacets::get` calls `actorClass.getChannel(ioCtx)` inside the
44
+ * reentry callback (`actor-state.c++:1044`) — so `api/actor-state.ts` now does
45
+ * the same and this field carries the resolved channel.
46
+ *
47
+ * `id` is upstream's `Worker::Actor::Id` as the string form of a
48
+ * `DurableObjectId`, which is all a `DurableObjectId` is once it leaves this
49
+ * package, since ids never cross the host boundary.
50
+ */
51
+ export type FacetStartInfo = {
52
+ readonly actorClass: ActorClassChannel;
53
+ /** `ctx.id` for the child. Defaults to the parent's, as upstream's does. */
54
+ readonly id: string;
55
+ };
56
+ /**
57
+ * ← `Worker::Actor::FacetManager` (`io/worker.h:901-931`).
58
+ *
59
+ * Upstream's comment on the last three: "These methods are C++ equivalents of
60
+ * the JavaScript ctx.facets API."
61
+ *
62
+ * `cloneFacet` is the fourth, and it is not in the vendored C++ snapshot — see
63
+ * the note on `DurableObjectFacets.clone` in `api/actor-state.ts`.
64
+ */
65
+ export interface FacetManager {
66
+ /** Returns the nesting depth of this facet. Root = 0, direct child of root = 1, etc. */
67
+ getDepth(): number;
68
+ getFacet<T extends Rpc.DurableObjectBranded | undefined = undefined>(name: string, getStartInfo: () => Promise<FacetStartInfo>): Fetcher<T>;
69
+ abortFacet(name: string, reason: unknown): void;
70
+ deleteFacet(name: string): void;
71
+ /** Aborts `dst`, deletes its storage, then copies the whole `src` subtree onto it. */
72
+ cloneFacet(src: string, dst: string): void;
73
+ }
74
+ /**
75
+ * The one type assertion the facet surface needs, in one named place so an
76
+ * implementation does not have to reinvent it.
77
+ *
78
+ * `Fetcher<T>` for an unresolved `T` is `Rpc.Provider<T, …> & { fetch, connect }`
79
+ * — a conditional type TypeScript defers until `T` is known, and `T` is the
80
+ * caller's claim about the shape of a class it named. No value can confirm that
81
+ * claim, so no value can be checked against it. Upstream is in exactly the same
82
+ * position and answers it the same way: `DurableObjectFacets::get` returns a
83
+ * plain `jsg::Ref<Fetcher>` and the type parameter exists only inside a
84
+ * `JSG_TS_OVERRIDE`. What IS checked is the half that carries behaviour —
85
+ * `fetch` and `connect` — because the argument is a `Fetcher` before it is
86
+ * widened.
87
+ */
88
+ export declare function asFacetStub<T extends Rpc.DurableObjectBranded | undefined>(stub: Fetcher): Fetcher<T>;