@lunora/platform-node 1.0.0-alpha.44 → 1.0.0-alpha.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -360,13 +360,17 @@ interface NodePlatform<Queues extends Record<string, {
360
360
  /** What this target supports — see `NODE_CAPABILITIES` in `@lunora/platform`. */
361
361
  capabilities: PlatformCapabilities;
362
362
  /**
363
- * Tear this platform instance down: clears the shard host's pending alarm
364
- * timer and closes its `better-sqlite3` database (and, with it, `kv`'s
365
- * table — both live on the same connection), then clears every armed
366
- * scheduler job timer. Nothing in this package closes these resources on
367
- * its own — a `NodePlatform` a caller stops using without calling `close()`
368
- * leaks the open file handle (plus its WAL/SHM sidecar files) and keeps
369
- * the process alive on outstanding timers. Safe to call more than once.
363
+ * Tear this platform instance down: every resource this root built, in
364
+ * reverse construction order — the global store's own connection, every
365
+ * armed scheduler job timer, the registry's live shards, and last the shard
366
+ * host's pending alarm timer and its `better-sqlite3` database (and, with
367
+ * it, `kv`'s table — both live on the same connection). Nothing in this
368
+ * package closes these resources on its own — a `NodePlatform` a caller
369
+ * stops using without calling `close()` leaks the open file handles (plus
370
+ * their WAL/SHM sidecar files) and keeps the process alive on outstanding
371
+ * timers. Safe to call more than once. A `createNodePlatform` that throws
372
+ * unwinds the same list itself, so a failed construction leaks nothing and
373
+ * leaves nothing to call this on.
370
374
  *
371
375
  * **`close()` is a terminal state, not merely a cleanup step.** After it
372
376
  * runs: `scheduler.schedule()` throws instead of arming a fresh timer
@@ -394,14 +398,27 @@ interface NodePlatform<Queues extends Record<string, {
394
398
  * shutdown is `await platform.drain()` then `platform.close()`.
395
399
  */
396
400
  drain: () => Promise<void>;
397
- /** Durable key-value storage backed by the same `better-sqlite3` database as `shard`. */
398
- kv: ShardKvStore;
399
401
  /**
400
- * The local-filesystem bucket, or `undefined` when the caller named no
401
- * bucket directory. Same reasoning as `queues`: `objectStorage` is rated
402
- * `emulated`, so codegen emits `ctx.storage` for this target, and a bucket
403
- * nobody bound fails at the first `put` with nothing upstream to warn.
402
+ * The `.global()` backend, or `undefined` when the caller named no database
403
+ * file for it. There is no default path, because a global store silently
404
+ * rooted at `:memory:` loses every row when the process exits.
405
+ *
406
+ * **A building block, not a wiring.** Unlike its three siblings, nothing
407
+ * downstream of this composition root reads it: a `.global()` read or write
408
+ * reaches its backend through exactly one seam, `createShardCtxDb({ globalDb
409
+ * })`, and the only thing that passes `globalDb` is the generated `shard.ts`,
410
+ * from its `d1` / `hyperdriveGlobal` config thunks. `createNodePlatform`
411
+ * constructs no shard DO, so it cannot make that hop itself. A caller that
412
+ * wants `.global()` on this host makes it: after `migrate(schema)` has
413
+ * provisioned the tables, give the generated `createShardDO` a `d1` thunk
414
+ * returning `platform.globalTables.writer({ schema, … })` — `writer` builds
415
+ * the `createSqlCtxDb` facade that seam expects, and `node-platform.test.ts`
416
+ * round-trips a row through exactly that object.
404
417
  */
418
+ globalTables?: NodeGlobalStore;
419
+ /** Durable key-value storage backed by the same `better-sqlite3` database as `shard`. */
420
+ kv: ShardKvStore;
421
+ /** The local-filesystem bucket, or `undefined` when the caller named no bucket directory. */
405
422
  objectStorage?: R2BucketLike;
406
423
  /**
407
424
  * The declared queues, or `undefined` when the caller declared none.
@@ -433,15 +450,21 @@ interface NodePlatform<Queues extends Record<string, {
433
450
  * directory resolves for fan-out file-backed too, and `onAlarm` gives their
434
451
  * durable alarms somewhere to land.
435
452
  *
436
- * `queues`, `workflows` and `objectStorageDirectory` are the three
437
- * declarations: each binds its half of an `emulated` capability, and each is
438
- * absent from the returned platform when its declaration is omitted.
453
+ * `queues`, `workflows`, `objectStorageDirectory` and `globalTablesPath` are the
454
+ * four declarations — each is absent from the returned platform when omitted.
439
455
  */
440
456
  type NodePlatformOptions<Queues extends Record<string, {
441
457
  isLunoraQueue: true;
442
458
  }> = Record<string, never>, Workflows extends Record<string, {
443
459
  isLunoraWorkflow: true;
444
460
  }> = Record<string, never>> = {
461
+ /**
462
+ * Database file the `.global()` tables live in — its own file, never a
463
+ * shard's, because a table every shard reads must not be inside any one of
464
+ * them. Omit when the app declares no `.global()` table; there is no
465
+ * default, for the same reason the bucket has none.
466
+ */
467
+ globalTablesPath?: string;
445
468
  /**
446
469
  * Directory the object-storage bucket keeps its objects in, one file per
447
470
  * key. Omit when the app declares no buckets — there is no default,
package/dist/index.d.ts CHANGED
@@ -360,13 +360,17 @@ interface NodePlatform<Queues extends Record<string, {
360
360
  /** What this target supports — see `NODE_CAPABILITIES` in `@lunora/platform`. */
361
361
  capabilities: PlatformCapabilities;
362
362
  /**
363
- * Tear this platform instance down: clears the shard host's pending alarm
364
- * timer and closes its `better-sqlite3` database (and, with it, `kv`'s
365
- * table — both live on the same connection), then clears every armed
366
- * scheduler job timer. Nothing in this package closes these resources on
367
- * its own — a `NodePlatform` a caller stops using without calling `close()`
368
- * leaks the open file handle (plus its WAL/SHM sidecar files) and keeps
369
- * the process alive on outstanding timers. Safe to call more than once.
363
+ * Tear this platform instance down: every resource this root built, in
364
+ * reverse construction order — the global store's own connection, every
365
+ * armed scheduler job timer, the registry's live shards, and last the shard
366
+ * host's pending alarm timer and its `better-sqlite3` database (and, with
367
+ * it, `kv`'s table — both live on the same connection). Nothing in this
368
+ * package closes these resources on its own — a `NodePlatform` a caller
369
+ * stops using without calling `close()` leaks the open file handles (plus
370
+ * their WAL/SHM sidecar files) and keeps the process alive on outstanding
371
+ * timers. Safe to call more than once. A `createNodePlatform` that throws
372
+ * unwinds the same list itself, so a failed construction leaks nothing and
373
+ * leaves nothing to call this on.
370
374
  *
371
375
  * **`close()` is a terminal state, not merely a cleanup step.** After it
372
376
  * runs: `scheduler.schedule()` throws instead of arming a fresh timer
@@ -394,14 +398,27 @@ interface NodePlatform<Queues extends Record<string, {
394
398
  * shutdown is `await platform.drain()` then `platform.close()`.
395
399
  */
396
400
  drain: () => Promise<void>;
397
- /** Durable key-value storage backed by the same `better-sqlite3` database as `shard`. */
398
- kv: ShardKvStore;
399
401
  /**
400
- * The local-filesystem bucket, or `undefined` when the caller named no
401
- * bucket directory. Same reasoning as `queues`: `objectStorage` is rated
402
- * `emulated`, so codegen emits `ctx.storage` for this target, and a bucket
403
- * nobody bound fails at the first `put` with nothing upstream to warn.
402
+ * The `.global()` backend, or `undefined` when the caller named no database
403
+ * file for it. There is no default path, because a global store silently
404
+ * rooted at `:memory:` loses every row when the process exits.
405
+ *
406
+ * **A building block, not a wiring.** Unlike its three siblings, nothing
407
+ * downstream of this composition root reads it: a `.global()` read or write
408
+ * reaches its backend through exactly one seam, `createShardCtxDb({ globalDb
409
+ * })`, and the only thing that passes `globalDb` is the generated `shard.ts`,
410
+ * from its `d1` / `hyperdriveGlobal` config thunks. `createNodePlatform`
411
+ * constructs no shard DO, so it cannot make that hop itself. A caller that
412
+ * wants `.global()` on this host makes it: after `migrate(schema)` has
413
+ * provisioned the tables, give the generated `createShardDO` a `d1` thunk
414
+ * returning `platform.globalTables.writer({ schema, … })` — `writer` builds
415
+ * the `createSqlCtxDb` facade that seam expects, and `node-platform.test.ts`
416
+ * round-trips a row through exactly that object.
404
417
  */
418
+ globalTables?: NodeGlobalStore;
419
+ /** Durable key-value storage backed by the same `better-sqlite3` database as `shard`. */
420
+ kv: ShardKvStore;
421
+ /** The local-filesystem bucket, or `undefined` when the caller named no bucket directory. */
405
422
  objectStorage?: R2BucketLike;
406
423
  /**
407
424
  * The declared queues, or `undefined` when the caller declared none.
@@ -433,15 +450,21 @@ interface NodePlatform<Queues extends Record<string, {
433
450
  * directory resolves for fan-out file-backed too, and `onAlarm` gives their
434
451
  * durable alarms somewhere to land.
435
452
  *
436
- * `queues`, `workflows` and `objectStorageDirectory` are the three
437
- * declarations: each binds its half of an `emulated` capability, and each is
438
- * absent from the returned platform when its declaration is omitted.
453
+ * `queues`, `workflows`, `objectStorageDirectory` and `globalTablesPath` are the
454
+ * four declarations — each is absent from the returned platform when omitted.
439
455
  */
440
456
  type NodePlatformOptions<Queues extends Record<string, {
441
457
  isLunoraQueue: true;
442
458
  }> = Record<string, never>, Workflows extends Record<string, {
443
459
  isLunoraWorkflow: true;
444
460
  }> = Record<string, never>> = {
461
+ /**
462
+ * Database file the `.global()` tables live in — its own file, never a
463
+ * shard's, because a table every shard reads must not be inside any one of
464
+ * them. Omit when the app declares no `.global()` table; there is no
465
+ * default, for the same reason the bucket has none.
466
+ */
467
+ globalTablesPath?: string;
445
468
  /**
446
469
  * Directory the object-storage bucket keeps its objects in, one file per
447
470
  * key. Omit when the app declares no buckets — there is no default,
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{createNodeGlobalStore as r,createNodeSqlExec as t}from"./packem_shared/createNodeGlobalStore-Cwi33XOk.mjs";import{createNodeShardKvStore as d}from"./packem_shared/createNodeShardKvStore-DVi1OsvH.mjs";import{createNodePlatform as f}from"./packem_shared/createNodePlatform-BGoxuZCi.mjs";import{createNodeQueueHost as x}from"./packem_shared/createNodeQueueHost--mBLGSxF.mjs";import{createNodeR2Bucket as p}from"./packem_shared/createNodeR2Bucket-BzNH1lBp.mjs";import{createNodeSchedulerHost as l}from"./packem_shared/createNodeSchedulerHost-BEAX6I4m.mjs";import{createNodeShardHost as h}from"./packem_shared/createNodeShardHost-B76kaXz-.mjs";import{createNodeShardRegistry as k}from"./packem_shared/createNodeShardRegistry-Dj1mXStS.mjs";import{createNodeShardState as w}from"./packem_shared/createNodeShardState-D6XMWbFs.mjs";import{createNodeSocketHost as W}from"./packem_shared/createNodeSocketHost-DQs85G7W.mjs";import{createNodeWorkflowHost as g}from"./packem_shared/createNodeWorkflowHost-CTVBYiuj.mjs";import{createNodeWorkflowStore as q}from"./packem_shared/createNodeWorkflowStore-CL7RYP6H.mjs";export{r as createNodeGlobalStore,f as createNodePlatform,x as createNodeQueueHost,p as createNodeR2Bucket,l as createNodeSchedulerHost,h as createNodeShardHost,d as createNodeShardKvStore,k as createNodeShardRegistry,w as createNodeShardState,W as createNodeSocketHost,t as createNodeSqlExec,g as createNodeWorkflowHost,q as createNodeWorkflowStore};
1
+ import{createNodeGlobalStore as r,createNodeSqlExec as t}from"./packem_shared/createNodeGlobalStore-Cwi33XOk.mjs";import{createNodeShardKvStore as d}from"./packem_shared/createNodeShardKvStore-DVi1OsvH.mjs";import{createNodePlatform as f}from"./packem_shared/createNodePlatform-DifFt1nR.mjs";import{createNodeQueueHost as x}from"./packem_shared/createNodeQueueHost--mBLGSxF.mjs";import{createNodeR2Bucket as p}from"./packem_shared/createNodeR2Bucket-BzNH1lBp.mjs";import{createNodeSchedulerHost as l}from"./packem_shared/createNodeSchedulerHost-BEAX6I4m.mjs";import{createNodeShardHost as h}from"./packem_shared/createNodeShardHost-B76kaXz-.mjs";import{createNodeShardRegistry as k}from"./packem_shared/createNodeShardRegistry-Dj1mXStS.mjs";import{createNodeShardState as w}from"./packem_shared/createNodeShardState-D6XMWbFs.mjs";import{createNodeSocketHost as W}from"./packem_shared/createNodeSocketHost-DQs85G7W.mjs";import{createNodeWorkflowHost as g}from"./packem_shared/createNodeWorkflowHost-CTVBYiuj.mjs";import{createNodeWorkflowStore as q}from"./packem_shared/createNodeWorkflowStore-CL7RYP6H.mjs";export{r as createNodeGlobalStore,f as createNodePlatform,x as createNodeQueueHost,p as createNodeR2Bucket,l as createNodeSchedulerHost,h as createNodeShardHost,d as createNodeShardKvStore,k as createNodeShardRegistry,w as createNodeShardState,W as createNodeSocketHost,t as createNodeSqlExec,g as createNodeWorkflowHost,q as createNodeWorkflowStore};
@@ -0,0 +1 @@
1
+ import{LunoraError as S}from"@lunora/errors";import{NODE_CAPABILITIES as b}from"@lunora/platform";import{createNodeGlobalStore as N}from"./createNodeGlobalStore-Cwi33XOk.mjs";import{createNodeShardKvStore as k}from"./createNodeShardKvStore-DVi1OsvH.mjs";import{createNodeQueueHost as g}from"./createNodeQueueHost--mBLGSxF.mjs";import{createNodeR2Bucket as y}from"./createNodeR2Bucket-BzNH1lBp.mjs";import{createNodeSchedulerHost as R}from"./createNodeSchedulerHost-BEAX6I4m.mjs";import{createNodeShardHost as q}from"./createNodeShardHost-B76kaXz-.mjs";import{createNodeShardRegistry as B}from"./createNodeShardRegistry-Dj1mXStS.mjs";import{createNodeSocketHost as H}from"./createNodeSocketHost-DQs85G7W.mjs";import{createNodeWorkflowHost as I}from"./createNodeWorkflowHost-CTVBYiuj.mjs";import{createNodeWorkflowStore as P}from"./createNodeWorkflowStore-CL7RYP6H.mjs";const G=(o={})=>{const e=[],{database:r,dispose:d,drain:u,host:i}=q(o);e.push(d);try{const s=k(r),t=B(o);e.push(()=>{t.close()});const{directory:l}=t,{socket:h}=H(r),{dispose:m,scheduler:f}=R(r,o);e.push(m);const n=o.queues===void 0?void 0:g(r,{onBatch:o.onQueueBatch??(()=>{throw new S("VALIDATION_ERROR","@lunora/platform-node: createNodePlatform was given `queues` without `onQueueBatch`, so a delivered batch has nowhere to go — pass dispatchQueueBatch from @lunora/queue")}),queues:o.queues}),p=o.objectStorageDirectory===void 0?void 0:y({directory:o.objectStorageDirectory}),a=o.globalTablesPath===void 0?void 0:N({path:o.globalTablesPath});a!==void 0&&e.push(()=>{a.dispose()});const w=o.workflows===void 0?void 0:I({store:P(r),workflows:o.workflows}),c=()=>{for(const v of e.toReversed())v()};return{capabilities:b,close:c,directory:l,drain:u,globalTables:a,kv:s,objectStorage:p,queues:n,scheduler:f,shard:i,sockets:h,workflows:w,[Symbol.dispose]:c}}catch(s){for(const t of e.toReversed())try{t()}catch{}throw s}};export{G as createNodePlatform};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/platform-node",
3
- "version": "1.0.0-alpha.44",
3
+ "version": "1.0.0-alpha.46",
4
4
  "description": "Node implementation of the Lunora platform contracts: ShardHost, SocketHost, ShardDirectory, ShardKvStore, SchedulerHost over better-sqlite3 and an in-process socket registry (dev/test target)",
5
5
  "keywords": [
6
6
  "better-sqlite3",
@@ -46,12 +46,12 @@
46
46
  "access": "public"
47
47
  },
48
48
  "dependencies": {
49
- "@lunora/d1": "1.0.0-alpha.104",
50
- "@lunora/errors": "1.0.0-alpha.30",
51
- "@lunora/platform": "1.0.0-alpha.25",
52
- "@lunora/queue": "1.0.0-alpha.43",
53
- "@lunora/sql-store": "1.0.0-alpha.106",
54
- "@lunora/workflow": "1.0.0-alpha.43",
49
+ "@lunora/d1": "1.0.0-alpha.106",
50
+ "@lunora/errors": "1.0.0-alpha.31",
51
+ "@lunora/platform": "1.0.0-alpha.26",
52
+ "@lunora/queue": "1.0.0-alpha.45",
53
+ "@lunora/sql-store": "1.0.0-alpha.108",
54
+ "@lunora/workflow": "1.0.0-alpha.44",
55
55
  "@visulima/workflow": "3.0.0",
56
56
  "better-sqlite3": "^13.0.3",
57
57
  "cron-parser": "5.8.1"
@@ -1 +0,0 @@
1
- import{LunoraError as n}from"@lunora/errors";import{NODE_CAPABILITIES as S}from"@lunora/platform";import{createNodeShardKvStore as N}from"./createNodeShardKvStore-DVi1OsvH.mjs";import{createNodeQueueHost as p}from"./createNodeQueueHost--mBLGSxF.mjs";import{createNodeR2Bucket as k}from"./createNodeR2Bucket-BzNH1lBp.mjs";import{createNodeSchedulerHost as v}from"./createNodeSchedulerHost-BEAX6I4m.mjs";import{createNodeShardHost as b}from"./createNodeShardHost-B76kaXz-.mjs";import{createNodeShardRegistry as g}from"./createNodeShardRegistry-Dj1mXStS.mjs";import{createNodeSocketHost as y}from"./createNodeSocketHost-DQs85G7W.mjs";import{createNodeWorkflowHost as q}from"./createNodeWorkflowHost-CTVBYiuj.mjs";import{createNodeWorkflowStore as B}from"./createNodeWorkflowStore-CL7RYP6H.mjs";const T=(e={})=>{const{database:o,dispose:c,drain:s,host:a}=b(e),d=N(o),r=g(e),{directory:u}=r,{socket:i}=y(o),{dispose:m,scheduler:f}=v(o,e),h=e.queues===void 0?void 0:p(o,{onBatch:e.onQueueBatch??(()=>{throw new n("VALIDATION_ERROR","@lunora/platform-node: createNodePlatform was given `queues` without `onQueueBatch`, so a delivered batch has nowhere to go — pass dispatchQueueBatch from @lunora/queue")}),queues:e.queues}),l=e.objectStorageDirectory===void 0?void 0:k({directory:e.objectStorageDirectory}),w=e.workflows===void 0?void 0:q({store:B(o),workflows:e.workflows}),t=()=>{m(),c(),r.close()};return{capabilities:S,close:t,directory:u,drain:s,kv:d,objectStorage:l,queues:h,scheduler:f,shard:a,sockets:i,workflows:w,[Symbol.dispose]:t}};export{T as createNodePlatform};