@lunora/do 1.0.0-alpha.21 → 1.0.0-alpha.23

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.
Files changed (25) hide show
  1. package/dist/index.d.mts +92 -90
  2. package/dist/index.d.ts +92 -90
  3. package/dist/index.mjs +19 -19
  4. package/dist/packem_shared/{ADMIN_FUNCTIONS-DSUQ5fX9.mjs → ADMIN_FUNCTIONS-BbQdj8h1.mjs} +5 -0
  5. package/dist/packem_shared/{AGGREGATE_SQL_FUNCTION-CFk6adSu.mjs → AGGREGATE_SQL_FUNCTION-CQsu2Xga.mjs} +5 -3
  6. package/dist/packem_shared/{CDC_LOG_TABLE-DSycmnDf.mjs → CDC_LOG_TABLE-DZSVKRr7.mjs} +1 -1
  7. package/dist/packem_shared/{ConflictError-C0STs6bU.mjs → ConflictError-CLoq37xH.mjs} +4 -5
  8. package/dist/packem_shared/{CountRlsUnsupportedError-28ZvvwKS.mjs → CountRlsUnsupportedError-BGxj0pgS.mjs} +4 -4
  9. package/dist/packem_shared/{DATA_MIGRATION_STATE_TABLE-DfPxn8I0.mjs → DATA_MIGRATION_STATE_TABLE-DB3IYUR3.mjs} +3 -1
  10. package/dist/packem_shared/{DEFAULT_MAX_RELATION_KEYS-DU-Y4-LJ.mjs → DEFAULT_MAX_RELATION_KEYS-CjM9Y1_G.mjs} +8 -6
  11. package/dist/packem_shared/NotFoundError-C70b9hLw.mjs +9 -0
  12. package/dist/packem_shared/{NotUniqueError-Do5h_jiW.mjs → NotUniqueError-D1U5SBFR.mjs} +63 -55
  13. package/dist/packem_shared/{RLS_UNWRAP_SYMBOL-EtGQdC9d.mjs → RLS_UNWRAP_SYMBOL-DnjkqVgY.mjs} +6 -5
  14. package/dist/packem_shared/{ROOT_DO_SIZE_WARN_BYTES-BfPNp3Jh.mjs → ROOT_DO_SIZE_WARN_BYTES-BM4TOOvf.mjs} +388 -49
  15. package/dist/packem_shared/{applyOnDelete-BQ-8ZlZ1.mjs → applyOnDelete-CAwZfp-5.mjs} +4 -3
  16. package/dist/packem_shared/{backfillAggregateIndexes-BZsOqDXP.mjs → backfillAggregateIndexes-DDoT-UUI.mjs} +1 -1
  17. package/dist/packem_shared/{compileWhereSql-MW_Lk8nJ.mjs → compileWhereSql-DE6yfRcQ.mjs} +2 -1
  18. package/dist/packem_shared/{createSystemReader-8CzSZP9V.mjs → createSystemReader-D12eNH13.mjs} +4 -2
  19. package/dist/packem_shared/{ctx-db-shapes-0RaIOy7J.mjs → ctx-db-shapes-Cz9dHyh1.mjs} +1 -1
  20. package/dist/packem_shared/{isSourceDue-9mJRJ9Ld.mjs → isSourceDue-BptUN8CR.mjs} +3 -2
  21. package/dist/packem_shared/{materializeExternalRows-Bj6EXy50.mjs → materializeExternalRows-DNcvoLRT.mjs} +2 -2
  22. package/dist/packem_shared/{runShardMigrations-nIwoQeOK.mjs → runShardMigrations-DeZr0KZp.mjs} +1 -1
  23. package/dist/packem_shared/{serveRelationFanout-C5axmGDj.mjs → serveRelationFanout-BhZF9AuB.mjs} +1 -1
  24. package/package.json +2 -1
  25. package/dist/packem_shared/NotFoundError-CMuMZt81.mjs +0 -10
package/dist/index.d.mts CHANGED
@@ -1,3 +1,4 @@
1
+ import { LunoraError } from '@lunora/errors';
1
2
  import { SQL } from 'drizzle-orm';
2
3
  import { DrizzleSqliteDODatabase } from 'drizzle-orm/durable-sqlite';
3
4
  /**
@@ -110,17 +111,13 @@ interface GroupByEntry {
110
111
  value: AggregateResult;
111
112
  }
112
113
  /**
113
- * Thrown when `count` runs in an RLS-restricted ctx. The structural shape
114
- * (`name: "LunoraError"`, `code`, `status`) lets the runtime's error mapper
115
- * route it without an `instanceof` check, so `@lunora/do` stays free of a
116
- * runtime dependency on `@lunora/server`. Status mirrors the
117
- * `COUNT_RLS_UNSUPPORTED` entry in the `LunoraErrorCode` taxonomy (422):
118
- * the operation is invalid in this context, not malformed.
114
+ * Thrown when `count` runs in an RLS-restricted ctx. A `LunoraError` subclass
115
+ * (`code: "COUNT_RLS_UNSUPPORTED"`, `status: 422`) recognised structurally by the
116
+ * runtime's error mapper (via `isLunoraError`), so `@lunora/do` needs no runtime
117
+ * dependency on `@lunora/server`. 422 = the operation is invalid in this context,
118
+ * not malformed.
119
119
  */
