@lunora/container 1.0.0-alpha.63 → 1.0.0-alpha.65

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/index.d.mts CHANGED
@@ -1,5 +1,9 @@
1
- import { D as DurableObjectJurisdiction, a as ContainerConfig, C as ContainerDefinition, b as ContainerImageSource, N as NormalizedContainerImage } from "./packem_shared/jurisdiction.d-DPvNG2h5.mjs";
2
- export type { B as BuildImageSource, c as ContainerInstanceType, d as ContainerReadinessCheck, e as ContainerRollout, f as CustomContainerInstanceType, g as NamedContainerInstanceType, R as RegistryImageSource } from "./packem_shared/jurisdiction.d-DPvNG2h5.mjs";
1
+ import { a as ContainerSpawnOptions, b as ContainerSnapshot, c as ContainerProcess, d as ContainerRuntimeInstanceType, e as ContainerSpawnRequest, S as SpawnResult, D as DurableObjectJurisdiction, f as DefaultScheduledContainerConfig, g as DurableObjectScheduledContainerConfig, C as ContainerDefinition, h as ContainerImageSource, N as NormalizedContainerImage } from "./packem_shared/jurisdiction.d-t4mtuqYW.mjs";
2
+ export type { B as BuildImageSource, i as ContainerBackupStorage, j as ContainerConfig, k as ContainerConfigBase, l as ContainerInstanceType, m as ContainerNamedImageSource, n as ContainerReadinessCheck, o as ContainerRollout, p as CustomContainerInstanceType, q as NamedContainerInstanceType, R as RegistryImageSource } from "./packem_shared/jurisdiction.d-t4mtuqYW.mjs";
3
+ import { b as ContainerBackupOptions, C as ContainerFileOptions, c as ContainerMountRequest, a as ContainerFileContent, d as ContainerSandboxControls } from "./packem_shared/sandbox-types.d-DXlHnsEg.mjs";
4
+ export type { e as ContainerFiles, f as ContainerMountCredentials } from "./packem_shared/sandbox-types.d-DXlHnsEg.mjs";
5
+ import { DirectoryBackupRecord, S3MountInspection, SandboxDirectoryEntry, SandboxFileStat } from '@cloudflare/sandbox';
6
+ export type { DirectoryBackupRecord, S3MountInspection, SandboxDirectoryEntry, SandboxFileStat } from '@cloudflare/sandbox';
3
7
  /**
4
8
  * Per-call options for `ContainerHandle.exec`.
5
9
  */
