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

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.
@@ -1,20 +1,21 @@
1
1
  import { LunoraError, toErrorBody } from '@lunora/errors';
2
2
  import { drizzle } from 'drizzle-orm/durable-sqlite';
3
+ import { j as jsonResponse } from './json-response-BdbtpOhm.mjs';
3
4
  import { e as encodeWire, a as awaitWsDrain, t as trySendFrame, d as decodeWire, s as subscriptionListDeltas, b as sendDeltaFrames } from './subscription-delivery-CK8qga-k.mjs';
4
- import { parseExportShardArgs, parseImportShardArgs } from './exportShardRows-DZEhUeyI.mjs';
5
+ import { parseExportShardArgs, parseImportShardArgs } from './exportShardRows-Dy3oFZ26.mjs';
5
6
  import { recordAuthEvent, readAuthMetrics } from './AUTH_METRICS_BUCKETS_TABLE-CiHHYeJi.mjs';
6
7
  import { DATA_MIGRATION_STATE_TABLE, readMigrationStatus } from './DATA_MIGRATION_STATE_TABLE-DB3IYUR3.mjs';
7
8
  import { SCAN_DEP, createDependencyTracker, tableFromDepKey } from './SCAN_DEP-DLJF8dsj.mjs';
8
9
  import { readFunctionMetricsTotals, readFunctionMetricIndexHits, recordFunctionMetric, mergeScanAttribution, readFunctionMetrics, readFunctionMetricBuckets } from './FUNCTION_METRICS_BUCKETS_TABLE-UDNVD7FS.mjs';
9
- import { createFanoutCounters, ADMIN_FUNCTION_PREFIX, RELATION_FUNCTION_PREFIX, selectMatchingIds, ADMIN_FUNCTIONS, findStorageReferences, listTables, summarizeSubscriptions, summarizeFanoutTopics, readTablePage, facetColumn, FLAGS_FUNCTION_PREFIX, recordFanoutPass, MAX_PAGE_SIZE } from './ADMIN_FUNCTIONS-BbQdj8h1.mjs';
10
+ import { createFanoutCounters, ADMIN_FUNCTION_PREFIX, RELATION_FUNCTION_PREFIX, selectMatchingIds, ADMIN_FUNCTIONS, findStorageReferences, listTables, summarizeSubscriptions, summarizeFanoutTopics, readTablePage, facetColumn, FLAGS_FUNCTION_PREFIX, recordFanoutPass, MAX_PAGE_SIZE } from './ADMIN_FUNCTIONS-Bxdijn66.mjs';
10
11
  import { LogBuffer } from './LogBuffer-B_Ezju_N.mjs';
11
12
  import { recordCapturedMail, clearCapturedMail, readCapturedMail, MAIL_TABLE } from './MAIL_RETENTION-CPpgl-dX.mjs';
12
- import { readBookmark, armRestore } from './armRestore-BJk53Ro8.mjs';
13
+ import { readBookmark, armRestore } from './armRestore-4Px61hHS.mjs';
13
14
  import { ReactiveCache, reactiveCacheKey } from './ReactiveCache-BYlSGY0N.mjs';
14
15
  import { stableStringify } from './stableStringify-MydiuScU.mjs';
15
16
  import { redact, standardRules } from '@visulima/redact';
16
17
  import { i as isDevEnvironment, c as buildSettings, b as buildSecurityAudit } from './security-audit-CucgBice.mjs';
17
- import { runReadonlySql } from './MAX_SQL_ROWS-dDcFE1YZ.mjs';
18
+ import { runReadonlySql } from './MAX_SQL_ROWS-D57CJaT9.mjs';
18
19
  import { ConflictError } from './ConflictError-CLoq37xH.mjs';
19
20
  import { e as deleteGlobalShapeSnapshotsForConnection, g as readIdempotent, h as writeIdempotent, t as trimIdempotent, r as readClientWatermark, m as migrateClientWatermark, c as advanceClientWatermark, d as deleteGlobalShapeSnapshot, f as readGlobalShapeSnapshot, w as writeGlobalShapeSnapshot } from './ctx-db-idempotency-BdcNpvY4.mjs';
20
21
  import { CDC_LOG_TABLE, readCdcChanges, readCdcCursor, readCdcEpoch, minCdcSeq, bumpCdcEpoch } from './CDC_LOG_TABLE-DZSVKRr7.mjs';
