@lunora/container 0.0.0 → 1.0.0-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,597 @@
1
+ import { DurableObject, WorkerEntrypoint } from 'cloudflare:workers';
2
+ import { a as ContainerDefinition, D as DurableObjectJurisdiction } from "../packem_shared/jurisdiction.d-TwTGkgTg.js";
3
+ /**
4
+ * ContainerStartOptions as they come from worker types
5
+ */
6
+ type ContainerStartOptions = NonNullable<Parameters<NonNullable<DurableObject['ctx']['container']>['start']>[0]>;
7
+ /**
8
+ * Options for container configuration
9
+ */
10
+ interface ContainerOptions {
11
+ /** Optional ID for the container */
12
+ id?: string;
13
+ /** Default port number to connect to (defaults to container.defaultPort) */
14
+ defaultPort?: number;
15
+ /** How long to keep the container alive without activity */
16
+ sleepAfter?: string | number;
17
+ /** Environment variables to pass to the container */
18
+ envVars?: Record<string, string>;
19
+ /** Custom entrypoint to override container default */
20
+ entrypoint?: string[];
21
+ /** Whether to enable internet access for the container */
22
+ enableInternet?: boolean;
23
+ }
24
+ /**
25
+ * Options for starting a container with specific configuration
26
+ */
27
+ interface ContainerStartConfigOptions {
28
+ /** Environment variables to pass to the container */
29
+ envVars?: Record<string, string>;
30
+ /** Custom entrypoint to override container default */
31
+ entrypoint?: string[];
32
+ /** Whether to enable internet access for the container */
33
+ enableInternet?: boolean;
34
+ /** Key-value metadata labels attached to the container for metrics/observability */
35
+ labels?: Record<string, string>;
36
+ }
37
+ interface StartAndWaitForPortsOptions {
38
+ startOptions?: ContainerStartConfigOptions;
39
+ ports?: number | number[];
40
+ cancellationOptions?: CancellationOptions;
41
+ }
42
+ /** cancellationOptions for startAndWaitForPorts() */
43
+ interface CancellationOptions {
44
+ /** abort signal, use to abort startAndWaitForPorts manually. */
45
+ abort?: AbortSignal;
46
+ /** max time to get container instance and start it (application inside may not be ready), in milliseconds */
47
+ instanceGetTimeoutMS?: number;
48
+ /** max time to wait for application to be listening at all specified ports, in milliseconds. */
49
+ portReadyTimeoutMS?: number;
50
+ /** time to wait between polling, in milliseconds */
51
+ waitInterval?: number;
52
+ }
53
+ /**
54
+ * Options for waitForPort()
55
+ */
56
+ interface WaitOptions {
57
+ /** The port number to check for readiness */
58
+ portToCheck: number;
59
+ /** Optional AbortSignal, use this to abort waiting for ports */
60
+ signal?: AbortSignal;
61
+ /** Number of attempts to wait for port to be ready */
62
+ retries?: number;
63
+ /** Time to wait in between polling port for readiness, in milliseconds */
64
+ waitInterval?: number;
65
+ }
66
+ /**
67
+ * Represents a scheduled task within a Container
68
+ * @template T Type of the payload data
69
+ */
70
+ type Schedule<T = string> = {
71
+ /** Unique identifier for the schedule */
72
+ taskId: string;
73
+ /** Name of the method to be called */
74
+ callback: string;
75
+ /** Data to be passed to the callback */
76
+ payload: T;
77
+ } & ({
78
+ /** Type of schedule for one-time execution at a specific time */
79
+ type: 'scheduled';
80
+ /** Timestamp when the task should execute */
81
+ time: number;
82
+ } | {
83
+ /** Type of schedule for delayed execution */
84
+ type: 'delayed';
85
+ /** Timestamp when the task should execute */
86
+ time: number;
87
+ /** Number of seconds to delay execution */
88
+ delayInSeconds: number;
89
+ });
90
+ /**
91
+ * Params sent to `onStop` method when the container stops
92
+ */
93
+ type StopParams = {
94
+ exitCode: number;
95
+ reason: 'exit' | 'runtime_signal';
96
+ };
97
+ type State = {
98
+ lastChange: number;
99
+ } & ({
100
+ status: 'running' | 'stopping' | 'stopped' | 'healthy';
101
+ } | {
102
+ status: 'stopped_with_code';
103
+ exitCode?: number;
104
+ });
105
+ type OutboundHandlerContext<Params = unknown> = {
106
+ containerId: string;
107
+ className: string;
108
+ } & ([Params] extends [undefined] ? {
109
+ params?: undefined;
110
+ } : undefined extends Params ? {
111
+ params?: Params;
112
+ } : {
113
+ params: Params;
114
+ });
115
+ type OutboundParamsArg<Params> = [Params] extends [undefined] ? [] : undefined extends Params ? [params?: Params] : [params: Params];
116
+ type OutboundHandler<E = Cloudflare.Env, P = unknown> = {
117
+ bivarianceHack(req: Request, env: E, ctx: OutboundHandlerContext<P>): Promise<Response> | Response;
118
+ }['bivarianceHack'];
119
+ type OutboundHandlerParams = Record<string, unknown>;
120
+ type OutboundHandlerParamsOf<THandler> = THandler extends ((req: Request, env: unknown, ctx: OutboundHandlerContext<infer Params>) => Promise<Response> | Response) ? Params : never;
121
+ declare function outboundParams<THandler extends OutboundHandler<unknown, unknown>>(_handler: THandler, params: OutboundHandlerParamsOf<THandler>): OutboundHandlerParamsOf<THandler>;
122
+ type OutboundHandlers<ParamsByMethod extends OutboundHandlerParams, E = Cloudflare.Env> = { [Method in keyof ParamsByMethod]?: OutboundHandler<E, ParamsByMethod[Method]> };
123
+ type OutboundHandlerOverride<Params = unknown> = {
124
+ method: string;
125
+ } & ([Params] extends [undefined] ? {
126
+ params?: undefined;
127
+ } : undefined extends Params ? {
128
+ params?: Params;
129
+ } : {
130
+ params: Params;
131
+ });
132
+ type OutboundByHostOverrides = Record<string, OutboundHandlerOverride>;
133
+ type OutboundByHostOverrideInput<Params = unknown> = Record<string, string | OutboundHandlerOverride<Params>>;
134
+ type Signal = 'SIGKILL' | 'SIGINT' | 'SIGTERM';
135
+ type SignalInteger = number;
136
+ type ContainerProxyOptions = {
137
+ enableInternet?: boolean;
138
+ containerId: string;
139
+ className: string;
140
+ outboundByHostOverrides?: OutboundByHostOverrides;
141
+ outboundHandlerOverride?: OutboundHandlerOverride;
142
+ allowedHosts?: string[];
143
+ deniedHosts?: string[];
144
+ interceptAll?: boolean;
145
+ };
146
+ declare class ContainerProxy extends WorkerEntrypoint<Cloudflare.Env, ContainerProxyOptions> {
147
+ fetch(request: Request): Promise<Response>;
148
+ }
149
+ declare class Container<Env = Cloudflare.Env> extends DurableObject<Env> {
150
+ static get outboundByHost(): Record<string, OutboundHandler> | undefined;
151
+ static set outboundByHost(handlers: Record<string, OutboundHandler>);
152
+ static get outboundHandlers(): Record<string, OutboundHandler> | undefined;
153
+ static set outboundHandlers(handlers: Record<string, OutboundHandler>);
154
+ static get outbound(): OutboundHandler | undefined;
155
+ static set outbound(handler: OutboundHandler);
156
+ static get outboundProxies(): Record<string, OutboundHandler> | undefined;
157
+ static set outboundProxies(handlers: Record<string, OutboundHandler>);
158
+ static get outboundProxy(): OutboundHandler | undefined;
159
+ static set outboundProxy(handler: OutboundHandler);
160
+ defaultPort?: number;
161
+ requiredPorts?: number[];
162
+ sleepAfter: string | number;
163
+ envVars: ContainerStartOptions['env'];
164
+ entrypoint: ContainerStartOptions['entrypoint'];
165
+ enableInternet: ContainerStartOptions['enableInternet'];
166
+ labels: ContainerStartOptions['labels'];
167
+ interceptHttps: boolean;
168
+ allowedHosts?: string[];
169
+ deniedHosts?: string[];
170
+ pingEndpoint: string;
171
+ applyOutboundInterceptionPromise: Promise<void>;
172
+ usingInterception: boolean;
173
+ constructor(ctx: DurableObject['ctx'], env: Env, options?: ContainerOptions);
174
+ /**
175
+ * Gets the current state of the container
176
+ * @returns Promise<State>
177
+ */
178
+ getState(): Promise<State>;
179
+ /**
180
+ * Set the catch-all outbound handler to a named method from `outboundHandlers`.
181
+ * Overrides the default `outbound` at runtime via ContainerProxy props.
182
+ *
183
+ * @param methodName - Name of a method defined in `static outboundHandlers`
184
+ * @param params - Optional params passed to the handler as `ctx.params`
185
+ * @throws Error if the method name is not found in `outboundHandlers`
186
+ */
187
+ setOutboundHandler<Params = unknown>(methodName: string, ...paramsArg: OutboundParamsArg<Params>): Promise<void>;
188
+ /**
189
+ * Add or override a hostname-specific outbound handler at runtime,
190
+ * referencing a named method from `outboundHandlers`.
191
+ * Overrides any matching entry in `static outboundByHost` for this hostname.
192
+ *
193
+ * @param hostname - The hostname or ip:port to intercept (e.g. `'google.com'`)
194
+ * @param methodName - Name of a method defined in `static outboundHandlers`
195
+ * @param params - Optional params passed to the handler as `ctx.params`
196
+ * @throws Error if the method name is not found in `outboundHandlers`
197
+ */
198
+ setOutboundByHost<Params = unknown>(hostname: string, methodName: string, ...paramsArg: OutboundParamsArg<Params>): Promise<void>;
199
+ /**
200
+ * Remove a runtime hostname override added via `setOutboundByHost`.
201
+ * The default handler from `static outboundByHost` (if any) will be used again.
202
+ *
203
+ * @param hostname - The hostname or ip:port to stop overriding
204
+ */
205
+ removeOutboundByHost(hostname: string): Promise<void>;
206
+ /**
207
+ * Replace all runtime hostname overrides at once.
208
+ * Each value may be either a method name or an object with `method` and `params`.
209
+ *
210
+ * @param handlers - Record mapping hostnames to handler configs in `outboundHandlers`
211
+ * @throws Error if any method name is not found in `outboundHandlers`
212
+ */
213
+ setOutboundByHosts<Params = unknown>(handlers: OutboundByHostOverrideInput<Params>): Promise<void>;
214
+ /**
215
+ * Replace all allowed hosts at runtime.
216
+ * Allowed hosts get internet access even when `enableInternet` is false.
217
+ *
218
+ * @param hosts - Array of hostnames to allow (e.g. `['api.stripe.com', 'example.com']`)
219
+ */
220
+ setAllowedHosts(hosts: string[]): Promise<void>;
221
+ /**
222
+ * Replace all denied hosts at runtime.
223
+ * Denied hosts are blocked unconditionally, even when `enableInternet` is true
224
+ * or a catch-all outbound handler is set.
225
+ *
226
+ * @param hosts - Array of hostnames to deny (e.g. `['evil.com', 'blocked.org']`)
227
+ */
228
+ setDeniedHosts(hosts: string[]): Promise<void>;
229
+ /**
230
+ * Add a single hostname to the allowed hosts list at runtime.
231
+ *
232
+ * @param hostname - The hostname to allow (e.g. `'api.stripe.com'`)
233
+ */
234
+ allowHost(hostname: string): Promise<void>;
235
+ /**
236
+ * Add a single hostname to the denied hosts list at runtime.
237
+ *
238
+ * @param hostname - The hostname to deny (e.g. `'evil.com'`)
239
+ */
240
+ denyHost(hostname: string): Promise<void>;
241
+ /**
242
+ * Remove a hostname from the allowed hosts list.
243
+ *
244
+ * @param hostname - The hostname to remove from the allow list
245
+ */
246
+ removeAllowedHost(hostname: string): Promise<void>;
247
+ /**
248
+ * Remove a hostname from the denied hosts list.
249
+ *
250
+ * @param hostname - The hostname to remove from the deny list
251
+ */
252
+ removeDeniedHost(hostname: string): Promise<void>;
253
+ /**
254
+ * Start the container if it's not running and set up monitoring and lifecycle hooks,
255
+ * without waiting for ports to be ready.
256
+ *
257
+ * It will automatically retry if the container fails to start, using the specified waitOptions
258
+ *
259
+ *
260
+ * @example
261
+ * await this.start({
262
+ * envVars: { DEBUG: 'true', NODE_ENV: 'development' },
263
+ * entrypoint: ['npm', 'run', 'dev'],
264
+ * enableInternet: false,
265
+ * labels: { tenant: 'acme', env: 'prod' },
266
+ * });
267
+ *
268
+ * @param startOptions - Override `envVars`, `entrypoint`, `enableInternet` and `labels` on a per-instance basis
269
+ * @param waitOptions - Optional wait configuration with abort signal for cancellation. Default ~8s timeout.
270
+ * @returns A promise that resolves when the container start command has been issued
271
+ * @throws Error if no container context is available or if all start attempts fail
272
+ */
273
+ start(startOptions?: ContainerStartConfigOptions, waitOptions?: WaitOptions): Promise<void>;
274
+ /**
275
+ * Start the container and wait for ports to be available.
276
+ *
277
+ * For each specified port, it polls until the port is available or `cancellationOptions.portReadyTimeoutMS` is reached.
278
+ *
279
+ * @param ports - The ports to wait for (if undefined, uses requiredPorts or defaultPort)
280
+ * @param cancellationOptions - Options to configure timeouts, polling intereva, and abort signal
281
+ * @param startOptions Override configuration on a per-instance basis for env vars, entrypoint command, internet access, and labels
282
+ * @returns A promise that resolves when the container has been started and the ports are listening
283
+ * @throws Error if port checks fail after the specified timeout or if the container fails to start.
284
+ */
285
+ startAndWaitForPorts(args: StartAndWaitForPortsOptions): Promise<void>;
286
+ startAndWaitForPorts(ports?: number | number[], cancellationOptions?: CancellationOptions, startOptions?: ContainerStartConfigOptions): Promise<void>;
287
+ startAndWaitForPorts(portsOrArgs?: number | number[] | StartAndWaitForPortsOptions, cancellationOptions?: CancellationOptions, startOptions?: ContainerStartConfigOptions): Promise<void>;
288
+ /**
289
+ *
290
+ * Waits for a specified port to be ready
291
+ *
292
+ * Returns the number of tries used to get the port, or throws if it couldn't get the port within the specified retry limits.
293
+ *
294
+ * @param waitOptions -
295
+ * - `portToCheck`: The port number to check
296
+ * - `abort`: Optional AbortSignal to cancel waiting
297
+ * - `retries`: Number of retries before giving up (default: TRIES_TO_GET_PORTS)
298
+ * - `waitInterval`: Interval between retries in milliseconds (default: INSTANCE_POLL_INTERVAL_MS)
299
+ */
300
+ waitForPort(waitOptions: WaitOptions): Promise<number>;
301
+ /**
302
+ * Send a signal to the container.
303
+ * @param signal - The signal to send to the container (default: 15 for SIGTERM)
304
+ */
305
+ stop(signal?: Signal | SignalInteger): Promise<void>;
306
+ /**
307
+ * Destroys the container with a SIGKILL. Triggers onStop.
308
+ */
309
+ destroy(): Promise<void>;
310
+ /**
311
+ * Lifecycle method called when container starts successfully
312
+ * Override this method in subclasses to handle container start events
313
+ */
314
+ onStart(): void | Promise<void>;
315
+ /**
316
+ * Lifecycle method called when container shuts down
317
+ * Override this method in subclasses to handle Container stopped events
318
+ * @param params - Object containing exitCode and reason for the stop
319
+ */
320
+ onStop(params: StopParams): void | Promise<void>;
321
+ /**
322
+ * Lifecycle method called when the container is running, and the activity timeout
323
+ * expiration (set by `sleepAfter`) has been reached.
324
+ *
325
+ * If you want to shutdown the container, you should call this.stop() here
326
+ *
327
+ * By default, this method calls `this.stop()`
328
+ */
329
+ onActivityExpired(): Promise<void>;
330
+ /**
331
+ * Error handler for container errors
332
+ * Override this method in subclasses to handle container errors
333
+ * @param error - The error that occurred
334
+ * @returns Can return any value or throw the error
335
+ */
336
+ onError(error: unknown): unknown;
337
+ /**
338
+ * Renew the container's activity timeout
339
+ *
340
+ * Call this method whenever there is activity on the container
341
+ */
342
+ renewActivityTimeout(): void;
343
+ /**
344
+ * Decrement the inflight request counter.
345
+ * When the counter transitions to 0, renew the activity timeout so the
346
+ * inactivity window starts fresh from the moment the last request completes.
347
+ */
348
+ private decrementInflight;
349
+ /**
350
+ * Schedule a task to be executed in the future.
351
+ *
352
+ * We strongly recommend using this instead of the `alarm` handler.
353
+ *
354
+ * @template T Type of the payload data
355
+ * @param when When to execute the task (Date object or number of seconds delay)
356
+ * @param callback Name of the method to call
357
+ * @param payload Data to pass to the callback
358
+ * @returns Schedule object representing the scheduled task
359
+ */
360
+ schedule<T = string>(when: Date | number, callback: string, payload?: T): Promise<Schedule<T>>;
361
+ /**
362
+ * Send a request to the container (HTTP or WebSocket) using standard fetch API signature
363
+ *
364
+ * This method handles HTTP requests to the container.
365
+ *
366
+ * WebSocket requests done outside the DO won't work until https://github.com/cloudflare/workerd/issues/2319 is addressed.
367
+ * Until then, please use `switchPort` + `fetch()`.
368
+ *
369
+ * Method supports multiple signatures to match standard fetch API:
370
+ * - containerFetch(request: Request, port?: number)
371
+ * - containerFetch(url: string | URL, init?: RequestInit, port?: number)
372
+ *
373
+ * Starts the container if not already running, and waits for the target port to be ready.
374
+ *
375
+ * @returns A Response from the container
376
+ */
377
+ containerFetch(requestOrUrl: Request | string | URL, portOrInit?: number | RequestInit, portParam?: number): Promise<Response>;
378
+ /**
379
+ *
380
+ * Fetch handler on the Container class.
381
+ * By default this forwards all requests to the container by calling `containerFetch`.
382
+ * Use `switchPort` to specify which port on the container to target, or this will use `defaultPort`.
383
+ * @param request The request to handle
384
+ */
385
+ fetch(request: Request): Promise<Response>;
386
+ private container;
387
+ private onStopCalled;
388
+ private state;
389
+ private monitor;
390
+ private startInFlight;
391
+ private monitoredPromise;
392
+ private sleepAfterMs;
393
+ private inflightRequests;
394
+ private outboundByHostOverrides;
395
+ private outboundHandlerOverride?;
396
+ private allowedHostsOverride?;
397
+ private deniedHostsOverride?;
398
+ private hasInterceptAllRegistration;
399
+ /**
400
+ * Validates that a method name exists in the outboundHandlers registry for this class.
401
+ * @throws Error if the method name is not found
402
+ */
403
+ private validateOutboundHandlerMethodName;
404
+ private get effectiveAllowedHosts();
405
+ private get effectiveDeniedHosts();
406
+ private getOutboundConfiguration;
407
+ private persistOutboundConfiguration;
408
+ private restoreOutboundConfiguration;
409
+ /**
410
+ * Returns true if a catch-all outbound HTTP interception is needed.
411
+ * This is the case when a static `outbound` handler or a runtime
412
+ * `outboundHandlerOverride` (catch-all) is configured.
413
+ * When false, we only intercept specific hosts to avoid overhead.
414
+ */
415
+ private needsCatchAllInterception;
416
+ private hasMutableOutboundConfiguration;
417
+ private shouldInterceptAllOutbound;
418
+ private getStaticOutboundByHostKeys;
419
+ /**
420
+ * Collects all hostnames that need per-host outbound interception.
421
+ * This path is only used for the narrow optimized case where outbound
422
+ * handling is static and host-specific.
423
+ */
424
+ private getHostsToIntercept;
425
+ private refreshOutboundInterception;
426
+ /**
427
+ * Applies (or re-applies) outbound HTTP interception with the current
428
+ * default registries + runtime overrides passed through ContainerProxy props.
429
+ *
430
+ * Uses per-host interception only for static host-specific outbound handlers.
431
+ * As soon as the config needs to evaluate all hosts (catch-all outbound,
432
+ * allow/deny lists, or runtime-mutated outbound config), we promote the
433
+ * container to intercept-all and keep it there until the instance restarts.
434
+ *
435
+ * When `interceptHttps` is enabled, also applies HTTPS interception:
436
+ * - Intercept-all mode: `interceptOutboundHttps('*', ...)` for all HTTPS traffic
437
+ * - Per-host mode: `interceptOutboundHttps(host, ...)` for each known host
438
+ */
439
+ private applyOutboundInterception;
440
+ /**
441
+ * Execute SQL queries against the Container's database
442
+ */
443
+ private sql;
444
+ private requestAndPortFromContainerFetchArgs;
445
+ /**
446
+ *
447
+ * The method prioritizes port sources in this order:
448
+ * 1. Ports specified directly in the method call
449
+ * 2. `requiredPorts` class property (if set)
450
+ * 3. `defaultPort` (if neither of the above is specified)
451
+ * 4. Falls back to port 33 if none of the above are set
452
+ */
453
+ private getPortsToCheck;
454
+ /**
455
+ * Tries to start a container if it's not already running
456
+ * Returns the number of tries used
457
+ */
458
+ private startContainerIfNotRunning;
459
+ private doStartContainer;
460
+ private setupMonitorCallbacks;
461
+ deleteSchedules(name: string): void;
462
+ /**
463
+ * Method called when an alarm fires
464
+ * Executes any scheduled tasks that are due
465
+ */
466
+ alarm(alarmProps?: AlarmInvocationInfo): Promise<void>;
467
+ timeout?: ReturnType<typeof setTimeout>;
468
+ resolve?: () => void;
469
+ private syncPendingStoppedEvents;
470
+ private callOnStop;
471
+ /**
472
+ * Schedule the next alarm based on upcoming tasks
473
+ */
474
+ scheduleNextAlarm(ms?: number): Promise<void>;
475
+ listSchedules<T = string>(name: string): Promise<Schedule<T>[]>;
476
+ private toSchedule;
477
+ /**
478
+ * Get a scheduled task by ID
479
+ * @template T Type of the payload data
480
+ * @param id ID of the scheduled task
481
+ * @returns The Schedule object or undefined if not found
482
+ */
483
+ getSchedule<T = string>(id: string): Promise<Schedule<T> | undefined>;
484
+ private isActivityExpired;
485
+ }
486
+ type DurableObjectContext = ConstructorParameters<typeof Container>[0];
487
+ /**
488
+ * Base class for the generated Container DO classes. Applies a
489
+ * `defineContainer` definition onto `@cloudflare/containers`' `Container`:
490
+ * port, sleep timeout, internet access, and the container environment (static
491
+ * `env` merged with the declared Worker secrets — a declared-but-unset secret
492
+ * fails fast here rather than starting a container without its credential).
493
+ *
494
+ * Generated subclasses stay one line of behavior:
495
+ *
496
+ * ```ts
497
+ * export class TranscoderContainer extends LunoraContainer {
498
+ * constructor(ctx: DurableObjectState, env: Env) {
499
+ * super(ctx, env, transcoder, "transcoder");
500
+ * }
501
+ * }
502
+ * ```
503
+ */
504
+ declare class LunoraContainer<Env = unknown> extends Container<Env> {
505
+ /**
506
+ * Data-residency jurisdiction the app's DOs are pinned to (codegen passes the
507
+ * schema's `.jurisdiction("…")`). Used to pin the best-effort lifecycle report
508
+ * to the same region as the root shard. `undefined` ⇒ un-pinned.
509
+ */
510
+ private readonly lunoraJurisdiction?;
511
+ /** The `lunora/containers.ts` export name, for lifecycle log correlation. */
512
+ private readonly lunoraName;
513
+ /** Default port the readiness probes target when a check omits its own `port`. */
514
+ private readonly lunoraDefaultPort?;
515
+ /** Hard-cap lifetime in whole seconds (from the `hardTimeout` config), or `undefined`. */
516
+ private readonly lunoraHardTimeoutSeconds?;
517
+ /** Declarative readiness probes that gate request proxying (from the `readyOn` config). */
518
+ private readonly lunoraReadyOn;
519
+ /** Map of container env-var name → Worker Secrets Store binding name (from the `secretsStore` config). */
520
+ private readonly lunoraSecretsStore?;
521
+ /** Memoised Secrets Store resolution: run once, then merged into `envVars` before the first start. */
522
+ private lunoraSecretsStoreResolved?;
523
+ constructor(context: DurableObjectContext, env: Env, definition: ContainerDefinition, exportName?: string, jurisdiction?: DurableObjectJurisdiction);
524
+ /**
525
+ * Proxy entry for every `ctx.containers.&lt;name>` fetch. Resolves the
526
+ * `secretsStore` bindings into `envVars` before delegating, so the values
527
+ * are present when the base implicitly starts the container for this
528
+ * request — a no-op when `secretsStore` is unset.
529
+ */
530
+ override containerFetch(...args: Parameters<Container<Env>["containerFetch"]>): Promise<Response>;
531
+ /**
532
+ * Explicit start (`ctx.containers.&lt;name>.get(id).start()`). Resolves the
533
+ * `secretsStore` bindings into `envVars` first, mirroring
534
+ * {@link containerFetch}. A per-instance `start({ envVars })` replaces the
535
+ * env set wholesale (base behavior), so the injected values only apply to a
536
+ * bare `start()` — same as the static `env`/`secrets`. When the caller
537
+ * supplies its own `envVars` we skip resolution entirely: those values would
538
+ * be discarded anyway, so a missing/unreadable binding shouldn't fail a start
539
+ * that never uses them.
540
+ */
541
+ override start(...args: Parameters<Container<Env>["start"]>): Promise<void>;
542
+ override onActivityExpired(): Promise<void>;
543
+ override onError(error: unknown): unknown;
544
+ override onStart(): Promise<void>;
545
+ /**
546
+ * Hook run when the container's `hardTimeout` elapses (dispatched by the base
547
+ * scheduler via the run-generation-stamped schedule armed in
548
+ * {@link onStart}). Default: stop the instance. Override to drain/checkpoint
549
+ * first. A stale schedule from a previous run, or an already-stopped
550
+ * instance, is ignored (upstream cloudflare/containers#85).
551
+ */
552
+ onHardTimeoutExpired(payload?: {
553
+ generation?: number;
554
+ }): Promise<void>;
555
+ override onStop(parameters: StopParams): Promise<void>;
556
+ /**
557
+ * Arm the hard-timeout kill via the base scheduler (so it integrates with
558
+ * the container's own alarm machinery instead of fighting it). Bumps the run
559
+ * generation and stamps the schedule with it, so {@link onHardTimeoutExpired}
560
+ * can tell a fresh schedule from a stale one. No-op without a `hardTimeout`.
561
+ */
562
+ private armHardTimeout;
563
+ /**
564
+ * Resolve the `secretsStore` bindings (async `.get()`) once and merge the
565
+ * values into `envVars`, so they're present when the base starts the
566
+ * container. Memoised on the first call — every later start reuses the
567
+ * resolved promise. A missing binding or a non-string value fails fast (the
568
+ * start surfaces the error), the same fail-closed stance the static
569
+ * `secrets` resolution takes for a missing Worker secret. No-op without
570
+ * `secretsStore`.
571
+ */
572
+ private resolveSecretsStoreEnv;
573
+ /**
574
+ * Block until every `readyOn` probe responds with its expected status, or
575
+ * throw once the readiness budget is spent. Probes run in parallel and hit
576
+ * the container's TCP port directly (NOT `containerFetch`, which would
577
+ * recurse back into the start path). No-op without `readyOn`.
578
+ */
579
+ private awaitContainerReadiness;
580
+ /** Poll one readiness probe until it returns its expected status or the shared deadline passes. */
581
+ private awaitReadinessCheck;
582
+ /**
583
+ * Best-effort push of `envelope` into the root ShardDO's log buffer so it
584
+ * also appears in the Studio Logs panel (the terminal already has it via
585
+ * `emitContainerLifecycle`). Fire-and-forget and fully swallowed: a missing
586
+ * `SHARD` binding, a missing admin token, or a fetch failure NEVER throws
587
+ * out of a lifecycle hook — the `console` path stays the source of truth.
588
+ */
589
+ private surfaceInStudioLogs;
590
+ /**
591
+ * Per-instance correlation id: the Durable Object id, which Cloudflare also
592
+ * injects into the container as `CLOUDFLARE_DURABLE_OBJECT_ID`. Read
593
+ * defensively — the id shape varies and isn't worth crashing a hook over.
594
+ */
595
+ private instanceId;
596
+ }
597
+ export { ContainerProxy, LunoraContainer, type OutboundHandler, type OutboundHandlerContext, type OutboundHandlerParams, type OutboundHandlerParamsOf, type OutboundHandlers, outboundParams };