@lunora/platform-cloudflare 0.0.0 → 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/LICENSE.md ADDED
@@ -0,0 +1,111 @@
1
+ # Functional Source License, Version 1.1, Apache 2.0 Future License
2
+
3
+ ## Abbreviation
4
+
5
+ FSL-1.1-Apache-2.0
6
+
7
+ ## Notice
8
+
9
+ Copyright 2026 anolilab and contributors
10
+
11
+ ## Terms and Conditions
12
+
13
+ ### Licensor ("We")
14
+
15
+ The party offering the Software under these Terms and Conditions.
16
+
17
+ ### The Software
18
+
19
+ The "Software" is each version of the software that we make available under
20
+ these Terms and Conditions, as indicated by our inclusion of these Terms and
21
+ Conditions with the Software.
22
+
23
+ ### License Grant
24
+
25
+ Subject to your compliance with this License Grant and the Patents,
26
+ Redistribution and Trademark clauses below, we hereby grant you the right to
27
+ use, copy, modify, create derivative works, publicly perform, publicly display
28
+ and redistribute the Software for any Permitted Purpose identified below.
29
+
30
+ ### Permitted Purpose
31
+
32
+ A Permitted Purpose is any purpose other than a Competing Use. A Competing Use
33
+ means making the Software available to others in a commercial product or service
34
+ that:
35
+
36
+ 1. substitutes for the Software;
37
+
38
+ 2. substitutes for any other product or service we offer using the Software that
39
+ exists as of the date we make the Software available; or
40
+
41
+ 3. offers the same or substantially similar functionality as the Software.
42
+
43
+ Permitted Purposes specifically include using the Software:
44
+
45
+ 1. for your internal use and access;
46
+
47
+ 2. for non-commercial education;
48
+
49
+ 3. for non-commercial research; and
50
+
51
+ 4. in connection with professional services that you provide to a licensee using
52
+ the Software in accordance with these Terms and Conditions.
53
+
54
+ ### Patents
55
+
56
+ To the extent your use for a Permitted Purpose would necessarily infringe our
57
+ patents, the license grant above includes a license under our patents. If you
58
+ make a claim against any party that the Software infringes or contributes to the
59
+ infringement of any patent, then your patent license to the Software ends
60
+ immediately.
61
+
62
+ ### Redistribution
63
+
64
+ The Terms and Conditions apply to all copies, modifications and derivatives of
65
+ the Software.
66
+
67
+ If you redistribute any copies, modifications or derivatives of the Software,
68
+ you must include a copy of or a link to these Terms and Conditions and not
69
+ remove any copyright notices provided in or with the Software.
70
+
71
+ ### Disclaimer
72
+
73
+ THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR
74
+ IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF FITNESS FOR A PARTICULAR
75
+ PURPOSE, MERCHANTABILITY, TITLE OR NON-INFRINGEMENT.
76
+
77
+ IN NO EVENT WILL WE HAVE ANY LIABILITY TO YOU ARISING OUT OF OR RELATED TO THE
78
+ SOFTWARE, INCLUDING INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, EVEN
79
+ IF WE HAVE BEEN INFORMED OF THEIR POSSIBILITY IN ADVANCE.
80
+
81
+ ### Trademarks
82
+
83
+ Except for displaying the License Details and identifying us as the origin of
84
+ the Software, you have no right under these Terms and Conditions to use our
85
+ trademarks, trade names, service marks or product names.
86
+
87
+ ## Grant of Future License
88
+
89
+ We hereby irrevocably grant you an additional license to use the Software under
90
+ the Apache License, Version 2.0 that is effective on the second anniversary of
91
+ the date we make the Software available. On or after that date, you may use the
92
+ Software under the Apache License, Version 2.0, in which case the following will
93
+ apply:
94
+
95
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not use
96
+ this file except in compliance with the License.
97
+
98
+ You may obtain a copy of the License at
99
+
100
+ http://www.apache.org/licenses/LICENSE-2.0
101
+
102
+ Unless required by applicable law or agreed to in writing, software distributed
103
+ under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
104
+ CONDITIONS OF ANY KIND, either express or implied. See the License for the
105
+ specific language governing permissions and limitations under the License.
106
+
107
+ <!-- DEPENDENCIES -->
108
+ <!-- /DEPENDENCIES -->
109
+
110
+ <!-- TYPE_DEPENDENCIES -->
111
+ <!-- /TYPE_DEPENDENCIES -->
package/README.md CHANGED
@@ -1,45 +1,18 @@
1
- # @lunora/platform-cloudflare
1
+ # `@lunora/platform-cloudflare`
2
2
 