@@ -67,6 +71,15 @@ interface ContainerExecResult {
67
71
  * un-gates model-chosen command execution.
68
72
  */
69
73
  declare const CONTAINER_EXEC_PATH = "/__lunora/exec";
74
+ /** Options for `handle.terminal()`. */
75
+ interface ContainerTerminalOptions extends Omit<ContainerSpawnOptions, "pty" | "signal" | "stdin"> {
76
+ /** Initial size. Defaults to the request's `?cols=&rows=` search params, else `80×24`. */
77
+ cols?: number;
78
+ /** The program to run. Defaults to `"sh"`. */
79
+ command?: string;
80
+ /** Initial size. Defaults to the request's `?cols=&rows=` search params, else `80×24`. */
81
+ rows?: number;
82
+ }
70
83
  /**
71
84
  * Options for explicitly starting an instance (mirrors `@cloudflare/containers`).
72
85
  */
@@ -89,8 +102,26 @@ interface ContainerStartOptions {
89
102
  * for as long as the instance exists.
90
103
  */
91
104
  envVars?: Record<string, string>;
105
+ /**
106
+ * The image to start (`schedulingPolicy: "durable_object"` only): a key of
107
+ * the definition's `images`, or a Cloudflare-managed `"cloudflare/…"` image.
108
+ * Persisted like `envVars`, so the implicit restart after a sleep boots the
109
+ * same image. Mutually exclusive with `snapshot`.
110
+ */
111
+ image?: string;
112
+ /**
113
+ * The instance size (`schedulingPolicy: "durable_object"` only). Persisted
114
+ * with `image`; defaults to the definition's `instanceType`, else `"lite"`.
115
+ */
116
+ instanceType?: ContainerRuntimeInstanceType;
92
117
  /** Metadata labels attached for metrics/observability. */
93
118
  labels?: Record<string, string>;
119
+ /**
120
+ * Restore a filesystem saved by `snapshot()` instead of starting from an
121
+ * image (`schedulingPolicy: "durable_object"` only). Applies to this start
122
+ * only — a later restart after a sleep boots the image again.
123
+ */
124
+ snapshot?: ContainerSnapshot;
94
125
  }
95
126
  /**
96
127
  * A container instance's runtime state, as returned by `getState()`. Structural — the platform adds fields over time.
@@ -111,8 +142,34 @@ interface ContainerStubLike {
111
142
  destroy?: () => Promise<void>;
112
143
  fetch: (input: Request) => Promise<Response>;
113
144
  getState?: () => Promise<ContainerInstanceState>;
145
+ lunoraBackup?: (directory: string, options?: ContainerBackupOptions) => Promise<DirectoryBackupRecord>;
146
+ lunoraDeleteBackup?: (backup: DirectoryBackupRecord) => Promise<void>;
114
147
  /** The container DO's exec entry (`LunoraContainer.lunoraExec`), the only way a request reaches `/__lunora/exec`. */
115
148
  lunoraExec?: (request: Request) => Promise<Response>;
149
+ lunoraInspectMount?: (path: string) => Promise<S3MountInspection>;
150
+ lunoraMkdir?: (path: string, options?: ContainerFileOptions & {
151
+ recursive?: boolean;
152
+ }) => Promise<void>;
153
+ lunoraMount?: (request: ContainerMountRequest) => Promise<void>;
154
+ lunoraReadDirectory?: (path: string, options?: ContainerFileOptions) => Promise<SandboxDirectoryEntry[]>;
155
+ lunoraReadFile?: (path: string, options?: ContainerFileOptions) => Promise<Response>;
156
+ lunoraRemove?: (path: string, options?: ContainerFileOptions & {
157
+ force?: boolean;
158
+ recursive?: boolean;
159
+ }) => Promise<void>;
160
+ lunoraRename?: (source: string, destination: string, options?: ContainerFileOptions) => Promise<void>;
161
+ lunoraRestore?: (backup: DirectoryBackupRecord, options?: {
162
+ directory?: string;
163
+ }) => Promise<void>;
164
+ /** The container DO's snapshot entry (`LunoraContainer.lunoraSnapshot`). */
165
+ lunoraSnapshot?: (options?: {
166
+ name?: string;
167
+ }) => Promise<ContainerSnapshot>;
168
+ /** The container DO's streaming-exec entry (`LunoraContainer.lunoraSpawn`). */
169
+ lunoraSpawn?: (request: ContainerSpawnRequest) => Promise<SpawnResult>;
170
+ lunoraStat?: (path: string, options?: ContainerFileOptions) => Promise<SandboxFileStat>;
171
+ lunoraUnmount?: (path: string) => Promise<void>;
172
+ lunoraWriteFile?: (path: string, content: ContainerFileContent, options?: ContainerFileOptions) => Promise<void>;
116
173
  removeAllowedHost?: (hostname: string) => Promise<void>;
117
174
  removeDeniedHost?: (hostname: string) => Promise<void>;
118
175
  renewActivityTimeout?: () => Promise<void>;
@@ -199,11 +256,43 @@ interface ContainerInstanceHandle extends ContainerHandle {
199
256
  * nor a WS message — e.g. a long out-of-band job running inside it.
200
257
  */
201
258
  renewActivityTimeout: () => Promise<void>;
259
+ /**
260
+ * Save the running container's filesystem and return a handle to restore it
261
+ * with `start({ snapshot })` — here or in another instance of the same
262
+ * container (`schedulingPolicy: "durable_object"` only; Cloudflare beta).
263
+ * Memory and processes are not captured.
264
+ */
265
+ snapshot: (options?: {
266
+ name?: string;
267
+ }) => Promise<ContainerSnapshot>;
268
+ /**
269
+ * Start a process and stream it, rather than buffer it the way `exec`
270
+ * does: its stdout/stderr arrive as streams, `stdin` can be piped, and the
271
+ * process can be killed or (under `pty`) resized while it runs. Needs the
272
+ * runtime's native exec; the container is started first when it is not
273
+ * running, and kept awake until the process exits.
274
+ */
275
+ spawn: (command: string, options?: ContainerSpawnOptions) => Promise<ContainerProcess>;
202
276
  /** Explicitly start the instance, optionally with per-instance env/entrypoint. */
203
277
  start: (options?: ContainerStartOptions) => Promise<void>;
204
278
  /** Stop the instance (optionally with a signal); it can start again on the next request. */
205
279
  stop: (signal?: number | string) => Promise<void>;
280
+ /**
281
+ * Answer a WebSocket upgrade `request` with a browser terminal: a shell
282
+ * (default `sh`) on a PTY, bridged to the socket. Binary frames are
283
+ * keystrokes, a text frame `{"cols":n,"rows":n}` resizes, and the socket
284
+ * closes when the shell exits. Authenticate the request first — whoever
285
+ * holds the socket has a shell in the container. Call it from a Worker
286
+ * route (see {@link getContainer}) and return the response as-is.
287
+ */
288
+ terminal: (request: Request, options?: ContainerTerminalOptions) => Promise<Response>;
206
289
  }
290
+ /**
291
+ * A named instance of a `defineContainer({ sandbox: true })` container: the
292
+ * {@link ContainerInstanceHandle} plus the Sandbox SDK helpers — structured
293
+ * file operations, directory backups to R2 and S3-compatible bucket mounts.
294
+ */
295
+ interface SandboxContainerInstanceHandle extends ContainerInstanceHandle, ContainerSandboxControls {}
207
296
  /**
208
297
  * Runtime egress-firewall controls for a named instance (`handle.egress.*`).
209
298
  * Each maps to the corresponding `@cloudflare/containers` `Container` RPC, so
@@ -266,6 +355,10 @@ interface ContainerAccessor {
266
355
  */
267
356
  pool: (options?: PoolOptions) => ContainerHandle;
268
357
  }
358
+ /** `ctx.containers.<name>` for a `defineContainer({ sandbox: true })` container: `.get()` adds the sandbox helpers. */
359
+ interface SandboxContainerAccessor extends ContainerAccessor {
360
+ get: (name: string, options?: InstanceRetryOptions) => SandboxContainerInstanceHandle;
361
+ }
269
362
  /**
270
363
  * Tuning for a pooled, retrying container handle. See {@link ContainerAccessor.pool}.
271
364
  */
