@lunora/platform 1.0.0-alpha.5 → 1.0.0-alpha.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/conformance/index.mjs +1 -1
- package/dist/index.d.mts +42 -31
- package/dist/index.d.ts +42 -31
- package/dist/index.mjs +1 -1
- package/dist/packem_shared/CLOUDFLARE_CAPABILITIES-C09dwm8a.mjs +1 -0
- package/dist/packem_shared/{createReferenceHost-fs0Q8_VA.mjs → createReferenceHost-NGFPX8d2.mjs} +1 -1
- package/package.json +1 -1
- package/dist/packem_shared/CLOUDFLARE_CAPABILITIES-DMLgo_TI.mjs +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createReferenceHost as o}from"../packem_shared/createReferenceHost-
|
|
1
|
+
import{createReferenceHost as o}from"../packem_shared/createReferenceHost-NGFPX8d2.mjs";import{defineHostContractSuite as f}from"./suite.mjs";export{o as createReferenceHost,f as defineHostContractSuite};
|
package/dist/index.d.mts
CHANGED
|
@@ -317,7 +317,7 @@ interface R2BucketLike {
|
|
|
317
317
|
objects: R2ObjectLike[];
|
|
318
318
|
truncated?: boolean;
|
|
319
319
|
}>;
|
|
320
|
-
put: (key: string, body: ReadableStream | ArrayBuffer | Blob | string | null, options?: {
|
|
320
|
+
put: (key: string, body: ReadableStream | ArrayBuffer | ArrayBufferView | Blob | string | null, options?: {
|
|
321
321
|
customMetadata?: Record<string, string>;
|
|
322
322
|
httpMetadata?: {
|
|
323
323
|
contentType?: string;
|
|
@@ -417,15 +417,15 @@ interface MessageSendRequestLike<Body = unknown> {
|
|
|
417
417
|
delaySeconds?: number;
|
|
418
418
|
}
|
|
419
419
|
/**
|
|
420
|
-
* Minimal structural projection of workers-types' `Queue
|
|
420
|
+
* Minimal structural projection of workers-types' `Queue<Body>` (the producer
|
|
421
421
|
* binding). The real binding's `send`/`sendBatch` resolve to a metadata object;
|
|
422
|
-
* we widen the return to `Promise
|
|
422
|
+
* we widen the return to `Promise<unknown>` so a plain-object fake satisfies it.
|
|
423
423
|
*/
|
|
424
424
|
interface QueueBindingLike<Body = unknown> {
|
|
425
425
|
send: (message: Body, options?: QueueSendOptions) => Promise<unknown>;
|
|
426
426
|
sendBatch: (messages: Iterable<MessageSendRequestLike<Body>>, options?: QueueSendBatchOptions) => Promise<unknown>;
|
|
427
427
|
}
|
|
428
|
-
/** Structural mirror of workers-types' `Message
|
|
428
|
+
/** Structural mirror of workers-types' `Message<Body>` (one delivered message). */
|
|
429
429
|
interface MessageLike<Body = unknown> {
|
|
430
430
|
/** Acknowledge this message so it is not redelivered. */
|
|
431
431
|
ack: () => void;
|
|
@@ -436,7 +436,7 @@ interface MessageLike<Body = unknown> {
|
|
|
436
436
|
retry: (options?: QueueRetryOptions) => void;
|
|
437
437
|
readonly timestamp: Date;
|
|
438
438
|
}
|
|
439
|
-
/** Structural mirror of workers-types' `MessageBatch
|
|
439
|
+
/** Structural mirror of workers-types' `MessageBatch<Body>` handed to a consumer. */
|
|
440
440
|
interface MessageBatchLike<Body = unknown> {
|
|
441
441
|
/** Acknowledge every message in the batch. */
|
|
442
442
|
ackAll: () => void;
|
|
@@ -535,33 +535,44 @@ declare const CLOUDFLARE_CAPABILITIES: PlatformCapabilities;
|
|
|
535
535
|
* The Node capability matrix — `@lunora/platform-node`'s honest self-rating
|
|
536
536
|
* (plan 234).
|
|
537
537
|
*
|
|
538
|
-
* `@lunora/platform-node`
|
|
539
|
-
* `
|
|
540
|
-
* `better-sqlite3` and an in-process registry,
|
|
541
|
-
*
|
|
542
|
-
*
|
|
543
|
-
*
|
|
544
|
-
*
|
|
545
|
-
*
|
|
546
|
-
* Hyperdrive) most `ctx.*` surfaces are built on. Every one of those is
|
|
547
|
-
* rated `"unsupported"` here rather than left undeclared — see
|
|
548
|
-
* `gateAgainstMatrix` in `@lunora/codegen`, whose fail-closed gate (plan
|
|
549
|
-
* 229) treats an undeclared feature as unsupported anyway, but under a
|
|
550
|
-
* different diagnostic name than an honest, explicit rating.
|
|
538
|
+
* `@lunora/platform-node` implements every contract in this package
|
|
539
|
+
* (`ShardHost`, `SocketHost`, `ShardDirectory`, `ShardKvStore`,
|
|
540
|
+
* `SchedulerHost`) over `better-sqlite3` and an in-process registry, plus the
|
|
541
|
+
* `.global()` table backend via `@lunora/sql-store`. It began as a spike to run
|
|
542
|
+
* the conformance TCK against a second host; the durability gaps that spike
|
|
543
|
+
* surfaced — alarms and scheduler jobs that were persisted but never re-armed,
|
|
544
|
+
* socket attachments that lived only in memory — are closed, and each is now
|
|
545
|
+
* pinned by a restart test rather than only by a simulated recycle.
|
|
551
546
|
*
|
|
552
|
-
*
|
|
553
|
-
*
|
|
554
|
-
*
|
|
555
|
-
*
|
|
556
|
-
*
|
|
557
|
-
*
|
|
558
|
-
*
|
|
559
|
-
*
|
|
560
|
-
*
|
|
561
|
-
*
|
|
562
|
-
*
|
|
563
|
-
*
|
|
564
|
-
*
|
|
547
|
+
* `scheduler` and `shardAlarms` were rated `"unsupported"` under plan 267, on
|
|
548
|
+
* the grounds that the host stored and timed both while its timer body only
|
|
549
|
+
* cleared bookkeeping — nothing dispatched the scheduled function or woke the
|
|
550
|
+
* alarm. That rating was correct for the code it described, and the code is
|
|
551
|
+
* what changed: both now dispatch (through `onDispatch` / `onAlarm`) and both
|
|
552
|
+
* re-arm from their durable rows on construction, so `"emulated"` — built on
|
|
553
|
+
* lower-level primitives and *working* — is now the honest reading.
|
|
554
|
+
*
|
|
555
|
+
* What remains genuinely absent is everything a single Node process cannot
|
|
556
|
+
* distribute: placement across nodes, failover, and most Cloudflare-specific
|
|
557
|
+
* product bindings (Vectorize, Workers AI, Containers, Browser Rendering,
|
|
558
|
+
* Analytics Engine, Secrets Store, Hyperdrive). Workflows, object storage and
|
|
559
|
+
* queues are the three that CAN be emulated locally — `defineWorkflow` handlers
|
|
560
|
+
* compile onto the `@visulima/workflow` engine, R2 becomes a filesystem bucket,
|
|
561
|
+
* and Queues becomes a durable table with the same batch/ack/retry/dead-letter
|
|
562
|
+
* semantics — so those three are rated `"emulated"`; the rest of the Cloudflare
|
|
563
|
+
* products most `ctx.*` surfaces are built on are rated `"unsupported"` here
|
|
564
|
+
* rather than left undeclared — see `gateAgainstMatrix` in `@lunora/codegen`,
|
|
565
|
+
* whose fail-closed gate (plan 229) treats an undeclared feature as unsupported
|
|
566
|
+
* anyway, but under a different diagnostic name than an honest, explicit rating.
|
|
567
|
+
*
|
|
568
|
+
* Almost nothing here is rated `"native"`, and that is the matrix's own
|
|
569
|
+
* definition doing its job rather than a hedge: `native` means the platform
|
|
570
|
+
* itself provides the feature, and a bare Node process provides essentially
|
|
571
|
+
* none of them — Lunora builds alarms out of `setTimeout` plus a durable row,
|
|
572
|
+
* a KV store out of a SQL table, and `.global()` tables out of a second SQLite
|
|
573
|
+
* file. `localSql` is the exception, because SQLite genuinely is the platform
|
|
574
|
+
* primitive there. The ratings say who does the work; the notes say how well.
|
|
575
|
+
* Both are argued in detail in `plans/234-node-host-findings.md`.
|
|
565
576
|
*/
|
|
566
577
|
declare const NODE_CAPABILITIES: PlatformCapabilities;
|
|
567
578
|
export { type AnalyticsEngineDataPoint, type AnalyticsEngineDataPointLike, type AnalyticsEngineDatasetLike, CLOUDFLARE_CAPABILITIES, type Capability, type CapabilityLevel, type D1DatabaseLike, type D1PreparedStatementLike, type D1SessionLike, type ExecutionContextLike, type KVNamespaceLike, type KvGetOptions, type KvListKey, type KvNamespaceListResult, type KvNamespacePutOptions, type KvValue, type KvValueType, type MessageBatchLike, type MessageLike, type MessageSendRequestLike, NODE_CAPABILITIES, NOOP_EXECUTION_CONTEXT, type PlatformCapabilities, type QueueBindingLike, type QueueContentType, type QueueMessageLike, type QueueRetryOptions, type QueueSendBatchOptions, type QueueSendOptions, type QueueSendOptionsLike, type QueueSendRequestLike, type R2BucketLike, type R2MultipartUploadLike, type R2ObjectBodyLike, type R2ObjectLike, type R2RangeLike, type R2UploadedPartLike, type VectorMatchLike, type VectorMetric, type VectorRecordLike, type VectorizeDeleteMutation, type VectorizeIndexDetails, type VectorizeIndexLike, type VectorizeMatch, type VectorizeMatches, type VectorizeQueryOptions, type VectorizeUpsertMutation, type VectorizeVector };
|
package/dist/index.d.ts
CHANGED
|
@@ -317,7 +317,7 @@ interface R2BucketLike {
|
|
|
317
317
|
objects: R2ObjectLike[];
|
|
318
318
|
truncated?: boolean;
|
|
319
319
|
}>;
|
|
320
|
-
put: (key: string, body: ReadableStream | ArrayBuffer | Blob | string | null, options?: {
|
|
320
|
+
put: (key: string, body: ReadableStream | ArrayBuffer | ArrayBufferView | Blob | string | null, options?: {
|
|
321
321
|
customMetadata?: Record<string, string>;
|
|
322
322
|
httpMetadata?: {
|
|
323
323
|
contentType?: string;
|
|
@@ -417,15 +417,15 @@ interface MessageSendRequestLike<Body = unknown> {
|
|
|
417
417
|
delaySeconds?: number;
|
|
418
418
|
}
|
|
419
419
|
/**
|
|
420
|
-
* Minimal structural projection of workers-types' `Queue
|
|
420
|
+
* Minimal structural projection of workers-types' `Queue<Body>` (the producer
|
|
421
421
|
* binding). The real binding's `send`/`sendBatch` resolve to a metadata object;
|
|
422
|
-
* we widen the return to `Promise
|
|
422
|
+
* we widen the return to `Promise<unknown>` so a plain-object fake satisfies it.
|
|
423
423
|
*/
|
|
424
424
|
interface QueueBindingLike<Body = unknown> {
|
|
425
425
|
send: (message: Body, options?: QueueSendOptions) => Promise<unknown>;
|
|
426
426
|
sendBatch: (messages: Iterable<MessageSendRequestLike<Body>>, options?: QueueSendBatchOptions) => Promise<unknown>;
|
|
427
427
|
}
|
|
428
|
-
/** Structural mirror of workers-types' `Message
|
|
428
|
+
/** Structural mirror of workers-types' `Message<Body>` (one delivered message). */
|
|
429
429
|
interface MessageLike<Body = unknown> {
|
|
430
430
|
/** Acknowledge this message so it is not redelivered. */
|
|
431
431
|
ack: () => void;
|
|
@@ -436,7 +436,7 @@ interface MessageLike<Body = unknown> {
|
|
|
436
436
|
retry: (options?: QueueRetryOptions) => void;
|
|
437
437
|
readonly timestamp: Date;
|
|
438
438
|
}
|
|
439
|
-
/** Structural mirror of workers-types' `MessageBatch
|
|
439
|
+
/** Structural mirror of workers-types' `MessageBatch<Body>` handed to a consumer. */
|
|
440
440
|
interface MessageBatchLike<Body = unknown> {
|
|
441
441
|
/** Acknowledge every message in the batch. */
|
|
442
442
|
ackAll: () => void;
|
|
@@ -535,33 +535,44 @@ declare const CLOUDFLARE_CAPABILITIES: PlatformCapabilities;
|
|
|
535
535
|
* The Node capability matrix — `@lunora/platform-node`'s honest self-rating
|
|
536
536
|
* (plan 234).
|
|
537
537
|
*
|
|
538
|
-
* `@lunora/platform-node`
|
|
539
|
-
* `
|
|
540
|
-
* `better-sqlite3` and an in-process registry,
|
|
541
|
-
*
|
|
542
|
-
*
|
|
543
|
-
*
|
|
544
|
-
*
|
|
545
|
-
*
|
|
546
|
-
* Hyperdrive) most `ctx.*` surfaces are built on. Every one of those is
|
|
547
|
-
* rated `"unsupported"` here rather than left undeclared — see
|
|
548
|
-
* `gateAgainstMatrix` in `@lunora/codegen`, whose fail-closed gate (plan
|
|
549
|
-
* 229) treats an undeclared feature as unsupported anyway, but under a
|
|
550
|
-
* different diagnostic name than an honest, explicit rating.
|
|
538
|
+
* `@lunora/platform-node` implements every contract in this package
|
|
539
|
+
* (`ShardHost`, `SocketHost`, `ShardDirectory`, `ShardKvStore`,
|
|
540
|
+
* `SchedulerHost`) over `better-sqlite3` and an in-process registry, plus the
|
|
541
|
+
* `.global()` table backend via `@lunora/sql-store`. It began as a spike to run
|
|
542
|
+
* the conformance TCK against a second host; the durability gaps that spike
|
|
543
|
+
* surfaced — alarms and scheduler jobs that were persisted but never re-armed,
|
|
544
|
+
* socket attachments that lived only in memory — are closed, and each is now
|
|
545
|
+
* pinned by a restart test rather than only by a simulated recycle.
|
|
551
546
|
*
|
|
552
|
-
*
|
|
553
|
-
*
|
|
554
|
-
*
|
|
555
|
-
*
|
|
556
|
-
*
|
|
557
|
-
*
|
|
558
|
-
*
|
|
559
|
-
*
|
|
560
|
-
*
|
|
561
|
-
*
|
|
562
|
-
*
|
|
563
|
-
*
|
|
564
|
-
*
|
|
547
|
+
* `scheduler` and `shardAlarms` were rated `"unsupported"` under plan 267, on
|
|
548
|
+
* the grounds that the host stored and timed both while its timer body only
|
|
549
|
+
* cleared bookkeeping — nothing dispatched the scheduled function or woke the
|
|
550
|
+
* alarm. That rating was correct for the code it described, and the code is
|
|
551
|
+
* what changed: both now dispatch (through `onDispatch` / `onAlarm`) and both
|
|
552
|
+
* re-arm from their durable rows on construction, so `"emulated"` — built on
|
|
553
|
+
* lower-level primitives and *working* — is now the honest reading.
|
|
554
|
+
*
|
|
555
|
+
* What remains genuinely absent is everything a single Node process cannot
|
|
556
|
+
* distribute: placement across nodes, failover, and most Cloudflare-specific
|
|
557
|
+
* product bindings (Vectorize, Workers AI, Containers, Browser Rendering,
|
|
558
|
+
* Analytics Engine, Secrets Store, Hyperdrive). Workflows, object storage and
|
|
559
|
+
* queues are the three that CAN be emulated locally — `defineWorkflow` handlers
|
|
560
|
+
* compile onto the `@visulima/workflow` engine, R2 becomes a filesystem bucket,
|
|
561
|
+
* and Queues becomes a durable table with the same batch/ack/retry/dead-letter
|
|
562
|
+
* semantics — so those three are rated `"emulated"`; the rest of the Cloudflare
|
|
563
|
+
* products most `ctx.*` surfaces are built on are rated `"unsupported"` here
|
|
564
|
+
* rather than left undeclared — see `gateAgainstMatrix` in `@lunora/codegen`,
|
|
565
|
+
* whose fail-closed gate (plan 229) treats an undeclared feature as unsupported
|
|
566
|
+
* anyway, but under a different diagnostic name than an honest, explicit rating.
|
|
567
|
+
*
|
|
568
|
+
* Almost nothing here is rated `"native"`, and that is the matrix's own
|
|
569
|
+
* definition doing its job rather than a hedge: `native` means the platform
|
|
570
|
+
* itself provides the feature, and a bare Node process provides essentially
|
|
571
|
+
* none of them — Lunora builds alarms out of `setTimeout` plus a durable row,
|
|
572
|
+
* a KV store out of a SQL table, and `.global()` tables out of a second SQLite
|
|
573
|
+
* file. `localSql` is the exception, because SQLite genuinely is the platform
|
|
574
|
+
* primitive there. The ratings say who does the work; the notes say how well.
|
|
575
|
+
* Both are argued in detail in `plans/234-node-host-findings.md`.
|
|
565
576
|
*/
|
|
566
577
|
declare const NODE_CAPABILITIES: PlatformCapabilities;
|
|
567
578
|
export { type AnalyticsEngineDataPoint, type AnalyticsEngineDataPointLike, type AnalyticsEngineDatasetLike, CLOUDFLARE_CAPABILITIES, type Capability, type CapabilityLevel, type D1DatabaseLike, type D1PreparedStatementLike, type D1SessionLike, type ExecutionContextLike, type KVNamespaceLike, type KvGetOptions, type KvListKey, type KvNamespaceListResult, type KvNamespacePutOptions, type KvValue, type KvValueType, type MessageBatchLike, type MessageLike, type MessageSendRequestLike, NODE_CAPABILITIES, NOOP_EXECUTION_CONTEXT, type PlatformCapabilities, type QueueBindingLike, type QueueContentType, type QueueMessageLike, type QueueRetryOptions, type QueueSendBatchOptions, type QueueSendOptions, type QueueSendOptionsLike, type QueueSendRequestLike, type R2BucketLike, type R2MultipartUploadLike, type R2ObjectBodyLike, type R2ObjectLike, type R2RangeLike, type R2UploadedPartLike, type VectorMatchLike, type VectorMetric, type VectorRecordLike, type VectorizeDeleteMutation, type VectorizeIndexDetails, type VectorizeIndexLike, type VectorizeMatch, type VectorizeMatches, type VectorizeQueryOptions, type VectorizeUpsertMutation, type VectorizeVector };
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{NOOP_EXECUTION_CONTEXT as E}from"./packem_shared/NOOP_EXECUTION_CONTEXT-YmXqH-jH.mjs";import{CLOUDFLARE_CAPABILITIES as O,NODE_CAPABILITIES as e}from"./packem_shared/CLOUDFLARE_CAPABILITIES-
|
|
1
|
+
import{NOOP_EXECUTION_CONTEXT as E}from"./packem_shared/NOOP_EXECUTION_CONTEXT-YmXqH-jH.mjs";import{CLOUDFLARE_CAPABILITIES as O,NODE_CAPABILITIES as e}from"./packem_shared/CLOUDFLARE_CAPABILITIES-C09dwm8a.mjs";import{resolveShard as C}from"./packem_shared/resolveShard-uGhAKuTB.mjs";export{O as CLOUDFLARE_CAPABILITIES,e as NODE_CAPABILITIES,E as NOOP_EXECUTION_CONTEXT,C as resolveShard};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e={id:"cloudflare",name:"Cloudflare",features:{shardedState:{level:"native",note:"Durable Objects with SQLite"},globalTables:{level:"native",note:"D1 with Sessions API"},websocketHibernation:{level:"native",note:"DO WebSocket hibernation"},localSql:{level:"native",note:"state.storage.sql (SQLite)"},shardAlarms:{level:"native",note:"state.storage.setAlarm"},crossShardFanout:{level:"emulated",note:"Lunora query coordinator + relay tier over Durable Objects"},queues:{level:"native",note:"Cloudflare Queues"},workflows:{level:"native",note:"Cloudflare Workflows"},scheduler:{level:"emulated",note:"SchedulerDO (Lunora, on DO alarms) + declarative Cron Triggers; no runtime cron registration"},objectStorage:{level:"native",note:"R2"},keyValueStore:{level:"native",note:"Workers KV"},vectorStore:{level:"native",note:"Vectorize; query/upsert namespace scoping is native (remote filter), but getByIds/deleteByIds id-path tenant isolation is facade-enforced (client-side verification) since Vectorize's id operations take no namespace option"},ai:{level:"native",note:"Workers AI"},browser:{level:"native",note:"Browser Rendering"},containers:{level:"native",note:"Cloudflare Containers"},analytics:{level:"native",note:"Analytics Engine"},pipelines:{level:"native",note:"Cloudflare Pipelines"},mail:{level:"emulated",note:"Resend (third-party) via Cloudflare Queues"},secrets:{level:"native",note:"Secrets Store"},hyperdrive:{level:"native",note:"Cloudflare Hyperdrive"}}},t={id:"node",name:"Node",features:{shardedState:{level:"emulated",note:"One better-sqlite3 database per shard key, one process — no distributed placement or failover"},globalTables:{level:"emulated",note:"The @lunora/sql-store core on its own SQLite file via the reference sqliteDialect — full store semantics, but one node with no replication"},websocketHibernation:{level:"emulated",note:"Socket registry with attachments/tags persisted to SQLite, so subscription state survives a process restart; nothing is ever actually evicted from memory, so this is durability without hibernation's memory saving"},localSql:{level:"native",note:"better-sqlite3 (synchronous, embedded)"},shardAlarms:{level:"emulated",note:"setTimeout over a durable row, dispatched to onAlarm and re-armed on construction, so an alarm survives a restart and one whose time elapsed while the process was down fires late rather than never"},crossShardFanout:{level:"emulated",note:"@lunora/runtime's query coordinator over the in-process shard registry; listShardKeys is seeded from the shard files on disk, and answers every shard rather than only those holding the table (a correct superset, at the cost of visiting shards with nothing to say)"},queues:{level:"emulated",note:`createNodeQueueHost (@lunora/platform-node) — a QueueBindingLike producer per declared queue over a durable _lunora_queue_messages table, and a batched consumer feeding the same dispatchQueueBatch the Cloudflare host uses. delaySeconds (capped at 12h), all four content types, maxBatchSize/maxBatchTimeout assembly, per-message ack/retry with workerd's implicit-ack-on-return and retry-on-throw, maxRetries into a declared deadLetterQueue (or parked in place, never dropped), and a visibility window so a crash mid-handler redelivers. Delivery is driven by poll(); there is no timer, because this host has no dev server to own one. mode: "pull" queues are written but not consumed — nothing here serves the HTTP pull endpoint`},workflows:{level:"emulated",note:"createNodeWorkflowHost (@lunora/platform-node) compiles defineWorkflow handlers onto the @visulima/workflow engine (createRuntime): step/sleep/waitForEvent are durable + replay-safe, status maps to complete/errored/waiting/terminated, create({ id }) is honoured through a durable alias row (so ctx.spawn resolves and a retried create is one run), and runs survive a restart when backed by createNodeWorkflowStore (a SQLite WorkflowStore; the store is required, so no caller silently gets in-process-only state). Gaps: no pause/restart; terminate is not a barrier, so an activation already in flight overwrites the tombstone; ctx.run dispatches to an endpoint no Node HTTP server serves; ctx.parallel's synchronous join cannot interleave within one trigger activation"},scheduler:{level:"emulated",note:"SQLite job table dispatched to onDispatch and re-armed on construction, with retry backoff and a dead-letter queue; the only host implementing runtime cron registration (SchedulerHost.cron), which Cloudflare cannot offer"},objectStorage:{level:"emulated",note:"createNodeR2Bucket (@lunora/platform-node) — an R2BucketLike over the local filesystem (fs/promises, head/list/range). One file per object with the metadata in a trailer, so the single rename that publishes the bytes publishes their checksum and content-type with them, and a get reads body and metadata through one handle rather than reopening the path. put streams into the staged file and .body streams the requested range; .arrayBuffer()/.text() still allocate the range they return. The body is single-use, as R2's is. Keys fold the way the host filesystem folds them, so `A` and `a` are one object on a case-insensitive volume where real R2 keeps two. No multipart uploads, no presigned URLs"},keyValueStore:{level:"emulated",note:"better-sqlite3 table behind the ShardKvStore API — not a dedicated KV product"},vectorStore:{level:"unsupported",note:"No Vectorize-equivalent binding implemented"},ai:{level:"unsupported",note:"No Workers AI-equivalent binding implemented"},browser:{level:"unsupported",note:"No headless-browser binding implemented"},containers:{level:"unsupported",note:"No container orchestration implemented"},analytics:{level:"unsupported",note:"No Analytics Engine-equivalent binding implemented"},pipelines:{level:"unsupported",note:"No Pipelines-equivalent binding implemented"},mail:{level:"unsupported",note:"@lunora/mail's queue-backed sends need a queues binding, which this target does not provide"},secrets:{level:"unsupported",note:"No Secrets Store-equivalent binding implemented (a real host would likely map this to env vars)"},hyperdrive:{level:"unsupported",note:"No connection-pooling binding implemented"}}};export{e as CLOUDFLARE_CAPABILITIES,t as NODE_CAPABILITIES};
|
package/dist/packem_shared/{createReferenceHost-fs0Q8_VA.mjs → createReferenceHost-NGFPX8d2.mjs}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{DatabaseSync as R}from"node:sqlite";let b=0,S=0;const j=()=>(b+=1,`socket-${b}`),C=()=>(S+=1,`job-${S}`),q=n=>n===void 0?null:n,E=n=>typeof n=="string"?new TextEncoder().encode(n).buffer:n instanceof ArrayBuffer?n:ArrayBuffer.isView(n)?n.buffer.slice(n.byteOffset,n.byteOffset+n.byteLength):new ArrayBuffer(0),O=()=>{const n=new R(":memory:"),s={alarmAt:null,alarmTimeout:null,pending:[],running:!1},l=new Map,f=new Map,u=new Map,x={exec:(e,...t)=>{const a=n.prepare(e),r=t.map(q),o=e.trim().toLowerCase().startsWith("select")?a.all(...r):(a.run(...r),[]);return{[Symbol.iterator]:()=>o[Symbol.iterator](),one:()=>{if(o.length!==1)throw new Error(`expected exactly one row, got ${String(o.length)}`);return o[0]},toArray:()=>[...o]}}},M={all:async(e,t)=>n.prepare(e).all(...t),run:async(e,t)=>{const a=n.prepare(e).run(...t);return{rowsAffected:Number(a.changes)}}},h=()=>{if(s.running||s.pending.length===0)return;const e=s.pending.shift();e!==void 0&&(s.running=!0,e.function_().then(e.resolve,e.reject).finally(()=>{s.running=!1,h()}))},F=e=>new Promise((t,a)=>{s.pending.push({function_:e,reject:r=>{a(r)},resolve:r=>{t(r)}}),h()});let g=Promise.resolve();const p=async e=>{n.exec("BEGIN");try{const t=await e();return n.exec("COMMIT"),t}catch(t){throw n.exec("ROLLBACK"),t}},D={alarms:{delete:()=>{s.alarmAt=null,s.alarmTimeout!==null&&(clearTimeout(s.alarmTimeout),s.alarmTimeout=null)},get:()=>s.alarmAt,set:e=>{const t=typeof e=="number"?e:e.getTime();s.alarmAt=t,s.alarmTimeout!==null&&clearTimeout(s.alarmTimeout);const a=Math.max(0,t-Date.now());s.alarmTimeout=setTimeout(()=>{s.alarmAt=null,s.alarmTimeout=null},a)}},asyncSql:M,runSerialized:F,sql:x,transaction:e=>{const t=g.then(()=>p(e),()=>p(e));return g=t.then(()=>{},()=>{}),t},waitUntil:()=>{}},c=new WeakMap,w=e=>{const t={bufferedAmount:e.bufferedAmount,close:(a,r)=>{e.closed=!0},deserializeAttachment:()=>e.attachment,send:a=>{e.received.push(typeof a=="string"?a:E(a))},serializeAttachment:a=>{e.attachment=a,f.set(e.id,a)}};return e.handle=t,c.set(t,e.id),t},P={accept:(e,t,a)=>{const r=j(),o={attachment:t,bufferedAmount:0,closed:!1,raw:e,handle:null,id:r,received:[],tags:new Set(a)};return l.set(r,o),u.set(r,new Set(a)),t!==void 0&&f.set(r,t),w(o)},getSockets:e=>{const t=[...l.values()];return(e===void 0?t:t.filter(a=>a.tags.has(e))).map(a=>a.handle)},handleFor:e=>[...l.values()].find(t=>t.raw===e)?.handle,idFor:e=>{const t=c.get(e);if(t===void 0)throw new Error("reference host: idFor called with a handle this host never issued");return t},removeTag:(e,t)=>{const a=
|
|
1
|
+
import{DatabaseSync as R}from"node:sqlite";let b=0,S=0;const j=()=>(b+=1,`socket-${b}`),C=()=>(S+=1,`job-${S}`),q=n=>n===void 0?null:n,E=n=>typeof n=="string"?new TextEncoder().encode(n).buffer:n instanceof ArrayBuffer?n:ArrayBuffer.isView(n)?n.buffer.slice(n.byteOffset,n.byteOffset+n.byteLength):new ArrayBuffer(0),O=()=>{const n=new R(":memory:"),s={alarmAt:null,alarmTimeout:null,pending:[],running:!1},l=new Map,f=new Map,u=new Map,x={exec:(e,...t)=>{const a=n.prepare(e),r=t.map(q),o=e.trim().toLowerCase().startsWith("select")?a.all(...r):(a.run(...r),[]);return{[Symbol.iterator]:()=>o[Symbol.iterator](),one:()=>{if(o.length!==1)throw new Error(`expected exactly one row, got ${String(o.length)}`);return o[0]},toArray:()=>[...o]}}},M={all:async(e,t)=>n.prepare(e).all(...t),run:async(e,t)=>{const a=n.prepare(e).run(...t);return{rowsAffected:Number(a.changes)}}},h=()=>{if(s.running||s.pending.length===0)return;const e=s.pending.shift();e!==void 0&&(s.running=!0,e.function_().then(e.resolve,e.reject).finally(()=>{s.running=!1,h()}))},F=e=>new Promise((t,a)=>{s.pending.push({function_:e,reject:r=>{a(r)},resolve:r=>{t(r)}}),h()});let g=Promise.resolve();const p=async e=>{n.exec("BEGIN");try{const t=await e();return n.exec("COMMIT"),t}catch(t){throw n.exec("ROLLBACK"),t}},D={alarms:{delete:()=>{s.alarmAt=null,s.alarmTimeout!==null&&(clearTimeout(s.alarmTimeout),s.alarmTimeout=null)},get:()=>s.alarmAt,set:e=>{const t=typeof e=="number"?e:e.getTime();s.alarmAt=t,s.alarmTimeout!==null&&clearTimeout(s.alarmTimeout);const a=Math.max(0,t-Date.now());s.alarmTimeout=setTimeout(()=>{s.alarmAt=null,s.alarmTimeout=null},a)}},asyncSql:M,runSerialized:F,sql:x,transaction:e=>{const t=g.then(()=>p(e),()=>p(e));return g=t.then(()=>{},()=>{}),t},waitUntil:()=>{}},c=new WeakMap,w=e=>{const t={bufferedAmount:e.bufferedAmount,close:(a,r)=>{e.closed=!0},deserializeAttachment:()=>e.attachment,send:a=>{e.received.push(typeof a=="string"?a:E(a))},serializeAttachment:a=>{e.attachment=a,f.set(e.id,a)}};return e.handle=t,c.set(t,e.id),t},P={accept:(e,t,a)=>{const r=j(),o={attachment:t,bufferedAmount:0,closed:!1,raw:e,handle:null,id:r,received:[],tags:new Set(a)};return l.set(r,o),u.set(r,new Set(a)),t!==void 0&&f.set(r,t),w(o)},getSockets:e=>{const t=[...l.values()];return(e===void 0?t:t.filter(a=>a.tags.has(e))).map(a=>a.handle)},handleFor:e=>[...l.values()].find(t=>t.raw===e)?.handle,idFor:e=>{const t=c.get(e);if(t===void 0)throw new Error("reference host: idFor called with a handle this host never issued");return t},removeTag:(e,t)=>{const a=c.get(e)??"",r=l.get(a);r!==void 0&&(t===void 0?r.tags.clear():r.tags.delete(t),u.set(a,new Set(r.tags)))},setTag:(e,t)=>{const a=c.get(e)??"",r=l.get(a);r!==void 0&&(r.tags.add(t),u.set(a,new Set(r.tags)))}},y={get:e=>({fetch:async()=>new Response(String(e))}),getByName:e=>({fetch:async()=>new Response(e)}),idForName:e=>`shard:${e}`,jurisdiction:e=>y},d=new Map,k={delete:async e=>d.delete(e),get:async e=>d.get(e),list:async e=>{const t=e?.prefix??"",a=new Map;for(const[r,o]of d)r.startsWith(t)&&a.set(r,o);return a},put:async(e,t)=>{d.set(e,structuredClone(t))}},i=new Map,m=new Map,v=new Set,T=(e,t)=>({attempts:t.attempts,functionPath:t.functionPath,id:e,scheduledFor:t.scheduledFor});return{awaitAlarmFired:async e=>{await new Promise(t=>{setTimeout(t,Math.max(0,e-Date.now())+30)})},awaitJobDispatched:async e=>{const t=i.get(e);return t!==void 0&&await new Promise(a=>{setTimeout(a,Math.max(0,t.scheduledFor-Date.now())+30)}),v.has(e)},cleanup:()=>{n.close(),s.alarmTimeout!==null&&clearTimeout(s.alarmTimeout);for(const e of i.values())clearTimeout(e.timer)},directory:y,kv:k,readFrames:e=>(l.get(c.get(e)??"")?.received??[]).filter(t=>typeof t=="string"),restoreSocket:(e,t)=>{const a={attachment:t,bufferedAmount:0,closed:!1,handle:null,id:e,raw:void 0,received:[],tags:new Set(u.get(e))};return l.set(e,a),w(a)},scheduler:{cancel:async e=>{const t=i.get(e);return t===void 0?!1:(clearTimeout(t.timer),i.delete(e),!0)},cron:async()=>{},deadLetter:{list:async()=>[...m].map(([e,t])=>T(e,t)),requeue:async e=>{const t=m.get(e);return t===void 0?!1:(m.delete(e),i.set(e,{...t,attempts:0,timer:void 0}),!0)}},list:async()=>[...i].map(([e,t])=>T(e,t)),schedule:async(e,t,a)=>{const r=C();let o;a?.at===void 0?o=Date.now()+(a?.delayMs??0):o=typeof a.at=="number"?a.at:a.at.getTime();const B=Math.max(0,o-Date.now()),L=setTimeout(()=>{const A=i.get(r);A!==void 0&&(A.attempts+=1),v.add(r),i.delete(r)},B);return i.set(r,{args:t,attempts:0,functionPath:e,options:a??{},scheduledFor:o,timer:L}),{id:r,scheduledFor:o}}},simulateDeadLetter:async e=>{const t=i.get(e);return t===void 0?!1:(clearTimeout(t.timer),i.delete(e),m.set(e,{...t,attempts:(t.options.retry?.maxAttempts??5)+1,timer:void 0}),!0)},shard:D,simulateRecycle:()=>{l.clear()},socket:P}};export{O as createReferenceHost};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/platform",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.7",
|
|
4
4
|
"description": "Provider-neutral host contracts for Lunora: shard/socket/directory/scheduler interfaces, binding projections, and the platform capability matrix",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
const e={id:"cloudflare",name:"Cloudflare",features:{shardedState:{level:"native",note:"Durable Objects with SQLite"},globalTables:{level:"native",note:"D1 with Sessions API"},websocketHibernation:{level:"native",note:"DO WebSocket hibernation"},localSql:{level:"native",note:"state.storage.sql (SQLite)"},shardAlarms:{level:"native",note:"state.storage.setAlarm"},crossShardFanout:{level:"emulated",note:"Lunora query coordinator + relay tier over Durable Objects"},queues:{level:"native",note:"Cloudflare Queues"},workflows:{level:"native",note:"Cloudflare Workflows"},scheduler:{level:"emulated",note:"SchedulerDO (Lunora, on DO alarms) + declarative Cron Triggers; no runtime cron registration"},objectStorage:{level:"native",note:"R2"},keyValueStore:{level:"native",note:"Workers KV"},vectorStore:{level:"native",note:"Vectorize; query/upsert namespace scoping is native (remote filter), but getByIds/deleteByIds id-path tenant isolation is facade-enforced (client-side verification) since Vectorize's id operations take no namespace option"},ai:{level:"native",note:"Workers AI"},browser:{level:"native",note:"Browser Rendering"},containers:{level:"native",note:"Cloudflare Containers"},analytics:{level:"native",note:"Analytics Engine"},pipelines:{level:"native",note:"Cloudflare Pipelines"},mail:{level:"emulated",note:"Resend (third-party) via Cloudflare Queues"},secrets:{level:"native",note:"Secrets Store"},hyperdrive:{level:"native",note:"Cloudflare Hyperdrive"}}},t={id:"node",name:"Node",features:{shardedState:{level:"emulated",note:"One better-sqlite3 database per shard key, one process — no distributed placement or failover"},globalTables:{level:"unsupported",note:"No replicated SQL store (D1-equivalent) implemented"},websocketHibernation:{level:"emulated",note:"In-process socket registry; attachments/tags survive a simulated recycle, not a process restart, and nothing is ever actually evicted from memory"},localSql:{level:"native",note:"better-sqlite3 (synchronous, embedded)"},shardAlarms:{level:"unsupported",note:"In-process bookkeeping only — the armed timer clears state and never wakes anything; no dispatch, and nothing re-arms across a restart"},crossShardFanout:{level:"unsupported",note:"No query coordinator / relay tier implemented"},queues:{level:"unsupported",note:"No Cloudflare Queues equivalent implemented"},workflows:{level:"unsupported",note:"No Cloudflare Workflows equivalent implemented"},scheduler:{level:"unsupported",note:"Jobs are stored and timed but never dispatched — no delivery, no retries; also not durable across a process restart"},objectStorage:{level:"unsupported",note:"No R2/S3-equivalent binding implemented"},keyValueStore:{level:"emulated",note:"better-sqlite3 table behind the ShardKvStore API — not a dedicated KV product"},vectorStore:{level:"unsupported",note:"No Vectorize-equivalent binding implemented"},ai:{level:"unsupported",note:"No Workers AI-equivalent binding implemented"},browser:{level:"unsupported",note:"No headless-browser binding implemented"},containers:{level:"unsupported",note:"No container orchestration implemented"},analytics:{level:"unsupported",note:"No Analytics Engine-equivalent binding implemented"},pipelines:{level:"unsupported",note:"No Pipelines-equivalent binding implemented"},mail:{level:"unsupported",note:"@lunora/mail's queue-backed sends need a queues binding, which this target does not provide"},secrets:{level:"unsupported",note:"No Secrets Store-equivalent binding implemented (a real host would likely map this to env vars)"},hyperdrive:{level:"unsupported",note:"No connection-pooling binding implemented"}}};export{e as CLOUDFLARE_CAPABILITIES,t as NODE_CAPABILITIES};
|