3
- ## ⚠️ IMPORTANT NOTICE ⚠️
3
+ The Cloudflare implementation of the [`@lunora/platform`](../platform) host contracts.
4
4
 
5
- **This package is created solely for the purpose of setting up OIDC (OpenID Connect) trusted publishing with npm.**
5
+ `@lunora/platform` defines _what_ a host must provide `ShardHost`, `SocketHost`, `ShardDirectory`, `ShardKvStore`. This package provides it for Cloudflare, over `DurableObjectState`, hibernatable WebSockets, and a `DurableObjectNamespace`.
6
6
 
7
- This is **NOT** a functional package and contains **NO** code or functionality beyond the OIDC setup configuration.
7
+ ```ts
8
+ import { createShardPlatform } from "@lunora/platform-cloudflare";
8
9
 
9
- ## Purpose
10
+ // Inside a Durable Object:
11
+ const platform = createShardPlatform(state);
12
+ ```
10
13
 
11
- This package exists to:
12
- 1. Configure OIDC trusted publishing for the package name `@lunora/platform-cloudflare`
13
- 2. Enable secure, token-less publishing from CI/CD workflows
14
- 3. Establish provenance for packages published under this name
14
+ ## Why it exists
15
15
 
16
- ## What is OIDC Trusted Publishing?
16
+ So a second target is an addition rather than a refactor. `@lunora/do` depends on this package, not on Cloudflare directly — every provider API it needs arrives through a contract. Plan 114's Node/AWS host (§§6–9) ships the same surface from `@lunora/platform-aws`, and `@lunora/do` changes only which package it composes.
17
17
 
