@lunora/container 1.0.0-alpha.1 → 1.0.0-alpha.2
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/__assets__/package-og.svg +1 -1
- package/dist/do/index.d.mts +21 -1
- package/dist/do/index.d.ts +21 -1
- package/dist/do/index.mjs +27 -8
- package/dist/index.d.mts +13 -2
- package/dist/index.d.ts +13 -2
- package/dist/index.mjs +1 -1
- package/dist/packem_shared/{createContainerContext-ChDD53ys.mjs → createContainerContext-CTpyUQ4J.mjs} +14 -3
- package/package.json +1 -1
package/dist/do/index.d.mts
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
import { Container, StopParams } from '@cloudflare/containers';
|
|
2
2
|
import { C as ContainerDefinition } from "../packem_shared/types.d-D2l2SYol.mjs";
|
|
3
|
+
/**
|
|
4
|
+
* Cloudflare Durable Object data-residency jurisdiction. Widening union —
|
|
5
|
+
* Cloudflare adds values over time.
|
|
6
|
+
* @see https://developers.cloudflare.com/durable-objects/reference/data-location/
|
|
7
|
+
*/
|
|
8
|
+
type DurableObjectJurisdiction = "eu" | "fedramp" | "us";
|
|
9
|
+
/**
|
|
10
|
+
* Forward one lifecycle envelope to the root ShardDO's log buffer, best-effort.
|
|
11
|
+
*
|
|
12
|
+
* `env` is the Container DO's worker `env`: we read the `SHARD` namespace and
|
|
13
|
+
* the `LUNORA_ADMIN_TOKEN` from it. Returns a promise that NEVER rejects — every
|
|
14
|
+
* failure path (missing binding, missing token, fetch error) resolves to
|
|
15
|
+
* `undefined` — so the caller can `void` it from a lifecycle hook safely.
|
|
16
|
+
*/
|
|
3
17
|
type DurableObjectContext = ConstructorParameters<typeof Container>[0];
|
|
4
18
|
/**
|
|
5
19
|
* Base class for the generated Container DO classes. Applies a
|
|
@@ -19,9 +33,15 @@ type DurableObjectContext = ConstructorParameters<typeof Container>[0];
|
|
|
19
33
|
* ```
|
|
20
34
|
*/
|
|
21
35
|
declare class LunoraContainer<Env = unknown> extends Container<Env> {
|
|
36
|
+
/**
|
|
37
|
+
* Data-residency jurisdiction the app's DOs are pinned to (codegen passes the
|
|
38
|
+
* schema's `.jurisdiction("…")`). Used to pin the best-effort lifecycle report
|
|
39
|
+
* to the same region as the root shard. `undefined` ⇒ un-pinned.
|
|
40
|
+
*/
|
|
41
|
+
private readonly lunoraJurisdiction?;
|
|
22
42
|
/** The `lunora/containers.ts` export name, for lifecycle log correlation. */
|
|
23
43
|
private readonly lunoraName;
|
|
24
|
-
constructor(context: DurableObjectContext, env: Env, definition: ContainerDefinition, exportName?: string);
|
|
44
|
+
constructor(context: DurableObjectContext, env: Env, definition: ContainerDefinition, exportName?: string, jurisdiction?: DurableObjectJurisdiction);
|
|
25
45
|
override onError(error: unknown): unknown;
|
|
26
46
|
override onStart(): Promise<void>;
|
|
27
47
|
override onStop(parameters: StopParams): Promise<void>;
|
package/dist/do/index.d.ts
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
import { Container, StopParams } from '@cloudflare/containers';
|
|
2
2
|
import { C as ContainerDefinition } from "../packem_shared/types.d-D2l2SYol.js";
|
|
3
|
+
/**
|
|
4
|
+
* Cloudflare Durable Object data-residency jurisdiction. Widening union —
|
|
5
|
+
* Cloudflare adds values over time.
|
|
6
|
+
* @see https://developers.cloudflare.com/durable-objects/reference/data-location/
|
|
7
|
+
*/
|
|
8
|
+
type DurableObjectJurisdiction = "eu" | "fedramp" | "us";
|
|
9
|
+
/**
|
|
10
|
+
* Forward one lifecycle envelope to the root ShardDO's log buffer, best-effort.
|
|
11
|
+
*
|
|
12
|
+
* `env` is the Container DO's worker `env`: we read the `SHARD` namespace and
|
|
13
|
+
* the `LUNORA_ADMIN_TOKEN` from it. Returns a promise that NEVER rejects — every
|
|
14
|
+
* failure path (missing binding, missing token, fetch error) resolves to
|
|
15
|
+
* `undefined` — so the caller can `void` it from a lifecycle hook safely.
|
|
16
|
+
*/
|
|
3
17
|
type DurableObjectContext = ConstructorParameters<typeof Container>[0];
|
|
4
18
|
/**
|
|
5
19
|
* Base class for the generated Container DO classes. Applies a
|
|
@@ -19,9 +33,15 @@ type DurableObjectContext = ConstructorParameters<typeof Container>[0];
|
|
|
19
33
|
* ```
|
|
20
34
|
*/
|
|
21
35
|
declare class LunoraContainer<Env = unknown> extends Container<Env> {
|
|
36
|
+
/**
|
|
37
|
+
* Data-residency jurisdiction the app's DOs are pinned to (codegen passes the
|
|
38
|
+
* schema's `.jurisdiction("…")`). Used to pin the best-effort lifecycle report
|
|
39
|
+
* to the same region as the root shard. `undefined` ⇒ un-pinned.
|
|
40
|
+
*/
|
|
41
|
+
private readonly lunoraJurisdiction?;
|
|
22
42
|
/** The `lunora/containers.ts` export name, for lifecycle log correlation. */
|
|
23
43
|
private readonly lunoraName;
|
|
24
|
-
constructor(context: DurableObjectContext, env: Env, definition: ContainerDefinition, exportName?: string);
|
|
44
|
+
constructor(context: DurableObjectContext, env: Env, definition: ContainerDefinition, exportName?: string, jurisdiction?: DurableObjectJurisdiction);
|
|
25
45
|
override onError(error: unknown): unknown;
|
|
26
46
|
override onStart(): Promise<void>;
|
|
27
47
|
override onStop(parameters: StopParams): Promise<void>;
|
package/dist/do/index.mjs
CHANGED
|
@@ -27,6 +27,17 @@ const emitContainerLifecycle = (container, instance, event, message) => {
|
|
|
27
27
|
|
|
28
28
|
const RECORD_CONTAINER_EVENT_OP = "__lunora_admin__:recordContainerEvent";
|
|
29
29
|
const ROOT_SHARD_NAME = "__root__";
|
|
30
|
+
const applyJurisdiction = (namespace, jurisdiction) => {
|
|
31
|
+
if (jurisdiction === void 0) {
|
|
32
|
+
return namespace;
|
|
33
|
+
}
|
|
34
|
+
if (typeof namespace.jurisdiction !== "function") {
|
|
35
|
+
throw new TypeError(
|
|
36
|
+
`@lunora/container: Durable Object namespace does not support jurisdiction("${jurisdiction}") — update @cloudflare/workers-types or remove the jurisdiction option`
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
return namespace.jurisdiction(jurisdiction);
|
|
40
|
+
};
|
|
30
41
|
const isShardNamespace = (value) => {
|
|
31
42
|
if (value === null || typeof value !== "object") {
|
|
32
43
|
return false;
|
|
@@ -34,13 +45,14 @@ const isShardNamespace = (value) => {
|
|
|
34
45
|
const candidate = value;
|
|
35
46
|
return typeof candidate.get === "function" && typeof candidate.idFromName === "function";
|
|
36
47
|
};
|
|
37
|
-
const resolveRootShard = (namespace) => {
|
|
38
|
-
|
|
39
|
-
|
|
48
|
+
const resolveRootShard = (namespace, jurisdiction) => {
|
|
49
|
+
const pinned = applyJurisdiction(namespace, jurisdiction);
|
|
50
|
+
if (typeof pinned.getByName === "function") {
|
|
51
|
+
return pinned.getByName(ROOT_SHARD_NAME);
|
|
40
52
|
}
|
|
41
|
-
return
|
|
53
|
+
return pinned.get(pinned.idFromName(ROOT_SHARD_NAME));
|
|
42
54
|
};
|
|
43
|
-
const reportContainerLifecycle = async (env, envelope) => {
|
|
55
|
+
const reportContainerLifecycle = async (env, envelope, jurisdiction) => {
|
|
44
56
|
try {
|
|
45
57
|
const envRecord = env ?? {};
|
|
46
58
|
const namespace = envRecord["SHARD"];
|
|
@@ -56,15 +68,21 @@ const reportContainerLifecycle = async (env, envelope) => {
|
|
|
56
68
|
headers: { authorization: `Bearer ${adminBearer}`, "content-type": "application/json" },
|
|
57
69
|
method: "POST"
|
|
58
70
|
});
|
|
59
|
-
await resolveRootShard(namespace).fetch(request);
|
|
71
|
+
await resolveRootShard(namespace, jurisdiction).fetch(request);
|
|
60
72
|
} catch {
|
|
61
73
|
}
|
|
62
74
|
};
|
|
63
75
|
|
|
64
76
|
class LunoraContainer extends Container {
|
|
77
|
+
/**
|
|
78
|
+
* Data-residency jurisdiction the app's DOs are pinned to (codegen passes the
|
|
79
|
+
* schema's `.jurisdiction("…")`). Used to pin the best-effort lifecycle report
|
|
80
|
+
* to the same region as the root shard. `undefined` ⇒ un-pinned.
|
|
81
|
+
*/
|
|
82
|
+
lunoraJurisdiction;
|
|
65
83
|
/** The `lunora/containers.ts` export name, for lifecycle log correlation. */
|
|
66
84
|
lunoraName;
|
|
67
|
-
constructor(context, env, definition, exportName) {
|
|
85
|
+
constructor(context, env, definition, exportName, jurisdiction) {
|
|
68
86
|
super(context, env, {
|
|
69
87
|
defaultPort: definition.defaultPort,
|
|
70
88
|
envVars: resolveContainerEnvVariables(definition, env, exportName),
|
|
@@ -74,6 +92,7 @@ class LunoraContainer extends Container {
|
|
|
74
92
|
this.enableInternet = definition.enableInternet;
|
|
75
93
|
}
|
|
76
94
|
this.lunoraName = exportName ?? "container";
|
|
95
|
+
this.lunoraJurisdiction = jurisdiction;
|
|
77
96
|
}
|
|
78
97
|
onError(error) {
|
|
79
98
|
const envelope = emitContainerLifecycle(this.lunoraName, this.instanceId(), "error", error instanceof Error ? error.message : String(error));
|
|
@@ -98,7 +117,7 @@ class LunoraContainer extends Container {
|
|
|
98
117
|
* out of a lifecycle hook — the `console` path stays the source of truth.
|
|
99
118
|
*/
|
|
100
119
|
surfaceInStudioLogs(envelope) {
|
|
101
|
-
reportContainerLifecycle(this.env, envelope).catch(() => {
|
|
120
|
+
reportContainerLifecycle(this.env, envelope, this.lunoraJurisdiction).catch(() => {
|
|
102
121
|
});
|
|
103
122
|
}
|
|
104
123
|
/**
|
package/dist/index.d.mts
CHANGED
|
@@ -33,10 +33,21 @@ interface ContainerStubLike {
|
|
|
33
33
|
start?: (options?: ContainerStartOptions) => Promise<void>;
|
|
34
34
|
stop?: (signal?: number | string) => Promise<void>;
|
|
35
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Cloudflare Durable Object data-residency jurisdiction. Widening union —
|
|
38
|
+
* Cloudflare adds values over time.
|
|
39
|
+
* @see https://developers.cloudflare.com/durable-objects/reference/data-location/
|
|
40
|
+
*/
|
|
41
|
+
type DurableObjectJurisdiction = "eu" | "fedramp" | "us";
|
|
36
42
|
/** What the client needs from a Durable Object namespace binding. */
|
|
37
43
|
interface ContainerNamespaceLike {
|
|
38
44
|
get: (id: unknown) => ContainerStubLike;
|
|
39
45
|
idFromName: (name: string) => unknown;
|
|
46
|
+
/**
|
|
47
|
+
* Derive a jurisdiction-restricted subnamespace. Optional because older
|
|
48
|
+
* workers-types releases (and test doubles) may not expose it.
|
|
49
|
+
*/
|
|
50
|
+
jurisdiction?: (jurisdiction: DurableObjectJurisdiction) => ContainerNamespaceLike;
|
|
40
51
|
}
|
|
41
52
|
/** A handle on one container instance (one Durable Object). */
|
|
42
53
|
interface ContainerHandle {
|
|
@@ -126,7 +137,7 @@ interface ContainerBindingSpec {
|
|
|
126
137
|
* handle is actually used — so one unprovisioned container never breaks
|
|
127
138
|
* unrelated functions.
|
|
128
139
|
*/
|
|
129
|
-
declare const createContainerContext: (env: Record<string, unknown>, specs: ReadonlyArray<ContainerBindingSpec
|
|
140
|
+
declare const createContainerContext: (env: Record<string, unknown>, specs: ReadonlyArray<ContainerBindingSpec>, jurisdiction?: DurableObjectJurisdiction) => Record<string, ContainerAccessor>;
|
|
130
141
|
/** A test handler: receives the request plus the targeted instance name. */
|
|
131
142
|
type ContainerTestHandler = (request: Request, instance: {
|
|
132
143
|
name: string;
|
|
@@ -186,4 +197,4 @@ declare const isContainerDefinition: (value: unknown) => value is ContainerDefin
|
|
|
186
197
|
* credential it was promised yields far worse errors downstream.
|
|
187
198
|
*/
|
|
188
199
|
declare const resolveContainerEnvVariables: (definition: ContainerDefinition, workerEnv: Record<string, unknown>, exportName?: string) => Record<string, string>;
|
|
189
|
-
export { type ContainerAccessor, type ContainerBindingSpec, type ContainerConfig, type ContainerDefinition, type ContainerHandle, type ContainerImageSource, type ContainerInstanceHandle, type ContainerInstanceState, type ContainerNamespaceLike, type ContainerStartOptions, type ContainerTestHandler, type NormalizedContainerImage, type PoolOptions, containerBindingName, containerBuildTag, containerClassName, createContainerContext, createContainerTestContext, defineContainer, isContainerDefinition, normalizeContainerImage, resolveContainerEnvVariables as resolveContainerEnvVars };
|
|
200
|
+
export { type ContainerAccessor, type ContainerBindingSpec, type ContainerConfig, type ContainerDefinition, type ContainerHandle, type ContainerImageSource, type ContainerInstanceHandle, type ContainerInstanceState, type ContainerNamespaceLike, type ContainerStartOptions, type ContainerTestHandler, type DurableObjectJurisdiction, type NormalizedContainerImage, type PoolOptions, containerBindingName, containerBuildTag, containerClassName, createContainerContext, createContainerTestContext, defineContainer, isContainerDefinition, normalizeContainerImage, resolveContainerEnvVariables as resolveContainerEnvVars };
|
package/dist/index.d.ts
CHANGED
|
@@ -33,10 +33,21 @@ interface ContainerStubLike {
|
|
|
33
33
|
start?: (options?: ContainerStartOptions) => Promise<void>;
|
|
34
34
|
stop?: (signal?: number | string) => Promise<void>;
|
|
35
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Cloudflare Durable Object data-residency jurisdiction. Widening union —
|
|
38
|
+
* Cloudflare adds values over time.
|
|
39
|
+
* @see https://developers.cloudflare.com/durable-objects/reference/data-location/
|
|
40
|
+
*/
|
|
41
|
+
type DurableObjectJurisdiction = "eu" | "fedramp" | "us";
|
|
36
42
|
/** What the client needs from a Durable Object namespace binding. */
|
|
37
43
|
interface ContainerNamespaceLike {
|
|
38
44
|
get: (id: unknown) => ContainerStubLike;
|
|
39
45
|
idFromName: (name: string) => unknown;
|
|
46
|
+
/**
|
|
47
|
+
* Derive a jurisdiction-restricted subnamespace. Optional because older
|
|
48
|
+
* workers-types releases (and test doubles) may not expose it.
|
|
49
|
+
*/
|
|
50
|
+
jurisdiction?: (jurisdiction: DurableObjectJurisdiction) => ContainerNamespaceLike;
|
|
40
51
|
}
|
|
41
52
|
/** A handle on one container instance (one Durable Object). */
|
|
42
53
|
interface ContainerHandle {
|
|
@@ -126,7 +137,7 @@ interface ContainerBindingSpec {
|
|
|
126
137
|
* handle is actually used — so one unprovisioned container never breaks
|
|
127
138
|
* unrelated functions.
|
|
128
139
|
*/
|
|
129
|
-
declare const createContainerContext: (env: Record<string, unknown>, specs: ReadonlyArray<ContainerBindingSpec
|
|
140
|
+
declare const createContainerContext: (env: Record<string, unknown>, specs: ReadonlyArray<ContainerBindingSpec>, jurisdiction?: DurableObjectJurisdiction) => Record<string, ContainerAccessor>;
|
|
130
141
|
/** A test handler: receives the request plus the targeted instance name. */
|
|
131
142
|
type ContainerTestHandler = (request: Request, instance: {
|
|
132
143
|
name: string;
|
|
@@ -186,4 +197,4 @@ declare const isContainerDefinition: (value: unknown) => value is ContainerDefin
|
|
|
186
197
|
* credential it was promised yields far worse errors downstream.
|
|
187
198
|
*/
|
|
188
199
|
declare const resolveContainerEnvVariables: (definition: ContainerDefinition, workerEnv: Record<string, unknown>, exportName?: string) => Record<string, string>;
|
|
189
|
-
export { type ContainerAccessor, type ContainerBindingSpec, type ContainerConfig, type ContainerDefinition, type ContainerHandle, type ContainerImageSource, type ContainerInstanceHandle, type ContainerInstanceState, type ContainerNamespaceLike, type ContainerStartOptions, type ContainerTestHandler, type NormalizedContainerImage, type PoolOptions, containerBindingName, containerBuildTag, containerClassName, createContainerContext, createContainerTestContext, defineContainer, isContainerDefinition, normalizeContainerImage, resolveContainerEnvVariables as resolveContainerEnvVars };
|
|
200
|
+
export { type ContainerAccessor, type ContainerBindingSpec, type ContainerConfig, type ContainerDefinition, type ContainerHandle, type ContainerImageSource, type ContainerInstanceHandle, type ContainerInstanceState, type ContainerNamespaceLike, type ContainerStartOptions, type ContainerTestHandler, type DurableObjectJurisdiction, 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-CTpyUQ4J.mjs';
|
|
2
2
|
export { containerBindingName, containerBuildTag, containerClassName, defineContainer, isContainerDefinition, normalizeContainerImage, resolveContainerEnvVars } from './packem_shared/containerBindingName-BGdSdFNA.mjs';
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
const applyJurisdiction = (namespace, jurisdiction) => {
|
|
2
|
+
if (jurisdiction === void 0) {
|
|
3
|
+
return namespace;
|
|
4
|
+
}
|
|
5
|
+
if (typeof namespace.jurisdiction !== "function") {
|
|
6
|
+
throw new TypeError(
|
|
7
|
+
`@lunora/container: Durable Object namespace does not support jurisdiction("${jurisdiction}") — update @cloudflare/workers-types or remove the jurisdiction option`
|
|
8
|
+
);
|
|
9
|
+
}
|
|
10
|
+
return namespace.jurisdiction(jurisdiction);
|
|
11
|
+
};
|
|
1
12
|
const DEFAULT_POOL_SIZE = 3;
|
|
2
13
|
const DEFAULT_MAX_BACKOFF_MS = 3e4;
|
|
3
14
|
const toRequest = (input, init) => {
|
|
@@ -83,11 +94,11 @@ const missingBindingAccessor = (spec) => {
|
|
|
83
94
|
};
|
|
84
95
|
return { any: fail, get: fail, pool: fail };
|
|
85
96
|
};
|
|
86
|
-
const createContainerContext = (env, specs) => {
|
|
97
|
+
const createContainerContext = (env, specs, jurisdiction) => {
|
|
87
98
|
const containers = {};
|
|
88
99
|
for (const spec of specs) {
|
|
89
|
-
const
|
|
90
|
-
containers[spec.exportName] =
|
|
100
|
+
const binding = env[spec.binding];
|
|
101
|
+
containers[spec.exportName] = binding && typeof binding.idFromName === "function" && typeof binding.get === "function" ? accessorFor(applyJurisdiction(binding, jurisdiction), spec) : missingBindingAccessor(spec);
|
|
91
102
|
}
|
|
92
103
|
return containers;
|
|
93
104
|
};
|
package/package.json
CHANGED