@lunora/container 1.0.0-alpha.10 → 1.0.0-alpha.12
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/README.md +2 -0
- package/dist/bridge.d.mts +18 -2
- package/dist/bridge.d.ts +18 -2
- package/dist/do/index.d.mts +2 -1
- package/dist/do/index.d.ts +2 -1
- package/dist/index.d.mts +60 -16
- package/dist/index.d.ts +60 -16
- package/dist/index.mjs +1 -1
- package/dist/otel.d.mts +45 -5
- package/dist/otel.d.ts +45 -5
- package/dist/otel.mjs +20 -3
- package/dist/packem_shared/{createContainerContext-CIVzsY5m.mjs → createContainerContext-Cg53QGdf.mjs} +19 -16
- package/dist/packem_shared/{jurisdiction.d-TwTGkgTg.d.mts → jurisdiction.d-CdUpqfc-.d.mts} +27 -3
- package/dist/packem_shared/{jurisdiction.d-TwTGkgTg.d.ts → jurisdiction.d-CdUpqfc-.d.ts} +27 -3
- package/package.json +2 -2
package/README.md
CHANGED
package/dist/bridge.d.mts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { LunoraError } from '@lunora/errors';
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* A `fetch` implementation — defaults to the runtime global.
|
|
4
|
+
* @experimental
|
|
5
|
+
*/
|
|
3
6
|
type FetchLike = (input: string, init: {
|
|
4
7
|
body: string;
|
|
5
8
|
headers: Record<string, string>;
|
|
@@ -10,6 +13,10 @@ type FetchLike = (input: string, init: {
|
|
|
10
13
|
status: number;
|
|
11
14
|
statusText?: string;
|
|
12
15
|
}>;
|
|
16
|
+
/**
|
|
17
|
+
* `ContainerBridgeOptions` is part of the experimental `@lunora/container` API and may change without a major version bump.
|
|
18
|
+
* @experimental
|
|
19
|
+
*/
|
|
13
20
|
interface ContainerBridgeOptions {
|
|
14
21
|
/**
|
|
15
22
|
* Base URL of the deployed Lunora Worker (no trailing `/_lunora/rpc`), e.g.
|
|
@@ -26,7 +33,10 @@ interface ContainerBridgeOptions {
|
|
|
26
33
|
*/
|
|
27
34
|
token?: string;
|
|
28
35
|
}
|
|
29
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* Thrown when a Lunora function returns an error envelope. A `LunoraError` subclass carrying the wire `code`.
|
|
38
|
+
* @experimental
|
|
39
|
+
*/
|
|
30
40
|
declare class ContainerBridgeError extends LunoraError {
|
|
31
41
|
constructor(code: string, message: string);
|
|
32
42
|
}
|
|
@@ -36,6 +46,7 @@ declare class ContainerBridgeError extends LunoraError {
|
|
|
36
46
|
* imported) so the bridge stays dependency-free and its `.d.ts` is
|
|
37
47
|
* self-contained; the `__lunoraPhantom` shape matches, so a real `api.x.y`
|
|
38
48
|
* reference is assignable and its arg/return types are inferable.
|
|
49
|
+
* @experimental
|
|
39
50
|
*/
|
|
40
51
|
interface BridgeFunctionReference<Args = unknown, Result = unknown> {
|
|
41
52
|
readonly __lunoraPhantom?: {
|
|
@@ -56,6 +67,10 @@ type ResultOfReference<Reference> = Reference extends {
|
|
|
56
67
|
returns: infer Result;
|
|
57
68
|
};
|
|
58
69
|
} ? Result : never;
|
|
70
|
+
/**
|
|
71
|
+
* `ContainerBridge` is part of the experimental `@lunora/container` API and may change without a major version bump.
|
|
72
|
+
* @experimental
|
|
73
|
+
*/
|
|
59
74
|
interface ContainerBridge {
|
|
60
75
|
/** Call an `action` by `namespace:fn` path. Alias of {@link ContainerBridge.call} for intent. */
|
|
61
76
|
action: <Result = unknown>(functionPath: string, args?: Record<string, unknown>, shardKey?: string) => Promise<Result>;
|
|
@@ -85,6 +100,7 @@ interface ContainerBridge {
|
|
|
85
100
|
* `query`/`mutation`/`action` are intent-revealing aliases of one `call` — the
|
|
86
101
|
* wire is identical and the server dispatches by the function's registered
|
|
87
102
|
* kind, so a query path called via `.mutation(...)` still runs as a query.
|
|
103
|
+
* @experimental
|
|
88
104
|
*/
|
|
89
105
|
declare const createContainerBridge: (options: ContainerBridgeOptions) => ContainerBridge;
|
|
90
106
|
export { type BridgeFunctionReference, type ContainerBridge, ContainerBridgeError, type ContainerBridgeOptions, type FetchLike, createContainerBridge };
|
package/dist/bridge.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { LunoraError } from '@lunora/errors';
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* A `fetch` implementation — defaults to the runtime global.
|
|
4
|
+
* @experimental
|
|
5
|
+
*/
|
|
3
6
|
type FetchLike = (input: string, init: {
|
|
4
7
|
body: string;
|
|
5
8
|
headers: Record<string, string>;
|
|
@@ -10,6 +13,10 @@ type FetchLike = (input: string, init: {
|
|
|
10
13
|
status: number;
|
|
11
14
|
statusText?: string;
|
|
12
15
|
}>;
|
|
16
|
+
/**
|
|
17
|
+
* `ContainerBridgeOptions` is part of the experimental `@lunora/container` API and may change without a major version bump.
|
|
18
|
+
* @experimental
|
|
19
|
+
*/
|
|
13
20
|
interface ContainerBridgeOptions {
|
|
14
21
|
/**
|
|
15
22
|
* Base URL of the deployed Lunora Worker (no trailing `/_lunora/rpc`), e.g.
|
|
@@ -26,7 +33,10 @@ interface ContainerBridgeOptions {
|
|
|
26
33
|
*/
|
|
27
34
|
token?: string;
|
|
28
35
|
}
|
|
29
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* Thrown when a Lunora function returns an error envelope. A `LunoraError` subclass carrying the wire `code`.
|
|
38
|
+
* @experimental
|
|
39
|
+
*/
|
|
30
40
|
declare class ContainerBridgeError extends LunoraError {
|
|
31
41
|
constructor(code: string, message: string);
|
|
32
42
|
}
|
|
@@ -36,6 +46,7 @@ declare class ContainerBridgeError extends LunoraError {
|
|
|
36
46
|
* imported) so the bridge stays dependency-free and its `.d.ts` is
|
|
37
47
|
* self-contained; the `__lunoraPhantom` shape matches, so a real `api.x.y`
|
|
38
48
|
* reference is assignable and its arg/return types are inferable.
|
|
49
|
+
* @experimental
|
|
39
50
|
*/
|
|
40
51
|
interface BridgeFunctionReference<Args = unknown, Result = unknown> {
|
|
41
52
|
readonly __lunoraPhantom?: {
|
|
@@ -56,6 +67,10 @@ type ResultOfReference<Reference> = Reference extends {
|
|
|
56
67
|
returns: infer Result;
|
|
57
68
|
};
|
|
58
69
|
} ? Result : never;
|
|
70
|
+
/**
|
|
71
|
+
* `ContainerBridge` is part of the experimental `@lunora/container` API and may change without a major version bump.
|
|
72
|
+
* @experimental
|
|
73
|
+
*/
|
|
59
74
|
interface ContainerBridge {
|
|
60
75
|
/** Call an `action` by `namespace:fn` path. Alias of {@link ContainerBridge.call} for intent. */
|
|
61
76
|
action: <Result = unknown>(functionPath: string, args?: Record<string, unknown>, shardKey?: string) => Promise<Result>;
|
|
@@ -85,6 +100,7 @@ interface ContainerBridge {
|
|
|
85
100
|
* `query`/`mutation`/`action` are intent-revealing aliases of one `call` — the
|
|
86
101
|
* wire is identical and the server dispatches by the function's registered
|
|
87
102
|
* kind, so a query path called via `.mutation(...)` still runs as a query.
|
|
103
|
+
* @experimental
|
|
88
104
|
*/
|
|
89
105
|
declare const createContainerBridge: (options: ContainerBridgeOptions) => ContainerBridge;
|
|
90
106
|
export { type BridgeFunctionReference, type ContainerBridge, ContainerBridgeError, type ContainerBridgeOptions, type FetchLike, createContainerBridge };
|
package/dist/do/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DurableObject, WorkerEntrypoint } from 'cloudflare:workers';
|
|
2
|
-
import { a as ContainerDefinition, D as DurableObjectJurisdiction } from "../packem_shared/jurisdiction.d-
|
|
2
|
+
import { a as ContainerDefinition, D as DurableObjectJurisdiction } from "../packem_shared/jurisdiction.d-CdUpqfc-.mjs";
|
|
3
3
|
/**
|
|
4
4
|
* ContainerStartOptions as they come from worker types
|
|
5
5
|
*/
|
|
@@ -500,6 +500,7 @@ type DurableObjectContext = ConstructorParameters<typeof Container>[0];
|
|
|
500
500
|
* }
|
|
501
501
|
* }
|
|
502
502
|
* ```
|
|
503
|
+
* @experimental
|
|
503
504
|
*/
|
|
504
505
|
declare class LunoraContainer<Env = unknown> extends Container<Env> {
|
|
505
506
|
/**
|
package/dist/do/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DurableObject, WorkerEntrypoint } from 'cloudflare:workers';
|
|
2
|
-
import { a as ContainerDefinition, D as DurableObjectJurisdiction } from "../packem_shared/jurisdiction.d-
|
|
2
|
+
import { a as ContainerDefinition, D as DurableObjectJurisdiction } from "../packem_shared/jurisdiction.d-CdUpqfc-.js";
|
|
3
3
|
/**
|
|
4
4
|
* ContainerStartOptions as they come from worker types
|
|
5
5
|
*/
|
|
@@ -500,6 +500,7 @@ type DurableObjectContext = ConstructorParameters<typeof Container>[0];
|
|
|
500
500
|
* }
|
|
501
501
|
* }
|
|
502
502
|
* ```
|
|
503
|
+
* @experimental
|
|
503
504
|
*/
|
|
504
505
|
declare class LunoraContainer<Env = unknown> extends Container<Env> {
|
|
505
506
|
/**
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import { D as DurableObjectJurisdiction, C as ContainerConfig, a as ContainerDefinition, b as ContainerImageSource, N as NormalizedContainerImage } from "./packem_shared/jurisdiction.d-
|
|
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-
|
|
3
|
-
/**
|
|
1
|
+
import { D as DurableObjectJurisdiction, C as ContainerConfig, a as ContainerDefinition, b as ContainerImageSource, N as NormalizedContainerImage } from "./packem_shared/jurisdiction.d-CdUpqfc-.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-CdUpqfc-.mjs";
|
|
3
|
+
/**
|
|
4
|
+
* Options for explicitly starting an instance (mirrors `@cloudflare/containers`).
|
|
5
|
+
* @experimental
|
|
6
|
+
*/
|
|
4
7
|
interface ContainerStartOptions {
|
|
5
8
|
/** Override outbound internet access for this start. */
|
|
6
9
|
enableInternet?: boolean;
|
|
@@ -11,7 +14,10 @@ interface ContainerStartOptions {
|
|
|
11
14
|
/** Metadata labels attached for metrics/observability. */
|
|
12
15
|
labels?: Record<string, string>;
|
|
13
16
|
}
|
|
14
|
-
/**
|
|
17
|
+
/**
|
|
18
|
+
* A container instance's runtime state, as returned by `getState()`. Structural — the platform adds fields over time.
|
|
19
|
+
* @experimental
|
|
20
|
+
*/
|
|
15
21
|
interface ContainerInstanceState {
|
|
16
22
|
[key: string]: unknown;
|
|
17
23
|
/** Process exit code, present once the instance has `stopped_with_code`. */
|
|
@@ -36,7 +42,10 @@ interface ContainerStubLike {
|
|
|
36
42
|
start?: (options?: ContainerStartOptions) => Promise<void>;
|
|
37
43
|
stop?: (signal?: number | string) => Promise<void>;
|
|
38
44
|
}
|
|
39
|
-
/**
|
|
45
|
+
/**
|
|
46
|
+
* What the client needs from a Durable Object namespace binding.
|
|
47
|
+
* @experimental
|
|
48
|
+
*/
|
|
40
49
|
interface ContainerNamespaceLike {
|
|
41
50
|
get: (id: unknown) => ContainerStubLike;
|
|
42
51
|
idFromName: (name: string) => unknown;
|
|
@@ -46,7 +55,10 @@ interface ContainerNamespaceLike {
|
|
|
46
55
|
*/
|
|
47
56
|
jurisdiction?: (jurisdiction: DurableObjectJurisdiction) => ContainerNamespaceLike;
|
|
48
57
|
}
|
|
49
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* A handle on one container instance (one Durable Object).
|
|
60
|
+
* @experimental
|
|
61
|
+
*/
|
|
50
62
|
interface ContainerHandle {
|
|
51
63
|
/**
|
|
52
64
|
* Send an HTTP (or WebSocket-upgrade) request to the container. A path
|
|
@@ -70,6 +82,7 @@ interface ContainerHandle {
|
|
|
70
82
|
* game, a job runner per id) often needs to tear down or inspect the instance
|
|
71
83
|
* rather than wait for `sleepAfter`, so these wrap the container DO's
|
|
72
84
|
* `start`/`stop`/`destroy`/`getState`.
|
|
85
|
+
* @experimental
|
|
73
86
|
*/
|
|
74
87
|
interface ContainerInstanceHandle extends ContainerHandle {
|
|
75
88
|
/** Stop and discard the instance (its ephemeral disk is lost). */
|
|
@@ -104,6 +117,7 @@ interface ContainerInstanceHandle extends ContainerHandle {
|
|
|
104
117
|
* Each maps to the corresponding `@cloudflare/containers` `Container` RPC, so
|
|
105
118
|
* an app can tighten or relax a single instance's allowed/denied hosts after
|
|
106
119
|
* start without redeploying.
|
|
120
|
+
* @experimental
|
|
107
121
|
*/
|
|
108
122
|
interface ContainerEgressControls {
|
|
109
123
|
/** Add one hostname (or glob) to the allow-list. */
|
|
@@ -119,7 +133,10 @@ interface ContainerEgressControls {
|
|
|
119
133
|
/** Replace the entire deny-list. */
|
|
120
134
|
setDenied: (hosts: ReadonlyArray<string>) => Promise<void>;
|
|
121
135
|
}
|
|
122
|
-
/**
|
|
136
|
+
/**
|
|
137
|
+
* The per-definition accessor exposed as `ctx.containers.<exportName>`.
|
|
138
|
+
* @experimental
|
|
139
|
+
*/
|
|
123
140
|
interface ContainerAccessor {
|
|
124
141
|
/**
|
|
125
142
|
* A random instance from a fixed pool of `count` (defaults to the
|
|
@@ -159,7 +176,10 @@ interface ContainerAccessor {
|
|
|
159
176
|
*/
|
|
160
177
|
pool: (options?: PoolOptions) => ContainerHandle;
|
|
161
178
|
}
|
|
162
|
-
/**
|
|
179
|
+
/**
|
|
180
|
+
* Tuning for a pooled, retrying container handle. See {@link ContainerAccessor.pool}.
|
|
181
|
+
* @experimental
|
|
182
|
+
*/
|
|
163
183
|
interface PoolOptions {
|
|
164
184
|
/** Total attempts before giving up (each on a freshly-picked instance). Default 3. */
|
|
165
185
|
attempts?: number;
|
|
@@ -185,6 +205,7 @@ interface PoolOptions {
|
|
|
185
205
|
* only on the platform's provisioning transients (no-instance / not-listening /
|
|
186
206
|
* rate-limited — see {@link isColdStartTransient}), which is why it's safe by
|
|
187
207
|
* default: those responses mean the request never reached the container.
|
|
208
|
+
* @experimental
|
|
188
209
|
*/
|
|
189
210
|
interface InstanceRetryOptions {
|
|
190
211
|
/**
|
|
@@ -198,7 +219,10 @@ interface InstanceRetryOptions {
|
|
|
198
219
|
/** Upper bound on a single backoff sleep, in ms. Default {@link DEFAULT_MAX_BACKOFF_MS} (30s). */
|
|
199
220
|
maxBackoffMs?: number;
|
|
200
221
|
}
|
|
201
|
-
/**
|
|
222
|
+
/**
|
|
223
|
+
* Wiring info for one definition, emitted by codegen into the generated DO.
|
|
224
|
+
* @experimental
|
|
225
|
+
*/
|
|
202
226
|
interface ContainerBindingSpec {
|
|
203
227
|
/** Durable Object binding name, e.g. `CONTAINER_TRANSCODER`. */
|
|
204
228
|
binding: string;
|
|
@@ -209,13 +233,20 @@ interface ContainerBindingSpec {
|
|
|
209
233
|
}
|
|
210
234
|
/**
|
|
211
235
|
* Build the `ctx.containers` record from the Worker `env`. Called by the
|
|
212
|
-
* generated ShardDO with the specs codegen derived from
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
236
|
+
* generated ShardDO with the specs codegen derived from `lunora/containers.ts`.
|
|
237
|
+
* A missing binding doesn't throw here — only when the handle is actually used —
|
|
238
|
+
* so one unprovisioned container never breaks unrelated functions.
|
|
239
|
+
*
|
|
240
|
+
* `traceparent` (the inbound RPC's W3C trace context, forwarded by the runtime
|
|
241
|
+
* and read off the request by the DO) is stamped onto every outbound container
|
|
242
|
+
* `fetch`, so the container's own spans stitch under the Worker's trace.
|
|
243
|
+
* @experimental
|
|
244
|
+
*/
|
|
245
|
+
declare const createContainerContext: (env: Record<string, unknown>, specs: ReadonlyArray<ContainerBindingSpec>, jurisdiction?: DurableObjectJurisdiction, traceparent?: string) => Record<string, ContainerAccessor>;
|
|
246
|
+
/**
|
|
247
|
+
* A test handler: receives the request plus the targeted instance name.
|
|
248
|
+
* @experimental
|
|
216
249
|
*/
|
|
217
|
-
declare const createContainerContext: (env: Record<string, unknown>, specs: ReadonlyArray<ContainerBindingSpec>, jurisdiction?: DurableObjectJurisdiction) => Record<string, ContainerAccessor>;
|
|
218
|
-
/** A test handler: receives the request plus the targeted instance name. */
|
|
219
250
|
type ContainerTestHandler = (request: Request, instance: {
|
|
220
251
|
name: string;
|
|
221
252
|
}) => Promise<Response> | Response;
|
|
@@ -229,6 +260,7 @@ type ContainerTestHandler = (request: Request, instance: {
|
|
|
229
260
|
* transcoder: (request) => new Response("ok"),
|
|
230
261
|
* });
|
|
231
262
|
* ```
|
|
263
|
+
* @experimental
|
|
232
264
|
*/
|
|
233
265
|
declare const createContainerTestContext: (handlers: Record<string, ContainerTestHandler>) => Record<string, ContainerAccessor>;
|
|
234
266
|
/**
|
|
@@ -240,6 +272,7 @@ declare const createContainerTestContext: (handlers: Record<string, ContainerTes
|
|
|
240
272
|
* `Dockerfile.dev` also counts) is used as-is with its directory as the build
|
|
241
273
|
* context; any other path is treated as the build-context directory and the
|
|
242
274
|
* Dockerfile is expected at `<dir>/Dockerfile`.
|
|
275
|
+
* @experimental
|
|
243
276
|
*/
|
|
244
277
|
declare const normalizeContainerImage: (image: ContainerImageSource) => NormalizedContainerImage;
|
|
245
278
|
/**
|
|
@@ -247,6 +280,7 @@ declare const normalizeContainerImage: (image: ContainerImageSource) => Normaliz
|
|
|
247
280
|
* `transcoder` → `TranscoderContainer`. wrangler's `containers[].class_name`
|
|
248
281
|
* and the Durable Object binding's `class_name` both reference it, so codegen
|
|
249
282
|
* and the config layer MUST derive it identically — always via this helper.
|
|
283
|
+
* @experimental
|
|
250
284
|
*/
|
|
251
285
|
declare const containerClassName: (exportName: string) => string;
|
|
252
286
|
/**
|
|
@@ -254,6 +288,7 @@ declare const containerClassName: (exportName: string) => string;
|
|
|
254
288
|
* `CONTAINER_TRANSCODER`, `imageResizer` → `CONTAINER_IMAGE_RESIZER`. The
|
|
255
289
|
* `CONTAINER_` prefix namespaces these away from `SHARD`/`SESSION`/`SCHEDULER`
|
|
256
290
|
* so a container export can never collide with the built-in bindings.
|
|
291
|
+
* @experimental
|
|
257
292
|
*/
|
|
258
293
|
declare const containerBindingName: (exportName: string) => string;
|
|
259
294
|
/**
|
|
@@ -262,16 +297,25 @@ declare const containerBindingName: (exportName: string) => string;
|
|
|
262
297
|
* it as the wrangler `containers[].image`, and `lunora deploy` builds that tag
|
|
263
298
|
* with Railpack and `wrangler containers push`es it before deploying — so all
|
|
264
299
|
* three derive the tag from this one helper and can never disagree.
|
|
300
|
+
* @experimental
|
|
265
301
|
*/
|
|
266
302
|
declare const containerBuildTag: (exportName: string) => string;
|
|
303
|
+
/**
|
|
304
|
+
* `defineContainer` is part of the experimental `@lunora/container` API and may change without a major version bump.
|
|
305
|
+
* @experimental
|
|
306
|
+
*/
|
|
267
307
|
declare const defineContainer: (config: ContainerConfig) => ContainerDefinition;
|
|
268
|
-
/**
|
|
308
|
+
/**
|
|
309
|
+
* True when a value is a `defineContainer` result (the runtime brand check).
|
|
310
|
+
* @experimental
|
|
311
|
+
*/
|
|
269
312
|
declare const isContainerDefinition: (value: unknown) => value is ContainerDefinition;
|
|
270
313
|
/**
|
|
271
314
|
* The container's full environment at instance start: the static `env` block
|
|
272
315
|
* plus every declared secret resolved from the Worker `env`. A declared secret
|
|
273
316
|
* missing from the Worker env fails fast — starting the container without a
|
|
274
317
|
* credential it was promised yields far worse errors downstream.
|
|
318
|
+
* @experimental
|
|
275
319
|
*/
|
|
276
320
|
declare const resolveContainerEnvVariables: (definition: ContainerDefinition, workerEnv: Record<string, unknown>, exportName?: string) => Record<string, string>;
|
|
277
321
|
export { type ContainerAccessor, type ContainerBindingSpec, type ContainerConfig, type ContainerDefinition, type ContainerEgressControls, type ContainerHandle, type ContainerImageSource, type ContainerInstanceHandle, type ContainerInstanceState, type ContainerNamespaceLike, type ContainerStartOptions, type ContainerTestHandler, type DurableObjectJurisdiction, type InstanceRetryOptions, type NormalizedContainerImage, type PoolOptions, containerBindingName, containerBuildTag, containerClassName, createContainerContext, createContainerTestContext, defineContainer, isContainerDefinition, normalizeContainerImage, resolveContainerEnvVariables as resolveContainerEnvVars };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import { D as DurableObjectJurisdiction, C as ContainerConfig, a as ContainerDefinition, b as ContainerImageSource, N as NormalizedContainerImage } from "./packem_shared/jurisdiction.d-
|
|
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-
|
|
3
|
-
/**
|
|
1
|
+
import { D as DurableObjectJurisdiction, C as ContainerConfig, a as ContainerDefinition, b as ContainerImageSource, N as NormalizedContainerImage } from "./packem_shared/jurisdiction.d-CdUpqfc-.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-CdUpqfc-.js";
|
|
3
|
+
/**
|
|
4
|
+
* Options for explicitly starting an instance (mirrors `@cloudflare/containers`).
|
|
5
|
+
* @experimental
|
|
6
|
+
*/
|
|
4
7
|
interface ContainerStartOptions {
|
|
5
8
|
/** Override outbound internet access for this start. */
|
|
6
9
|
enableInternet?: boolean;
|
|
@@ -11,7 +14,10 @@ interface ContainerStartOptions {
|
|
|
11
14
|
/** Metadata labels attached for metrics/observability. */
|
|
12
15
|
labels?: Record<string, string>;
|
|
13
16
|
}
|
|
14
|
-
/**
|
|
17
|
+
/**
|
|
18
|
+
* A container instance's runtime state, as returned by `getState()`. Structural — the platform adds fields over time.
|
|
19
|
+
* @experimental
|
|
20
|
+
*/
|
|
15
21
|
interface ContainerInstanceState {
|
|
16
22
|
[key: string]: unknown;
|
|
17
23
|
/** Process exit code, present once the instance has `stopped_with_code`. */
|
|
@@ -36,7 +42,10 @@ interface ContainerStubLike {
|
|
|
36
42
|
start?: (options?: ContainerStartOptions) => Promise<void>;
|
|
37
43
|
stop?: (signal?: number | string) => Promise<void>;
|
|
38
44
|
}
|
|
39
|
-
/**
|
|
45
|
+
/**
|
|
46
|
+
* What the client needs from a Durable Object namespace binding.
|
|
47
|
+
* @experimental
|
|
48
|
+
*/
|
|
40
49
|
interface ContainerNamespaceLike {
|
|
41
50
|
get: (id: unknown) => ContainerStubLike;
|
|
42
51
|
idFromName: (name: string) => unknown;
|
|
@@ -46,7 +55,10 @@ interface ContainerNamespaceLike {
|
|
|
46
55
|
*/
|
|
47
56
|
jurisdiction?: (jurisdiction: DurableObjectJurisdiction) => ContainerNamespaceLike;
|
|
48
57
|
}
|
|
49
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* A handle on one container instance (one Durable Object).
|
|
60
|
+
* @experimental
|
|
61
|
+
*/
|
|
50
62
|
interface ContainerHandle {
|
|
51
63
|
/**
|
|
52
64
|
* Send an HTTP (or WebSocket-upgrade) request to the container. A path
|
|
@@ -70,6 +82,7 @@ interface ContainerHandle {
|
|
|
70
82
|
* game, a job runner per id) often needs to tear down or inspect the instance
|
|
71
83
|
* rather than wait for `sleepAfter`, so these wrap the container DO's
|
|
72
84
|
* `start`/`stop`/`destroy`/`getState`.
|
|
85
|
+
* @experimental
|
|
73
86
|
*/
|
|
74
87
|
interface ContainerInstanceHandle extends ContainerHandle {
|
|
75
88
|
/** Stop and discard the instance (its ephemeral disk is lost). */
|
|
@@ -104,6 +117,7 @@ interface ContainerInstanceHandle extends ContainerHandle {
|
|
|
104
117
|
* Each maps to the corresponding `@cloudflare/containers` `Container` RPC, so
|
|
105
118
|
* an app can tighten or relax a single instance's allowed/denied hosts after
|
|
106
119
|
* start without redeploying.
|
|
120
|
+
* @experimental
|
|
107
121
|
*/
|
|
108
122
|
interface ContainerEgressControls {
|
|
109
123
|
/** Add one hostname (or glob) to the allow-list. */
|
|
@@ -119,7 +133,10 @@ interface ContainerEgressControls {
|
|
|
119
133
|
/** Replace the entire deny-list. */
|
|
120
134
|
setDenied: (hosts: ReadonlyArray<string>) => Promise<void>;
|
|
121
135
|
}
|
|
122
|
-
/**
|
|
136
|
+
/**
|
|
137
|
+
* The per-definition accessor exposed as `ctx.containers.<exportName>`.
|
|
138
|
+
* @experimental
|
|
139
|
+
*/
|
|
123
140
|
interface ContainerAccessor {
|
|
124
141
|
/**
|
|
125
142
|
* A random instance from a fixed pool of `count` (defaults to the
|
|
@@ -159,7 +176,10 @@ interface ContainerAccessor {
|
|
|
159
176
|
*/
|
|
160
177
|
pool: (options?: PoolOptions) => ContainerHandle;
|
|
161
178
|
}
|
|
162
|
-
/**
|
|
179
|
+
/**
|
|
180
|
+
* Tuning for a pooled, retrying container handle. See {@link ContainerAccessor.pool}.
|
|
181
|
+
* @experimental
|
|
182
|
+
*/
|
|
163
183
|
interface PoolOptions {
|
|
164
184
|
/** Total attempts before giving up (each on a freshly-picked instance). Default 3. */
|
|
165
185
|
attempts?: number;
|
|
@@ -185,6 +205,7 @@ interface PoolOptions {
|
|
|
185
205
|
* only on the platform's provisioning transients (no-instance / not-listening /
|
|
186
206
|
* rate-limited — see {@link isColdStartTransient}), which is why it's safe by
|
|
187
207
|
* default: those responses mean the request never reached the container.
|
|
208
|
+
* @experimental
|
|
188
209
|
*/
|
|
189
210
|
interface InstanceRetryOptions {
|
|
190
211
|
/**
|
|
@@ -198,7 +219,10 @@ interface InstanceRetryOptions {
|
|
|
198
219
|
/** Upper bound on a single backoff sleep, in ms. Default {@link DEFAULT_MAX_BACKOFF_MS} (30s). */
|
|
199
220
|
maxBackoffMs?: number;
|
|
200
221
|
}
|
|
201
|
-
/**
|
|
222
|
+
/**
|
|
223
|
+
* Wiring info for one definition, emitted by codegen into the generated DO.
|
|
224
|
+
* @experimental
|
|
225
|
+
*/
|
|
202
226
|
interface ContainerBindingSpec {
|
|
203
227
|
/** Durable Object binding name, e.g. `CONTAINER_TRANSCODER`. */
|
|
204
228
|
binding: string;
|
|
@@ -209,13 +233,20 @@ interface ContainerBindingSpec {
|
|
|
209
233
|
}
|
|
210
234
|
/**
|
|
211
235
|
* Build the `ctx.containers` record from the Worker `env`. Called by the
|
|
212
|
-
* generated ShardDO with the specs codegen derived from
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
236
|
+
* generated ShardDO with the specs codegen derived from `lunora/containers.ts`.
|
|
237
|
+
* A missing binding doesn't throw here — only when the handle is actually used —
|
|
238
|
+
* so one unprovisioned container never breaks unrelated functions.
|
|
239
|
+
*
|
|
240
|
+
* `traceparent` (the inbound RPC's W3C trace context, forwarded by the runtime
|
|
241
|
+
* and read off the request by the DO) is stamped onto every outbound container
|
|
242
|
+
* `fetch`, so the container's own spans stitch under the Worker's trace.
|
|
243
|
+
* @experimental
|
|
244
|
+
*/
|
|
245
|
+
declare const createContainerContext: (env: Record<string, unknown>, specs: ReadonlyArray<ContainerBindingSpec>, jurisdiction?: DurableObjectJurisdiction, traceparent?: string) => Record<string, ContainerAccessor>;
|
|
246
|
+
/**
|
|
247
|
+
* A test handler: receives the request plus the targeted instance name.
|
|
248
|
+
* @experimental
|
|
216
249
|
*/
|
|
217
|
-
declare const createContainerContext: (env: Record<string, unknown>, specs: ReadonlyArray<ContainerBindingSpec>, jurisdiction?: DurableObjectJurisdiction) => Record<string, ContainerAccessor>;
|
|
218
|
-
/** A test handler: receives the request plus the targeted instance name. */
|
|
219
250
|
type ContainerTestHandler = (request: Request, instance: {
|
|
220
251
|
name: string;
|
|
221
252
|
}) => Promise<Response> | Response;
|
|
@@ -229,6 +260,7 @@ type ContainerTestHandler = (request: Request, instance: {
|
|
|
229
260
|
* transcoder: (request) => new Response("ok"),
|
|
230
261
|
* });
|
|
231
262
|
* ```
|
|
263
|
+
* @experimental
|
|
232
264
|
*/
|
|
233
265
|
declare const createContainerTestContext: (handlers: Record<string, ContainerTestHandler>) => Record<string, ContainerAccessor>;
|
|
234
266
|
/**
|
|
@@ -240,6 +272,7 @@ declare const createContainerTestContext: (handlers: Record<string, ContainerTes
|
|
|
240
272
|
* `Dockerfile.dev` also counts) is used as-is with its directory as the build
|
|
241
273
|
* context; any other path is treated as the build-context directory and the
|
|
242
274
|
* Dockerfile is expected at `<dir>/Dockerfile`.
|
|
275
|
+
* @experimental
|
|
243
276
|
*/
|
|
244
277
|
declare const normalizeContainerImage: (image: ContainerImageSource) => NormalizedContainerImage;
|
|
245
278
|
/**
|
|
@@ -247,6 +280,7 @@ declare const normalizeContainerImage: (image: ContainerImageSource) => Normaliz
|
|
|
247
280
|
* `transcoder` → `TranscoderContainer`. wrangler's `containers[].class_name`
|
|
248
281
|
* and the Durable Object binding's `class_name` both reference it, so codegen
|
|
249
282
|
* and the config layer MUST derive it identically — always via this helper.
|
|
283
|
+
* @experimental
|
|
250
284
|
*/
|
|
251
285
|
declare const containerClassName: (exportName: string) => string;
|
|
252
286
|
/**
|
|
@@ -254,6 +288,7 @@ declare const containerClassName: (exportName: string) => string;
|
|
|
254
288
|
* `CONTAINER_TRANSCODER`, `imageResizer` → `CONTAINER_IMAGE_RESIZER`. The
|
|
255
289
|
* `CONTAINER_` prefix namespaces these away from `SHARD`/`SESSION`/`SCHEDULER`
|
|
256
290
|
* so a container export can never collide with the built-in bindings.
|
|
291
|
+
* @experimental
|
|
257
292
|
*/
|
|
258
293
|
declare const containerBindingName: (exportName: string) => string;
|
|
259
294
|
/**
|
|
@@ -262,16 +297,25 @@ declare const containerBindingName: (exportName: string) => string;
|
|
|
262
297
|
* it as the wrangler `containers[].image`, and `lunora deploy` builds that tag
|
|
263
298
|
* with Railpack and `wrangler containers push`es it before deploying — so all
|
|
264
299
|
* three derive the tag from this one helper and can never disagree.
|
|
300
|
+
* @experimental
|
|
265
301
|
*/
|
|
266
302
|
declare const containerBuildTag: (exportName: string) => string;
|
|
303
|
+
/**
|
|
304
|
+
* `defineContainer` is part of the experimental `@lunora/container` API and may change without a major version bump.
|
|
305
|
+
* @experimental
|
|
306
|
+
*/
|
|
267
307
|
declare const defineContainer: (config: ContainerConfig) => ContainerDefinition;
|
|
268
|
-
/**
|
|
308
|
+
/**
|
|
309
|
+
* True when a value is a `defineContainer` result (the runtime brand check).
|
|
310
|
+
* @experimental
|
|
311
|
+
*/
|
|
269
312
|
declare const isContainerDefinition: (value: unknown) => value is ContainerDefinition;
|
|
270
313
|
/**
|
|
271
314
|
* The container's full environment at instance start: the static `env` block
|
|
272
315
|
* plus every declared secret resolved from the Worker `env`. A declared secret
|
|
273
316
|
* missing from the Worker env fails fast — starting the container without a
|
|
274
317
|
* credential it was promised yields far worse errors downstream.
|
|
318
|
+
* @experimental
|
|
275
319
|
*/
|
|
276
320
|
declare const resolveContainerEnvVariables: (definition: ContainerDefinition, workerEnv: Record<string, unknown>, exportName?: string) => Record<string, string>;
|
|
277
321
|
export { type ContainerAccessor, type ContainerBindingSpec, type ContainerConfig, type ContainerDefinition, type ContainerEgressControls, type ContainerHandle, type ContainerImageSource, type ContainerInstanceHandle, type ContainerInstanceState, type ContainerNamespaceLike, type ContainerStartOptions, type ContainerTestHandler, type DurableObjectJurisdiction, type InstanceRetryOptions, type NormalizedContainerImage, type PoolOptions, containerBindingName, containerBuildTag, containerClassName, createContainerContext, createContainerTestContext, defineContainer, isContainerDefinition, normalizeContainerImage, resolveContainerEnvVariables as resolveContainerEnvVars };
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { createContainerContext, createContainerTestContext } from './packem_shared/createContainerContext-
|
|
1
|
+
export { createContainerContext, createContainerTestContext } from './packem_shared/createContainerContext-Cg53QGdf.mjs';
|
|
2
2
|
export { containerBindingName, containerBuildTag, containerClassName, defineContainer, isContainerDefinition, normalizeContainerImage, resolveContainerEnvVars } from './packem_shared/containerBindingName-BiTrAF1J.mjs';
|
package/dist/otel.d.mts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* An attribute value carried on a span or log.
|
|
3
|
+
* @experimental
|
|
4
|
+
*/
|
|
2
5
|
type ContainerAttributeValue = boolean | number | string;
|
|
3
6
|
/**
|
|
4
7
|
* A `fetch` implementation — defaults to the runtime global. The exporter passes
|
|
@@ -6,6 +9,7 @@ type ContainerAttributeValue = boolean | number | string;
|
|
|
6
9
|
* cancels the response `body` so Node/undici can release the socket for
|
|
7
10
|
* keep-alive reuse instead of leaving it occupied by an unread stream. It reads
|
|
8
11
|
* `ok`/`status` to detect a rejected export and nothing else from the response.
|
|
12
|
+
* @experimental
|
|
9
13
|
*/
|
|
10
14
|
type OtelFetchLike = (input: string, init: {
|
|
11
15
|
body: string;
|
|
@@ -19,7 +23,10 @@ type OtelFetchLike = (input: string, init: {
|
|
|
19
23
|
ok: boolean;
|
|
20
24
|
status: number;
|
|
21
25
|
}>;
|
|
22
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* A single span the container process asks the exporter to record.
|
|
28
|
+
* @experimental
|
|
29
|
+
*/
|
|
23
30
|
interface ContainerSpanInput {
|
|
24
31
|
/** Attributes attached to the span (rendered under the OTLP `attributes` list). */
|
|
25
32
|
attributes?: Record<string, ContainerAttributeValue>;
|
|
@@ -35,7 +42,10 @@ interface ContainerSpanInput {
|
|
|
35
42
|
/** Wall-clock millis when the operation started. */
|
|
36
43
|
startMs: number;
|
|
37
44
|
}
|
|
38
|
-
/**
|
|
45
|
+
/**
|
|
46
|
+
* A single log line the container process asks the exporter to record.
|
|
47
|
+
* @experimental
|
|
48
|
+
*/
|
|
39
49
|
interface ContainerLogInput {
|
|
40
50
|
/** Attributes attached to the log record. */
|
|
41
51
|
attributes?: Record<string, ContainerAttributeValue>;
|
|
@@ -46,7 +56,10 @@ interface ContainerLogInput {
|
|
|
46
56
|
/** Wall-clock millis the line was emitted; defaults to now. */
|
|
47
57
|
ts?: number;
|
|
48
58
|
}
|
|
49
|
-
/**
|
|
59
|
+
/**
|
|
60
|
+
* Options for {@link createContainerTelemetry}.
|
|
61
|
+
* @experimental
|
|
62
|
+
*/
|
|
50
63
|
interface ContainerTelemetryOptions {
|
|
51
64
|
/** Base OTLP collector endpoint; defaults to the `LUNORA_OTLP_ENDPOINT` env var. */
|
|
52
65
|
endpoint?: string;
|
|
@@ -62,8 +75,34 @@ interface ContainerTelemetryOptions {
|
|
|
62
75
|
timeoutMs?: number;
|
|
63
76
|
/** Bearer token sent as an `Authorization: Bearer` header; defaults to the `LUNORA_OTLP_TOKEN` env var. */
|
|
64
77
|
token?: string;
|
|
78
|
+
/**
|
|
79
|
+
* W3C `traceparent` of the Worker RPC that invoked this container; defaults to
|
|
80
|
+
* the `LUNORA_TRACEPARENT` env var. When present (and well-formed) every span
|
|
81
|
+
* inherits its trace id and hangs off its span id, so container spans stitch
|
|
82
|
+
* under the Worker's trace instead of forming a fresh, disconnected trace.
|
|
83
|
+
*
|
|
84
|
+
* `@lunora/container` stamps this trace context as the **`traceparent` request
|
|
85
|
+
* header** on every proxied fetch (`ctx.containers.<name>.…`), so a container
|
|
86
|
+
* that serves many requests should read it per request and create a telemetry
|
|
87
|
+
* instance scoped to that request — the trace context differs each call, so a
|
|
88
|
+
* single process-lifetime instance can't carry it:
|
|
89
|
+
*
|
|
90
|
+
* ```ts
|
|
91
|
+
* // inside the container's request handler
|
|
92
|
+
* const telemetry = createContainerTelemetry({ traceparent: request.headers.get("traceparent") ?? undefined });
|
|
93
|
+
* await telemetry.trace("transcode", () => transcode(job));
|
|
94
|
+
* await telemetry.flush();
|
|
95
|
+
* ```
|
|
96
|
+
*
|
|
97
|
+
* The `LUNORA_TRACEPARENT` env fallback fits a one-shot container that
|
|
98
|
+
* processes a single job per start (the value is fixed for the process).
|
|
99
|
+
*/
|
|
100
|
+
traceparent?: string;
|
|
65
101
|
}
|
|
66
|
-
/**
|
|
102
|
+
/**
|
|
103
|
+
* The exporter handle {@link createContainerTelemetry} returns.
|
|
104
|
+
* @experimental
|
|
105
|
+
*/
|
|
67
106
|
interface ContainerTelemetry {
|
|
68
107
|
/** Record one log line (no-op when disabled). */
|
|
69
108
|
emitLog: (log: ContainerLogInput) => void;
|
|
@@ -90,6 +129,7 @@ interface ContainerTelemetry {
|
|
|
90
129
|
* false`): `emitSpan`/`emitLog` no-op and `trace` still runs its work but records
|
|
91
130
|
* nothing — so the same code runs unchanged locally and in the cloud.
|
|
92
131
|
* @param options Exporter options; every field falls back to a `LUNORA_*` env var.
|
|
132
|
+
* @experimental
|
|
93
133
|
*/
|
|
94
134
|
declare const createContainerTelemetry: (options?: ContainerTelemetryOptions) => ContainerTelemetry;
|
|
95
135
|
export { type ContainerAttributeValue, type ContainerLogInput, type ContainerSpanInput, type ContainerTelemetry, type ContainerTelemetryOptions, type OtelFetchLike, createContainerTelemetry };
|
package/dist/otel.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* An attribute value carried on a span or log.
|
|
3
|
+
* @experimental
|
|
4
|
+
*/
|
|
2
5
|
type ContainerAttributeValue = boolean | number | string;
|
|
3
6
|
/**
|
|
4
7
|
* A `fetch` implementation — defaults to the runtime global. The exporter passes
|
|
@@ -6,6 +9,7 @@ type ContainerAttributeValue = boolean | number | string;
|
|
|
6
9
|
* cancels the response `body` so Node/undici can release the socket for
|
|
7
10
|
* keep-alive reuse instead of leaving it occupied by an unread stream. It reads
|
|
8
11
|
* `ok`/`status` to detect a rejected export and nothing else from the response.
|
|
12
|
+
* @experimental
|
|
9
13
|
*/
|
|
10
14
|
type OtelFetchLike = (input: string, init: {
|
|
11
15
|
body: string;
|
|
@@ -19,7 +23,10 @@ type OtelFetchLike = (input: string, init: {
|
|
|
19
23
|
ok: boolean;
|
|
20
24
|
status: number;
|
|
21
25
|
}>;
|
|
22
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* A single span the container process asks the exporter to record.
|
|
28
|
+
* @experimental
|
|
29
|
+
*/
|
|
23
30
|
interface ContainerSpanInput {
|
|
24
31
|
/** Attributes attached to the span (rendered under the OTLP `attributes` list). */
|
|
25
32
|
attributes?: Record<string, ContainerAttributeValue>;
|
|
@@ -35,7 +42,10 @@ interface ContainerSpanInput {
|
|
|
35
42
|
/** Wall-clock millis when the operation started. */
|
|
36
43
|
startMs: number;
|
|
37
44
|
}
|
|
38
|
-
/**
|
|
45
|
+
/**
|
|
46
|
+
* A single log line the container process asks the exporter to record.
|
|
47
|
+
* @experimental
|
|
48
|
+
*/
|
|
39
49
|
interface ContainerLogInput {
|
|
40
50
|
/** Attributes attached to the log record. */
|
|
41
51
|
attributes?: Record<string, ContainerAttributeValue>;
|
|
@@ -46,7 +56,10 @@ interface ContainerLogInput {
|
|
|
46
56
|
/** Wall-clock millis the line was emitted; defaults to now. */
|
|
47
57
|
ts?: number;
|
|
48
58
|
}
|
|
49
|
-
/**
|
|
59
|
+
/**
|
|
60
|
+
* Options for {@link createContainerTelemetry}.
|
|
61
|
+
* @experimental
|
|
62
|
+
*/
|
|
50
63
|
interface ContainerTelemetryOptions {
|
|
51
64
|
/** Base OTLP collector endpoint; defaults to the `LUNORA_OTLP_ENDPOINT` env var. */
|
|
52
65
|
endpoint?: string;
|
|
@@ -62,8 +75,34 @@ interface ContainerTelemetryOptions {
|
|
|
62
75
|
timeoutMs?: number;
|
|
63
76
|
/** Bearer token sent as an `Authorization: Bearer` header; defaults to the `LUNORA_OTLP_TOKEN` env var. */
|
|
64
77
|
token?: string;
|
|
78
|
+
/**
|
|
79
|
+
* W3C `traceparent` of the Worker RPC that invoked this container; defaults to
|
|
80
|
+
* the `LUNORA_TRACEPARENT` env var. When present (and well-formed) every span
|
|
81
|
+
* inherits its trace id and hangs off its span id, so container spans stitch
|
|
82
|
+
* under the Worker's trace instead of forming a fresh, disconnected trace.
|
|
83
|
+
*
|
|
84
|
+
* `@lunora/container` stamps this trace context as the **`traceparent` request
|
|
85
|
+
* header** on every proxied fetch (`ctx.containers.<name>.…`), so a container
|
|
86
|
+
* that serves many requests should read it per request and create a telemetry
|
|
87
|
+
* instance scoped to that request — the trace context differs each call, so a
|
|
88
|
+
* single process-lifetime instance can't carry it:
|
|
89
|
+
*
|
|
90
|
+
* ```ts
|
|
91
|
+
* // inside the container's request handler
|
|
92
|
+
* const telemetry = createContainerTelemetry({ traceparent: request.headers.get("traceparent") ?? undefined });
|
|
93
|
+
* await telemetry.trace("transcode", () => transcode(job));
|
|
94
|
+
* await telemetry.flush();
|
|
95
|
+
* ```
|
|
96
|
+
*
|
|
97
|
+
* The `LUNORA_TRACEPARENT` env fallback fits a one-shot container that
|
|
98
|
+
* processes a single job per start (the value is fixed for the process).
|
|
99
|
+
*/
|
|
100
|
+
traceparent?: string;
|
|
65
101
|
}
|
|
66
|
-
/**
|
|
102
|
+
/**
|
|
103
|
+
* The exporter handle {@link createContainerTelemetry} returns.
|
|
104
|
+
* @experimental
|
|
105
|
+
*/
|
|
67
106
|
interface ContainerTelemetry {
|
|
68
107
|
/** Record one log line (no-op when disabled). */
|
|
69
108
|
emitLog: (log: ContainerLogInput) => void;
|
|
@@ -90,6 +129,7 @@ interface ContainerTelemetry {
|
|
|
90
129
|
* false`): `emitSpan`/`emitLog` no-op and `trace` still runs its work but records
|
|
91
130
|
* nothing — so the same code runs unchanged locally and in the cloud.
|
|
92
131
|
* @param options Exporter options; every field falls back to a `LUNORA_*` env var.
|
|
132
|
+
* @experimental
|
|
93
133
|
*/
|
|
94
134
|
declare const createContainerTelemetry: (options?: ContainerTelemetryOptions) => ContainerTelemetry;
|
|
95
135
|
export { type ContainerAttributeValue, type ContainerLogInput, type ContainerSpanInput, type ContainerTelemetry, type ContainerTelemetryOptions, type OtelFetchLike, createContainerTelemetry };
|
package/dist/otel.mjs
CHANGED
|
@@ -20,6 +20,19 @@ const otlpRandomHex = (bytes) => {
|
|
|
20
20
|
}
|
|
21
21
|
return hex;
|
|
22
22
|
};
|
|
23
|
+
const HEX_ONLY = /^[0-9a-f]+$/;
|
|
24
|
+
const parseTraceparent = (header) => {
|
|
25
|
+
if (header === null || header === void 0) {
|
|
26
|
+
return void 0;
|
|
27
|
+
}
|
|
28
|
+
const parts = header.trim().toLowerCase().split("-");
|
|
29
|
+
const [version, traceId, parentSpanId, flags] = parts;
|
|
30
|
+
if (parts.length < 4 || version === void 0 || version.length !== 2 || !HEX_ONLY.test(version) || version === "ff" || // Version 00 forbids trailing fields; only a future version may carry them.
|
|
31
|
+
version === "00" && parts.length !== 4 || traceId === void 0 || parentSpanId === void 0 || flags === void 0 || flags.length !== 2 || !HEX_ONLY.test(flags) || traceId.length !== 32 || parentSpanId.length !== 16 || !HEX_ONLY.test(traceId) || !HEX_ONLY.test(parentSpanId) || traceId === "00000000000000000000000000000000" || parentSpanId === "0000000000000000") {
|
|
32
|
+
return void 0;
|
|
33
|
+
}
|
|
34
|
+
return { parentSpanId, traceId };
|
|
35
|
+
};
|
|
23
36
|
const encodeAttribute = (key, value) => {
|
|
24
37
|
if (typeof value === "boolean") {
|
|
25
38
|
return { key, value: { boolValue: value } };
|
|
@@ -96,7 +109,7 @@ const resolveFetch = (injected) => {
|
|
|
96
109
|
}
|
|
97
110
|
return void 0;
|
|
98
111
|
};
|
|
99
|
-
const traceBody = (span, serviceName) => {
|
|
112
|
+
const traceBody = (span, serviceName, parent) => {
|
|
100
113
|
const attributes = encodeAttributes(span.attributes);
|
|
101
114
|
if (span.error?.type !== void 0) {
|
|
102
115
|
attributes.push(encodeAttribute("error.type", span.error.type));
|
|
@@ -107,11 +120,14 @@ const traceBody = (span, serviceName) => {
|
|
|
107
120
|
// SPAN_KIND_INTERNAL — the container's own work, not a server/client edge.
|
|
108
121
|
kind: 1,
|
|
109
122
|
name: span.name,
|
|
123
|
+
// Always the span's own (child) id; with a parent, hang it off the parent
|
|
124
|
+
// span and inherit the parent's trace id so the spans stitch into one trace.
|
|
125
|
+
...parent === void 0 ? {} : { parentSpanId: parent.parentSpanId },
|
|
110
126
|
spanId: otlpRandomHex(8),
|
|
111
127
|
startTimeUnixNano: otlpUnixNano(span.startMs),
|
|
112
128
|
// STATUS_CODE_OK (1) / STATUS_CODE_ERROR (2).
|
|
113
129
|
status: span.error === void 0 ? { code: 1 } : { code: 2, message: span.error.message },
|
|
114
|
-
traceId: otlpRandomHex(16)
|
|
130
|
+
traceId: parent?.traceId ?? otlpRandomHex(16)
|
|
115
131
|
};
|
|
116
132
|
return wrapResourceSpans(otlpSpan, "@lunora/container", serviceName);
|
|
117
133
|
};
|
|
@@ -131,6 +147,7 @@ const createContainerTelemetry = (options = {}) => {
|
|
|
131
147
|
const enabled = endpoint !== void 0 && endpoint.length > 0;
|
|
132
148
|
const token = options.token ?? readEnv("LUNORA_OTLP_TOKEN");
|
|
133
149
|
const serviceName = options.serviceName ?? readEnv("LUNORA_SERVICE_NAME") ?? "lunora-container";
|
|
150
|
+
const parent = parseTraceparent(options.traceparent ?? readEnv("LUNORA_TRACEPARENT"));
|
|
134
151
|
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
135
152
|
const fetchImpl = resolveFetch(options.fetch);
|
|
136
153
|
const headers = mergeHeaders({ "content-type": "application/json" }, options.headers, token);
|
|
@@ -169,7 +186,7 @@ const createContainerTelemetry = (options = {}) => {
|
|
|
169
186
|
if (!enabled) {
|
|
170
187
|
return;
|
|
171
188
|
}
|
|
172
|
-
send(tracesUrl, traceBody(span, serviceName));
|
|
189
|
+
send(tracesUrl, traceBody(span, serviceName, parent));
|
|
173
190
|
};
|
|
174
191
|
const emitLog = (log) => {
|
|
175
192
|
if (!enabled) {
|
|
@@ -7,11 +7,14 @@ const DEFAULT_MAX_BACKOFF_MS = 3e4;
|
|
|
7
7
|
const DEFAULT_COLD_START_ATTEMPTS = 3;
|
|
8
8
|
const DEFAULT_COLD_START_BACKOFF_MS = 500;
|
|
9
9
|
const TARGET_PORT_HEADER = "cf-container-target-port";
|
|
10
|
-
const toRequest = (input, init, port) => {
|
|
10
|
+
const toRequest = (input, init, port, traceparent) => {
|
|
11
11
|
const request = typeof input === "string" && input.startsWith("/") ? new Request(`http://container${input}`, init) : new Request(input, init);
|
|
12
12
|
if (port !== void 0) {
|
|
13
13
|
request.headers.set(TARGET_PORT_HEADER, String(port));
|
|
14
14
|
}
|
|
15
|
+
if (traceparent !== void 0) {
|
|
16
|
+
request.headers.set("traceparent", traceparent);
|
|
17
|
+
}
|
|
15
18
|
return request;
|
|
16
19
|
};
|
|
17
20
|
const sleep = async (ms) => {
|
|
@@ -62,7 +65,7 @@ const isColdStartTransient = async (response) => {
|
|
|
62
65
|
return false;
|
|
63
66
|
}
|
|
64
67
|
};
|
|
65
|
-
const coldStartRetryingHandle = (send, options = {}, port) => {
|
|
68
|
+
const coldStartRetryingHandle = (send, options = {}, port, traceparent) => {
|
|
66
69
|
const attempts = Math.max(1, options.attempts ?? DEFAULT_COLD_START_ATTEMPTS);
|
|
67
70
|
const baseBackoff = options.backoffMs ?? DEFAULT_COLD_START_BACKOFF_MS;
|
|
68
71
|
const maxBackoff = options.maxBackoffMs ?? DEFAULT_MAX_BACKOFF_MS;
|
|
@@ -76,7 +79,7 @@ const coldStartRetryingHandle = (send, options = {}, port) => {
|
|
|
76
79
|
await sleep(Math.min(baseBackoff * 2 ** (attempt - 1), maxBackoff));
|
|
77
80
|
}
|
|
78
81
|
try {
|
|
79
|
-
const response = await send(toRequest(input, init, port));
|
|
82
|
+
const response = await send(toRequest(input, init, port, traceparent));
|
|
80
83
|
if (isLastAttempt || !await isColdStartTransient(response)) {
|
|
81
84
|
return response;
|
|
82
85
|
}
|
|
@@ -89,10 +92,10 @@ const coldStartRetryingHandle = (send, options = {}, port) => {
|
|
|
89
92
|
}
|
|
90
93
|
throw lastError instanceof Error ? lastError : new Error("ctx.containers: cold-start retry exhausted");
|
|
91
94
|
},
|
|
92
|
-
port: (targetPort) => coldStartRetryingHandle(send, options, targetPort)
|
|
95
|
+
port: (targetPort) => coldStartRetryingHandle(send, options, targetPort, traceparent)
|
|
93
96
|
};
|
|
94
97
|
};
|
|
95
|
-
const handleFor = (namespace, instanceName, options) => coldStartRetryingHandle(async (request) => namespace.get(namespace.idFromName(instanceName)).fetch(request), options);
|
|
98
|
+
const handleFor = (namespace, instanceName, options, traceparent) => coldStartRetryingHandle(async (request) => namespace.get(namespace.idFromName(instanceName)).fetch(request), options, void 0, traceparent);
|
|
96
99
|
const lifecycleCall = async (stub, method, binding, argument) => {
|
|
97
100
|
const rpc = stub[method];
|
|
98
101
|
if (typeof rpc !== "function") {
|
|
@@ -110,10 +113,10 @@ const egressControlsFor = (stub, binding) => {
|
|
|
110
113
|
setDenied: async (hosts) => lifecycleCall(stub(), "setDeniedHosts", binding, [...hosts])
|
|
111
114
|
};
|
|
112
115
|
};
|
|
113
|
-
const instanceHandleFor = (namespace, spec, instanceName, options) => {
|
|
116
|
+
const instanceHandleFor = (namespace, spec, instanceName, options, traceparent) => {
|
|
114
117
|
const stub = () => namespace.get(namespace.idFromName(instanceName));
|
|
115
118
|
return {
|
|
116
|
-
...coldStartRetryingHandle(async (request) => stub().fetch(request), options),
|
|
119
|
+
...coldStartRetryingHandle(async (request) => stub().fetch(request), options, void 0, traceparent),
|
|
117
120
|
destroy: async () => lifecycleCall(stub(), "destroy", spec.binding),
|
|
118
121
|
egress: egressControlsFor(stub, spec.binding),
|
|
119
122
|
getState: async () => lifecycleCall(stub(), "getState", spec.binding),
|
|
@@ -127,7 +130,7 @@ const randomPoolName = (size) => (
|
|
|
127
130
|
`pool-${String(Math.floor(Math.random() * size))}`
|
|
128
131
|
);
|
|
129
132
|
const retryOnServerError = (response) => response.status >= 500;
|
|
130
|
-
const poolHandleFor = (namespace, spec, options = {}, port) => {
|
|
133
|
+
const poolHandleFor = (namespace, spec, options = {}, port, traceparent) => {
|
|
131
134
|
const size = options.size ?? spec.maxInstances ?? DEFAULT_POOL_SIZE;
|
|
132
135
|
const attempts = Math.max(1, options.attempts ?? 3);
|
|
133
136
|
const baseBackoff = options.backoffMs ?? 100;
|
|
@@ -141,7 +144,7 @@ const poolHandleFor = (namespace, spec, options = {}, port) => {
|
|
|
141
144
|
if (attempt > 0) {
|
|
142
145
|
await sleep(Math.min(baseBackoff * 2 ** (attempt - 1), maxBackoff));
|
|
143
146
|
}
|
|
144
|
-
const request = toRequest(input, init, port);
|
|
147
|
+
const request = toRequest(input, init, port, traceparent);
|
|
145
148
|
try {
|
|
146
149
|
const response = await namespace.get(namespace.idFromName(randomPoolName(size))).fetch(request);
|
|
147
150
|
if (attempt === totalAttempts - 1 || !shouldRetry(response)) {
|
|
@@ -153,14 +156,14 @@ const poolHandleFor = (namespace, spec, options = {}, port) => {
|
|
|
153
156
|
}
|
|
154
157
|
throw lastError instanceof Error ? lastError : new Error(`ctx.containers.${spec.exportName}.pool(): all ${String(totalAttempts)} attempts failed`);
|
|
155
158
|
},
|
|
156
|
-
port: (targetPort) => poolHandleFor(namespace, spec, options, targetPort)
|
|
159
|
+
port: (targetPort) => poolHandleFor(namespace, spec, options, targetPort, traceparent)
|
|
157
160
|
};
|
|
158
161
|
};
|
|
159
|
-
const accessorFor = (namespace, spec) => {
|
|
162
|
+
const accessorFor = (namespace, spec, traceparent) => {
|
|
160
163
|
return {
|
|
161
|
-
any: (count, options) => handleFor(namespace, randomPoolName(count ?? spec.maxInstances ?? DEFAULT_POOL_SIZE), options),
|
|
162
|
-
get: (name, options) => instanceHandleFor(namespace, spec, name, options),
|
|
163
|
-
pool: (options) => poolHandleFor(namespace, spec, options)
|
|
164
|
+
any: (count, options) => handleFor(namespace, randomPoolName(count ?? spec.maxInstances ?? DEFAULT_POOL_SIZE), options, traceparent),
|
|
165
|
+
get: (name, options) => instanceHandleFor(namespace, spec, name, options, traceparent),
|
|
166
|
+
pool: (options) => poolHandleFor(namespace, spec, options, void 0, traceparent)
|
|
164
167
|
};
|
|
165
168
|
};
|
|
166
169
|
const missingBindingAccessor = (spec) => {
|
|
@@ -172,11 +175,11 @@ const missingBindingAccessor = (spec) => {
|
|
|
172
175
|
};
|
|
173
176
|
return { any: fail, get: fail, pool: fail };
|
|
174
177
|
};
|
|
175
|
-
const createContainerContext = (env, specs, jurisdiction) => {
|
|
178
|
+
const createContainerContext = (env, specs, jurisdiction, traceparent) => {
|
|
176
179
|
const containers = {};
|
|
177
180
|
for (const spec of specs) {
|
|
178
181
|
const binding = env[spec.binding];
|
|
179
|
-
containers[spec.exportName] = binding && typeof binding.idFromName === "function" && typeof binding.get === "function" ? accessorFor(applyJurisdiction(binding, jurisdiction), spec) : missingBindingAccessor(spec);
|
|
182
|
+
containers[spec.exportName] = binding && typeof binding.idFromName === "function" && typeof binding.get === "function" ? accessorFor(applyJurisdiction(binding, jurisdiction), spec, traceparent) : missingBindingAccessor(spec);
|
|
180
183
|
}
|
|
181
184
|
return containers;
|
|
182
185
|
};
|
|
@@ -5,12 +5,16 @@
|
|
|
5
5
|
* it is safe to import from Node tooling (codegen, the config layer) as well
|
|
6
6
|
* as from worker code.
|
|
7
7
|
*/
|
|
8
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* Named instance types Cloudflare Containers provides.
|
|
10
|
+
* @experimental
|
|
11
|
+
*/
|
|
9
12
|
type NamedContainerInstanceType = "basic" | "lite" | "standard-1" | "standard-2" | "standard-3" | "standard-4";
|
|
10
13
|
/**
|
|
11
14
|
* A custom instance type. Cloudflare's bounds at the time of writing: up to
|
|
12
15
|
* 4 vCPU, 12 GiB memory, 20 GB disk, ≥ 3 GiB memory per vCPU and ≤ 2 GB disk
|
|
13
16
|
* per GiB memory. The config-layer validator enforces the documented ranges.
|
|
17
|
+
* @experimental
|
|
14
18
|
*/
|
|
15
19
|
interface CustomContainerInstanceType {
|
|
16
20
|
/** Disk in MB. Cloudflare's default is 2000 (2 GB). */
|
|
@@ -20,8 +24,15 @@ interface CustomContainerInstanceType {
|
|
|
20
24
|
/** vCPU count. Cloudflare's default is 0.0625 (1/16 vCPU). */
|
|
21
25
|
vcpu?: number;
|
|
22
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* `ContainerInstanceType` is part of the experimental `@lunora/container` API and may change without a major version bump.
|
|
29
|
+
* @experimental
|
|
30
|
+
*/
|
|
23
31
|
type ContainerInstanceType = CustomContainerInstanceType | NamedContainerInstanceType;
|
|
24
|
-
/**
|
|
32
|
+
/**
|
|
33
|
+
* Rolling-deploy tuning for a container.
|
|
34
|
+
* @experimental
|
|
35
|
+
*/
|
|
25
36
|
interface ContainerRollout {
|
|
26
37
|
/** Seconds an active instance runs before it's eligible for update (wrangler `rollout_active_grace_period`). */
|
|
27
38
|
gracePeriodSeconds?: number;
|
|
@@ -32,6 +43,7 @@ interface ContainerRollout {
|
|
|
32
43
|
* A pre-built image pulled from a registry — the Cloudflare Registry, Docker
|
|
33
44
|
* Hub, or Amazon ECR (the registries `wrangler deploy` supports). The
|
|
34
45
|
* reference must be fully qualified, e.g. `docker.io/acme/transcoder:1.4`.
|
|
46
|
+
* @experimental
|
|
35
47
|
*/
|
|
36
48
|
interface RegistryImageSource {
|
|
37
49
|
registry: string;
|
|
@@ -41,6 +53,7 @@ interface RegistryImageSource {
|
|
|
41
53
|
* source directory and `lunora deploy` builds an OCI image with Railpack
|
|
42
54
|
* (needs a BuildKit instance) and pushes it to the Cloudflare Registry before
|
|
43
55
|
* wrangler runs. Opt-in — the Dockerfile path is the zero-extra-deps default.
|
|
56
|
+
* @experimental
|
|
44
57
|
*/
|
|
45
58
|
interface BuildImageSource {
|
|
46
59
|
build: string;
|
|
@@ -50,6 +63,7 @@ interface BuildImageSource {
|
|
|
50
63
|
* either a directory containing a `Dockerfile` (normalized to
|
|
51
64
|
* `<dir>/Dockerfile` with the directory as the build context) or a path to
|
|
52
65
|
* the Dockerfile itself — while `{ registry }` is a pre-built image reference.
|
|
66
|
+
* @experimental
|
|
53
67
|
*/
|
|
54
68
|
type ContainerImageSource = BuildImageSource | RegistryImageSource | string;
|
|
55
69
|
/**
|
|
@@ -62,6 +76,7 @@ type ContainerImageSource = BuildImageSource | RegistryImageSource | string;
|
|
|
62
76
|
* functions), so codegen and the config layer can read it without evaluating
|
|
63
77
|
* code. (Upstream cloudflare/containers#188 expresses the same idea as handler
|
|
64
78
|
* functions; the Lunora config is data-only, so it's modelled as descriptors.)
|
|
79
|
+
* @experimental
|
|
65
80
|
*/
|
|
66
81
|
interface ContainerReadinessCheck {
|
|
67
82
|
/** HTTP path probed on the container, e.g. `"/ready"` (a leading slash is optional). */
|
|
@@ -71,6 +86,10 @@ interface ContainerReadinessCheck {
|
|
|
71
86
|
/** HTTP status that means "ready". Defaults to `200`. */
|
|
72
87
|
status?: number;
|
|
73
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* `ContainerConfig` is part of the experimental `@lunora/container` API and may change without a major version bump.
|
|
91
|
+
* @experimental
|
|
92
|
+
*/
|
|
74
93
|
interface ContainerConfig {
|
|
75
94
|
/**
|
|
76
95
|
* Hostnames the container may reach **even when {@link ContainerConfig.enableInternet}
|
|
@@ -227,12 +246,16 @@ interface ContainerConfig {
|
|
|
227
246
|
/**
|
|
228
247
|
* The value `defineContainer` returns: the validated config plus a brand the
|
|
229
248
|
* codegen discovery and the generated Container DO class key on.
|
|
249
|
+
* @experimental
|
|
230
250
|
*/
|
|
231
251
|
interface ContainerDefinition extends ContainerConfig {
|
|
232
252
|
/** Brand marking a value as a Lunora container definition. */
|
|
233
253
|
readonly isLunoraContainer: true;
|
|
234
254
|
}
|
|
235
|
-
/**
|
|
255
|
+
/**
|
|
256
|
+
* A normalized image source, as written into `wrangler.jsonc`.
|
|
257
|
+
* @experimental
|
|
258
|
+
*/
|
|
236
259
|
type NormalizedContainerImage = {
|
|
237
260
|
/** Build context directory (wrangler `image_build_context`). */
|
|
238
261
|
buildContext: string;
|
|
@@ -251,6 +274,7 @@ type NormalizedContainerImage = {
|
|
|
251
274
|
* Cloudflare Durable Object data-residency jurisdiction. Widening union —
|
|
252
275
|
* Cloudflare adds values over time.
|
|
253
276
|
* @see https://developers.cloudflare.com/durable-objects/reference/data-location/
|
|
277
|
+
* @experimental
|
|
254
278
|
*/
|
|
255
279
|
type DurableObjectJurisdiction = "eu" | "fedramp" | "us";
|
|
256
280
|
/**
|
|
@@ -5,12 +5,16 @@
|
|
|
5
5
|
* it is safe to import from Node tooling (codegen, the config layer) as well
|
|
6
6
|
* as from worker code.
|
|
7
7
|
*/
|
|
8
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* Named instance types Cloudflare Containers provides.
|
|
10
|
+
* @experimental
|
|
11
|
+
*/
|
|
9
12
|
type NamedContainerInstanceType = "basic" | "lite" | "standard-1" | "standard-2" | "standard-3" | "standard-4";
|
|
10
13
|
/**
|
|
11
14
|
* A custom instance type. Cloudflare's bounds at the time of writing: up to
|
|
12
15
|
* 4 vCPU, 12 GiB memory, 20 GB disk, ≥ 3 GiB memory per vCPU and ≤ 2 GB disk
|
|
13
16
|
* per GiB memory. The config-layer validator enforces the documented ranges.
|
|
17
|
+
* @experimental
|
|
14
18
|
*/
|
|
15
19
|
interface CustomContainerInstanceType {
|
|
16
20
|
/** Disk in MB. Cloudflare's default is 2000 (2 GB). */
|
|
@@ -20,8 +24,15 @@ interface CustomContainerInstanceType {
|
|
|
20
24
|
/** vCPU count. Cloudflare's default is 0.0625 (1/16 vCPU). */
|
|
21
25
|
vcpu?: number;
|
|
22
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* `ContainerInstanceType` is part of the experimental `@lunora/container` API and may change without a major version bump.
|
|
29
|
+
* @experimental
|
|
30
|
+
*/
|
|
23
31
|
type ContainerInstanceType = CustomContainerInstanceType | NamedContainerInstanceType;
|
|
24
|
-
/**
|
|
32
|
+
/**
|
|
33
|
+
* Rolling-deploy tuning for a container.
|
|
34
|
+
* @experimental
|
|
35
|
+
*/
|
|
25
36
|
interface ContainerRollout {
|
|
26
37
|
/** Seconds an active instance runs before it's eligible for update (wrangler `rollout_active_grace_period`). */
|
|
27
38
|
gracePeriodSeconds?: number;
|
|
@@ -32,6 +43,7 @@ interface ContainerRollout {
|
|
|
32
43
|
* A pre-built image pulled from a registry — the Cloudflare Registry, Docker
|
|
33
44
|
* Hub, or Amazon ECR (the registries `wrangler deploy` supports). The
|
|
34
45
|
* reference must be fully qualified, e.g. `docker.io/acme/transcoder:1.4`.
|
|
46
|
+
* @experimental
|
|
35
47
|
*/
|
|
36
48
|
interface RegistryImageSource {
|
|
37
49
|
registry: string;
|
|
@@ -41,6 +53,7 @@ interface RegistryImageSource {
|
|
|
41
53
|
* source directory and `lunora deploy` builds an OCI image with Railpack
|
|
42
54
|
* (needs a BuildKit instance) and pushes it to the Cloudflare Registry before
|
|
43
55
|
* wrangler runs. Opt-in — the Dockerfile path is the zero-extra-deps default.
|
|
56
|
+
* @experimental
|
|
44
57
|
*/
|
|
45
58
|
interface BuildImageSource {
|
|
46
59
|
build: string;
|
|
@@ -50,6 +63,7 @@ interface BuildImageSource {
|
|
|
50
63
|
* either a directory containing a `Dockerfile` (normalized to
|
|
51
64
|
* `<dir>/Dockerfile` with the directory as the build context) or a path to
|
|
52
65
|
* the Dockerfile itself — while `{ registry }` is a pre-built image reference.
|
|
66
|
+
* @experimental
|
|
53
67
|
*/
|
|
54
68
|
type ContainerImageSource = BuildImageSource | RegistryImageSource | string;
|
|
55
69
|
/**
|
|
@@ -62,6 +76,7 @@ type ContainerImageSource = BuildImageSource | RegistryImageSource | string;
|
|
|
62
76
|
* functions), so codegen and the config layer can read it without evaluating
|
|
63
77
|
* code. (Upstream cloudflare/containers#188 expresses the same idea as handler
|
|
64
78
|
* functions; the Lunora config is data-only, so it's modelled as descriptors.)
|
|
79
|
+
* @experimental
|
|
65
80
|
*/
|
|
66
81
|
interface ContainerReadinessCheck {
|
|
67
82
|
/** HTTP path probed on the container, e.g. `"/ready"` (a leading slash is optional). */
|
|
@@ -71,6 +86,10 @@ interface ContainerReadinessCheck {
|
|
|
71
86
|
/** HTTP status that means "ready". Defaults to `200`. */
|
|
72
87
|
status?: number;
|
|
73
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* `ContainerConfig` is part of the experimental `@lunora/container` API and may change without a major version bump.
|
|
91
|
+
* @experimental
|
|
92
|
+
*/
|
|
74
93
|
interface ContainerConfig {
|
|
75
94
|
/**
|
|
76
95
|
* Hostnames the container may reach **even when {@link ContainerConfig.enableInternet}
|
|
@@ -227,12 +246,16 @@ interface ContainerConfig {
|
|
|
227
246
|
/**
|
|
228
247
|
* The value `defineContainer` returns: the validated config plus a brand the
|
|
229
248
|
* codegen discovery and the generated Container DO class key on.
|
|
249
|
+
* @experimental
|
|
230
250
|
*/
|
|
231
251
|
interface ContainerDefinition extends ContainerConfig {
|
|
232
252
|
/** Brand marking a value as a Lunora container definition. */
|
|
233
253
|
readonly isLunoraContainer: true;
|
|
234
254
|
}
|
|
235
|
-
/**
|
|
255
|
+
/**
|
|
256
|
+
* A normalized image source, as written into `wrangler.jsonc`.
|
|
257
|
+
* @experimental
|
|
258
|
+
*/
|
|
236
259
|
type NormalizedContainerImage = {
|
|
237
260
|
/** Build context directory (wrangler `image_build_context`). */
|
|
238
261
|
buildContext: string;
|
|
@@ -251,6 +274,7 @@ type NormalizedContainerImage = {
|
|
|
251
274
|
* Cloudflare Durable Object data-residency jurisdiction. Widening union —
|
|
252
275
|
* Cloudflare adds values over time.
|
|
253
276
|
* @see https://developers.cloudflare.com/durable-objects/reference/data-location/
|
|
277
|
+
* @experimental
|
|
254
278
|
*/
|
|
255
279
|
type DurableObjectJurisdiction = "eu" | "fedramp" | "us";
|
|
256
280
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/container",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.12",
|
|
4
4
|
"description": "Cloudflare Containers for Lunora: defineContainer, generated Container DO classes, and the ctx.containers action surface",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"access": "public"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@lunora/errors": "1.0.0-alpha.
|
|
59
|
+
"@lunora/errors": "1.0.0-alpha.5"
|
|
60
60
|
},
|
|
61
61
|
"engines": {
|
|
62
62
|
"node": "^22.15.0 || >=24.11.0"
|