@@ -340,6 +433,22 @@ interface ContainerBindingSpec {
340
433
  * header and leaves the container on its own configuration.
341
434
  */
342
435
  declare const createContainerContext: (env: Record<string, unknown>, specs: ReadonlyArray<ContainerBindingSpec>, jurisdiction?: DurableObjectJurisdiction, traceparent?: string, sampleErrors?: boolean) => Record<string, ContainerAccessor>;
436
+ /**
437
+ * A named container instance straight off the Worker `env`, for code that has
438
+ * no `ctx.containers` — typically an `httpRouter` route that opens a
439
+ * {@link ContainerInstanceHandle.terminal} or proxies a preview port, both of
440
+ * which must hand a WebSocket upgrade response back to the browser. The
441
+ * binding is derived from `exportName` exactly as codegen derives it. Pass
442
+ * {@link SandboxContainerInstanceHandle} as the type argument for a
443
+ * `sandbox: true` container.
444
+ *
445
+ * ```ts
446
+ * app.get("/terminal", async (c) => getContainer(c.env, "box", userId).terminal(c.req.raw));
447
+ * ```
448
+ */
449
+ declare const getContainer: <Handle extends ContainerInstanceHandle = ContainerInstanceHandle>(env: Record<string, unknown>, exportName: string, name: string, options?: InstanceRetryOptions & {
450
+ jurisdiction?: DurableObjectJurisdiction;
451
+ }) => Handle;
343
452
  /**
344
453
  * A test handler: receives the request plus the targeted instance name.
345
454
  */
@@ -358,6 +467,14 @@ type ContainerTestHandler = (request: Request, instance: {
358
467
  * ```
359
468
  */
360
469
  declare const createContainerTestContext: (handlers: Record<string, ContainerTestHandler>) => Record<string, ContainerAccessor>;
470
+ /** Whether an image name is a Cloudflare-managed image (`cloudflare/debian-trixie`), which needs no `images` entry. */
471
+ declare const isManagedImage: (name: string) => boolean;
472
+ /**
473
+ * The default-policy keys the `durable_object` policy refuses — wrangler rejects
474
+ * `max_instances` under it, and a rollout has nothing to roll. One table, read by
475
+ * `defineContainer` and by codegen's static discovery.
476
+ */
477
+ declare const DURABLE_OBJECT_POLICY_FORBIDDEN_KEYS: readonly ["maxInstances", "rollout"];
361
478
  /**
362
479
  * Normalize a `ContainerImageSource` into the shape wrangler wants: a
363
480
  * Dockerfile path + build context for local builds, or a fully-qualified
@@ -391,10 +508,19 @@ declare const containerBindingName: (exportName: string) => string;
391
508
  * three derive the tag from this one helper and can never disagree.
392
509
  */
393
510
  declare const containerBuildTag: (exportName: string) => string;
511
+ /** Whether a registry reference is digest-pinned in the Cloudflare registry — the only kind a named image accepts. */
512
+ declare const isCloudflareRegistryDigest: (reference: unknown) => boolean;
394
513
  /**
395
514
  * `defineContainer` is part of the experimental `@lunora/container` API and may change without a major version bump.
396
515
  */
397
- declare const defineContainer: (config: ContainerConfig) => ContainerDefinition;
516
+ declare const defineContainer: {
517
+ (config: DefaultScheduledContainerConfig): DefaultScheduledContainerConfig & {
518
+ readonly isLunoraContainer: true;
519
+ };
520
+ (config: DurableObjectScheduledContainerConfig): DurableObjectScheduledContainerConfig & {
521
+ readonly isLunoraContainer: true;
522
+ };
523
+ };
398
524
  /**
399
525
  * True when a value is a `defineContainer` result (the runtime brand check).
400
526
  */
@@ -417,7 +543,7 @@ export { CONTAINER_EXEC_PATH,
417
543
  * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
418
544
  * behind the `@lunora/container/do` subpath.
419
545
  */
420
- type ContainerAccessor,
546
+ type ContainerAccessor, type ContainerBackupOptions,
421
547
  /**
422
548
  * `@lunora/container` — Cloudflare Containers for Lunora.
423
549
  *
@@ -428,7 +554,7 @@ type ContainerAccessor,
428
554
  * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
429
555
  * behind the `@lunora/container/do` subpath.
430
556
  */
431
- type ContainerBindingSpec, type ContainerConfig, type ContainerDefinition,
557
+ type ContainerBindingSpec, type ContainerDefinition,
432
558
  /**
433
559
  * `@lunora/container` — Cloudflare Containers for Lunora.
434
560
  *
@@ -439,7 +565,7 @@ type ContainerBindingSpec, type ContainerConfig, type ContainerDefinition,
439
565
  * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
440
566
  * behind the `@lunora/container/do` subpath.
441
567
  */
442
- type ContainerEgressControls, type ContainerExecOptions, type ContainerExecResult,
568
+ type ContainerEgressControls, type ContainerExecOptions, type ContainerExecResult, type ContainerFileContent, type ContainerFileOptions,
443
569
  /**
444
570
  * `@lunora/container` — Cloudflare Containers for Lunora.
445
571
  *
@@ -472,7 +598,7 @@ type ContainerInstanceHandle,
472
598
  * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
473
599
  * behind the `@lunora/container/do` subpath.
474
600
  */
475
- type ContainerInstanceState,
601
+ type ContainerInstanceState, type ContainerMountRequest,
476
602
  /**
477
603
  * `@lunora/container` — Cloudflare Containers for Lunora.
478
604
  *
@@ -483,7 +609,7 @@ type ContainerInstanceState,
483
609
  * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
484
610
  * behind the `@lunora/container/do` subpath.
485
611
  */
486
- type ContainerNamespaceLike,
612
+ type ContainerNamespaceLike, type ContainerProcess, type ContainerRuntimeInstanceType, type ContainerSandboxControls, type ContainerSnapshot, type ContainerSpawnOptions,
487
613
  /**
488
614
  * `@lunora/container` — Cloudflare Containers for Lunora.
489
615
  *
@@ -494,7 +620,7 @@ type ContainerNamespaceLike,
494
620
  * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
495
621
  * behind the `@lunora/container/do` subpath.
496
622
  */
497
- type ContainerStartOptions,
623
+ type ContainerStartOptions, type ContainerTerminalOptions,
498
624
  /**
499
625
  * `@lunora/container` — Cloudflare Containers for Lunora.
500
626
  *
@@ -505,7 +631,7 @@ type ContainerStartOptions,
505
631
  * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
506
632
  * behind the `@lunora/container/do` subpath.
507
633
  */
508
- type ContainerTestHandler,
634
+ type ContainerTestHandler, DURABLE_OBJECT_POLICY_FORBIDDEN_KEYS, type DefaultScheduledContainerConfig,
509
635
  /**
510
636
  * `@lunora/container` — Cloudflare Containers for Lunora.
511
637
  *
@@ -516,7 +642,7 @@ type ContainerTestHandler,
516
642
  * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
517
643
  * behind the `@lunora/container/do` subpath.
518
644
  */
519
- type DurableObjectJurisdiction,
645
+ type DurableObjectJurisdiction, type DurableObjectScheduledContainerConfig,
520
646
  /**
521
647
  * `@lunora/container` — Cloudflare Containers for Lunora.
522
648
  *
@@ -538,4 +664,26 @@ type InstanceRetryOptions, type NormalizedContainerImage,
538
664
  * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
539
665
  * behind the `@lunora/container/do` subpath.
540
666
  */
541
- type PoolOptions, containerBindingName, containerBuildTag, containerClassName, createContainerContext, createContainerTestContext, defineContainer, isContainerDefinition, normalizeContainerImage, resolveContainerEnvVariables as resolveContainerEnvVars };
667
+ type PoolOptions,
668
+ /**
669
+ * `@lunora/container` — Cloudflare Containers for Lunora.
670
+ *
671
+ * This root export is Node-safe (no Cloudflare runtime imports): the
672
+ * `defineContainer` authoring surface, the naming/normalization helpers
673
+ * codegen and `@lunora/config` share, the `ctx.containers` client wiring, and
674
+ * a Docker-free test double. The workerd-only `LunoraContainer` base class
675
+ * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
676
+ * behind the `@lunora/container/do` subpath.
677
+ */
678
+ type SandboxContainerAccessor,
679
+ /**
680
+ * `@lunora/container` — Cloudflare Containers for Lunora.
681
+ *
682
+ * This root export is Node-safe (no Cloudflare runtime imports): the
683
+ * `defineContainer` authoring surface, the naming/normalization helpers
684
+ * codegen and `@lunora/config` share, the `ctx.containers` client wiring, and
685
+ * a Docker-free test double. The workerd-only `LunoraContainer` base class
686
+ * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
687
+ * behind the `@lunora/container/do` subpath.
688
+ */
689
+ type SandboxContainerInstanceHandle, containerBindingName, containerBuildTag, containerClassName, createContainerContext, createContainerTestContext, defineContainer, getContainer, isCloudflareRegistryDigest, isContainerDefinition, isManagedImage, normalizeContainerImage, resolveContainerEnvVariables as resolveContainerEnvVars };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,9 @@
1
- import { D as DurableObjectJurisdiction, a as ContainerConfig, C as ContainerDefinition, b as ContainerImageSource, N as NormalizedContainerImage } from "./packem_shared/jurisdiction.d-DPvNG2h5.js";
2
- export type { B as BuildImageSource, c as ContainerInstanceType, d as ContainerReadinessCheck, e as ContainerRollout, f as CustomContainerInstanceType, g as NamedContainerInstanceType, R as RegistryImageSource } from "./packem_shared/jurisdiction.d-DPvNG2h5.js";
1
+ import { a as ContainerSpawnOptions, b as ContainerSnapshot, c as ContainerProcess, d as ContainerRuntimeInstanceType, e as ContainerSpawnRequest, S as SpawnResult, D as DurableObjectJurisdiction, f as DefaultScheduledContainerConfig, g as DurableObjectScheduledContainerConfig, C as ContainerDefinition, h as ContainerImageSource, N as NormalizedContainerImage } from "./packem_shared/jurisdiction.d-t4mtuqYW.js";
2
+ export type { B as BuildImageSource, i as ContainerBackupStorage, j as ContainerConfig, k as ContainerConfigBase, l as ContainerInstanceType, m as ContainerNamedImageSource, n as ContainerReadinessCheck, o as ContainerRollout, p as CustomContainerInstanceType, q as NamedContainerInstanceType, R as RegistryImageSource } from "./packem_shared/jurisdiction.d-t4mtuqYW.js";
3
+ import { b as ContainerBackupOptions, C as ContainerFileOptions, c as ContainerMountRequest, a as ContainerFileContent, d as ContainerSandboxControls } from "./packem_shared/sandbox-types.d-DXlHnsEg.js";
4
+ export type { e as ContainerFiles, f as ContainerMountCredentials } from "./packem_shared/sandbox-types.d-DXlHnsEg.js";
5
+ import { DirectoryBackupRecord, S3MountInspection, SandboxDirectoryEntry, SandboxFileStat } from '@cloudflare/sandbox';
6
+ export type { DirectoryBackupRecord, S3MountInspection, SandboxDirectoryEntry, SandboxFileStat } from '@cloudflare/sandbox';
3
7
  /**
4
8
  * Per-call options for `ContainerHandle.exec`.
5
9
  */
@@ -67,6 +71,15 @@ interface ContainerExecResult {
67
71
  * un-gates model-chosen command execution.
68
72
  */
69
73
  declare const CONTAINER_EXEC_PATH = "/__lunora/exec";
74
+ /** Options for `handle.terminal()`. */
75
+ interface ContainerTerminalOptions extends Omit<ContainerSpawnOptions, "pty" | "signal" | "stdin"> {
76
+ /** Initial size. Defaults to the request's `?cols=&rows=` search params, else `80×24`. */
77
+ cols?: number;
78
+ /** The program to run. Defaults to `"sh"`. */
79
+ command?: string;
80
+ /** Initial size. Defaults to the request's `?cols=&rows=` search params, else `80×24`. */
81
+ rows?: number;
82
+ }
70
83
  /**
71
84
  * Options for explicitly starting an instance (mirrors `@cloudflare/containers`).
72
85
  */
@@ -89,8 +102,26 @@ interface ContainerStartOptions {
89
102
  * for as long as the instance exists.
90
103
  */
91
104
  envVars?: Record<string, string>;
105
+ /**
106
+ * The image to start (`schedulingPolicy: "durable_object"` only): a key of
107
+ * the definition's `images`, or a Cloudflare-managed `"cloudflare/…"` image.
108
+ * Persisted like `envVars`, so the implicit restart after a sleep boots the
109
+ * same image. Mutually exclusive with `snapshot`.
110
+ */
111
+ image?: string;
112
+ /**
113
+ * The instance size (`schedulingPolicy: "durable_object"` only). Persisted
114
+ * with `image`; defaults to the definition's `instanceType`, else `"lite"`.
115
+ */
116
+ instanceType?: ContainerRuntimeInstanceType;
92
117
  /** Metadata labels attached for metrics/observability. */
93
118
  labels?: Record<string, string>;
119
+ /**
120
+ * Restore a filesystem saved by `snapshot()` instead of starting from an
121
+ * image (`schedulingPolicy: "durable_object"` only). Applies to this start
122
+ * only — a later restart after a sleep boots the image again.
123
+ */
124
+ snapshot?: ContainerSnapshot;
94
125
  }
95
126
  /**
96
127
  * A container instance's runtime state, as returned by `getState()`. Structural — the platform adds fields over time.
@@ -111,8 +142,34 @@ interface ContainerStubLike {
111
142
  destroy?: () => Promise<void>;
112
143
  fetch: (input: Request) => Promise<Response>;
113
144
  getState?: () => Promise<ContainerInstanceState>;
145
+ lunoraBackup?: (directory: string, options?: ContainerBackupOptions) => Promise<DirectoryBackupRecord>;
146
+ lunoraDeleteBackup?: (backup: DirectoryBackupRecord) => Promise<void>;
114
147
  /** The container DO's exec entry (`LunoraContainer.lunoraExec`), the only way a request reaches `/__lunora/exec`. */
115
148
  lunoraExec?: (request: Request) => Promise<Response>;
149
+ lunoraInspectMount?: (path: string) => Promise<S3MountInspection>;
150
+ lunoraMkdir?: (path: string, options?: ContainerFileOptions & {
151
+ recursive?: boolean;
152
+ }) => Promise<void>;
153
+ lunoraMount?: (request: ContainerMountRequest) => Promise<void>;
154
+ lunoraReadDirectory?: (path: string, options?: ContainerFileOptions) => Promise<SandboxDirectoryEntry[]>;
155
+ lunoraReadFile?: (path: string, options?: ContainerFileOptions) => Promise<Response>;
156
+ lunoraRemove?: (path: string, options?: ContainerFileOptions & {
157
+ force?: boolean;
158
+ recursive?: boolean;
159
+ }) => Promise<void>;
160
+ lunoraRename?: (source: string, destination: string, options?: ContainerFileOptions) => Promise<void>;
161
+ lunoraRestore?: (backup: DirectoryBackupRecord, options?: {
162
+ directory?: string;
163
+ }) => Promise<void>;
164
+ /** The container DO's snapshot entry (`LunoraContainer.lunoraSnapshot`). */
165
+ lunoraSnapshot?: (options?: {
166
+ name?: string;
167
+ }) => Promise<ContainerSnapshot>;
168
+ /** The container DO's streaming-exec entry (`LunoraContainer.lunoraSpawn`). */
169
+ lunoraSpawn?: (request: ContainerSpawnRequest) => Promise<SpawnResult>;
170
+ lunoraStat?: (path: string, options?: ContainerFileOptions) => Promise<SandboxFileStat>;
171
+ lunoraUnmount?: (path: string) => Promise<void>;
172
+ lunoraWriteFile?: (path: string, content: ContainerFileContent, options?: ContainerFileOptions) => Promise<void>;
116
173
  removeAllowedHost?: (hostname: string) => Promise<void>;
117
174
  removeDeniedHost?: (hostname: string) => Promise<void>;
118
175
  renewActivityTimeout?: () => Promise<void>;
@@ -199,11 +256,43 @@ interface ContainerInstanceHandle extends ContainerHandle {
199
256
  * nor a WS message — e.g. a long out-of-band job running inside it.
200
257
  */
201
258
  renewActivityTimeout: () => Promise<void>;
259
+ /**
260
+ * Save the running container's filesystem and return a handle to restore it
261
+ * with `start({ snapshot })` — here or in another instance of the same
262
+ * container (`schedulingPolicy: "durable_object"` only; Cloudflare beta).
263
+ * Memory and processes are not captured.
264
+ */
265
+ snapshot: (options?: {
266
+ name?: string;
267
+ }) => Promise<ContainerSnapshot>;
268
+ /**
269
+ * Start a process and stream it, rather than buffer it the way `exec`
270
+ * does: its stdout/stderr arrive as streams, `stdin` can be piped, and the
271
+ * process can be killed or (under `pty`) resized while it runs. Needs the
272
+ * runtime's native exec; the container is started first when it is not
273
+ * running, and kept awake until the process exits.
274
+ */
275
+ spawn: (command: string, options?: ContainerSpawnOptions) => Promise<ContainerProcess>;
202
276
  /** Explicitly start the instance, optionally with per-instance env/entrypoint. */
203
277
  start: (options?: ContainerStartOptions) => Promise<void>;
204
278
  /** Stop the instance (optionally with a signal); it can start again on the next request. */
205
279
  stop: (signal?: number | string) => Promise<void>;
280
+ /**
281
+ * Answer a WebSocket upgrade `request` with a browser terminal: a shell
282
+ * (default `sh`) on a PTY, bridged to the socket. Binary frames are
283
+ * keystrokes, a text frame `{"cols":n,"rows":n}` resizes, and the socket
284
+ * closes when the shell exits. Authenticate the request first — whoever
285
+ * holds the socket has a shell in the container. Call it from a Worker
286
+ * route (see {@link getContainer}) and return the response as-is.
287
+ */
288
+ terminal: (request: Request, options?: ContainerTerminalOptions) => Promise<Response>;
206
289
  }
290
+ /**
291
+ * A named instance of a `defineContainer({ sandbox: true })` container: the
292
+ * {@link ContainerInstanceHandle} plus the Sandbox SDK helpers — structured
293
+ * file operations, directory backups to R2 and S3-compatible bucket mounts.
294
+ */
295
+ interface SandboxContainerInstanceHandle extends ContainerInstanceHandle, ContainerSandboxControls {}
207
296
  /**
208
297
  * Runtime egress-firewall controls for a named instance (`handle.egress.*`).
209
298
  * Each maps to the corresponding `@cloudflare/containers` `Container` RPC, so
@@ -266,6 +355,10 @@ interface ContainerAccessor {
266
355
  */
267
356
  pool: (options?: PoolOptions) => ContainerHandle;
268
357
  }
358
+ /** `ctx.containers.<name>` for a `defineContainer({ sandbox: true })` container: `.get()` adds the sandbox helpers. */
359
+ interface SandboxContainerAccessor extends ContainerAccessor {
360
+ get: (name: string, options?: InstanceRetryOptions) => SandboxContainerInstanceHandle;
361
+ }
269
362
  /**
270
363
  * Tuning for a pooled, retrying container handle. See {@link ContainerAccessor.pool}.
271
364
  */
@@ -340,6 +433,22 @@ interface ContainerBindingSpec {
340
433
  * header and leaves the container on its own configuration.
341
434
  */
342
435
  declare const createContainerContext: (env: Record<string, unknown>, specs: ReadonlyArray<ContainerBindingSpec>, jurisdiction?: DurableObjectJurisdiction, traceparent?: string, sampleErrors?: boolean) => Record<string, ContainerAccessor>;
436
+ /**
437
+ * A named container instance straight off the Worker `env`, for code that has
438
+ * no `ctx.containers` — typically an `httpRouter` route that opens a
439
+ * {@link ContainerInstanceHandle.terminal} or proxies a preview port, both of
440
+ * which must hand a WebSocket upgrade response back to the browser. The
441
+ * binding is derived from `exportName` exactly as codegen derives it. Pass
442
+ * {@link SandboxContainerInstanceHandle} as the type argument for a
443
+ * `sandbox: true` container.
444
+ *
445
+ * ```ts
446
+ * app.get("/terminal", async (c) => getContainer(c.env, "box", userId).terminal(c.req.raw));
447
+ * ```
448
+ */
449
+ declare const getContainer: <Handle extends ContainerInstanceHandle = ContainerInstanceHandle>(env: Record<string, unknown>, exportName: string, name: string, options?: InstanceRetryOptions & {
450
+ jurisdiction?: DurableObjectJurisdiction;
451
+ }) => Handle;
343
452
  /**
344
453
  * A test handler: receives the request plus the targeted instance name.
345
454
  */
@@ -358,6 +467,14 @@ type ContainerTestHandler = (request: Request, instance: {
358
467
  * ```
359
468
  */
360
469
  declare const createContainerTestContext: (handlers: Record<string, ContainerTestHandler>) => Record<string, ContainerAccessor>;
470
+ /** Whether an image name is a Cloudflare-managed image (`cloudflare/debian-trixie`), which needs no `images` entry. */
471
+ declare const isManagedImage: (name: string) => boolean;
472
+ /**
473
+ * The default-policy keys the `durable_object` policy refuses — wrangler rejects
474
+ * `max_instances` under it, and a rollout has nothing to roll. One table, read by
475
+ * `defineContainer` and by codegen's static discovery.
476
+ */
477
+ declare const DURABLE_OBJECT_POLICY_FORBIDDEN_KEYS: readonly ["maxInstances", "rollout"];
361
478
  /**
362
479
  * Normalize a `ContainerImageSource` into the shape wrangler wants: a
363
480
  * Dockerfile path + build context for local builds, or a fully-qualified
@@ -391,10 +508,19 @@ declare const containerBindingName: (exportName: string) => string;
391
508
  * three derive the tag from this one helper and can never disagree.
392
509
  */
393
510
  declare const containerBuildTag: (exportName: string) => string;
511
+ /** Whether a registry reference is digest-pinned in the Cloudflare registry — the only kind a named image accepts. */
512
+ declare const isCloudflareRegistryDigest: (reference: unknown) => boolean;
394
513
  /**
395
514
  * `defineContainer` is part of the experimental `@lunora/container` API and may change without a major version bump.
396
515
  */
397
- declare const defineContainer: (config: ContainerConfig) => ContainerDefinition;
516
+ declare const defineContainer: {
517
+ (config: DefaultScheduledContainerConfig): DefaultScheduledContainerConfig & {
518
+ readonly isLunoraContainer: true;
519
+ };
520
+ (config: DurableObjectScheduledContainerConfig): DurableObjectScheduledContainerConfig & {
521
+ readonly isLunoraContainer: true;
522
+ };
523
+ };
398
524
  /**
399
525
  * True when a value is a `defineContainer` result (the runtime brand check).
400
526
  */
@@ -417,7 +543,7 @@ export { CONTAINER_EXEC_PATH,
417
543
  * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
418
544
  * behind the `@lunora/container/do` subpath.
419
545
  */
420
- type ContainerAccessor,
546
+ type ContainerAccessor, type ContainerBackupOptions,
421
547
  /**
422
548
  * `@lunora/container` — Cloudflare Containers for Lunora.
423
549
  *
@@ -428,7 +554,7 @@ type ContainerAccessor,
428
554
  * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
429
555
  * behind the `@lunora/container/do` subpath.
430
556
  */
431
- type ContainerBindingSpec, type ContainerConfig, type ContainerDefinition,
557
+ type ContainerBindingSpec, type ContainerDefinition,
432
558
  /**
433
559
  * `@lunora/container` — Cloudflare Containers for Lunora.
434
560
  *
@@ -439,7 +565,7 @@ type ContainerBindingSpec, type ContainerConfig, type ContainerDefinition,
439
565
  * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
440
566
  * behind the `@lunora/container/do` subpath.
441
567
  */
442
- type ContainerEgressControls, type ContainerExecOptions, type ContainerExecResult,
568
+ type ContainerEgressControls, type ContainerExecOptions, type ContainerExecResult, type ContainerFileContent, type ContainerFileOptions,
443
569
  /**
444
570
  * `@lunora/container` — Cloudflare Containers for Lunora.
445
571
  *
@@ -472,7 +598,7 @@ type ContainerInstanceHandle,
472
598
  * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
473
599
  * behind the `@lunora/container/do` subpath.
474
600
  */
475
- type ContainerInstanceState,
601
+ type ContainerInstanceState, type ContainerMountRequest,
476
602
  /**
477
603
  * `@lunora/container` — Cloudflare Containers for Lunora.
478
604
  *
@@ -483,7 +609,7 @@ type ContainerInstanceState,
483
609
  * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
484
610
  * behind the `@lunora/container/do` subpath.
485
611
  */
486
- type ContainerNamespaceLike,
612
+ type ContainerNamespaceLike, type ContainerProcess, type ContainerRuntimeInstanceType, type ContainerSandboxControls, type ContainerSnapshot, type ContainerSpawnOptions,
487
613
  /**
488
614
  * `@lunora/container` — Cloudflare Containers for Lunora.
489
615
  *
@@ -494,7 +620,7 @@ type ContainerNamespaceLike,
494
620
  * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
495
621
  * behind the `@lunora/container/do` subpath.
496
622
  */
497
- type ContainerStartOptions,
623
+ type ContainerStartOptions, type ContainerTerminalOptions,
498
624
  /**
499
625
  * `@lunora/container` — Cloudflare Containers for Lunora.
500
626
  *
@@ -505,7 +631,7 @@ type ContainerStartOptions,
505
631
  * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
506
632
  * behind the `@lunora/container/do` subpath.
507
633
  */
508
- type ContainerTestHandler,
634
+ type ContainerTestHandler, DURABLE_OBJECT_POLICY_FORBIDDEN_KEYS, type DefaultScheduledContainerConfig,
509
635
  /**
510
636
  * `@lunora/container` — Cloudflare Containers for Lunora.
511
637
  *
@@ -516,7 +642,7 @@ type ContainerTestHandler,
516
642
  * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
517
643
  * behind the `@lunora/container/do` subpath.
518
644
  */
519
- type DurableObjectJurisdiction,
645
+ type DurableObjectJurisdiction, type DurableObjectScheduledContainerConfig,
520
646
  /**
521
647
  * `@lunora/container` — Cloudflare Containers for Lunora.
522
648
  *
@@ -538,4 +664,26 @@ type InstanceRetryOptions, type NormalizedContainerImage,
538
664
  * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
539
665
  * behind the `@lunora/container/do` subpath.
540
666
  */
541
- type PoolOptions, containerBindingName, containerBuildTag, containerClassName, createContainerContext, createContainerTestContext, defineContainer, isContainerDefinition, normalizeContainerImage, resolveContainerEnvVariables as resolveContainerEnvVars };
667
+ type PoolOptions,
668
+ /**
669
+ * `@lunora/container` — Cloudflare Containers for Lunora.
670
+ *
671
+ * This root export is Node-safe (no Cloudflare runtime imports): the
672
+ * `defineContainer` authoring surface, the naming/normalization helpers
673
+ * codegen and `@lunora/config` share, the `ctx.containers` client wiring, and
674
+ * a Docker-free test double. The workerd-only `LunoraContainer` base class
675
+ * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
676
+ * behind the `@lunora/container/do` subpath.
677
+ */
678
+ type SandboxContainerAccessor,
679
+ /**
680
+ * `@lunora/container` — Cloudflare Containers for Lunora.
681
+ *
682
+ * This root export is Node-safe (no Cloudflare runtime imports): the
683
+ * `defineContainer` authoring surface, the naming/normalization helpers
684
+ * codegen and `@lunora/config` share, the `ctx.containers` client wiring, and
685
+ * a Docker-free test double. The workerd-only `LunoraContainer` base class
686
+ * (which pulls in `@cloudflare/containers` → `cloudflare:workers`) lives
687
+ * behind the `@lunora/container/do` subpath.
688
+ */
689
+ type SandboxContainerInstanceHandle, containerBindingName, containerBuildTag, containerClassName, createContainerContext, createContainerTestContext, defineContainer, getContainer, isCloudflareRegistryDigest, isContainerDefinition, isManagedImage, normalizeContainerImage, resolveContainerEnvVariables as resolveContainerEnvVars };
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{createContainerContext as o,createContainerTestContext as r}from"./packem_shared/createContainerContext-CLvjjJLs.mjs";import{containerBindingName as a,containerBuildTag as i,containerClassName as C,defineContainer as m,isContainerDefinition as s,normalizeContainerImage as c,resolveContainerEnvVars as f}from"./packem_shared/containerBindingName-C7SonAIK.mjs";import{C as l}from"./packem_shared/exec-WbCOLswq.mjs";export{l as CONTAINER_EXEC_PATH,a as containerBindingName,i as containerBuildTag,C as containerClassName,o as createContainerContext,r as createContainerTestContext,m as defineContainer,s as isContainerDefinition,c as normalizeContainerImage,f as resolveContainerEnvVars};
1
+ import{createContainerContext as a,createContainerTestContext as t,getContainer as i}from"./packem_shared/createContainerContext-CcW1olml.mjs";import{DURABLE_OBJECT_POLICY_FORBIDDEN_KEYS as o,containerBindingName as C,containerBuildTag as s,containerClassName as g,defineContainer as m,isCloudflareRegistryDigest as E,isContainerDefinition as f,isManagedImage as l,normalizeContainerImage as _,resolveContainerEnvVars as c}from"./packem_shared/DURABLE_OBJECT_POLICY_FORBIDDEN_KEYS-B9DkqZkf.mjs";import{C as x}from"./packem_shared/exec-BYLW70sR.mjs";export{x as CONTAINER_EXEC_PATH,o as DURABLE_OBJECT_POLICY_FORBIDDEN_KEYS,C as containerBindingName,s as containerBuildTag,g as containerClassName,a as createContainerContext,t as createContainerTestContext,m as defineContainer,i as getContainer,E as isCloudflareRegistryDigest,f as isContainerDefinition,l as isManagedImage,_ as normalizeContainerImage,c as resolveContainerEnvVars};
@@ -0,0 +1 @@
1
+ import"./abort-deadline-jwbW9Ala.mjs";import{a as e,C as A,D as T,e as s,p as C}from"./exec-BYLW70sR.mjs";export{e as CONTAINER_EXEC_HEADER,A as CONTAINER_EXEC_PATH,T as DEFAULT_EXEC_MAX_OUTPUT_BYTES,s as execViaFetch,C as pathMatchesAnyDecoding};