120
- declare class CountRlsUnsupportedError extends Error {
121
- readonly code: string;
122
- override readonly name = "LunoraError";
123
- readonly status: number;
120
+ declare class CountRlsUnsupportedError extends LunoraError {
124
121
  constructor(table?: string);
125
122
  }
126
123
  /**
@@ -761,37 +758,6 @@ declare class ReactiveCache {
761
758
  * everyone. Anonymous/subscription callers pass `null` (their own bucket).
762
759
  */
763
760
  declare const reactiveCacheKey: (functionPath: string, args: Record<string, unknown>, identity: null | string) => string;
764
- /**
765
- * `ctx.db.system` — a best-effort, read-only reader over Lunora's *system*
766
- * tables.
767
- *
768
- * Convex surfaces a handful of read-only system tables (`_scheduled_functions`,
769
- * `_storage`, ...) through `ctx.db.system`. Lunora mirrors that surface, but with
770
- * one load-bearing caveat: **the data these tables expose does not live in the
771
- * shard's SQLite**. Scheduled functions live in the `SchedulerDO`; storage
772
- * objects live in R2. So unlike `ctx.db.&lt;table>` — which reads the same
773
- * transactional SQLite snapshot the mutation writes into — `ctx.db.system`
774
- * reaches across a network/DO boundary on every call.
775
- *
776
- * Consequences callers must keep in mind:
777
- *
778
- * Asynchronous + eventually consistent: each `collect()` / `get()` issues a fresh
779
- * read against the backing source. A row a mutation just scheduled may not yet be
780
- * visible; a job that just fired may still appear pending.
781
- *
782
- * NOT part of the transaction snapshot: reading a system table inside a mutation
783
- * does not pin it; there is no OCC guard and no subscription dependency is
784
- * recorded. Treat the result as a point-in-time best effort.
785
- *
786
- * Read-only: there is no `insert`/`patch`/`delete`. Mutate scheduled jobs via
787
- * `ctx.scheduler`, storage objects via `ctx.storage`.
788
- *
789
- * The reader is intentionally minimal: `query(table).collect()` returns the full
790
- * list (no indexes, no filtering, no pagination) and `get(table, id)` resolves a
791
- * single row. That matches Convex's system-table read surface closely enough for
792
- * the studio / introspection use cases without re-implementing the query
793
- * planner against a remote source.
794
- */
795
761
  /** The system tables `ctx.db.system` can read. */
796
762
  type SystemTableName = "_scheduled_functions" | "_storage";
797
763
  /**
@@ -1893,14 +1859,12 @@ interface DatabaseWriterLike {
1893
1859
  system?: SystemDatabaseReader;
1894
1860
  }
1895
1861
  /**
1896
- * Thrown by `.unique()` when more than one row matches. Like {@link ConflictError}
1897
- * / `NotFoundError`, `code` / `status` are declared as own properties so the
1898
- * cross-package structural error mapper renders it as a 400 without an
1899
- * `instanceof` check against `@lunora/do`.
1862
+ * Thrown by `.unique()` when more than one row matches. A `LunoraError` subclass
1863
+ * (`code: "NOT_UNIQUE"`, `status: 400`) recognised structurally by the
1864
+ * cross-package transport mapper (via `isLunoraError`) without an `instanceof`
1865
+ * check against `@lunora/do`.
1900
1866
  */
1901
- declare class NotUniqueError extends Error {
1902
- readonly code: string;
1903
- readonly status: number;
1867
+ declare class NotUniqueError extends LunoraError {
1904
1868
  constructor(message?: string);
1905
1869
  }
1906
1870
  /**
@@ -2496,6 +2460,7 @@ declare const ADMIN_FUNCTIONS: {
2496
2460
  readonly applyCdc: "__lunora_admin__:applyCdc";
2497
2461
  readonly cdcSync: "__lunora_admin__:cdcSync";
2498
2462
  readonly clearCapturedMail: "__lunora_admin__:clearCapturedMail";
2463
+ readonly clearQueueMessages: "__lunora_admin__:clearQueueMessages";
2499
2464
  readonly clearTable: "__lunora_admin__:clearTable";
2500
2465
  readonly createWorkflowInstance: "__lunora_admin__:createWorkflowInstance";
2501
2466
  readonly deleteRows: "__lunora_admin__:deleteRows";
@@ -2514,6 +2479,7 @@ declare const ADMIN_FUNCTIONS: {
2514
2479
  readonly getLogs: "__lunora_admin__:getLogs";
2515
2480
  readonly getMetrics: "__lunora_admin__:getMetrics";
2516
2481
  readonly getPitrBookmark: "__lunora_admin__:getPitrBookmark";
2482
+ readonly getQueueMessages: "__lunora_admin__:getQueueMessages";
2517
2483
  readonly getRequestLog: "__lunora_admin__:getRequestLog";
2518
2484
  readonly getSecurityAudit: "__lunora_admin__:getSecurityAudit";
2519
2485
  readonly getSettings: "__lunora_admin__:getSettings";
@@ -2532,10 +2498,13 @@ declare const ADMIN_FUNCTIONS: {
2532
2498
  readonly recordAuthEvent: "__lunora_admin__:recordAuthEvent";
2533
2499
  readonly recordContainerEvent: "__lunora_admin__:recordContainerEvent";
2534
2500
  readonly recordMail: "__lunora_admin__:recordMail";
2501
+ readonly recordQueueMessage: "__lunora_admin__:recordQueueMessage";
2502
+ readonly replayQueueMessage: "__lunora_admin__:replayQueueMessage";
2535
2503
  readonly rlsPolicies: "__lunora_admin__:rlsPolicies";
2536
2504
  readonly runAs: "__lunora_admin__:runAs";
2537
2505
  readonly runMigration: "__lunora_admin__:runMigration";
2538
2506
  readonly runSql: "__lunora_admin__:runSql";
2507
+ readonly sendQueueMessage: "__lunora_admin__:sendQueueMessage";
2539
2508
  readonly sendTestMail: "__lunora_admin__:sendTestMail";
2540
2509
  readonly storageOrphans: "__lunora_admin__:storageOrphans";
2541
2510
  readonly storageReferences: "__lunora_admin__:storageReferences";
@@ -3449,13 +3418,11 @@ declare const clearCapturedMail: (sql: SqlExec) => {
3449
3418
  /**
3450
3419
  * Thrown by `findFirstOrThrow` when no document matches the query.
3451
3420
  *
3452
- * Like `ConflictError`, `code` / `status` are declared as own properties
3453
- * so the cross-package structural error mapper maps it to a 404 without an
3454
- * `instanceof` check against `@lunora/do`.
3421
+ * A `LunoraError` subclass (`code: "NOT_FOUND"`, `status: 404`) so the
3422
+ * cross-package transport mapper maps it to a 404 structurally (via
3423
+ * `isLunoraError`) without an `instanceof` check against `@lunora/do`.
3455
3424
  */
3456
- declare class NotFoundError extends Error {
3457
- readonly code: string;
3458
- readonly status: number;
3425
+ declare class NotFoundError extends LunoraError {
3459
3426
  constructor(message?: string);
3460
3427
  }
3461
3428
  /**
@@ -3691,24 +3658,6 @@ interface LogEventInput {
3691
3658
  * that want the raw values.
3692
3659
  */
3693
3660
  /**
3694
- * Secure-by-default write-path guard for `ctx.db`.
3695
- *
3696
- * When a schema is marked `defineSchema(...).rls("required")`, the generated
3697
- * user-facing ctx wraps its writer with {@link guardWriter}. The guard denies
3698
- * every read/write against a PROTECTED table (any table not marked `.public()`)
3699
- * so a procedure that forgot `.use(rls(policies))` fails CLOSED — it can never
3700
- * silently see or mutate a protected table through the unwrapped writer.
3701
- *
3702
- * The guard is transparent to the RLS middleware: it hangs the UNWRAPPED writer
3703
- * off {@link RLS_UNWRAP_SYMBOL}, so `@lunora/server`'s `rls()` middleware
3704
- * recovers the raw writer (via the same `Symbol.for` key — no cross-package
3705
- * import) to evaluate policies and issue policy-filtered reads without tripping
3706
- * the guard. Only procedures that NEVER engaged RLS keep talking to the guard.
3707
- *
3708
- * Admin / migration / studio writers (built from `createShardCtxDb` WITHOUT
3709
- * `enforceRls`) are never guarded — they are trusted system paths.
3710
- */
3711
- /**
3712
3661
  * Well-known symbol the guard hangs the unwrapped writer off of. `Symbol.for`
3713
3662
  * (the cross-realm global registry) lets `@lunora/server`'s RLS middleware read
3714
3663
  * it WITHOUT importing this module — both sides reference the same registered
@@ -3717,14 +3666,12 @@ interface LogEventInput {
3717
3666
  declare const RLS_UNWRAP_SYMBOL: symbol;
3718
3667
  /**
3719
3668
  * Thrown when a raw (non-RLS) handler touches a protected table under a
3720
- * `.rls("required")` schema. `code` / `status` / `table` are own properties (not
3721
- * just inherited prototype state) so structural callers across packages — which
3722
- * deliberately avoid a hard `@lunora/do` runtime dependency — recognise the
3723
- * shape without an `instanceof` check (mirrors `ConflictError`).
3724
- */
3725
- declare class RlsRequiredError extends Error {
3726
- readonly code: string;
3727
- readonly status: number;
3669
+ * `.rls("required")` schema. A `LunoraError` subclass (`code: "RLS_REQUIRED"`,
3670
+ * `status: 403`) recognised structurally across packages (via `isLunoraError`)
3671
+ * which deliberately avoid a hard `@lunora/do` runtime dependency — without an
3672
+ * `instanceof` check. `table` is kept as an own property.
3673
+ */
3674
+ declare class RlsRequiredError extends LunoraError {
3728
3675
  readonly table: string;
3729
3676
  constructor(table: string);
3730
3677
  }
@@ -5713,6 +5660,54 @@ declare abstract class ShardDO {
5713
5660
  */
5714
5661
  private handleSendTestMail;
5715
5662
  /**
5663
+ * Serve `__lunora_admin__:recordQueueMessage` — the capture sink the generated
5664
+ * worker `queue()` handler (via `@lunora/queue`'s `dispatchQueueBatch`) posts
5665
+ * every consumed message batch to. Records it into the reserved
5666
+ * `__lunora_queue_messages` table (bounded, auto-trimmed) so the studio Queues
5667
+ * panel shows one unified consumed-message log across every push consumer. Like
5668
+ * the mail catcher, the gate is the admin token alone — a token holder can
5669
+ * already mutate the shard, so a token-gated capture insert adds no privilege.
5670
+ */
5671
+ private handleRecordQueueMessage;
5672
+ /** Empty the dev queue consumed-message log (studio "clear log" action). Admin-gated by the caller. */
5673
+ private handleClearQueueMessages;
5674
+ /**
5675
+ * Serve `__lunora_admin__:sendQueueMessage` — the studio's "Send test message"
5676
+ * button. Resolves the declared queue's `QUEUE_*` producer binding and calls
5677
+ * `.send(body, { delaySeconds?, contentType? })`, or `.sendBatch(...)` when a
5678
+ * `batch` array is supplied. No SQLite write happens here (the message is only
5679
+ * captured once a consumer processes it), so this only records an audit entry.
5680
+ * Admin-gated by `handleAdminRpc`'s caller.
5681
+ */
5682
+ private handleSendQueueMessage;
5683
+ /**
5684
+ * Serve `__lunora_admin__:replayQueueMessage` — the studio's one-click replay /
5685
+ * DLQ redrive. Looks the captured row up by id, resolves the destination export
5686
+ * (explicit `target` → the parent queue when the message was captured off a
5687
+ * dead-letter queue → the queue it was consumed from), and re-enqueues the
5688
+ * stored body onto that producer. Records an audit entry; no SQLite write beyond
5689
+ * that (the replayed message is re-captured when a consumer processes it).
5690
+ * Admin-gated by `handleAdminRpc`'s caller.
5691
+ */
5692
+ private handleReplayQueueMessage;
5693
+ /**
5694
+ * Resolve a declared queue's runtime producer binding from this shard's `env`.
5695
+ * Looks the `exportName` up in {@link queuesMetadata} (the codegen subclass's
5696
+ * statically-discovered list) to find its generated `QUEUE_*` binding, then
5697
+ * reads `env[binding]` and validates it carries `send`/`sendBatch`. A bad export
5698
+ * name or a missing/malformed binding throws a 400 `LunoraError` so the studio
5699
+ * surfaces an actionable message. Mirrors {@link resolveWorkflowBinding}.
5700
+ */
5701
+ private resolveQueueBinding;
5702
+ /**
5703
+ * Pick the replay destination export for a captured message's origin queue.
5704
+ * When the message was consumed off a queue that is another queue's dead-letter
5705
+ * queue, prefer that PARENT queue's producer (a DLQ usually has no producer of
5706
+ * its own) so replay redrives onto the original; otherwise re-enqueue onto the
5707
+ * queue the message came from. Returns `undefined` when neither is declared.
5708
+ */
5709
+ private resolveReplayTarget;
5710
+ /**
5716
5711
  * Append one durable audit entry for a state-changing admin op that just
5717
5712
  * succeeded, folding the acting user (from `getCurrentUserId`) into `detail`.
5718
5713
  * Called only on the success path, so a rejected/validated op leaves no
@@ -5918,6 +5913,17 @@ declare abstract class ShardDO {
5918
5913
  * JSON memo still suppresses byte-identical pushes).
5919
5914
  */
5920
5915
  private readAdminCapturedMail;
5916
+ /**
5917
+ * Resolve a `getQueueMessages` admin read — the dev queue catcher's consumed
5918
+ * message log (`queue-catcher.ts`), newest-first, optionally filtered to one
5919
+ * queue. Best-effort: a SQL failure returns an empty log rather than throwing.
5920
+ * Reported against the {@link QUEUE_TABLE} so this read participates in
5921
+ * table-scoped subscription invalidation, but new captures arrive via the
5922
+ * worker→root-shard `recordQueueMessage` write, which (like the mail catcher)
5923
+ * inserts directly without a `flushChangedTables` — so the panel refreshes on
5924
+ * its poll (`useAutoRefresh`) rather than a live push.
5925
+ */
5926
+ private readAdminQueueMessages;
5921
5927
  /** Resolve a `readTablePage` admin read, parsing the loosely-typed args into the reader's options. */
5922
5928
  private readAdminTablePage;
5923
5929
  /**
@@ -6587,18 +6593,14 @@ type ConflictKind = "conflict" | "occ" | "restrict" | "trigger" | "unique";
6587
6593
  * Thrown by mutation handlers when an optimistic-concurrency check fails (or a
6588
6594
  * related write guard trips — see {@link ConflictKind}).
6589
6595
  *
6590
- * The runtime maps this to a 409 response so clients can decide whether to
6591
- * refetch + retry or surface the conflict. `code` / `status` / `kind` are
6592
- * declared as own properties (not just inherited prototype state) so structural
6593
- * callers across packages which deliberately avoid taking a hard runtime
6594
- * dependency on `@lunora/do` — can recognise the shape without an `instanceof`
6595
- * check.
6596
- */
6597
- declare class ConflictError extends Error {
6598
- readonly code: string;
6596
+ * A `LunoraError` subclass (`code: "CONFLICT"`, `status: 409`) so the runtime/DO
6597
+ * transport mappers recognise it structurally (via `isLunoraError`) structural
6598
+ * callers across packages still avoid a hard `instanceof` dependency on
6599
+ * `@lunora/do`. `kind` is kept as an own property for the metrics layer.
6600
+ */
6601
+ declare class ConflictError extends LunoraError {
6599
6602
  /** Why the conflict fired; `occ` is the contention signal the metrics layer counts. */
6600
6603
  readonly kind: ConflictKind;
6601
- readonly status: number;
6602
6604
  constructor(message?: string, kind?: ConflictKind);
6603
6605
  }
6604
6606
  /**
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { LunoraError } from '@lunora/errors';
1
2
  import { SQL } from 'drizzle-orm';
2
3
  import { DrizzleSqliteDODatabase } from 'drizzle-orm/durable-sqlite';
3
4
  /**
@@ -110,17 +111,13 @@ interface GroupByEntry {
110
111
  value: AggregateResult;
111
112
  }
112
113
  /**
113
- * Thrown when `count` runs in an RLS-restricted ctx. The structural shape
114
- * (`name: "LunoraError"`, `code`, `status`) lets the runtime's error mapper
115
- * route it without an `instanceof` check, so `@lunora/do` stays free of a
116
- * runtime dependency on `@lunora/server`. Status mirrors the
117
- * `COUNT_RLS_UNSUPPORTED` entry in the `LunoraErrorCode` taxonomy (422):
118
- * the operation is invalid in this context, not malformed.
114
+ * Thrown when `count` runs in an RLS-restricted ctx. A `LunoraError` subclass
115
+ * (`code: "COUNT_RLS_UNSUPPORTED"`, `status: 422`) recognised structurally by the
116
+ * runtime's error mapper (via `isLunoraError`), so `@lunora/do` needs no runtime
117
+ * dependency on `@lunora/server`. 422 = the operation is invalid in this context,
118
+ * not malformed.
119
119
  */
120
- declare class CountRlsUnsupportedError extends Error {
121
- readonly code: string;
122
- override readonly name = "LunoraError";
123
- readonly status: number;
120
+ declare class CountRlsUnsupportedError extends LunoraError {
124
121
  constructor(table?: string);
125
122
  }
126
123
  /**
@@ -761,37 +758,6 @@ declare class ReactiveCache {
761
758
  * everyone. Anonymous/subscription callers pass `null` (their own bucket).
762
759
  */
763
760
  declare const reactiveCacheKey: (functionPath: string, args: Record<string, unknown>, identity: null | string) => string;
764
- /**
765
- * `ctx.db.system` — a best-effort, read-only reader over Lunora's *system*
766
- * tables.
767
- *
768
- * Convex surfaces a handful of read-only system tables (`_scheduled_functions`,
769
- * `_storage`, ...) through `ctx.db.system`. Lunora mirrors that surface, but with
770
- * one load-bearing caveat: **the data these tables expose does not live in the
771
- * shard's SQLite**. Scheduled functions live in the `SchedulerDO`; storage
772
- * objects live in R2. So unlike `ctx.db.&lt;table>` — which reads the same
773
- * transactional SQLite snapshot the mutation writes into — `ctx.db.system`
774
- * reaches across a network/DO boundary on every call.
775
- *
776
- * Consequences callers must keep in mind:
777
- *
778
- * Asynchronous + eventually consistent: each `collect()` / `get()` issues a fresh
779
- * read against the backing source. A row a mutation just scheduled may not yet be
780
- * visible; a job that just fired may still appear pending.
781
- *
782
- * NOT part of the transaction snapshot: reading a system table inside a mutation
783
- * does not pin it; there is no OCC guard and no subscription dependency is
784
- * recorded. Treat the result as a point-in-time best effort.
785
- *
786
- * Read-only: there is no `insert`/`patch`/`delete`. Mutate scheduled jobs via
787
- * `ctx.scheduler`, storage objects via `ctx.storage`.
788
- *
789
- * The reader is intentionally minimal: `query(table).collect()` returns the full
790
- * list (no indexes, no filtering, no pagination) and `get(table, id)` resolves a
791
- * single row. That matches Convex's system-table read surface closely enough for
792
- * the studio / introspection use cases without re-implementing the query
793
- * planner against a remote source.
794
- */
795
761
  /** The system tables `ctx.db.system` can read. */
796
762
  type SystemTableName = "_scheduled_functions" | "_storage";
797
763
  /**
@@ -1893,14 +1859,12 @@ interface DatabaseWriterLike {
1893
1859
  system?: SystemDatabaseReader;
1894
1860
  }
1895
1861
  /**
1896
- * Thrown by `.unique()` when more than one row matches. Like {@link ConflictError}
1897
- * / `NotFoundError`, `code` / `status` are declared as own properties so the
1898
- * cross-package structural error mapper renders it as a 400 without an
1899
- * `instanceof` check against `@lunora/do`.
1862
+ * Thrown by `.unique()` when more than one row matches. A `LunoraError` subclass
1863
+ * (`code: "NOT_UNIQUE"`, `status: 400`) recognised structurally by the
1864
+ * cross-package transport mapper (via `isLunoraError`) without an `instanceof`
1865
+ * check against `@lunora/do`.
1900
1866
  */
1901
- declare class NotUniqueError extends Error {
1902
- readonly code: string;
1903
- readonly status: number;
1867
+ declare class NotUniqueError extends LunoraError {
1904
1868
  constructor(message?: string);
1905
1869
  }
1906
1870
  /**
@@ -2496,6 +2460,7 @@ declare const ADMIN_FUNCTIONS: {
2496
2460
  readonly applyCdc: "__lunora_admin__:applyCdc";
2497
2461
  readonly cdcSync: "__lunora_admin__:cdcSync";
2498
2462
  readonly clearCapturedMail: "__lunora_admin__:clearCapturedMail";
2463
+ readonly clearQueueMessages: "__lunora_admin__:clearQueueMessages";
2499
2464
  readonly clearTable: "__lunora_admin__:clearTable";
2500
2465
  readonly createWorkflowInstance: "__lunora_admin__:createWorkflowInstance";
2501
2466
  readonly deleteRows: "__lunora_admin__:deleteRows";
@@ -2514,6 +2479,7 @@ declare const ADMIN_FUNCTIONS: {
2514
2479
  readonly getLogs: "__lunora_admin__:getLogs";
2515
2480
  readonly getMetrics: "__lunora_admin__:getMetrics";
2516
2481
  readonly getPitrBookmark: "__lunora_admin__:getPitrBookmark";
2482
+ readonly getQueueMessages: "__lunora_admin__:getQueueMessages";
2517
2483
  readonly getRequestLog: "__lunora_admin__:getRequestLog";
2518
2484
  readonly getSecurityAudit: "__lunora_admin__:getSecurityAudit";
2519
2485
  readonly getSettings: "__lunora_admin__:getSettings";
@@ -2532,10 +2498,13 @@ declare const ADMIN_FUNCTIONS: {
2532
2498
  readonly recordAuthEvent: "__lunora_admin__:recordAuthEvent";
2533
2499
  readonly recordContainerEvent: "__lunora_admin__:recordContainerEvent";
2534
2500
  readonly recordMail: "__lunora_admin__:recordMail";
2501
+ readonly recordQueueMessage: "__lunora_admin__:recordQueueMessage";
2502
+ readonly replayQueueMessage: "__lunora_admin__:replayQueueMessage";
2535
2503
  readonly rlsPolicies: "__lunora_admin__:rlsPolicies";
2536
2504
  readonly runAs: "__lunora_admin__:runAs";
2537
2505
  readonly runMigration: "__lunora_admin__:runMigration";
2538
2506
  readonly runSql: "__lunora_admin__:runSql";
2507
+ readonly sendQueueMessage: "__lunora_admin__:sendQueueMessage";
2539
2508
  readonly sendTestMail: "__lunora_admin__:sendTestMail";
2540
2509
  readonly storageOrphans: "__lunora_admin__:storageOrphans";
2541
2510
  readonly storageReferences: "__lunora_admin__:storageReferences";
@@ -3449,13 +3418,11 @@ declare const clearCapturedMail: (sql: SqlExec) => {
3449
3418
  /**
3450
3419
  * Thrown by `findFirstOrThrow` when no document matches the query.
3451
3420
  *
3452
- * Like `ConflictError`, `code` / `status` are declared as own properties
3453
- * so the cross-package structural error mapper maps it to a 404 without an
3454
- * `instanceof` check against `@lunora/do`.
3421
+ * A `LunoraError` subclass (`code: "NOT_FOUND"`, `status: 404`) so the
3422
+ * cross-package transport mapper maps it to a 404 structurally (via
3423
+ * `isLunoraError`) without an `instanceof` check against `@lunora/do`.
3455
3424
  */
3456
- declare class NotFoundError extends Error {
3457
- readonly code: string;
3458
- readonly status: number;
3425
+ declare class NotFoundError extends LunoraError {
3459
3426
  constructor(message?: string);
3460
3427
  }
3461
3428
  /**
@@ -3691,24 +3658,6 @@ interface LogEventInput {
3691
3658
  * that want the raw values.
3692
3659
  */
3693
3660
  /**
3694
- * Secure-by-default write-path guard for `ctx.db`.
3695
- *
3696
- * When a schema is marked `defineSchema(...).rls("required")`, the generated
3697
- * user-facing ctx wraps its writer with {@link guardWriter}. The guard denies
3698
- * every read/write against a PROTECTED table (any table not marked `.public()`)
3699
- * so a procedure that forgot `.use(rls(policies))` fails CLOSED — it can never
3700
- * silently see or mutate a protected table through the unwrapped writer.
3701
- *
3702
- * The guard is transparent to the RLS middleware: it hangs the UNWRAPPED writer
3703
- * off {@link RLS_UNWRAP_SYMBOL}, so `@lunora/server`'s `rls()` middleware
3704
- * recovers the raw writer (via the same `Symbol.for` key — no cross-package
3705
- * import) to evaluate policies and issue policy-filtered reads without tripping
3706
- * the guard. Only procedures that NEVER engaged RLS keep talking to the guard.
3707
- *
3708
- * Admin / migration / studio writers (built from `createShardCtxDb` WITHOUT
3709
- * `enforceRls`) are never guarded — they are trusted system paths.
3710
- */
3711
- /**
3712
3661
  * Well-known symbol the guard hangs the unwrapped writer off of. `Symbol.for`
3713
3662
  * (the cross-realm global registry) lets `@lunora/server`'s RLS middleware read
3714
3663
  * it WITHOUT importing this module — both sides reference the same registered
@@ -3717,14 +3666,12 @@ interface LogEventInput {
3717
3666
  declare const RLS_UNWRAP_SYMBOL: symbol;
3718
3667
  /**
3719
3668
  * Thrown when a raw (non-RLS) handler touches a protected table under a
3720
- * `.rls("required")` schema. `code` / `status` / `table` are own properties (not
3721
- * just inherited prototype state) so structural callers across packages — which
3722
- * deliberately avoid a hard `@lunora/do` runtime dependency — recognise the
3723
- * shape without an `instanceof` check (mirrors `ConflictError`).
3724
- */
3725
- declare class RlsRequiredError extends Error {
3726
- readonly code: string;
3727
- readonly status: number;
3669
+ * `.rls("required")` schema. A `LunoraError` subclass (`code: "RLS_REQUIRED"`,
3670
+ * `status: 403`) recognised structurally across packages (via `isLunoraError`)
3671
+ * which deliberately avoid a hard `@lunora/do` runtime dependency — without an
3672
+ * `instanceof` check. `table` is kept as an own property.
3673
+ */
3674
+ declare class RlsRequiredError extends LunoraError {
3728
3675
  readonly table: string;
3729
3676
  constructor(table: string);
3730
3677
  }
@@ -5713,6 +5660,54 @@ declare abstract class ShardDO {
5713
5660
  */
5714
5661
  private handleSendTestMail;
5715
5662
  /**
5663
+ * Serve `__lunora_admin__:recordQueueMessage` — the capture sink the generated
5664
+ * worker `queue()` handler (via `@lunora/queue`'s `dispatchQueueBatch`) posts
5665
+ * every consumed message batch to. Records it into the reserved
5666
+ * `__lunora_queue_messages` table (bounded, auto-trimmed) so the studio Queues
5667
+ * panel shows one unified consumed-message log across every push consumer. Like
5668
+ * the mail catcher, the gate is the admin token alone — a token holder can
5669
+ * already mutate the shard, so a token-gated capture insert adds no privilege.
5670
+ */
5671
+ private handleRecordQueueMessage;
5672
+ /** Empty the dev queue consumed-message log (studio "clear log" action). Admin-gated by the caller. */
5673
+ private handleClearQueueMessages;
5674
+ /**
5675
+ * Serve `__lunora_admin__:sendQueueMessage` — the studio's "Send test message"
5676
+ * button. Resolves the declared queue's `QUEUE_*` producer binding and calls
5677
+ * `.send(body, { delaySeconds?, contentType? })`, or `.sendBatch(...)` when a
5678
+ * `batch` array is supplied. No SQLite write happens here (the message is only
5679
+ * captured once a consumer processes it), so this only records an audit entry.
5680
+ * Admin-gated by `handleAdminRpc`'s caller.
5681
+ */
5682
+ private handleSendQueueMessage;
5683
+ /**
5684
+ * Serve `__lunora_admin__:replayQueueMessage` — the studio's one-click replay /
5685
+ * DLQ redrive. Looks the captured row up by id, resolves the destination export
5686
+ * (explicit `target` → the parent queue when the message was captured off a
5687
+ * dead-letter queue → the queue it was consumed from), and re-enqueues the
5688
+ * stored body onto that producer. Records an audit entry; no SQLite write beyond
5689
+ * that (the replayed message is re-captured when a consumer processes it).
5690
+ * Admin-gated by `handleAdminRpc`'s caller.
5691
+ */
5692
+ private handleReplayQueueMessage;
5693
+ /**
5694
+ * Resolve a declared queue's runtime producer binding from this shard's `env`.
5695
+ * Looks the `exportName` up in {@link queuesMetadata} (the codegen subclass's
5696
+ * statically-discovered list) to find its generated `QUEUE_*` binding, then
5697
+ * reads `env[binding]` and validates it carries `send`/`sendBatch`. A bad export
5698
+ * name or a missing/malformed binding throws a 400 `LunoraError` so the studio
5699
+ * surfaces an actionable message. Mirrors {@link resolveWorkflowBinding}.
5700
+ */
5701
+ private resolveQueueBinding;
5702
+ /**
5703
+ * Pick the replay destination export for a captured message's origin queue.
5704
+ * When the message was consumed off a queue that is another queue's dead-letter
5705
+ * queue, prefer that PARENT queue's producer (a DLQ usually has no producer of
5706
+ * its own) so replay redrives onto the original; otherwise re-enqueue onto the
5707
+ * queue the message came from. Returns `undefined` when neither is declared.
5708
+ */
5709
+ private resolveReplayTarget;
5710
+ /**
5716
5711
  * Append one durable audit entry for a state-changing admin op that just
5717
5712
  * succeeded, folding the acting user (from `getCurrentUserId`) into `detail`.
5718
5713
  * Called only on the success path, so a rejected/validated op leaves no
@@ -5918,6 +5913,17 @@ declare abstract class ShardDO {
5918
5913
  * JSON memo still suppresses byte-identical pushes).
5919
5914
  */
5920
5915
  private readAdminCapturedMail;
5916
+ /**
5917
+ * Resolve a `getQueueMessages` admin read — the dev queue catcher's consumed
5918
+ * message log (`queue-catcher.ts`), newest-first, optionally filtered to one
5919
+ * queue. Best-effort: a SQL failure returns an empty log rather than throwing.
5920
+ * Reported against the {@link QUEUE_TABLE} so this read participates in
5921
+ * table-scoped subscription invalidation, but new captures arrive via the
5922
+ * worker→root-shard `recordQueueMessage` write, which (like the mail catcher)
5923
+ * inserts directly without a `flushChangedTables` — so the panel refreshes on
5924
+ * its poll (`useAutoRefresh`) rather than a live push.
5925
+ */
5926
+ private readAdminQueueMessages;
5921
5927
  /** Resolve a `readTablePage` admin read, parsing the loosely-typed args into the reader's options. */
5922
5928
  private readAdminTablePage;
5923
5929
  /**
@@ -6587,18 +6593,14 @@ type ConflictKind = "conflict" | "occ" | "restrict" | "trigger" | "unique";
6587
6593
  * Thrown by mutation handlers when an optimistic-concurrency check fails (or a
6588
6594
  * related write guard trips — see {@link ConflictKind}).
6589
6595
  *
6590
- * The runtime maps this to a 409 response so clients can decide whether to
6591
- * refetch + retry or surface the conflict. `code` / `status` / `kind` are
6592
- * declared as own properties (not just inherited prototype state) so structural
6593
- * callers across packages which deliberately avoid taking a hard runtime
6594
- * dependency on `@lunora/do` — can recognise the shape without an `instanceof`
6595
- * check.
6596
- */
6597
- declare class ConflictError extends Error {
6598
- readonly code: string;
6596
+ * A `LunoraError` subclass (`code: "CONFLICT"`, `status: 409`) so the runtime/DO
6597
+ * transport mappers recognise it structurally (via `isLunoraError`) structural
6598
+ * callers across packages still avoid a hard `instanceof` dependency on
6599
+ * `@lunora/do`. `kind` is kept as an own property for the metrics layer.
6600
+ */
6601
+ declare class ConflictError extends LunoraError {
6599
6602
  /** Why the conflict fired; `occ` is the contention signal the metrics layer counts. */
6600
6603
  readonly kind: ConflictKind;
6601
- readonly status: number;
6602
6604
  constructor(message?: string, kind?: ConflictKind);
6603
6605
  }
6604
6606
  /**
package/dist/index.mjs CHANGED
@@ -1,40 +1,40 @@
1
1
  export { exportShardRows, exportShardTable, importShardRows, parseExportShardArgs, parseImportShardArgs, selectExportTables, validateImportRow } from './packem_shared/exportShardRows-DZEhUeyI.mjs';
2
- export { AGGREGATE_SQL_FUNCTION, aggregateSqlFunction, matchesStaticWhere, normalizeCountArgument, throwingScheduler } from './packem_shared/AGGREGATE_SQL_FUNCTION-CFk6adSu.mjs';
2
+ export { AGGREGATE_SQL_FUNCTION, aggregateSqlFunction, matchesStaticWhere, normalizeCountArgument, throwingScheduler } from './packem_shared/AGGREGATE_SQL_FUNCTION-CQsu2Xga.mjs';
3
3
  export { aggregateTableName, coerceAggregateNumber, encodeAggregateKey, foldAggregateTally, readAggregateValue } from './packem_shared/aggregateTableName-CxNqY1Sl.mjs';
4
- export { CountRlsUnsupportedError, mergeWhere, planAggregateLookup, selectIndexForAggregate, selectIndexForCount, selectIndexForGroupBy } from './packem_shared/CountRlsUnsupportedError-28ZvvwKS.mjs';
4
+ export { CountRlsUnsupportedError, mergeWhere, planAggregateLookup, selectIndexForAggregate, selectIndexForCount, selectIndexForGroupBy } from './packem_shared/CountRlsUnsupportedError-BGxj0pgS.mjs';
5
5
  export { AUTH_METRICS_BUCKETS_TABLE, AUTH_METRICS_BUCKET_MS, AUTH_METRICS_BUCKET_RETENTION, AUTH_METRICS_TABLE, ensureAuthMetricsTables, readAuthMetrics, recordAuthEvent } from './packem_shared/AUTH_METRICS_BUCKETS_TABLE-CiHHYeJi.mjs';
6
- export { NotUniqueError, assertValidClientId, createShardCtxDb, normalizeIdStructurally } from './packem_shared/NotUniqueError-Do5h_jiW.mjs';
7
- export { DATA_MIGRATION_STATE_TABLE, readMigrationStatus, runDataMigration } from './packem_shared/DATA_MIGRATION_STATE_TABLE-DfPxn8I0.mjs';
6
+ export { NotUniqueError, assertValidClientId, createShardCtxDb, normalizeIdStructurally } from './packem_shared/NotUniqueError-D1U5SBFR.mjs';
7
+ export { DATA_MIGRATION_STATE_TABLE, readMigrationStatus, runDataMigration } from './packem_shared/DATA_MIGRATION_STATE_TABLE-DB3IYUR3.mjs';
8
8
  export { SCAN_DEP, createDependencyTracker, depKey } from './packem_shared/SCAN_DEP-DLJF8dsj.mjs';
9
9
  export { renderSql } from './packem_shared/renderSql-D6eUcn2N.mjs';
10
10
  export { diffExternalSource } from './packem_shared/diffExternalSource-Cx9HUPJj.mjs';
11
- export { materializeExternalRows, readExternalSourceBaseline, runExternalSourceTick } from './packem_shared/materializeExternalRows-Bj6EXy50.mjs';
12
- export { isSourceDue, liftSourceId, pullExternalSourceTick } from './packem_shared/isSourceDue-9mJRJ9Ld.mjs';
11
+ export { materializeExternalRows, readExternalSourceBaseline, runExternalSourceTick } from './packem_shared/materializeExternalRows-DNcvoLRT.mjs';
12
+ export { isSourceDue, liftSourceId, pullExternalSourceTick } from './packem_shared/isSourceDue-BptUN8CR.mjs';
13
13
  export { FUNCTION_METRICS_BUCKETS_TABLE, FUNCTION_METRICS_BUCKET_MS, FUNCTION_METRICS_BUCKET_RETENTION, FUNCTION_METRICS_INDEX_TABLE, FUNCTION_METRICS_TABLE, ensureFunctionMetricsTables, readFunctionMetricBuckets, readFunctionMetricIndexHits, readFunctionMetrics, readFunctionMetricsTotals, recordFunctionMetric } from './packem_shared/FUNCTION_METRICS_BUCKETS_TABLE-UDNVD7FS.mjs';
14
- export { ADMIN_FUNCTIONS, ADMIN_FUNCTION_PREFIX, FLAGS_FUNCTION_PREFIX, RELATION_FUNCTION_PREFIX, facetColumn, listTables, readTablePage, selectMatchingIds } from './packem_shared/ADMIN_FUNCTIONS-DSUQ5fX9.mjs';
14
+ export { ADMIN_FUNCTIONS, ADMIN_FUNCTION_PREFIX, FLAGS_FUNCTION_PREFIX, RELATION_FUNCTION_PREFIX, facetColumn, listTables, readTablePage, selectMatchingIds } from './packem_shared/ADMIN_FUNCTIONS-BbQdj8h1.mjs';
15
15
  export { LogBuffer } from './packem_shared/LogBuffer-B_Ezju_N.mjs';
16
16
  export { MAIL_RETENTION, MAIL_TABLE, clearCapturedMail, ensureMailTable, readCapturedMail, recordCapturedMail } from './packem_shared/MAIL_RETENTION-CPpgl-dX.mjs';
17
- export { default as NotFoundError } from './packem_shared/NotFoundError-CMuMZt81.mjs';
17
+ export { default as NotFoundError } from './packem_shared/NotFoundError-C70b9hLw.mjs';
18
18
  export { armRestore, readBookmark } from './packem_shared/armRestore-BJk53Ro8.mjs';
19
19
  export { applySelect, buildSeekWhere, decodeCursor, encodeCursor, normalizeOrderKeys, softDeleteScope } from './packem_shared/applySelect-BvZdFUBT.mjs';
20
20
  export { RANK_TIEBREAK, encodePartitionKey, matchesRankStaticWhere, rankTableName, resolveRankPartition, sortColumnName } from './packem_shared/RANK_TIEBREAK-CXhdcA1o.mjs';
21
21
  export { ReactiveCache, reactiveCacheKey } from './packem_shared/ReactiveCache-BYlSGY0N.mjs';
22
- export { serveRelationFanout } from './packem_shared/serveRelationFanout-C5axmGDj.mjs';
23
- export { DEFAULT_MAX_RELATION_KEYS, assertFlatPredicate, assertShapeShardable, containsRelationPredicate, isRelationPredicate, resolveRelationPredicates } from './packem_shared/DEFAULT_MAX_RELATION_KEYS-DU-Y4-LJ.mjs';
24
- export { applyOnDelete, fanOutScalarCounts, resolveWith, runRowValidators } from './packem_shared/applyOnDelete-BQ-8ZlZ1.mjs';
25
- export { RLS_UNWRAP_SYMBOL, RlsRequiredError, guardWriter } from './packem_shared/RLS_UNWRAP_SYMBOL-EtGQdC9d.mjs';
22
+ export { serveRelationFanout } from './packem_shared/serveRelationFanout-BhZF9AuB.mjs';
23
+ export { DEFAULT_MAX_RELATION_KEYS, assertFlatPredicate, assertShapeShardable, containsRelationPredicate, isRelationPredicate, resolveRelationPredicates } from './packem_shared/DEFAULT_MAX_RELATION_KEYS-CjM9Y1_G.mjs';
24
+ export { applyOnDelete, fanOutScalarCounts, resolveWith, runRowValidators } from './packem_shared/applyOnDelete-CAwZfp-5.mjs';
25
+ export { RLS_UNWRAP_SYMBOL, RlsRequiredError, guardWriter } from './packem_shared/RLS_UNWRAP_SYMBOL-DnjkqVgY.mjs';
26
26
  export { buildFtsMatch, ftsTableName, scoreDocument, stringifySearchText, tokenizeSearch } from './packem_shared/buildFtsMatch-BLEMawrp.mjs';
27
27
  export { M as MIN_ADMIN_TOKEN_LENGTH, a as MIN_AUTH_SECRET_LENGTH, b as buildSecurityAudit } from './packem_shared/security-audit-CucgBice.mjs';
28
28
  export { SESSION_DO_TTL_DEFAULT, SessionDO } from './packem_shared/SESSION_DO_TTL_DEFAULT-ilPZsVwu.mjs';
29
- export { ROOT_DO_SIZE_WARN_BYTES, ROOT_SHARD_NAME, ShardDO } from './packem_shared/ROOT_DO_SIZE_WARN_BYTES-BfPNp3Jh.mjs';
29
+ export { ROOT_DO_SIZE_WARN_BYTES, ROOT_SHARD_NAME, ShardDO } from './packem_shared/ROOT_DO_SIZE_WARN_BYTES-BM4TOOvf.mjs';
30
30
  export { SHARD_REGISTRY_DO_NAME, ShardRegistryDO } from './packem_shared/SHARD_REGISTRY_DO_NAME-BsAbi5Mn.mjs';
31
31
  export { MAX_SQL_ROWS, assertReadonly, runReadonlySql } from './packem_shared/MAX_SQL_ROWS-dDcFE1YZ.mjs';
32
- export { createSystemReader } from './packem_shared/createSystemReader-8CzSZP9V.mjs';
33
- export { ConflictError } from './packem_shared/ConflictError-C0STs6bU.mjs';
32
+ export { createSystemReader } from './packem_shared/createSystemReader-D12eNH13.mjs';
33
+ export { ConflictError } from './packem_shared/ConflictError-CLoq37xH.mjs';
34
34
  export { hasTrigger, runTriggers } from './packem_shared/hasTrigger-5N6_Fx0A.mjs';
35
- export { compileWhereSql } from './packem_shared/compileWhereSql-MW_Lk8nJ.mjs';
36
- export { CDC_LOG_TABLE, applyCdcChanges, readCdcChanges, trimCdcChanges } from './packem_shared/CDC_LOG_TABLE-DSycmnDf.mjs';
37
- export { backfillAggregateIndexes, backfillRankIndexes } from './packem_shared/backfillAggregateIndexes-BZsOqDXP.mjs';
38
- export { runShardMigrations } from './packem_shared/runShardMigrations-nIwoQeOK.mjs';
35
+ export { compileWhereSql } from './packem_shared/compileWhereSql-DE6yfRcQ.mjs';
36
+ export { CDC_LOG_TABLE, applyCdcChanges, readCdcChanges, trimCdcChanges } from './packem_shared/CDC_LOG_TABLE-DZSVKRr7.mjs';
37
+ export { backfillAggregateIndexes, backfillRankIndexes } from './packem_shared/backfillAggregateIndexes-DDoT-UUI.mjs';
38
+ export { runShardMigrations } from './packem_shared/runShardMigrations-DeZr0KZp.mjs';
39
39
  export { stableStringify } from './packem_shared/stableStringify-MydiuScU.mjs';
40
40
  export { s as subscriptionListDeltas } from './packem_shared/subscription-delivery-CK8qga-k.mjs';