@@ -764,7 +765,8 @@ class OwnerRelay extends RelayLink {
764
765
  try {
765
766
  resolved = this.host.resolveShape(request.name, request.args, identity);
766
767
  } catch (error) {
767
- return { error: { code: "SHAPE_RESOLVE_FAILED", message: error instanceof Error ? error.message : "shape resolve failed" } };
768
+ const { body } = toErrorBody(error, { fallbackCode: "SHAPE_RESOLVE_FAILED", redactedMessage: "shape resolution failed" });
769
+ return { error: { code: body.code, message: body.message } };
768
770
  }
769
771
  if (resolved === void 0 || resolved.global === true) {
770
772
  return { error: { code: "SHAPE_NOT_FOUND", message: `shape not relayable: ${request.name}` } };
@@ -1402,7 +1404,7 @@ const setsIntersect = (a, b) => {
1402
1404
  const parseRunMigrationArgs = (args) => {
1403
1405
  const id = typeof args["id"] === "string" ? args["id"] : "";
1404
1406
  if (id.trim() === "") {
1405
- throw Object.assign(new Error("runMigration: `id` is required"), { code: "MIGRATION_ID_REQUIRED", name: "LunoraError", status: 400 });
1407
+ throw new LunoraError("MIGRATION_ID_REQUIRED", "runMigration: `id` is required", { status: 400 });
1406
1408
  }
1407
1409
  return {
1408
1410
  batchSize: typeof args["batchSize"] === "number" ? args["batchSize"] : void 0,
@@ -1417,25 +1419,25 @@ const parseWriteRowArgs = (args) => {
1417
1419
  const { op } = args;
1418
1420
  const table = typeof args["table"] === "string" ? args["table"] : "";
1419
1421
  if (op !== "insert" && op !== "patch" && op !== "replace" && op !== "delete") {
1420
- throw Object.assign(new Error("writeRow: `op` must be insert|patch|replace|delete"), { code: "BAD_REQUEST", name: "LunoraError", status: 400 });
1422
+ throw new LunoraError("BAD_REQUEST", "writeRow: `op` must be insert|patch|replace|delete");
1421
1423
  }
1422
1424
  if (table.trim() === "") {
1423
- throw Object.assign(new Error("writeRow: `table` is required"), { code: "BAD_REQUEST", name: "LunoraError", status: 400 });
1425
+ throw new LunoraError("BAD_REQUEST", "writeRow: `table` is required");
1424
1426
  }
1425
1427
  const id = typeof args["id"] === "string" ? args["id"] : void 0;
1426
1428
  const record = typeof args["doc"] === "object" && args["doc"] !== null && !Array.isArray(args["doc"]) ? args["doc"] : void 0;
1427
1429
  if (op !== "insert" && (id === void 0 || id === "")) {
1428
- throw Object.assign(new Error(`writeRow: \`id\` is required for op "${op}"`), { code: "BAD_REQUEST", name: "LunoraError", status: 400 });
1430
+ throw new LunoraError("BAD_REQUEST", `writeRow: \`id\` is required for op "${op}"`);
1429
1431
  }
1430
1432
  if (op !== "delete" && record === void 0) {
1431
- throw Object.assign(new Error(`writeRow: \`doc\` is required for op "${op}"`), { code: "BAD_REQUEST", name: "LunoraError", status: 400 });
1433
+ throw new LunoraError("BAD_REQUEST", `writeRow: \`doc\` is required for op "${op}"`);
1432
1434
  }
1433
1435
  return { doc: record, id, op, table };
1434
1436
  };
1435
1437
  const parseCreateWorkflowInstanceArgs = (args) => {
1436
1438
  const exportName = typeof args["exportName"] === "string" ? args["exportName"].trim() : "";
1437
1439
  if (exportName === "") {
1438
- throw Object.assign(new Error("createWorkflowInstance: `exportName` is required"), { code: "BAD_REQUEST", name: "LunoraError", status: 400 });
1440
+ throw new LunoraError("BAD_REQUEST", "createWorkflowInstance: `exportName` is required");
1439
1441
  }
1440
1442
  const id = typeof args["id"] === "string" && args["id"] !== "" ? args["id"] : void 0;
1441
1443
  return { exportName, id, params: args["params"] };
@@ -1444,10 +1446,10 @@ const parseGetWorkflowInstanceStatusArgs = (args) => {
1444
1446
  const exportName = typeof args["exportName"] === "string" ? args["exportName"].trim() : "";
1445
1447
  const id = typeof args["id"] === "string" ? args["id"].trim() : "";
1446
1448
  if (exportName === "") {
1447
- throw Object.assign(new Error("getWorkflowInstanceStatus: `exportName` is required"), { code: "BAD_REQUEST", name: "LunoraError", status: 400 });
1449
+ throw new LunoraError("BAD_REQUEST", "getWorkflowInstanceStatus: `exportName` is required");
1448
1450
  }
1449
1451
  if (id === "") {
1450
- throw Object.assign(new Error("getWorkflowInstanceStatus: `id` is required"), { code: "BAD_REQUEST", name: "LunoraError", status: 400 });
1452
+ throw new LunoraError("BAD_REQUEST", "getWorkflowInstanceStatus: `id` is required");
1451
1453
  }
1452
1454
  return { exportName, id };
1453
1455
  };
@@ -1502,7 +1504,7 @@ const parseTablePageOrderBy = (raw) => {
1502
1504
  const parseBulkDeleteArgs = (args) => {
1503
1505
  const table = typeof args["table"] === "string" ? args["table"] : "";
1504
1506
  if (table.trim() === "") {
1505
- throw Object.assign(new Error("deleteRows: `table` is required"), { code: "BAD_REQUEST", name: "LunoraError", status: 400 });
1507
+ throw new LunoraError("BAD_REQUEST", "deleteRows: `table` is required");
1506
1508
  }
1507
1509
  return {
1508
1510
  filters: parseTablePageFilters(args["filters"]),
@@ -1514,31 +1516,27 @@ const parseBulkDeleteArgs = (args) => {
1514
1516
  const parseClearTableArgs = (args) => {
1515
1517
  const table = typeof args["table"] === "string" ? args["table"] : "";
1516
1518
  if (table.trim() === "") {
1517
- throw Object.assign(new Error("clearTable: `table` is required"), { code: "BAD_REQUEST", name: "LunoraError", status: 400 });
1519
+ throw new LunoraError("BAD_REQUEST", "clearTable: `table` is required");
1518
1520
  }
1519
1521
  return { limit: typeof args["limit"] === "number" ? args["limit"] : void 0, table };
1520
1522
  };
1521
1523
  const parseRecordAuthEventArgs = (args) => {
1522
1524
  const { outcome } = args;
1523
1525
  if (outcome !== "ok" && outcome !== "fail") {
1524
- throw Object.assign(new Error('recordAuthEvent: `outcome` must be "ok" or "fail"'), { code: "BAD_REQUEST", name: "LunoraError", status: 400 });
1526
+ throw new LunoraError("BAD_REQUEST", 'recordAuthEvent: `outcome` must be "ok" or "fail"');
1525
1527
  }
1526
1528
  return { outcome };
1527
1529
  };
1528
1530
  const parseRecordContainerEventArgs = (args) => {
1529
1531
  const raw = args["event"];
1530
1532
  if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
1531
- throw Object.assign(new Error("recordContainerEvent: `event` must be an object"), { code: "BAD_REQUEST", name: "LunoraError", status: 400 });
1533
+ throw new LunoraError("BAD_REQUEST", "recordContainerEvent: `event` must be an object");
1532
1534
  }
1533
1535
  const envelope = raw;
1534
1536
  const container = typeof envelope["container"] === "string" ? envelope["container"] : "";
1535
1537
  const event = typeof envelope["event"] === "string" ? envelope["event"] : "";
1536
1538
  if (container.trim() === "" || event.trim() === "") {
1537
- throw Object.assign(new Error("recordContainerEvent: `event.container` and `event.event` are required"), {
1538
- code: "BAD_REQUEST",
1539
- name: "LunoraError",
1540
- status: 400
1541
- });
1539
+ throw new LunoraError("BAD_REQUEST", "recordContainerEvent: `event.container` and `event.event` are required");
1542
1540
  }
1543
1541
  const level = envelope["level"] === "error" ? "error" : "info";
1544
1542
  const detail = typeof envelope["message"] === "string" ? envelope["message"] : void 0;
@@ -1554,21 +1552,21 @@ const parseRunAsArgs = (args) => {
1554
1552
  const functionPath = typeof args["functionPath"] === "string" ? args["functionPath"] : "";
1555
1553
  const userId = typeof args["userId"] === "string" ? args["userId"] : "";
1556
1554
  if (functionPath.trim() === "") {
1557
- throw Object.assign(new Error("runAs: `functionPath` is required"), { code: "BAD_REQUEST", name: "LunoraError", status: 400 });
1555
+ throw new LunoraError("BAD_REQUEST", "runAs: `functionPath` is required");
1558
1556
  }
1559
1557
  if (functionPath.startsWith(ADMIN_FUNCTION_PREFIX)) {
1560
- throw Object.assign(new Error("runAs: cannot target a reserved admin function"), { code: "BAD_REQUEST", name: "LunoraError", status: 400 });
1558
+ throw new LunoraError("BAD_REQUEST", "runAs: cannot target a reserved admin function");
1561
1559
  }
1562
1560
  if (userId.trim() === "") {
1563
- throw Object.assign(new Error("runAs: `userId` is required"), { code: "BAD_REQUEST", name: "LunoraError", status: 400 });
1561
+ throw new LunoraError("BAD_REQUEST", "runAs: `userId` is required");
1564
1562
  }
1565
1563
  const rawArgs = args["args"];
1566
1564
  if (rawArgs !== void 0 && (typeof rawArgs !== "object" || rawArgs === null || Array.isArray(rawArgs))) {
1567
- throw Object.assign(new Error("runAs: `args` must be an object"), { code: "BAD_REQUEST", name: "LunoraError", status: 400 });
1565
+ throw new LunoraError("BAD_REQUEST", "runAs: `args` must be an object");
1568
1566
  }
1569
1567
  const rawIdentity = args["identity"];
1570
1568
  if (rawIdentity !== void 0 && (typeof rawIdentity !== "object" || rawIdentity === null || Array.isArray(rawIdentity))) {
1571
- throw Object.assign(new Error("runAs: `identity` must be an object"), { code: "BAD_REQUEST", name: "LunoraError", status: 400 });
1569
+ throw new LunoraError("BAD_REQUEST", "runAs: `identity` must be an object");
1572
1570
  }
1573
1571
  return {
1574
1572
  args: rawArgs === void 0 ? {} : rawArgs,
@@ -1579,7 +1577,7 @@ const parseRunAsArgs = (args) => {
1579
1577
  };
1580
1578
  const parseRecordMailArgs = (args) => {
1581
1579
  const bad = (message) => {
1582
- throw Object.assign(new Error(`recordMail: ${message}`), { code: "BAD_REQUEST", name: "LunoraError", status: 400 });
1580
+ throw new LunoraError("BAD_REQUEST", `recordMail: ${message}`);
1583
1581
  };
1584
1582
  const { bcc, cc, from, headers, html, replyTo, subject, text, to } = args;
1585
1583
  if (typeof subject !== "string") {
@@ -1620,7 +1618,7 @@ const TEST_MAIL_DEFAULT_TO = "test@lunora.sh";
1620
1618
  const buildTestMailInput = (args) => {
1621
1619
  const { to } = args;
1622
1620
  if (to !== void 0 && typeof to !== "string") {
1623
- throw Object.assign(new Error("sendTestMail: `to` must be a string"), { code: "BAD_REQUEST", name: "LunoraError", status: 400 });
1621
+ throw new LunoraError("BAD_REQUEST", "sendTestMail: `to` must be a string");
1624
1622
  }
1625
1623
  const recipient = to ?? TEST_MAIL_DEFAULT_TO;
1626
1624
  const link = "https://example.test/verify?token=demo";
@@ -1636,7 +1634,7 @@ Verify your email: ${link}`,
1636
1634
  };
1637
1635
  const parseRecordQueueMessageArgs = (args) => {
1638
1636
  const bad = (message) => {
1639
- throw Object.assign(new Error(`recordQueueMessage: ${message}`), { code: "BAD_REQUEST", name: "LunoraError", status: 400 });
1637
+ throw new LunoraError("BAD_REQUEST", `recordQueueMessage: ${message}`);
1640
1638
  };
1641
1639
  const raw = args["messages"];
1642
1640
  if (!Array.isArray(raw)) {
@@ -1678,23 +1676,15 @@ const MAX_QUEUE_SEND_BATCH = 100;
1678
1676
  const parseSendQueueMessageArgs = (args) => {
1679
1677
  const exportName = typeof args["exportName"] === "string" ? args["exportName"].trim() : "";
1680
1678
  if (exportName === "") {
1681
- throw Object.assign(new Error("sendQueueMessage: `exportName` is required"), { code: "BAD_REQUEST", name: "LunoraError", status: 400 });
1679
+ throw new LunoraError("BAD_REQUEST", "sendQueueMessage: `exportName` is required");
1682
1680
  }
1683
1681
  const delayRaw = args["delaySeconds"];
1684
1682
  if (delayRaw !== void 0 && (typeof delayRaw !== "number" || !Number.isFinite(delayRaw) || delayRaw < 0)) {
1685
- throw Object.assign(new Error("sendQueueMessage: `delaySeconds` must be a non-negative number"), {
1686
- code: "BAD_REQUEST",
1687
- name: "LunoraError",
1688
- status: 400
1689
- });
1683
+ throw new LunoraError("BAD_REQUEST", "sendQueueMessage: `delaySeconds` must be a non-negative number");
1690
1684
  }
1691
1685
  const batch = Array.isArray(args["batch"]) ? args["batch"] : void 0;
1692
1686
  if (batch !== void 0 && (batch.length === 0 || batch.length > MAX_QUEUE_SEND_BATCH)) {
1693
- throw Object.assign(new Error(`sendQueueMessage: \`batch\` must contain between 1 and ${String(MAX_QUEUE_SEND_BATCH)} messages`), {
1694
- code: "BAD_REQUEST",
1695
- name: "LunoraError",
1696
- status: 400
1697
- });
1687
+ throw new LunoraError("BAD_REQUEST", `sendQueueMessage: \`batch\` must contain between 1 and ${String(MAX_QUEUE_SEND_BATCH)} messages`);
1698
1688
  }
1699
1689
  return {
1700
1690
  batch,
@@ -1707,7 +1697,7 @@ const parseSendQueueMessageArgs = (args) => {
1707
1697
  const parseReplayQueueMessageArgs = (args) => {
1708
1698
  const id = typeof args["id"] === "string" ? args["id"].trim() : "";
1709
1699
  if (id === "") {
1710
- throw Object.assign(new Error("replayQueueMessage: `id` is required"), { code: "BAD_REQUEST", name: "LunoraError", status: 400 });
1700
+ throw new LunoraError("BAD_REQUEST", "replayQueueMessage: `id` is required");
1711
1701
  }
1712
1702
  const target = typeof args["target"] === "string" && args["target"].trim() !== "" ? args["target"].trim() : void 0;
1713
1703
  return { id, target };
@@ -1717,24 +1707,24 @@ const parseRankBeforeArgs = (args) => {
1717
1707
  const index = typeof args["index"] === "string" ? args["index"] : "";
1718
1708
  const rowId = typeof args["rowId"] === "string" ? args["rowId"] : "";
1719
1709
  if (table.trim() === "") {
1720
- throw Object.assign(new Error("rankBefore: `table` is required"), { code: "BAD_REQUEST", name: "LunoraError", status: 400 });
1710
+ throw new LunoraError("BAD_REQUEST", "rankBefore: `table` is required");
1721
1711
  }
1722
1712
  if (index.trim() === "") {
1723
- throw Object.assign(new Error("rankBefore: `index` is required"), { code: "BAD_REQUEST", name: "LunoraError", status: 400 });
1713
+ throw new LunoraError("BAD_REQUEST", "rankBefore: `index` is required");
1724
1714
  }
1725
1715
  if (typeof args["partitionKey"] !== "string") {
1726
- throw Object.assign(new Error("rankBefore: `partitionKey` must be a string"), { code: "BAD_REQUEST", name: "LunoraError", status: 400 });
1716
+ throw new LunoraError("BAD_REQUEST", "rankBefore: `partitionKey` must be a string");
1727
1717
  }
1728
1718
  if (rowId.trim() === "") {
1729
- throw Object.assign(new Error("rankBefore: `rowId` is required"), { code: "BAD_REQUEST", name: "LunoraError", status: 400 });
1719
+ throw new LunoraError("BAD_REQUEST", "rankBefore: `rowId` is required");
1730
1720
  }
1731
1721
  if (!Array.isArray(args["sortValues"])) {
1732
- throw Object.assign(new Error("rankBefore: `sortValues` must be an array"), { code: "BAD_REQUEST", name: "LunoraError", status: 400 });
1722
+ throw new LunoraError("BAD_REQUEST", "rankBefore: `sortValues` must be an array");
1733
1723
  }
1734
1724
  return { index, partitionKey: args["partitionKey"], rowId, sortValues: args["sortValues"], table };
1735
1725
  };
1736
1726
  const badRequest = (message) => {
1737
- throw Object.assign(new Error(message), { code: "BAD_REQUEST", name: "LunoraError", status: 400 });
1727
+ throw new LunoraError("BAD_REQUEST", message);
1738
1728
  };
1739
1729
  const requireNonEmptyString = (value, field) => {
1740
1730
  if (typeof value !== "string" || value.trim() === "") {
@@ -1794,7 +1784,7 @@ const decodeIndexHitKey = (key) => {
1794
1784
  const parseApplyCdcArgs = (args) => {
1795
1785
  const raw = args["changes"];
1796
1786
  if (!Array.isArray(raw)) {
1797
- throw Object.assign(new Error("applyCdc: `changes` must be an array"), { code: "BAD_REQUEST", name: "LunoraError", status: 400 });
1787
+ throw new LunoraError("BAD_REQUEST", "applyCdc: `changes` must be an array");
1798
1788
  }
1799
1789
  const changes = raw.map((entry, index) => {
1800
1790
  const record = entry;
@@ -1802,27 +1792,15 @@ const parseApplyCdcArgs = (args) => {
1802
1792
  const table = typeof record["table"] === "string" ? record["table"] : "";
1803
1793
  const id = typeof record["id"] === "string" ? record["id"] : "";
1804
1794
  if (table === "" || id === "" || op !== "insert" && op !== "update" && op !== "delete") {
1805
- throw Object.assign(new Error(`applyCdc: changes[${String(index)}] must have a table, id, and op of insert|update|delete`), {
1806
- code: "BAD_REQUEST",
1807
- name: "LunoraError",
1808
- status: 400
1809
- });
1795
+ throw new LunoraError("BAD_REQUEST", `applyCdc: changes[${String(index)}] must have a table, id, and op of insert|update|delete`);
1810
1796
  }
1811
1797
  const rawDocument = record["doc"];
1812
1798
  if (rawDocument !== void 0 && (typeof rawDocument !== "object" || rawDocument === null || Array.isArray(rawDocument))) {
1813
- throw Object.assign(new Error(`applyCdc: changes[${String(index)}].doc must be an object`), {
1814
- code: "BAD_REQUEST",
1815
- name: "LunoraError",
1816
- status: 400
1817
- });
1799
+ throw new LunoraError("BAD_REQUEST", `applyCdc: changes[${String(index)}].doc must be an object`);
1818
1800
  }
1819
1801
  const document = rawDocument;
1820
1802
  if (document !== void 0 && typeof document["_id"] === "string" && document["_id"] !== id) {
1821
- throw Object.assign(new Error(`applyCdc: changes[${String(index)}].doc._id must match the entry id`), {
1822
- code: "BAD_REQUEST",
1823
- name: "LunoraError",
1824
- status: 400
1825
- });
1803
+ throw new LunoraError("BAD_REQUEST", `applyCdc: changes[${String(index)}].doc._id must match the entry id`);
1826
1804
  }
1827
1805
  return {
1828
1806
  doc: document,
@@ -1842,13 +1820,7 @@ const parseCdcSyncArgs = (args) => {
1842
1820
  };
1843
1821
  return { limit: toCount(args["limit"]), sinceSeq: toCount(args["sinceSeq"]) ?? 0 };
1844
1822
  };
1845
- const jsonResponse = (body, status = 200, bookmark) => {
1846
- const headers = { "content-type": "application/json" };
1847
- if (bookmark) {
1848
- headers["x-d1-bookmark"] = bookmark;
1849
- }
1850
- return Response.json(body, { headers, status });
1851
- };
1823
+ const bookmarkHeaders = (bookmark) => bookmark ? { "x-d1-bookmark": bookmark } : void 0;
1852
1824
  const parseIdentityHeader = (raw) => {
1853
1825
  if (!raw) {
1854
1826
  return void 0;
@@ -2394,7 +2366,7 @@ class ShardDO {
2394
2366
  try {
2395
2367
  if (payload.functionPath.startsWith(RELATION_FUNCTION_PREFIX)) {
2396
2368
  const value = await this.runRelationFanoutRead(payload.functionPath, payload.args ?? {});
2397
- return jsonResponse(value, 200, this.currentResponseBookmark);
2369
+ return jsonResponse(value, 200, bookmarkHeaders(this.currentResponseBookmark));
2398
2370
  }
2399
2371
  const mutatorClass = this.isCustomMutator(payload.functionPath) ? this.classifyClientMutation() : void 0;
2400
2372
  this.currentMutatorClass = mutatorClass;
@@ -2684,9 +2656,7 @@ class ShardDO {
2684
2656
  */
2685
2657
  // eslint-disable-next-line class-methods-use-this -- base-class override hook: the codegen subclass overrides this with a schema-aware reader that uses `this`
2686
2658
  runRelationFanoutRead(_functionPath, _args) {
2687
- throw Object.assign(new Error("__lunora_relation__: no schema bound — the base ShardDO cannot serve cross-shard relation reads"), {
2688
- code: "NOT_IMPLEMENTED",
2689
- name: "LunoraError",
2659
+ throw new LunoraError("NOT_IMPLEMENTED", "__lunora_relation__: no schema bound — the base ShardDO cannot serve cross-shard relation reads", {
2690
2660
  status: 500
2691
2661
  });
2692
2662
  }
@@ -2813,19 +2783,11 @@ class ShardDO {
2813
2783
  */
2814
2784
  async runInTransaction(handler) {
2815
2785
  if (this.transactionDepth > 0) {
2816
- throw Object.assign(new Error("nested transactions are not supported in SQLite-in-DO"), {
2817
- code: "NESTED_TRANSACTION",
2818
- name: "LunoraError",
2819
- status: 500
2820
- });
2786
+ throw new LunoraError("NESTED_TRANSACTION", "nested transactions are not supported in SQLite-in-DO", { status: 500 });
2821
2787
  }
2822
2788
  const sqlHandle = this.state.storage.sql;
2823
2789
  if (!sqlHandle || typeof sqlHandle.exec !== "function") {
2824
- throw Object.assign(new Error("storage.sql is not available on this ShardDO state"), {
2825
- code: "SQL_UNAVAILABLE",
2826
- name: "LunoraError",
2827
- status: 500
2828
- });
2790
+ throw new LunoraError("SQL_UNAVAILABLE", "storage.sql is not available on this ShardDO state", { status: 500 });
2829
2791
  }
2830
2792
  const transactionalStorage = this.state.storage;
2831
2793
  const run = async () => {
@@ -2905,9 +2867,7 @@ class ShardDO {
2905
2867
  */
2906
2868
  // eslint-disable-next-line class-methods-use-this -- base-class override hook: the codegen subclass overrides this and uses `this` to reach the generated migration registry
2907
2869
  runShardDataMigration(args) {
2908
- return Promise.reject(
2909
- Object.assign(new Error(`data migration "${args.id}" is not registered`), { code: "MIGRATION_NOT_FOUND", name: "LunoraError", status: 404 })
2910
- );
2870
+ return Promise.reject(new LunoraError("MIGRATION_NOT_FOUND", `data migration "${args.id}" is not registered`, { status: 404 }));
2911
2871
  }
2912
2872
  /**
2913
2873
  * Lazily provision the shard's physical tables before an operation that
@@ -3165,7 +3125,7 @@ class ShardDO {
3165
3125
  */
3166
3126
  // eslint-disable-next-line class-methods-use-this -- base-class override hook: the codegen subclass overrides this and uses `this` to build a schema-aware writer
3167
3127
  runShardWrite(args) {
3168
- return Promise.reject(Object.assign(new Error(`unknown table: ${args.table}`), { code: "UNKNOWN_TABLE", name: "LunoraError", status: 404 }));
3128
+ return Promise.reject(new LunoraError("UNKNOWN_TABLE", `unknown table: ${args.table}`, { status: 404 }));
3169
3129
  }
3170
3130
  /**
3171
3131
  * Delete one row by primary key THROUGH the schema-aware writer — the
@@ -3180,7 +3140,7 @@ class ShardDO {
3180
3140
  */
3181
3141
  // eslint-disable-next-line class-methods-use-this -- base-class override hook: the codegen subclass overrides this and uses `this` to build a schema-aware writer
3182
3142
  deleteRowThroughWriter(_table, _id) {
3183
- return Promise.reject(Object.assign(new Error(`unknown table: ${_table}`), { code: "UNKNOWN_TABLE", name: "LunoraError", status: 404 }));
3143
+ return Promise.reject(new LunoraError("UNKNOWN_TABLE", `unknown table: ${_table}`, { status: 404 }));
3184
3144
  }
3185
3145
  /**
3186
3146
  * Bulk-delete the rows of `table` matching the active `filters`/`search`
@@ -3222,9 +3182,7 @@ class ShardDO {
3222
3182
  */
3223
3183
  // eslint-disable-next-line class-methods-use-this -- base-class override hook: the codegen subclass overrides this and uses `this` to build a schema-aware writer
3224
3184
  runShardRankBefore(_args) {
3225
- return Promise.reject(
3226
- Object.assign(new Error("rankBefore is not implemented in base ShardDO"), { code: "NOT_IMPLEMENTED", name: "LunoraError", status: 500 })
3227
- );
3185
+ return Promise.reject(new LunoraError("NOT_IMPLEMENTED", "rankBefore is not implemented in base ShardDO", { status: 500 }));
3228
3186
  }
3229
3187
  /**
3230
3188
  * Page this shard's local ranked slice under `index`, each row tagged with
@@ -3238,9 +3196,7 @@ class ShardDO {
3238
3196
  */
3239
3197
  // eslint-disable-next-line class-methods-use-this -- base-class override hook: the codegen subclass overrides this and uses `this` to build a schema-aware writer
3240
3198
  runShardRankPage(_args) {
3241
- return Promise.reject(
3242
- Object.assign(new Error("rankPage is not implemented in base ShardDO"), { code: "NOT_IMPLEMENTED", name: "LunoraError", status: 500 })
3243
- );
3199
+ return Promise.reject(new LunoraError("NOT_IMPLEMENTED", "rankPage is not implemented in base ShardDO", { status: 500 }));
3244
3200
  }
3245
3201
  /**
3246
3202
  * Page this shard's change-data-capture log past `sinceSeq`. Read-only and
@@ -3439,7 +3395,7 @@ class ShardDO {
3439
3395
  }
3440
3396
  this.recordFunctionCall(functionPath, Date.now() - dispatchStartedAt, void 0, this.currentScannedTables, this.currentIndexHits);
3441
3397
  if (mutatorClass.kind === "already") {
3442
- return jsonResponse({ lastMutationId: mutatorClass.expected - 1, result: null }, 200, this.currentResponseBookmark);
3398
+ return jsonResponse({ lastMutationId: mutatorClass.expected - 1, result: null }, 200, bookmarkHeaders(this.currentResponseBookmark));
3443
3399
  }
3444
3400
  return jsonResponse(
3445
3401
  {
@@ -3450,7 +3406,7 @@ class ShardDO {
3450
3406
  }
3451
3407
  },
3452
3408
  409,
3453
- this.currentResponseBookmark
3409
+ bookmarkHeaders(this.currentResponseBookmark)
3454
3410
  );
3455
3411
  }
3456
3412
  /**
@@ -3469,7 +3425,11 @@ class ShardDO {
3469
3425
  return this.buildDispatchResponse(mutatorClass, cachedValue);
3470
3426
  }
3471
3427
  const commitCursor = this.mutationCommitCursor();
3472
- return jsonResponse(commitCursor === void 0 ? { result: cachedValue } : { commitCursor, result: cachedValue }, 200, this.currentResponseBookmark);
3428
+ return jsonResponse(
3429
+ commitCursor === void 0 ? { result: cachedValue } : { commitCursor, result: cachedValue },
3430
+ 200,
3431
+ bookmarkHeaders(this.currentResponseBookmark)
3432
+ );
3473
3433
  }
3474
3434
  /**
3475
3435
  * The CDC cursor a just-committed plain mutation landed at — the post-write
@@ -3493,10 +3453,10 @@ class ShardDO {
3493
3453
  */
3494
3454
  buildDispatchResponse(mutatorClass, result) {
3495
3455
  if (mutatorClass?.kind === "next") {
3496
- return jsonResponse({ lastMutationId: this.currentRequestClientSeq, result }, 200, this.currentResponseBookmark);
3456
+ return jsonResponse({ lastMutationId: this.currentRequestClientSeq, result }, 200, bookmarkHeaders(this.currentResponseBookmark));
3497
3457
  }
3498
3458
  const commitCursor = this.mutationCommitCursor();
3499
- return jsonResponse(commitCursor === void 0 ? { result } : { commitCursor, result }, 200, this.currentResponseBookmark);
3459
+ return jsonResponse(commitCursor === void 0 ? { result } : { commitCursor, result }, 200, bookmarkHeaders(this.currentResponseBookmark));
3500
3460
  }
3501
3461
  /**
3502
3462
  * Commit a mutation's replay bookkeeping — the `(identity, mutationId)`
@@ -3565,9 +3525,7 @@ class ShardDO {
3565
3525
  */
3566
3526
  // eslint-disable-next-line class-methods-use-this -- base-class override hook: the codegen subclass overrides this and uses `this` to build a schema-aware writer
3567
3527
  runShardApplyCdc(_args) {
3568
- return Promise.reject(
3569
- Object.assign(new Error("applyCdc is not implemented in base ShardDO"), { code: "NOT_IMPLEMENTED", name: "LunoraError", status: 500 })
3570
- );
3528
+ return Promise.reject(new LunoraError("NOT_IMPLEMENTED", "applyCdc is not implemented in base ShardDO", { status: 500 }));
3571
3529
  }
3572
3530
  /**
3573
3531
  * Register a subscription on the given socket. Stored via
@@ -4255,7 +4213,7 @@ class ShardDO {
4255
4213
  }
4256
4214
  results.push({ body: outcome.body, id: outcome.id, status: outcome.status });
4257
4215
  }
4258
- return jsonResponse({ results }, 200, latestBookmark);
4216
+ return jsonResponse({ results }, 200, bookmarkHeaders(latestBookmark));
4259
4217
  }
4260
4218
  /** Dispatch one batch entry through the single-call `/rpc` path and capture its envelope (plan 088). */
4261
4219
  async dispatchBatchEntry(batchRequest, entry) {
@@ -4263,12 +4221,12 @@ class ShardDO {
4263
4221
  const response = await this.fetch(buildBatchEntryRequest(batchRequest, entry));
4264
4222
  return { body: await response.json(), bookmark: response.headers.get("x-d1-bookmark") ?? void 0, id: entry.id, status: response.status };
4265
4223
  } catch (error) {
4266
- const message = error instanceof Error ? error.message : String(error);
4224
+ const { body, status } = toErrorBody(error, { fallbackCode: "BATCH_ENTRY_FAILED" });
4267
4225
  return {
4268
- body: { error: { code: "BATCH_ENTRY_FAILED", message } },
4226
+ body: { error: body },
4269
4227
  bookmark: void 0,
4270
4228
  id: entry?.id,
4271
- status: 500
4229
+ status
4272
4230
  };
4273
4231
  }
4274
4232
  }
@@ -4477,15 +4435,11 @@ class ShardDO {
4477
4435
  resolveWorkflowBinding(exportName) {
4478
4436
  const metadata = this.workflowsMetadata().workflows.find((workflow) => workflow.exportName === exportName);
4479
4437
  if (!metadata) {
4480
- throw Object.assign(new Error(`workflow "${exportName}" is not declared`), { code: "BAD_REQUEST", name: "LunoraError", status: 400 });
4438
+ throw new LunoraError("BAD_REQUEST", `workflow "${exportName}" is not declared`);
4481
4439
  }
4482
4440
  const binding = this.env?.[metadata.binding];
4483
4441
  if (typeof binding !== "object" || binding === null || typeof binding.create !== "function" || typeof binding.get !== "function") {
4484
- throw Object.assign(new Error(`workflow binding "${metadata.binding}" is not available on this deployment`), {
4485
- code: "BAD_REQUEST",
4486
- name: "LunoraError",
4487
- status: 400
4488
- });
4442
+ throw new LunoraError("BAD_REQUEST", `workflow binding "${metadata.binding}" is not available on this deployment`);
4489
4443
  }
4490
4444
  return binding;
4491
4445
  }
@@ -4665,25 +4619,21 @@ class ShardDO {
4665
4619
  const parsed = parseReplayQueueMessageArgs(args);
4666
4620
  const row = readQueueMessageById(this.state.storage.sql, parsed.id);
4667
4621
  if (row === void 0) {
4668
- throw Object.assign(new Error(`replayQueueMessage: captured message "${parsed.id}" was not found`), {
4669
- code: "BAD_REQUEST",
4670
- name: "LunoraError",
4671
- status: 404
4672
- });
4622
+ throw new LunoraError("BAD_REQUEST", `replayQueueMessage: captured message "${parsed.id}" was not found`, { status: 404 });
4673
4623
  }
4674
4624
  if (isLossyBody(row.body)) {
4675
- throw Object.assign(
4676
- new Error(`replayQueueMessage: captured message "${parsed.id}" has a truncated or unserializable body and can't be replayed faithfully`),
4677
- { code: "BAD_REQUEST", name: "LunoraError", status: 422 }
4625
+ throw new LunoraError(
4626
+ "BAD_REQUEST",
4627
+ `replayQueueMessage: captured message "${parsed.id}" has a truncated or unserializable body and can't be replayed faithfully`,
4628
+ { status: 422 }
4678
4629
  );
4679
4630
  }
4680
4631
  const target = parsed.target ?? this.resolveReplayTarget(row.queue) ?? row.exportName;
4681
4632
  if (typeof target !== "string" || target === "") {
4682
- throw Object.assign(new Error(`replayQueueMessage: captured message "${parsed.id}" has no declared producer to replay onto (pass \`target\`)`), {
4683
- code: "BAD_REQUEST",
4684
- name: "LunoraError",
4685
- status: 400
4686
- });
4633
+ throw new LunoraError(
4634
+ "BAD_REQUEST",
4635
+ `replayQueueMessage: captured message "${parsed.id}" has no declared producer to replay onto (pass \`target\`)`
4636
+ );
4687
4637
  }
4688
4638
  const { binding } = this.resolveQueueBinding(target);
4689
4639
  await binding.send(row.body);
@@ -4701,15 +4651,11 @@ class ShardDO {
4701
4651
  resolveQueueBinding(exportName) {
4702
4652
  const metadata = this.queuesMetadata().queues.find((queue) => queue.exportName === exportName);
4703
4653
  if (!metadata) {
4704
- throw Object.assign(new Error(`queue "${exportName}" is not declared`), { code: "BAD_REQUEST", name: "LunoraError", status: 400 });
4654
+ throw new LunoraError("BAD_REQUEST", `queue "${exportName}" is not declared`);
4705
4655
  }
4706
4656
  const binding = this.env?.[metadata.binding];
4707
4657
  if (typeof binding !== "object" || binding === null || typeof binding.send !== "function") {
4708
- throw Object.assign(new Error(`queue binding "${metadata.binding}" is not available on this deployment`), {
4709
- code: "BAD_REQUEST",
4710
- name: "LunoraError",
4711
- status: 400
4712
- });
4658
+ throw new LunoraError("BAD_REQUEST", `queue binding "${metadata.binding}" is not available on this deployment`);
4713
4659
  }
4714
4660
  return { binding, metadata };
4715
4661
  }
@@ -1,3 +1,5 @@
1
+ import { j as jsonResponse } from './json-response-BdbtpOhm.mjs';
2
+
1
3
  const SESSION_DO_TTL_DEFAULT = 7 * 24 * 60 * 60;
2
4
  const SESSION_DO_TTL_MAX = 90 * 24 * 60 * 60;
3
5
  const SESSION_GC_INTERVAL_MS = 24 * 60 * 60 * 1e3;
@@ -7,10 +9,6 @@ const SESSION_TOKEN_PATTERN = /^[\w-]+$/;
7
9
  const MIN_TOKEN_LENGTH = 32;
8
10
  const MAX_TOKEN_LENGTH = 256;
9
11
  const MAX_USER_ID_LENGTH = 256;
10
- const jsonResponse = (status, body) => Response.json(body, {
11
- headers: { "content-type": "application/json" },
12
- status
13
- });
14
12
  const constantTimeEqual = (a, b) => {
15
13
  const max = Math.max(a.length, b.length);
16
14
  let diff = a.length ^ b.length;
@@ -68,7 +66,7 @@ class SessionDO {
68
66
  async fetch(request) {
69
67
  const env = this.env ?? {};
70
68
  if (!isAuthorized(request, env)) {
71
- return jsonResponse(401, { error: { code: "UNAUTHORIZED", message: "missing or invalid SessionDO secret" } });
69
+ return jsonResponse({ error: { code: "UNAUTHORIZED", message: "missing or invalid SessionDO secret" } }, 401);
72
70
  }
73
71
  const url = new URL(request.url);
74
72
  if (request.method === "POST" && url.pathname === "/create") {
@@ -80,7 +78,7 @@ class SessionDO {
80
78
  if (request.method === "DELETE" && url.pathname === "/revoke") {
81
79
  return this.handleRevoke(request);
82
80
  }
83
- return jsonResponse(404, { error: { code: "NOT_FOUND", message: "no such session route" } });
81
+ return jsonResponse({ error: { code: "NOT_FOUND", message: "no such session route" } }, 404);
84
82
  }
85
83
  /**
86
84
  * Sweep expired session records. Lazy expiry-on-read ({@link handleGet})
@@ -116,25 +114,25 @@ class SessionDO {
116
114
  try {
117
115
  body = await request.json();
118
116
  } catch {
119
- return jsonResponse(400, { error: "invalid_request" });
117
+ return jsonResponse({ error: "invalid_request" }, 400);
120
118
  }
121
119
  const token = validateToken(body.token);
122
120
  if (token === void 0) {
123
- return jsonResponse(400, { error: "invalid_request" });
121
+ return jsonResponse({ error: "invalid_request" }, 400);
124
122
  }
125
123
  const { userId } = body;
126
124
  if (typeof userId !== "string" || userId.length === 0 || userId.length > MAX_USER_ID_LENGTH) {
127
- return jsonResponse(400, { error: "invalid_request" });
125
+ return jsonResponse({ error: "invalid_request" }, 400);
128
126
  }
129
127
  const ttlSeconds = resolveTtlSeconds(body.ttlSeconds);
130
128
  if (ttlSeconds === void 0) {
131
- return jsonResponse(400, { error: "invalid_request" });
129
+ return jsonResponse({ error: "invalid_request" }, 400);
132
130
  }
133
131
  const now = Date.now();
134
132
  const record = { createdAt: now, expiresAt: now + ttlSeconds * 1e3, userId };
135
133
  await this.state.storage.put(`s:${token}`, record);
136
134
  await this.armGcAlarm();
137
- return jsonResponse(201, { token, ...record });
135
+ return jsonResponse({ token, ...record }, 201);
138
136
  }
139
137
  /**
140
138
  * Ensure a GC alarm is pending. Only sets one when none is currently
@@ -155,25 +153,25 @@ class SessionDO {
155
153
  async handleGet(request) {
156
154
  const token = request.headers.get(SESSION_TOKEN_HEADER);
157
155
  if (!token) {
158
- return jsonResponse(400, { error: { code: "INVALID_INPUT", message: "token required" } });
156
+ return jsonResponse({ error: { code: "INVALID_INPUT", message: "token required" } }, 400);
159
157
  }
160
158
  const record = await this.state.storage.get(`s:${token}`);
161
159
  if (!record) {
162
- return jsonResponse(404, { error: { code: "NOT_FOUND", message: "session not found" } });
160
+ return jsonResponse({ error: { code: "NOT_FOUND", message: "session not found" } }, 404);
163
161
  }
164
162
  if (record.expiresAt < Date.now()) {
165
163
  await this.state.storage.delete(`s:${token}`);
166
- return jsonResponse(404, { error: { code: "EXPIRED", message: "session expired" } });
164
+ return jsonResponse({ error: { code: "EXPIRED", message: "session expired" } }, 404);
167
165
  }
168
- return jsonResponse(200, { token, ...record });
166
+ return jsonResponse({ token, ...record }, 200);
169
167
  }
170
168
  async handleRevoke(request) {
171
169
  const token = request.headers.get(SESSION_TOKEN_HEADER);
172
170
  if (!token) {
173
- return jsonResponse(400, { error: { code: "INVALID_INPUT", message: "token required" } });
171
+ return jsonResponse({ error: { code: "INVALID_INPUT", message: "token required" } }, 400);
174
172
  }
175
173
  await this.state.storage.delete(`s:${token}`);
176
- return jsonResponse(200, { ok: true });
174
+ return jsonResponse({ ok: true }, 200);
177
175
  }
178
176
  }
179
177