18
- OIDC trusted publishing allows package maintainers to publish packages directly from their CI/CD workflows without needing to manage npm access tokens. Instead, it uses OpenID Connect to establish trust between the CI/CD provider (like GitHub Actions) and npm.
19
-
20
- ## Setup Instructions
21
-
22
- To properly configure OIDC trusted publishing for this package:
23
-
24
- 1. Go to [npmjs.com](https://www.npmjs.com/) and navigate to your package settings
25
- 2. Configure the trusted publisher (e.g., GitHub Actions)
26
- 3. Specify the repository and workflow that should be allowed to publish
27
- 4. Use the configured workflow to publish your actual package
28
-
29
- ## DO NOT USE THIS PACKAGE
30
-
31
- This package is a placeholder for OIDC configuration only. It:
32
- - Contains no executable code
33
- - Provides no functionality
34
- - Should not be installed as a dependency
35
- - Exists only for administrative purposes
36
-
37
- ## More Information
38
-
39
- For more details about npm's trusted publishing feature, see:
40
- - [npm Trusted Publishing Documentation](https://docs.npmjs.com/generating-provenance-statements)
41
- - [GitHub Actions OIDC Documentation](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect)
42
-
43
- ---
44
-
45
- **Maintained for OIDC setup purposes only**
18
+ The adapters are verified by the conformance suites in `@lunora/platform/conformance` and `@lunora/shard-engine/conformance`, run against a real Durable Object in `@lunora/do`'s workerd project.
@@ -0,0 +1,127 @@
1
+ import { DurableObjectNamespace, DurableObjectState } from '@cloudflare/workers-types';
2
+ import { ShardAlarms, ShardDirectory, ShardHost, ShardKvStore, SocketHost, PlatformCapabilities, SchedulerHost } from '@lunora/platform';
3
+ /** The alarm subset of `state.storage`, structurally (shared by shard + session hosts). */
4
+ interface AlarmStorageLike {
5
+ deleteAlarm?: () => Promise<void>;
6
+ getAlarm?: () => Promise<number | null>;
7
+ setAlarm?: (scheduledTime: number | Date) => Promise<void>;
8
+ }
9
+ /**
10
+ * Turn a DO's `state.storage` alarm surface into {@link ShardAlarms}. Each
11
+ * primitive is probed at call time so a test double lacking the alarm API
12
+ * degrades to a no-op (and a missing alarm reads as `null`) rather than
13
+ * throwing — the pre-contract behavior on those doubles.
14
+ */
15
+ declare const createShardAlarms: (storage: AlarmStorageLike) => ShardAlarms;
16
+ declare const createShardHost: (state: DurableObjectState) => ShardHost;
17
+ /**
18
+ * The `state.storage` key-value surface, structurally. Declared here rather
19
+ * than taking a full `DurableObjectState` so the adapter also accepts the
20
+ * plain-object doubles `SessionDO`'s unit tests pass — they carry exactly this
21
+ * shape and nothing else.
22
+ */
23
+ interface KvStorageLike {
24
+ delete: (key: string) => Promise<boolean | number>;
25
+ get: <T = unknown>(key: string) => Promise<T | undefined>;
26
+ list?: <T = unknown>(options?: {
27
+ prefix?: string;
28
+ }) => Promise<Map<string, T>>;
29
+ put: (key: string, value: unknown) => Promise<void>;
30
+ }
31
+ /**
32
+ * Turn a Durable Object's `state.storage` into the provider-neutral
33
+ * {@link ShardKvStore}. The DO's KV surface already matches the contract
34
+ * method-for-method; this adapter only normalizes the return of `delete`
35
+ * (workerd resolves a boolean, some doubles a number) and fails closed on a
36
+ * `list` the underlying storage does not provide.
37
+ */
38
+ declare const createShardKvStore: (storage: KvStorageLike) => ShardKvStore;
39
+ /**
40
+ * Build the socket host for a DO.
41
+ *
42
+ * Note what is deliberately absent: `setTag` / `removeTag`. Cloudflare freezes
43
+ * a socket's tags at `acceptWebSocket`, so declaring mutable tagging would be a
44
+ * lie the engine could route on. Per the `SocketHost` contract, omitting both
45
+ * tells callers to re-accept instead.
46
+ */
47
+ declare const createSocketHost: (state: DurableObjectState) => SocketHost;
48
+ /**
49
+ * Turn a Durable Object namespace binding into a {@link ShardDirectory}.
50
+ *
51
+ * Cloudflare populates the whole direct branch: `idFromName` is the
52
+ * deterministic placement function, `get` materializes the stub, and
53
+ * `jurisdiction` narrows placement for data-residency regimes. A jurisdiction
54
+ * the runtime doesn't recognize throws rather than silently placing the shard
55
+ * anywhere — the contract requires callers to fail closed.
56
+ */
57
+ declare const createShardDirectory: (namespace: DurableObjectNamespace) => ShardDirectory;
58
+ /**
59
+ * The contracts available inside one Durable Object instance.
60
+ *
61
+ * `shard.alarms` is the alarm surface — there is deliberately no separate
62
+ * `alarms` member, because a second route to the same thing is interface weight
63
+ * without leverage.
64
+ */
65
+ interface ShardPlatform {
66
+ /** Durable key-value storage for this shard. */
67
+ kv: ShardKvStore;
68
+ /** Single-writer execution, local SQL, transactions, alarms, identity. */
69
+ shard: ShardHost;
70
+ /** Hibernated WebSocket subscriptions for this shard. */
71
+ sockets: SocketHost;
72
+ }
73
+ /** The contracts available in the Worker entry, resolved from its bindings. */
74
+ interface WorkerPlatform {
75
+ /** What this target supports, for codegen diagnostics and parity reporting. */
76
+ capabilities: PlatformCapabilities;
77
+ /**
78
+ * Resolve a Durable Object namespace binding to a shard directory.
79
+ *
80
+ * A function rather than a value because a Worker routinely binds several
81
+ * namespaces (`SHARD`, `SESSION`, `SCHEDULER`), and which one a caller wants
82
+ * is call-site knowledge.
83
+ * @throws when the named binding is absent from `env` — a missing namespace
84
+ * is a deploy misconfiguration, and failing here beats surfacing later as an
85
+ * unroutable shard.
86
+ */
87
+ directory: (binding: string) => ShardDirectory;
88
+ /**
89
+ * Durable delayed jobs, present only when the app supplies the `SchedulerDO`
90
+ * wiring. Its `cron` member is always absent on this target — Cloudflare
91
+ * crons are declared in `wrangler.jsonc`, not registered at runtime.
92
+ */
93
+ scheduler?: SchedulerHost;
94
+ }
95
+ /** Options for {@link createWorkerPlatform}. */
96
+ interface WorkerPlatformOptions {
97
+ /**
98
+ * The durable scheduler host, when the app has one. Injected rather than
99
+ * constructed here: building it requires `@lunora/scheduler` (it wraps
100
+ * `SchedulerDO`), and that is an edge this package must not take for a
101
+ * feature most shards never use. Build it once at the worker entry with
102
+ * `createSchedulerHost` from `@lunora/scheduler` and pass it in.
103
+ */
104
+ scheduler?: SchedulerHost;
105
+ }
106
+ /**
107
+ * Compose every shard-scoped contract from a Durable Object's state.
108
+ *
109
+ * Cheap and allocation-light, so a DO can call it once in its constructor. The
110
+ * adapters read through to `state` on each call rather than snapshotting it,
111
+ * which is what keeps live values correct across a hibernation wake — the alarm
112
+ * timestamp, the database size, and the live socket set all move underneath.
113
+ *
114
+ * `state` is typed `unknown` so this package does not force
115
+ * `@cloudflare/workers-types` onto callers that are already holding the runtime
116
+ * object; the adapters narrow it internally.
117
+ */
118
+ declare const createShardPlatform: (state: unknown) => ShardPlatform;
119
+ /**
120
+ * Compose every Worker-scoped contract from the Worker's `env`.
121
+ *
122
+ * `env` is typed `unknown` on purpose: its shape is the app's, generated per
123
+ * project, and this package must not require a project-specific type to be
124
+ * threaded through it.
125
+ */
126
+ declare const createWorkerPlatform: (env: unknown, options?: WorkerPlatformOptions) => WorkerPlatform;
127
+ export { type ShardPlatform, type WorkerPlatform, type WorkerPlatformOptions, createShardAlarms, createShardDirectory, createShardHost, createShardKvStore, createShardPlatform, createSocketHost, createWorkerPlatform };
@@ -0,0 +1,127 @@
1
+ import { DurableObjectNamespace, DurableObjectState } from '@cloudflare/workers-types';
2
+ import { ShardAlarms, ShardDirectory, ShardHost, ShardKvStore, SocketHost, PlatformCapabilities, SchedulerHost } from '@lunora/platform';
3
+ /** The alarm subset of `state.storage`, structurally (shared by shard + session hosts). */
4
+ interface AlarmStorageLike {
5
+ deleteAlarm?: () => Promise<void>;
6
+ getAlarm?: () => Promise<number | null>;
7
+ setAlarm?: (scheduledTime: number | Date) => Promise<void>;
8
+ }
9
+ /**
10
+ * Turn a DO's `state.storage` alarm surface into {@link ShardAlarms}. Each
11
+ * primitive is probed at call time so a test double lacking the alarm API
12
+ * degrades to a no-op (and a missing alarm reads as `null`) rather than
13
+ * throwing — the pre-contract behavior on those doubles.
14
+ */
15
+ declare const createShardAlarms: (storage: AlarmStorageLike) => ShardAlarms;
16
+ declare const createShardHost: (state: DurableObjectState) => ShardHost;
17
+ /**
18
+ * The `state.storage` key-value surface, structurally. Declared here rather
19
+ * than taking a full `DurableObjectState` so the adapter also accepts the
20
+ * plain-object doubles `SessionDO`'s unit tests pass — they carry exactly this
21
+ * shape and nothing else.
22
+ */
23
+ interface KvStorageLike {
24
+ delete: (key: string) => Promise<boolean | number>;
25
+ get: <T = unknown>(key: string) => Promise<T | undefined>;
26
+ list?: <T = unknown>(options?: {
27
+ prefix?: string;
28
+ }) => Promise<Map<string, T>>;
29
+ put: (key: string, value: unknown) => Promise<void>;
30
+ }
31
+ /**
32
+ * Turn a Durable Object's `state.storage` into the provider-neutral
33
+ * {@link ShardKvStore}. The DO's KV surface already matches the contract
34
+ * method-for-method; this adapter only normalizes the return of `delete`
35
+ * (workerd resolves a boolean, some doubles a number) and fails closed on a
36
+ * `list` the underlying storage does not provide.
37
+ */
38
+ declare const createShardKvStore: (storage: KvStorageLike) => ShardKvStore;
39
+ /**
40
+ * Build the socket host for a DO.
41
+ *
42
+ * Note what is deliberately absent: `setTag` / `removeTag`. Cloudflare freezes
43
+ * a socket's tags at `acceptWebSocket`, so declaring mutable tagging would be a
44
+ * lie the engine could route on. Per the `SocketHost` contract, omitting both
45
+ * tells callers to re-accept instead.
46
+ */
47
+ declare const createSocketHost: (state: DurableObjectState) => SocketHost;
48
+ /**
49
+ * Turn a Durable Object namespace binding into a {@link ShardDirectory}.
50
+ *
51
+ * Cloudflare populates the whole direct branch: `idFromName` is the
52
+ * deterministic placement function, `get` materializes the stub, and
53
+ * `jurisdiction` narrows placement for data-residency regimes. A jurisdiction
54
+ * the runtime doesn't recognize throws rather than silently placing the shard
55
+ * anywhere — the contract requires callers to fail closed.
56
+ */
57
+ declare const createShardDirectory: (namespace: DurableObjectNamespace) => ShardDirectory;
58
+ /**
59
+ * The contracts available inside one Durable Object instance.
60
+ *
61
+ * `shard.alarms` is the alarm surface — there is deliberately no separate
62
+ * `alarms` member, because a second route to the same thing is interface weight
63
+ * without leverage.
64
+ */
65
+ interface ShardPlatform {
66
+ /** Durable key-value storage for this shard. */
67
+ kv: ShardKvStore;
68
+ /** Single-writer execution, local SQL, transactions, alarms, identity. */
69
+ shard: ShardHost;
70
+ /** Hibernated WebSocket subscriptions for this shard. */
71
+ sockets: SocketHost;
72
+ }
73
+ /** The contracts available in the Worker entry, resolved from its bindings. */
74
+ interface WorkerPlatform {
75
+ /** What this target supports, for codegen diagnostics and parity reporting. */
76
+ capabilities: PlatformCapabilities;
77
+ /**
78
+ * Resolve a Durable Object namespace binding to a shard directory.
79
+ *
80
+ * A function rather than a value because a Worker routinely binds several
81
+ * namespaces (`SHARD`, `SESSION`, `SCHEDULER`), and which one a caller wants
82
+ * is call-site knowledge.
83
+ * @throws when the named binding is absent from `env` — a missing namespace
84
+ * is a deploy misconfiguration, and failing here beats surfacing later as an
85
+ * unroutable shard.
86
+ */
87
+ directory: (binding: string) => ShardDirectory;
88
+ /**
89
+ * Durable delayed jobs, present only when the app supplies the `SchedulerDO`
90
+ * wiring. Its `cron` member is always absent on this target — Cloudflare
91
+ * crons are declared in `wrangler.jsonc`, not registered at runtime.
92
+ */
93
+ scheduler?: SchedulerHost;
94
+ }
95
+ /** Options for {@link createWorkerPlatform}. */
96
+ interface WorkerPlatformOptions {
97
+ /**
98
+ * The durable scheduler host, when the app has one. Injected rather than
99
+ * constructed here: building it requires `@lunora/scheduler` (it wraps
100
+ * `SchedulerDO`), and that is an edge this package must not take for a
101
+ * feature most shards never use. Build it once at the worker entry with
102
+ * `createSchedulerHost` from `@lunora/scheduler` and pass it in.
103
+ */
104
+ scheduler?: SchedulerHost;
105
+ }
106
+ /**
107
+ * Compose every shard-scoped contract from a Durable Object's state.
108
+ *
109
+ * Cheap and allocation-light, so a DO can call it once in its constructor. The
110
+ * adapters read through to `state` on each call rather than snapshotting it,
111
+ * which is what keeps live values correct across a hibernation wake — the alarm
112
+ * timestamp, the database size, and the live socket set all move underneath.
113
+ *
114
+ * `state` is typed `unknown` so this package does not force
115
+ * `@cloudflare/workers-types` onto callers that are already holding the runtime
116
+ * object; the adapters narrow it internally.
117
+ */
118
+ declare const createShardPlatform: (state: unknown) => ShardPlatform;
119
+ /**
120
+ * Compose every Worker-scoped contract from the Worker's `env`.
121
+ *
122
+ * `env` is typed `unknown` on purpose: its shape is the app's, generated per
123
+ * project, and this package must not require a project-specific type to be
124
+ * threaded through it.
125
+ */
126
+ declare const createWorkerPlatform: (env: unknown, options?: WorkerPlatformOptions) => WorkerPlatform;
127
+ export { type ShardPlatform, type WorkerPlatform, type WorkerPlatformOptions, createShardAlarms, createShardDirectory, createShardHost, createShardKvStore, createShardPlatform, createSocketHost, createWorkerPlatform };
package/dist/index.mjs ADDED
@@ -0,0 +1 @@
1
+ import{createShardAlarms as t,createShardDirectory as a,createShardHost as o,createShardKvStore as c,createSocketHost as S}from"./packem_shared/createShardAlarms-CbNRtmSR.mjs";import{createShardPlatform as h,createWorkerPlatform as m}from"./packem_shared/createShardPlatform-BhZo43dZ.mjs";export{t as createShardAlarms,a as createShardDirectory,o as createShardHost,c as createShardKvStore,h as createShardPlatform,S as createSocketHost,m as createWorkerPlatform};
@@ -0,0 +1 @@
1
+ const h=(t,e,n)=>{const a=t.storage.sql;if(typeof a?.exec!="function")throw new TypeError("storage.sql.exec is not available on this DurableObjectState");return a.exec(e,...n)},y=t=>({delete:()=>typeof t.deleteAlarm=="function"?t.deleteAlarm():Promise.resolve(),get:()=>typeof t.getAlarm=="function"?t.getAlarm():null,set:e=>typeof t.setAlarm=="function"?t.setAlarm(e):Promise.resolve()}),b=t=>{const{storage:e}=t,n={get databaseSize(){return t.storage.sql?.databaseSize},exec:(r,...s)=>h(t,r,s)},a=y(e),i=async r=>typeof t.blockConcurrencyWhile=="function"?t.blockConcurrencyWhile(r):r(),o=async r=>{const s=e;return typeof s?.transaction=="function"?s.transaction(async()=>r()):r()};return{alarms:a,runSerialized:i,shardKey:t.id?.name,sql:n,transaction:o,waitUntil:typeof t.waitUntil=="function"?r=>{t.waitUntil(r)}:void 0}},k=t=>({delete:async e=>!!await t.delete(e),get:e=>t.get(e),list:e=>{if(typeof t.list!="function")throw new TypeError("storage.list is not available on this DurableObjectStorage");return t.list(e)},put:(e,n)=>t.put(e,n)}),l="lunora-socket:",u=new WeakMap,g=new WeakMap;let d=0;const m=(t,e)=>{const{getTags:n}=t;if(typeof n!="function")return!1;try{return n.call(t,e).some(a=>a.startsWith(l))}catch{return!1}},p=(t,e)=>{const{getTags:n}=t;if(typeof n=="function"){let r;try{r=n.call(t,e).find(s=>s.startsWith(l))}catch{r=void 0}if(r!==void 0)return r.slice(l.length)}const a=u.get(e);if(a!==void 0)return a;const i=g.get(e);if(i!==void 0)return i;d+=1;const o=`cf-socket-${String(d)}`;return g.set(e,o),o},w=t=>{const e=new WeakSet;let n=0,a;const i=()=>{const o=t.getWebSockets();return(a?.generation!==n||a.length!==o.length)&&(a={generation:n,length:o.length,set:new WeakSet(o)}),a.set};return{accept:(o,r,s)=>{const c=o,f=crypto.randomUUID();return t.acceptWebSocket(c,[`${l}${f}`,...s??[]]),u.set(c,f),n+=1,r!==void 0&&c.serializeAttachment?.(r),c},getSockets:o=>t.getWebSockets(o),handleFor:o=>{const r=o;if(u.has(r)||m(t,r))return r;if(!e.has(r)){if(i().has(r))return r;e.add(r)}},idFor:o=>p(t,o)}},S=t=>{const e=n=>({fetch:a=>n.fetch(a)});return{get:n=>e(t.get(n)),getByName:n=>e(t.get(t.idFromName(n))),idForName:n=>t.idFromName(n),jurisdiction:n=>S(t.jurisdiction(n))}};export{y as createShardAlarms,S as createShardDirectory,b as createShardHost,k as createShardKvStore,w as createSocketHost};
@@ -0,0 +1 @@
1
+ import{CLOUDFLARE_CAPABILITIES as c}from"@lunora/platform";import{createSocketHost as d,createShardHost as n,createShardKvStore as i,createShardDirectory as l}from"./createShardAlarms-CbNRtmSR.mjs";const b=e=>{const r=e;return{kv:i(r.storage),shard:n(r),sockets:d(r)}},m=(e,r={})=>{const s=e??{},t=o=>{const a=s[o];if(a==null)throw new Error(`@lunora/platform-cloudflare: no Durable Object namespace bound as "${o}" — add it to wrangler.jsonc's durable_objects.bindings`);return l(a)};return r.scheduler===void 0?{capabilities:c,directory:t}:{capabilities:c,directory:t,scheduler:r.scheduler}};export{b as createShardPlatform,m as createWorkerPlatform};
package/package.json CHANGED
@@ -1,10 +1,51 @@
1
1
  {
2
2
  "name": "@lunora/platform-cloudflare",
3
- "version": "0.0.0",
4
- "description": "OIDC trusted publishing setup package for @lunora/platform-cloudflare",
3
+ "version": "1.0.0-alpha.2",
4
+ "description": "Cloudflare implementation of the Lunora platform contracts: ShardHost, SocketHost, ShardDirectory, ShardKvStore over Durable Objects",
5
5
  "keywords": [
6
- "oidc",
7
- "trusted-publishing",
8
- "setup"
9
- ]
10
- }
6
+ "cloudflare",
7
+ "durable-objects",
8
+ "lunora",
9
+ "platform",
10
+ "portability",
11
+ "workers"
12
+ ],
13
+ "homepage": "https://lunora.sh",
14
+ "bugs": "https://github.com/anolilab/lunora/issues",
15
+ "license": "FSL-1.1-Apache-2.0",
16
+ "author": {
17
+ "name": "Daniel Bannert",
18
+ "email": "d.bannert@anolilab.de"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/anolilab/lunora.git",
23
+ "directory": "packages/platform-cloudflare"
24
+ },
25
+ "files": [
26
+ "./dist",
27
+ "README.md",
28
+ "LICENSE.md"
29
+ ],
30
+ "type": "module",
31
+ "sideEffects": false,
32
+ "main": "./dist/index.mjs",
33
+ "module": "./dist/index.mjs",
34
+ "types": "./dist/index.d.ts",
35
+ "exports": {
36
+ ".": {
37
+ "types": "./dist/index.d.ts",
38
+ "import": "./dist/index.mjs"
39
+ },
40
+ "./package.json": "./package.json"
41
+ },
42
+ "publishConfig": {
43
+ "access": "public"
44
+ },
45
+ "dependencies": {
46
+ "@lunora/platform": "1.0.0-alpha.2"
47
+ },
48
+ "engines": {
49
+ "node": "^22.15.0 || >=24.11.0"
50
+ }
51
+ }