@vercel/board 0.29.0 → 0.30.0

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 (124) hide show
  1. package/dist/{a2-HUbQJ0RD.mjs → a2-D_28Pdip.mjs} +190 -76
  2. package/dist/access-CQ39gqEV.mjs +226 -0
  3. package/dist/access.d.mts +1 -1
  4. package/dist/access.mjs +3 -3
  5. package/dist/{actors-DcJhFbwJ.mjs → actors-xPiamLWk.mjs} +2 -2
  6. package/dist/{auth-JO22iIwr.mjs → auth-BPinwfN0.mjs} +3 -226
  7. package/dist/backend-a2/blob-vercel.d.mts +1 -1
  8. package/dist/backend-a2/contract.d.mts +2 -2
  9. package/dist/backend-a2/contract.mjs +1 -1
  10. package/dist/backend-a2/scheduler-local.d.mts +1 -1
  11. package/dist/backend-a2/scheduler-local.mjs +1 -1
  12. package/dist/backend-a2/scheduler-qstash.d.mts +3 -3
  13. package/dist/backend-a2/scheduler-qstash.mjs +8 -8
  14. package/dist/backend-a2/scheduler-vercel.d.mts +3 -3
  15. package/dist/backend-a2/scheduler-vercel.mjs +6 -6
  16. package/dist/backend-a2/store-memory.d.mts +2 -2
  17. package/dist/backend-a2/store-memory.mjs +3 -3
  18. package/dist/backend-a2/store-postgres.d.mts +1 -1
  19. package/dist/backend-a2/store-postgres.mjs +34 -15
  20. package/dist/backend-a2/store-redis-http.d.mts +1 -1
  21. package/dist/backend-a2/store-redis-http.mjs +6 -6
  22. package/dist/backend-a2/store-redis.d.mts +2 -2
  23. package/dist/backend-a2/store-redis.mjs +5 -5
  24. package/dist/backend-a2/store-sqlite.d.mts +1 -1
  25. package/dist/backend-a2/store-sqlite.mjs +3 -3
  26. package/dist/backend-a2.d.mts +17 -7
  27. package/dist/backend-a2.mjs +2 -2
  28. package/dist/{backend-http-Bmp0IgD3.mjs → backend-http-16SbvnAK.mjs} +2 -2
  29. package/dist/{backend-http-CqfKhrnn.d.mts → backend-http-3PoBYQoo.d.mts} +13 -3
  30. package/dist/{backend-http-CzIJMm58.mjs → backend-http-BPaNYLWj.mjs} +2 -3
  31. package/dist/backend-http.d.mts +1 -1
  32. package/dist/backend-http.mjs +1 -1
  33. package/dist/backend-http.node.d.mts +1 -1
  34. package/dist/backend-http.node.mjs +1 -1
  35. package/dist/{backend-CPC_vyOo.d.mts → backend-n3hajfrD.d.mts} +11 -5
  36. package/dist/{backend-vercel-BNauAs7w.mjs → backend-vercel-C4Kee2-K.mjs} +203 -31
  37. package/dist/{backend-vercel-DQc_TaHp.mjs → backend-vercel-Kd8nvW5A.mjs} +3 -3
  38. package/dist/{backend-vercel-4tvcPKqX.d.mts → backend-vercel-qznuDxnN.d.mts} +16 -5
  39. package/dist/backend-vercel.d.mts +1 -1
  40. package/dist/backend-vercel.mjs +1 -1
  41. package/dist/backend-vercel.node.d.mts +1 -1
  42. package/dist/backend-vercel.node.mjs +1 -1
  43. package/dist/{blob-DmiQjrYy.d.mts → blob-CqILvdmr.d.mts} +2 -2
  44. package/dist/{blob-DdbpJqN1.mjs → blob-DQK5prXT.mjs} +1 -1
  45. package/dist/{chat-provider-BWHbChcQ.d.mts → chat-provider-D6jVT4wS.d.mts} +3 -3
  46. package/dist/cli-commands.d.mts +1 -1
  47. package/dist/cli-commands.mjs +1 -1
  48. package/dist/cli-embedded.d.mts +2 -2
  49. package/dist/cli-embedded.mjs +1 -1
  50. package/dist/cli.mjs +4 -4
  51. package/dist/{client-BqAjk0Q4.d.mts → client-CjAatpV4.d.mts} +60 -10
  52. package/dist/{commands-C3R1AWgm.mjs → commands-B5DHjZKK.mjs} +50 -9
  53. package/dist/{commands-D6gvrOh3.d.mts → commands-BtH69yqt.d.mts} +17 -0
  54. package/dist/{conformance-DlnfuzEB.mjs → conformance-C7fwIvmN.mjs} +258 -18
  55. package/dist/conformance.d.mts +1 -1
  56. package/dist/conformance.mjs +1 -1
  57. package/dist/{engine-DQxXk7dX.mjs → engine-DkdkXQEy.mjs} +2 -2
  58. package/dist/{errors-DDktVeUa.d.mts → errors-87TVtXeb.d.mts} +1 -1
  59. package/dist/{client-D0Px7KzF.mjs → errors-C_5rB8Iz.mjs} +104 -4
  60. package/dist/{exports-BG-0Wyn-.mjs → exports-CG0P8Qi4.mjs} +54 -28
  61. package/dist/exports-CrGA5_yN.d.mts +5 -0
  62. package/dist/{folds-ZkHM4M-v.d.mts → folds-8wRRXjAt.d.mts} +2 -0
  63. package/dist/{folds-BDMSxBUf.mjs → folds-DGYkMW19.mjs} +1 -0
  64. package/dist/{index-D3VvNfh_.d.mts → index-BygAXP7t.d.mts} +2 -2
  65. package/dist/index.d.mts +6 -6
  66. package/dist/{index.default-rB8sJ9RX.mjs → index.default-DhkgpfR2.mjs} +1 -1
  67. package/dist/index.mjs +5 -6
  68. package/dist/index.node.d.mts +6 -6
  69. package/dist/index.node.mjs +3 -4
  70. package/dist/inspect/app.js +29 -29
  71. package/dist/{internal-CvsrprnU-CRY89I-b.mjs → internal-CvsrprnU-zZMpDiRY.mjs} +1 -1
  72. package/dist/{local-DhkrAqPP.mjs → local-C76Fy5ad.mjs} +1 -1
  73. package/dist/{main-CVBqe3VO.mjs → main-D2s-QBOK.mjs} +70 -23
  74. package/dist/{middleware-CXjEeef4.mjs → middleware-DlJQYiwV.mjs} +1 -1
  75. package/dist/{node-Zd_C-gxP.mjs → node-D8Rtg1su.mjs} +1 -1
  76. package/dist/{platform-B4TnJtWu-CwcTyKg2.mjs → platform-B4TnJtWu-Do3agKr5.mjs} +1 -1
  77. package/dist/{project-CBXlLftU.mjs → project-C_2xs57L.mjs} +1 -1
  78. package/dist/{provider-DmSTp9lI.d.mts → provider-Bm46LAdp.d.mts} +2 -2
  79. package/dist/{redis-tables-BJQVUspu.mjs → redis-tables-BWJZHUGg.mjs} +40 -24
  80. package/dist/{reducer-CjmvZSAb-D_OSISmj.mjs → reducer-Bswr11ar-P324o9vn.mjs} +2 -2
  81. package/dist/{reducer-CYPHsSmd-BQIfozGi.d.mts → reducer-CYPHsSmd-BXjGiptm.d.mts} +1 -1
  82. package/dist/{reducers-DJzVpXwM.mjs → reducers-8jqLewgw.mjs} +3 -3
  83. package/dist/{retryable-lazy-DZWmHpii-Bye-W8q7.mjs → retryable-lazy-DZWmHpii-DpTc5PIP.mjs} +1 -1
  84. package/dist/{scheduler-task-X1SToDjP-BVoWuInI.mjs → scheduler-task-X1SToDjP-D2Il2rln.mjs} +1 -1
  85. package/dist/{serve-G9RuaDSr.mjs → serve-lPoBDEds.mjs} +7 -7
  86. package/dist/{server-qgez0Xny-D5mLfqFQ.d.mts → server-B9gu0qi1-DI1WvcVK.d.mts} +10 -4
  87. package/dist/{server-BixV_byP.mjs → server-D82a4uMe.mjs} +4 -4
  88. package/dist/{server-DtFrWxi3-Boa6gdWO.mjs → server-DX7mM6nm-D7N_7bug.mjs} +32 -23
  89. package/dist/{serving-B75Y4BF-.mjs → serving-DKny38LK.mjs} +1 -1
  90. package/dist/{session-clear-wHd5GCpZ-BnKSxReK.mjs → session-clear-XJYpmUpg-2q8l_FJR.mjs} +14 -2
  91. package/dist/{sql-D4Z_efJX.mjs → sql-Bj0fk6dn.mjs} +1 -1
  92. package/dist/{sqlite-db-Bz2JkfCU.mjs → sqlite-db-Dc8G78XV.mjs} +1 -1
  93. package/dist/{store-D0MhBvg6-4Z2L0Kqd.d.mts → store-DEzcHZOA-B-5vhxef.d.mts} +12 -2
  94. package/dist/store-N8PXxDAS-DWWgv-Vz.mjs +5 -0
  95. package/dist/{store-codec-DwrWlgQx-CYxGW0aD.mjs → store-codec-pAG2oPgQ-SqDXlPBR.mjs} +4 -4
  96. package/dist/store-memory-4IBl0Ztu.mjs +2 -0
  97. package/dist/{store-memory-Bas9Uq5C.mjs → store-memory-B0PkVSuQ.mjs} +14 -7
  98. package/dist/{store-polling-BZt2Rf3D-BiEM6_HB.mjs → store-polling-BZt2Rf3D-Div-bJ_D.mjs} +2 -2
  99. package/dist/{store-presence-polling-JuAy2Ck2-CYpuK75X.mjs → store-presence-polling-JuAy2Ck2-Dh-g_KYM.mjs} +3 -3
  100. package/dist/{store-sqlite-CxxPCcCT.mjs → store-sqlite-D85t3tE7.mjs} +14 -7
  101. package/dist/store-sqlite-iBTYYKBj.mjs +2 -0
  102. package/dist/{stream-buffer-DrTyiIuo-BKy-vI14.mjs → stream-buffer-DrTyiIuo-Be10yOBR.mjs} +2 -2
  103. package/dist/sync-github.d.mts +2 -2
  104. package/dist/sync-kapso.d.mts +2 -2
  105. package/dist/sync-linear.d.mts +3 -3
  106. package/dist/sync-linear.mjs +4 -2
  107. package/dist/sync-slack.d.mts +3 -3
  108. package/dist/sync.chat.d.mts +1 -1
  109. package/dist/sync.d.mts +2 -2
  110. package/dist/{tokens-CC3izSNr.mjs → tokens-C5_yGRlL.mjs} +2 -2
  111. package/dist/{types-No0WdhE5.d.mts → types-shZmGZ-q.d.mts} +2 -2
  112. package/dist/{watchers-hash-BDhLVkV5.mjs → watchers-hash-B_5b0-ZG.mjs} +46 -17
  113. package/docs/01-board/04-messages.md +93 -0
  114. package/docs/01-board/08-middleware.md +5 -2
  115. package/docs/04-reference/01-cli.md +23 -10
  116. package/docs/04-reference/02-board.md +20 -5
  117. package/docs/04-reference/03-http.md +17 -6
  118. package/docs/04-reference/05-conformance.md +14 -3
  119. package/package.json +2 -2
  120. package/dist/errors-CusN4x2l.mjs +0 -88
  121. package/dist/exports-mhAYiU4i.d.mts +0 -5
  122. package/dist/store-N8PXxDAS-BWBgzBHp.mjs +0 -5
  123. package/dist/store-memory-ZLiZbH3R.mjs +0 -2
  124. package/dist/store-sqlite-BmwL3pUR.mjs +0 -2
@@ -1,11 +1,11 @@
1
- import { a as isSessionCleared, i as asStoreUnavailable, o as sessionClearedError, r as NonRetriableError, t as A2Error } from "./session-clear-wHd5GCpZ-BnKSxReK.mjs";
2
- import { n as cloneInitial, o as validateSync, r as foldEvent } from "./reducer-CjmvZSAb-D_OSISmj.mjs";
3
- import { _ as serverInternals, a as RESERVED_PARTICIPANT_IDS, c as STREAM_TIMINGS, d as drainSettledHooks, f as failedPreviousAttempt, g as runtimeConsumers, h as runtimeConsumerFactory, m as nullProtoRecord, o as SOCKET_TIMINGS, p as markSchedulerSendFailure, r as POLL_TIMINGS, s as STATE_CACHE, t as DRAIN_TIMINGS, v as stateTailReaders } from "./internal-CvsrprnU-CRY89I-b.mjs";
4
- import { a as takeBuffered, i as presenceTombstones, n as isSerializedEvent, r as parseSerializedEvent, t as bufferedEvents } from "./stream-buffer-DrTyiIuo-BKy-vI14.mjs";
5
- import { i as streamActivities, n as defaultSleep, t as createStreamActivity } from "./store-polling-BZt2Rf3D-BiEM6_HB.mjs";
6
- import { r as platformWaitUntil, t as invocationDeadlineMs } from "./platform-B4TnJtWu-CwcTyKg2.mjs";
7
- import { t as retryableLazy } from "./retryable-lazy-DZWmHpii-Bye-W8q7.mjs";
8
- //#region ../../node_modules/.pnpm/experimental-a2@0.22.0_@upstash+qstash@2.12.0_@vercel+queue@0.7.0_ai@7.0.130_zod@4.6.5__52060f00b21aecfab049c27fa3abd2f9/node_modules/experimental-a2/dist/reducer-runtime-DQwz_J59.js
1
+ import { c as sessionClearedError, i as asStoreUnavailable, o as isSessionCleared, r as NonRetriableError, t as A2Error } from "./session-clear-XJYpmUpg-2q8l_FJR.mjs";
2
+ import { n as cloneInitial, o as validateSync, r as foldEvent } from "./reducer-Bswr11ar-P324o9vn.mjs";
3
+ import { _ as serverInternals, a as RESERVED_PARTICIPANT_IDS, c as STREAM_TIMINGS, d as drainSettledHooks, f as failedPreviousAttempt, g as runtimeConsumers, h as runtimeConsumerFactory, m as nullProtoRecord, o as SOCKET_TIMINGS, p as markSchedulerSendFailure, r as POLL_TIMINGS, s as STATE_CACHE, t as DRAIN_TIMINGS, v as stateTailReaders } from "./internal-CvsrprnU-zZMpDiRY.mjs";
4
+ import { a as takeBuffered, i as presenceTombstones, n as isSerializedEvent, r as parseSerializedEvent, t as bufferedEvents } from "./stream-buffer-DrTyiIuo-Be10yOBR.mjs";
5
+ import { i as streamActivities, n as defaultSleep, t as createStreamActivity } from "./store-polling-BZt2Rf3D-Div-bJ_D.mjs";
6
+ import { r as platformWaitUntil, t as invocationDeadlineMs } from "./platform-B4TnJtWu-Do3agKr5.mjs";
7
+ import { t as retryableLazy } from "./retryable-lazy-DZWmHpii-DpTc5PIP.mjs";
8
+ //#region ../../node_modules/.pnpm/experimental-a2@0.24.0_@upstash+qstash@2.12.0_@vercel+queue@0.7.0_ai@7.0.130_zod@4.6.5__b1e2c243a963f2620a5d202817417c26/node_modules/experimental-a2/dist/reducer-runtime-DQwz_J59.js
9
9
  const runtimeKey = Symbol("a2.reducerRuntime");
10
10
  function encodeState(options) {
11
11
  const storage = options.reducer[runtimeKey]?.storage;
@@ -16,7 +16,7 @@ function decodeState(options) {
16
16
  return storage ? storage.decode(options.state) : options.state;
17
17
  }
18
18
  //#endregion
19
- //#region ../../node_modules/.pnpm/experimental-a2@0.22.0_@upstash+qstash@2.12.0_@vercel+queue@0.7.0_ai@7.0.130_zod@4.6.5__52060f00b21aecfab049c27fa3abd2f9/node_modules/experimental-a2/dist/bounded-cache-CPHWF-8h.js
19
+ //#region ../../node_modules/.pnpm/experimental-a2@0.24.0_@upstash+qstash@2.12.0_@vercel+queue@0.7.0_ai@7.0.130_zod@4.6.5__b1e2c243a963f2620a5d202817417c26/node_modules/experimental-a2/dist/bounded-cache-CPHWF-8h.js
20
20
  function boundedCache({ maxEntries, maxBytes }) {
21
21
  const entries = /* @__PURE__ */ new Map();
22
22
  let total = 0;
@@ -54,7 +54,7 @@ function boundedCache({ maxEntries, maxBytes }) {
54
54
  };
55
55
  }
56
56
  //#endregion
57
- //#region ../../node_modules/.pnpm/experimental-a2@0.22.0_@upstash+qstash@2.12.0_@vercel+queue@0.7.0_ai@7.0.130_zod@4.6.5__52060f00b21aecfab049c27fa3abd2f9/node_modules/experimental-a2/dist/wire-CV-Z7wz-.js
57
+ //#region ../../node_modules/.pnpm/experimental-a2@0.24.0_@upstash+qstash@2.12.0_@vercel+queue@0.7.0_ai@7.0.130_zod@4.6.5__b1e2c243a963f2620a5d202817417c26/node_modules/experimental-a2/dist/wire-BFE9sIQf.js
58
58
  /**
59
59
  * The wire format shared by server.fetch and experimental-a2/client
60
60
  * (browser side): events as JSON with ISO timestamps, and the A2Error
@@ -168,6 +168,7 @@ const ERROR_STATUS = {
168
168
  PARTIAL_DUPLICATE_BATCH: 400,
169
169
  SUPERSEDED_ATTEMPT: 409,
170
170
  SESSION_CLEARED: 409,
171
+ LAST_INDEX_MISMATCH: 409,
171
172
  CLAIM_EXPIRED: 409,
172
173
  STORE_UNAVAILABLE: 503,
173
174
  STORE_NOT_CONFIGURED: 500,
@@ -267,7 +268,7 @@ function socketUnsubscribedFor(options) {
267
268
  });
268
269
  }
269
270
  //#endregion
270
- //#region ../../node_modules/.pnpm/experimental-a2@0.22.0_@upstash+qstash@2.12.0_@vercel+queue@0.7.0_ai@7.0.130_zod@4.6.5__52060f00b21aecfab049c27fa3abd2f9/node_modules/experimental-a2/dist/server-DtFrWxi3.js
271
+ //#region ../../node_modules/.pnpm/experimental-a2@0.24.0_@upstash+qstash@2.12.0_@vercel+queue@0.7.0_ai@7.0.130_zod@4.6.5__b1e2c243a963f2620a5d202817417c26/node_modules/experimental-a2/dist/server-DX7mM6nm.js
271
272
  /**
272
273
  * The push envelope's trust boundary for `{ sessionId, events, presence? }`,
273
274
  * shared verbatim by the HTTP
@@ -1522,7 +1523,7 @@ function currentSchedulerSlot(now) {
1522
1523
  * it prefixes every storage key.
1523
1524
  */
1524
1525
  const NS = "";
1525
- const devDefaultStore = retryableLazy(() => import("./store-sqlite-BmwL3pUR.mjs").then((m) => m.sqlite()));
1526
+ const devDefaultStore = retryableLazy(() => import("./store-sqlite-iBTYYKBj.mjs").then((m) => m.sqlite()));
1526
1527
  /** Waits for a scheduler arm for at most `schedulerArmTimeoutMs`. */
1527
1528
  async function joinSchedulerArm(arm) {
1528
1529
  let timeout = null;
@@ -1613,7 +1614,7 @@ function createServer(options) {
1613
1614
  const error = () => new A2Error("STORE_NOT_CONFIGURED", `the server for '${name}' has no store configured and NODE_ENV is 'production' — pass an explicit store backend (e.g. postgres from 'experimental-a2/store-postgres')`);
1614
1615
  if (process.env["NEXT_PHASE"] !== "phase-production-build") throw error();
1615
1616
  makeStore = () => Promise.reject(error());
1616
- } else makeStore = env === "test" ? () => import("./store-memory-ZLiZbH3R.mjs").then((m) => m.memory()) : devDefaultStore.get;
1617
+ } else makeStore = env === "test" ? () => import("./store-memory-4IBl0Ztu.mjs").then((m) => m.memory()) : devDefaultStore.get;
1617
1618
  }
1618
1619
  if (declaresPresence && !options.store) {
1619
1620
  const inner = makeStore;
@@ -1815,7 +1816,7 @@ function createServer(options) {
1815
1816
  * the drain it schedules is created in the append's active context —
1816
1817
  * with a real tracer, causal work remains connected.
1817
1818
  */
1818
- const appendCore = (sessionId, events, source, mode, onAppended, cause, generatedIds, requireDurableInitialArm = false, originIndex) => telemetry.span("a2.append", {
1819
+ const appendCore = (sessionId, events, source, mode, onAppended, cause, generatedIds, requireDurableInitialArm = false, condition = {}) => telemetry.span("a2.append", {
1819
1820
  "a2.contract": name,
1820
1821
  "a2.session_id": sessionId,
1821
1822
  "a2.append.source": source,
@@ -1836,7 +1837,7 @@ function createServer(options) {
1836
1837
  try {
1837
1838
  const result = await store.append(nsId(sessionId), validated, {
1838
1839
  consumers: storeConsumers,
1839
- ...originIndex === void 0 ? {} : { originIndex }
1840
+ ...condition
1840
1841
  });
1841
1842
  rows = result.events;
1842
1843
  shouldHealSession = result.hasPending && !(source === "consumer" && !validated.some(startsWork));
@@ -2260,7 +2261,7 @@ function createServer(options) {
2260
2261
  assertScheduleName(scheduleName);
2261
2262
  if (clearOptions === null || typeof clearOptions !== "object") throw new TypeError("schedule.clear requires an ifLastIndex");
2262
2263
  const { ifLastIndex, ...timing } = clearOptions;
2263
- assertClearIndex(ifLastIndex);
2264
+ assertIfLastIndex(ifLastIndex);
2264
2265
  const dueAt = scheduleDueAt(timing, triggerCreatedAt ?? Date.now());
2265
2266
  const store = await resolveStore();
2266
2267
  if (!store.clear || !store.reclaim) throw new TypeError("session.schedule.clear requires a store that supports clearing");
@@ -2688,7 +2689,7 @@ function createServer(options) {
2688
2689
  };
2689
2690
  const clearSession = async (sessionId, clearOptions, attempt) => {
2690
2691
  const ifLastIndex = clearOptions?.ifLastIndex;
2691
- if (ifLastIndex !== void 0) assertClearIndex(ifLastIndex);
2692
+ if (ifLastIndex !== void 0) assertIfLastIndex(ifLastIndex);
2692
2693
  const store = await resolveStore();
2693
2694
  if (!store.clear || !store.reclaim) throw new TypeError("session.clear requires a store that supports clearing");
2694
2695
  const ns = nsId(sessionId);
@@ -3424,14 +3425,22 @@ function createServer(options) {
3424
3425
  ...schedulerArm ? { schedulerArm } : {}
3425
3426
  };
3426
3427
  });
3427
- const appendExternal = async (sessionId, mode, events, requireDurableInitialArm = false, originIndex) => {
3428
- return appendCore(sessionId, events, "external", mode, (_rows, watchdogDueAt) => scheduleDrain(sessionId, watchdogDueAt), void 0, void 0, requireDurableInitialArm, originIndex);
3428
+ const appendExternal = async (sessionId, mode, events, requireDurableInitialArm = false, condition = {}) => {
3429
+ return appendCore(sessionId, events, "external", mode, (_rows, watchdogDueAt) => scheduleDrain(sessionId, watchdogDueAt), void 0, void 0, requireDurableInitialArm, condition);
3429
3430
  };
3430
3431
  const session = (id) => {
3431
3432
  assertSessionId(id);
3432
3433
  const appendInline = async (...events) => appendExternal(id, "inline", events);
3433
3434
  const appendDispatch = async (...events) => appendExternal(id, "dispatch", events);
3434
- const append = Object.assign(appendInline, { dispatch: appendDispatch });
3435
+ const appendIfLastIndex = async (index, ...events) => {
3436
+ assertIfLastIndex(index);
3437
+ if (events.length === 0) throw new TypeError("append.ifLastIndex requires at least one event");
3438
+ return appendExternal(id, "inline", events, false, { ifLastIndex: index });
3439
+ };
3440
+ const append = Object.assign(appendInline, {
3441
+ dispatch: appendDispatch,
3442
+ ifLastIndex: appendIfLastIndex
3443
+ });
3435
3444
  return Object.assign(makeSession(id, append, null), {
3436
3445
  deadLetters: () => listDeadLetters(id),
3437
3446
  redrive: (target, redriveOptions) => redriveEvent(id, target, redriveOptions)
@@ -3475,7 +3484,7 @@ function createServer(options) {
3475
3484
  if (!scheduler) throw new TypeError("scheduled append delivery requires a configured scheduler adapter");
3476
3485
  assertSessionId(sessionId);
3477
3486
  try {
3478
- await appendExternal(sessionId, "inline", [...events], true, originIndex);
3487
+ await appendExternal(sessionId, "inline", [...events], true, originIndex === void 0 ? {} : { originIndex });
3479
3488
  } catch (error) {
3480
3489
  if (originIndex !== void 0 && error instanceof A2Error && error.code === "SESSION_CLEARED") return;
3481
3490
  throw error;
@@ -3484,7 +3493,7 @@ function createServer(options) {
3484
3493
  historyWithMarkers: async (sessionId, gte) => (await readHistory(sessionId, { gte })).map(toPublic),
3485
3494
  schedulerClear: async (sessionId, ifLastIndex) => {
3486
3495
  assertSessionId(sessionId);
3487
- assertClearIndex(ifLastIndex);
3496
+ assertIfLastIndex(ifLastIndex);
3488
3497
  await clearSession(sessionId, { ifLastIndex }, void 0);
3489
3498
  }
3490
3499
  });
@@ -3509,7 +3518,7 @@ function assertConsumeIndex(value) {
3509
3518
  function assertRedriveIndex(value) {
3510
3519
  if (!Number.isSafeInteger(value) || value < 1) throw new TypeError("redrive requires a positive safe-integer index");
3511
3520
  }
3512
- function assertClearIndex(value) {
3521
+ function assertIfLastIndex(value) {
3513
3522
  if (!Number.isSafeInteger(value) || value < 0) throw new TypeError("ifLastIndex must be a non-negative safe integer");
3514
3523
  }
3515
3524
  function assertAppendName(name) {
@@ -1,2 +1,2 @@
1
- import { i as ownTeamId, n as discoveryIdentity, r as ownProjectId, t as oidcTokens } from "./tokens-CC3izSNr.mjs";
1
+ import { i as ownTeamId, n as discoveryIdentity, r as ownProjectId, t as oidcTokens } from "./tokens-C5_yGRlL.mjs";
2
2
  export { discoveryIdentity, oidcTokens, ownProjectId, ownTeamId };
@@ -1,4 +1,4 @@
1
- //#region ../../node_modules/.pnpm/experimental-a2@0.22.0_@upstash+qstash@2.12.0_@vercel+queue@0.7.0_ai@7.0.130_zod@4.6.5__52060f00b21aecfab049c27fa3abd2f9/node_modules/experimental-a2/dist/session-clear-wHd5GCpZ.js
1
+ //#region ../../node_modules/.pnpm/experimental-a2@0.24.0_@upstash+qstash@2.12.0_@vercel+queue@0.7.0_ai@7.0.130_zod@4.6.5__b1e2c243a963f2620a5d202817417c26/node_modules/experimental-a2/dist/session-clear-XJYpmUpg.js
2
2
  var A2Error = class extends Error {
3
3
  code;
4
4
  /** e.g. the Standard Schema issues for INVALID_PAYLOAD */
@@ -15,6 +15,18 @@ function supersededAttemptError(sessionId, cause) {
15
15
  const of = cause.consumer === void 0 ? "" : ` for consumer '${cause.consumer}'`;
16
16
  return new A2Error("SUPERSEDED_ATTEMPT", `attempt ${cause.attempt} no longer owns event ${cause.index}${of} in session '${sessionId}'`);
17
17
  }
18
+ /** A conditional append whose `ifLastIndex` is not the session's head. */
19
+ function lastIndexMismatchError(sessionId, ifLastIndex, head) {
20
+ return new A2Error("LAST_INDEX_MISMATCH", `session '${sessionId}' is at index ${head}, not ${ifLastIndex}`, { details: { index: head } });
21
+ }
22
+ /**
23
+ * A batch whose ids conflict with committed events. In a conditional append
24
+ * whose head moved, the condition failed first, as when another writer's
25
+ * batch took those ids, so the conflict reports the head instead.
26
+ */
27
+ function duplicateBatchError(message, conditional) {
28
+ return conditional && conditional.head !== conditional.ifLastIndex ? lastIndexMismatchError(conditional.sessionId, conditional.ifLastIndex, conditional.head) : new A2Error("PARTIAL_DUPLICATE_BATCH", message);
29
+ }
18
30
  /**
19
31
  * Wrap an arbitrary thrown value as STORE_UNAVAILABLE, preserving the
20
32
  * original as `cause`. A2Errors pass through untouched — they already
@@ -48,4 +60,4 @@ function sessionClearedError(message) {
48
60
  return new A2Error("SESSION_CLEARED", message);
49
61
  }
50
62
  //#endregion
51
- export { isSessionCleared as a, asStoreUnavailable as i, CLEAR_EVENT_TYPE as n, sessionClearedError as o, NonRetriableError as r, supersededAttemptError as s, A2Error as t };
63
+ export { duplicateBatchError as a, sessionClearedError as c, asStoreUnavailable as i, supersededAttemptError as l, CLEAR_EVENT_TYPE as n, isSessionCleared as o, NonRetriableError as r, lastIndexMismatchError as s, A2Error as t };
@@ -1,6 +1,6 @@
1
1
  import { c as externalMessageKey } from "./external-D3p5T57R.mjs";
2
2
  import { n as setOwn } from "./own-OwgPWdmh.mjs";
3
- import { i as syncReads, n as project, r as projectSync, t as concernedMessageId } from "./project-CBXlLftU.mjs";
3
+ import { i as syncReads, n as project, r as projectSync, t as concernedMessageId } from "./project-C_2xs57L.mjs";
4
4
  //#region src/store/sql.ts
5
5
  /** The projection's name in `board_positions`, and the A2 consumer that runs it. */
6
6
  const TABLES_CONSUMER = "board-tables";
@@ -1,4 +1,4 @@
1
- import { n as ddl } from "./sql-D4Z_efJX.mjs";
1
+ import { n as ddl } from "./sql-Bj0fk6dn.mjs";
2
2
  import { mkdirSync } from "node:fs";
3
3
  import { dirname, resolve } from "node:path";
4
4
  //#region src/store/sqlite-db.ts
@@ -1,5 +1,5 @@
1
- import { s as PresencePatch } from "./reducer-CYPHsSmd-BQIfozGi.mjs";
2
- //#region ../../node_modules/.pnpm/experimental-a2@0.22.0_@upstash+qstash@2.12.0_@vercel+queue@0.7.0_ai@7.0.130_zod@4.6.5__52060f00b21aecfab049c27fa3abd2f9/node_modules/experimental-a2/dist/store-D0MhBvg6.d.ts
1
+ import { s as PresencePatch } from "./reducer-CYPHsSmd-BXjGiptm.mjs";
2
+ //#region ../../node_modules/.pnpm/experimental-a2@0.24.0_@upstash+qstash@2.12.0_@vercel+queue@0.7.0_ai@7.0.130_zod@4.6.5__b1e2c243a963f2620a5d202817417c26/node_modules/experimental-a2/dist/store-DEzcHZOA.d.ts
3
3
  //#region src/store.d.ts
4
4
  /** A stored event, as the public API exposes it. */
5
5
  type Event = {
@@ -295,9 +295,19 @@ interface A2Store {
295
295
  * a `cause` at or below the latest clear marker throws
296
296
  * `SUPERSEDED_ATTEMPT`, an `originIndex` there throws `SESSION_CLEARED`,
297
297
  * and ids whose rows lie below the marker are free to reuse.
298
+ *
299
+ * `ifLastIndex` conditions a non-empty batch on the session's head, the
300
+ * last index including any clear marker: when the head is anything else,
301
+ * throw `lastIndexMismatchError` carrying the head and write nothing. It is
302
+ * checked last, after the replay path and both fences, inside the same
303
+ * atomic operation, never as a read before it. A conditional batch whose
304
+ * ids conflict (mixed, or not matching their rows) reports that head
305
+ * instead of `PARTIAL_DUPLICATE_BATCH` when it isn't `ifLastIndex`
306
+ * (`duplicateBatchError`).
298
307
  */
299
308
  append(sessionId: string, events: AppendEvent[], options?: {
300
309
  originIndex?: number;
310
+ ifLastIndex?: number;
301
311
  consumers?: readonly StoreConsumer[];
302
312
  }): Promise<StoreAppendResult>;
303
313
  /**
@@ -0,0 +1,5 @@
1
+ //#region ../../node_modules/.pnpm/experimental-a2@0.24.0_@upstash+qstash@2.12.0_@vercel+queue@0.7.0_ai@7.0.130_zod@4.6.5__b1e2c243a963f2620a5d202817417c26/node_modules/experimental-a2/dist/store-N8PXxDAS.js
2
+ const SYSTEM_CLOCK = { now: () => /* @__PURE__ */ new Date() };
3
+ const RANDOM_IDS = () => crypto.randomUUID();
4
+ //#endregion
5
+ export { SYSTEM_CLOCK as n, RANDOM_IDS as t };
@@ -1,10 +1,10 @@
1
- import { t as A2Error } from "./session-clear-wHd5GCpZ-BnKSxReK.mjs";
2
- //#region ../../node_modules/.pnpm/experimental-a2@0.22.0_@upstash+qstash@2.12.0_@vercel+queue@0.7.0_ai@7.0.130_zod@4.6.5__52060f00b21aecfab049c27fa3abd2f9/node_modules/experimental-a2/dist/store-codec-DwrWlgQx.js
1
+ import { a as duplicateBatchError } from "./session-clear-XJYpmUpg-2q8l_FJR.mjs";
2
+ //#region ../../node_modules/.pnpm/experimental-a2@0.24.0_@upstash+qstash@2.12.0_@vercel+queue@0.7.0_ai@7.0.130_zod@4.6.5__b1e2c243a963f2620a5d202817417c26/node_modules/experimental-a2/dist/store-codec-pAG2oPgQ.js
3
3
  const canonicalJson = (value) => JSON.stringify(value, (_key, candidate) => {
4
4
  if (candidate === null || typeof candidate !== "object" || Array.isArray(candidate)) return candidate;
5
5
  return Object.fromEntries(Object.entries(candidate).toSorted(([left], [right]) => left < right ? -1 : left > right ? 1 : 0));
6
6
  }) ?? "null";
7
- const idempotentReplay = (events, existing) => {
7
+ const idempotentReplay = (events, existing, conditional) => {
8
8
  const byId = new Map(existing.map((event) => [event.id, event]));
9
9
  const ordered = events.map((event) => event.id === void 0 ? void 0 : byId.get(event.id));
10
10
  const firstIndex = ordered[0]?.index;
@@ -12,7 +12,7 @@ const idempotentReplay = (events, existing) => {
12
12
  if (firstIndex === void 0 || batchSize !== void 0 && batchSize !== events.length || ordered.some((stored, index) => {
13
13
  const event = events[index];
14
14
  return stored === void 0 || stored.index !== firstIndex + index || stored.type !== event.type || stored.cause?.batchSize !== event.cause?.batchSize || canonicalJson(stored.payload) !== canonicalJson(event.payload);
15
- })) throw new A2Error("PARTIAL_DUPLICATE_BATCH", "already-appended events do not match the retried batch");
15
+ })) throw duplicateBatchError("already-appended events do not match the retried batch", conditional);
16
16
  return ordered;
17
17
  };
18
18
  const decodeReturnedEventIds = (value) => {
@@ -0,0 +1,2 @@
1
+ import { t as memory } from "./store-memory-B0PkVSuQ.mjs";
2
+ export { memory };
@@ -1,8 +1,8 @@
1
- import { n as CLEAR_EVENT_TYPE, o as sessionClearedError, s as supersededAttemptError, t as A2Error } from "./session-clear-wHd5GCpZ-BnKSxReK.mjs";
2
- import { m as nullProtoRecord } from "./internal-CvsrprnU-CRY89I-b.mjs";
3
- import { a as idleLogCursor, i as idempotentReplay } from "./store-codec-DwrWlgQx-CYxGW0aD.mjs";
4
- import { n as SYSTEM_CLOCK, t as RANDOM_IDS } from "./store-N8PXxDAS-BWBgzBHp.mjs";
5
- //#region ../../node_modules/.pnpm/experimental-a2@0.22.0_@upstash+qstash@2.12.0_@vercel+queue@0.7.0_ai@7.0.130_zod@4.6.5__52060f00b21aecfab049c27fa3abd2f9/node_modules/experimental-a2/dist/store-memory.js
1
+ import { a as duplicateBatchError, c as sessionClearedError, l as supersededAttemptError, n as CLEAR_EVENT_TYPE, s as lastIndexMismatchError, t as A2Error } from "./session-clear-XJYpmUpg-2q8l_FJR.mjs";
2
+ import { m as nullProtoRecord } from "./internal-CvsrprnU-zZMpDiRY.mjs";
3
+ import { a as idleLogCursor, i as idempotentReplay } from "./store-codec-pAG2oPgQ-SqDXlPBR.mjs";
4
+ import { n as SYSTEM_CLOCK, t as RANDOM_IDS } from "./store-N8PXxDAS-DWWgv-Vz.mjs";
5
+ //#region ../../node_modules/.pnpm/experimental-a2@0.24.0_@upstash+qstash@2.12.0_@vercel+queue@0.7.0_ai@7.0.130_zod@4.6.5__b1e2c243a963f2620a5d202817417c26/node_modules/experimental-a2/dist/store-memory.js
6
6
  const RECLAIM_BATCH = 256;
7
7
  const headOf = (log) => log ? log.offset + log.rows.length : 0;
8
8
  const freshDispatch = () => ({
@@ -363,17 +363,24 @@ function memory(options = {}) {
363
363
  events: [],
364
364
  hasPending: hasPending(sessionId, consumers)
365
365
  };
366
+ const ifLastIndex = appendOptions?.ifLastIndex;
367
+ const conditional = ifLastIndex === void 0 ? void 0 : {
368
+ sessionId,
369
+ ifLastIndex,
370
+ head: headOf(sessions.get(sessionId))
371
+ };
366
372
  const existing = checkBatchIds(sessionId, events);
367
373
  if (existing.length > 0) {
368
374
  if (existing.length === events.length) return {
369
- events: idempotentReplay(events, existing.map(toStored)),
375
+ events: idempotentReplay(events, existing.map(toStored), conditional),
370
376
  hasPending: hasPending(sessionId, consumers)
371
377
  };
372
- throw new A2Error("PARTIAL_DUPLICATE_BATCH", `batch mixes ${existing.length} already-appended and ${events.length - existing.length} fresh events`);
378
+ throw duplicateBatchError(`batch mixes ${existing.length} already-appended and ${events.length - existing.length} fresh events`, conditional);
373
379
  }
374
380
  const originIndex = appendOptions?.originIndex;
375
381
  if (originIndex !== void 0 && originIndex <= clearIndexOf(sessionId)) throw sessionClearedError(`scheduled work from event ${originIndex} was cleared in session '${sessionId}'`);
376
382
  for (const event of events) if (event.cause) assertCurrentCause(sessionId, event.cause);
383
+ if (conditional && conditional.head !== conditional.ifLastIndex) throw lastIndexMismatchError(sessionId, conditional.ifLastIndex, conditional.head);
377
384
  const inserted = insert(sessionId, events, clock.now(), consumers);
378
385
  notifyStreams(sessionId, inserted);
379
386
  return {
@@ -1,5 +1,5 @@
1
- import { r as POLL_TIMINGS } from "./internal-CvsrprnU-CRY89I-b.mjs";
2
- //#region ../../node_modules/.pnpm/experimental-a2@0.22.0_@upstash+qstash@2.12.0_@vercel+queue@0.7.0_ai@7.0.130_zod@4.6.5__52060f00b21aecfab049c27fa3abd2f9/node_modules/experimental-a2/dist/store-polling-BZt2Rf3D.js
1
+ import { r as POLL_TIMINGS } from "./internal-CvsrprnU-zZMpDiRY.mjs";
2
+ //#region ../../node_modules/.pnpm/experimental-a2@0.24.0_@upstash+qstash@2.12.0_@vercel+queue@0.7.0_ai@7.0.130_zod@4.6.5__b1e2c243a963f2620a5d202817417c26/node_modules/experimental-a2/dist/store-polling-BZt2Rf3D.js
3
3
  const streamActivities = /* @__PURE__ */ new WeakMap();
4
4
  function createStreamActivity(wake) {
5
5
  let idle = false;
@@ -1,6 +1,6 @@
1
- import { r as POLL_TIMINGS } from "./internal-CvsrprnU-CRY89I-b.mjs";
2
- import { n as defaultSleep } from "./store-polling-BZt2Rf3D-BiEM6_HB.mjs";
3
- //#region ../../node_modules/.pnpm/experimental-a2@0.22.0_@upstash+qstash@2.12.0_@vercel+queue@0.7.0_ai@7.0.130_zod@4.6.5__52060f00b21aecfab049c27fa3abd2f9/node_modules/experimental-a2/dist/store-presence-polling-JuAy2Ck2.js
1
+ import { r as POLL_TIMINGS } from "./internal-CvsrprnU-zZMpDiRY.mjs";
2
+ import { n as defaultSleep } from "./store-polling-BZt2Rf3D-Div-bJ_D.mjs";
3
+ //#region ../../node_modules/.pnpm/experimental-a2@0.24.0_@upstash+qstash@2.12.0_@vercel+queue@0.7.0_ai@7.0.130_zod@4.6.5__b1e2c243a963f2620a5d202817417c26/node_modules/experimental-a2/dist/store-presence-polling-JuAy2Ck2.js
4
4
  const key = ({ participant, field }) => JSON.stringify([participant, field]);
5
5
  function pollPresence({ read, deliver, sleep = defaultSleep }) {
6
6
  let stopped = false;
@@ -1,11 +1,11 @@
1
- import { n as CLEAR_EVENT_TYPE, o as sessionClearedError, s as supersededAttemptError, t as A2Error } from "./session-clear-wHd5GCpZ-BnKSxReK.mjs";
2
- import { r as pollingStream } from "./store-polling-BZt2Rf3D-BiEM6_HB.mjs";
3
- import { a as idleLogCursor, i as idempotentReplay, n as decodeCause, r as decodeReturnedEventIds, t as cursorKeyOf } from "./store-codec-DwrWlgQx-CYxGW0aD.mjs";
4
- import { n as SYSTEM_CLOCK, t as RANDOM_IDS } from "./store-N8PXxDAS-BWBgzBHp.mjs";
1
+ import { a as duplicateBatchError, c as sessionClearedError, l as supersededAttemptError, n as CLEAR_EVENT_TYPE, s as lastIndexMismatchError, t as A2Error } from "./session-clear-XJYpmUpg-2q8l_FJR.mjs";
2
+ import { r as pollingStream } from "./store-polling-BZt2Rf3D-Div-bJ_D.mjs";
3
+ import { a as idleLogCursor, i as idempotentReplay, n as decodeCause, r as decodeReturnedEventIds, t as cursorKeyOf } from "./store-codec-pAG2oPgQ-SqDXlPBR.mjs";
4
+ import { n as SYSTEM_CLOCK, t as RANDOM_IDS } from "./store-N8PXxDAS-DWWgv-Vz.mjs";
5
5
  import { mkdirSync } from "node:fs";
6
6
  import { dirname, resolve } from "node:path";
7
7
  import { DatabaseSync } from "node:sqlite";
8
- //#region ../../node_modules/.pnpm/experimental-a2@0.22.0_@upstash+qstash@2.12.0_@vercel+queue@0.7.0_ai@7.0.130_zod@4.6.5__52060f00b21aecfab049c27fa3abd2f9/node_modules/experimental-a2/dist/store-sqlite.js
8
+ //#region ../../node_modules/.pnpm/experimental-a2@0.24.0_@upstash+qstash@2.12.0_@vercel+queue@0.7.0_ai@7.0.130_zod@4.6.5__b1e2c243a963f2620a5d202817417c26/node_modules/experimental-a2/dist/store-sqlite.js
9
9
  /**
10
10
  * experimental-a2/store-sqlite — sqlite store backend (the dev default, `.a2/dev.db`).
11
11
  *
@@ -470,14 +470,20 @@ function sqlite(options = {}) {
470
470
  const clearIndex = clearIndexOf(sessionId);
471
471
  const suppliedIds = events.filter((e) => e.id !== void 0).map((e) => e.id);
472
472
  if (new Set(suppliedIds).size !== suppliedIds.length) throw new A2Error("PARTIAL_DUPLICATE_BATCH", "batch contains the same event id more than once");
473
+ const ifLastIndex = appendOptions?.ifLastIndex;
474
+ const conditional = ifLastIndex === void 0 ? void 0 : {
475
+ sessionId,
476
+ ifLastIndex,
477
+ head: headOf(sessionId)
478
+ };
473
479
  if (suppliedIds.length > 0) {
474
480
  const existing = liveOwnersOf(sessionId, clearIndex, suppliedIds);
475
481
  if (existing.length > 0) {
476
482
  if (existing.length === events.length) return {
477
- events: idempotentReplay(events, existing.map(toStored)),
483
+ events: idempotentReplay(events, existing.map(toStored), conditional),
478
484
  hasPending: hasPending(sessionId, clearIndex, consumers)
479
485
  };
480
- throw new A2Error("PARTIAL_DUPLICATE_BATCH", `batch mixes ${existing.length} already-appended and ${events.length - existing.length} fresh events`);
486
+ throw duplicateBatchError(`batch mixes ${existing.length} already-appended and ${events.length - existing.length} fresh events`, conditional);
481
487
  }
482
488
  }
483
489
  const originIndex = appendOptions?.originIndex;
@@ -487,6 +493,7 @@ function sqlite(options = {}) {
487
493
  cause: e.cause,
488
494
  clearIndex
489
495
  });
496
+ if (conditional && conditional.head !== conditional.ifLastIndex) throw lastIndexMismatchError(sessionId, conditional.ifLastIndex, conditional.head);
490
497
  return {
491
498
  events: insertBatch({
492
499
  sessionId,
@@ -0,0 +1,2 @@
1
+ import { t as sqlite } from "./store-sqlite-D85t3tE7.mjs";
2
+ export { sqlite };
@@ -1,5 +1,5 @@
1
- import { i as PRESENCE_TIMINGS } from "./internal-CvsrprnU-CRY89I-b.mjs";
2
- //#region ../../node_modules/.pnpm/experimental-a2@0.22.0_@upstash+qstash@2.12.0_@vercel+queue@0.7.0_ai@7.0.130_zod@4.6.5__52060f00b21aecfab049c27fa3abd2f9/node_modules/experimental-a2/dist/stream-buffer-DrTyiIuo.js
1
+ import { i as PRESENCE_TIMINGS } from "./internal-CvsrprnU-zZMpDiRY.mjs";
2
+ //#region ../../node_modules/.pnpm/experimental-a2@0.24.0_@upstash+qstash@2.12.0_@vercel+queue@0.7.0_ai@7.0.130_zod@4.6.5__b1e2c243a963f2620a5d202817417c26/node_modules/experimental-a2/dist/stream-buffer-DrTyiIuo.js
3
3
  const key = ({ participant, field }) => JSON.stringify([participant, field]);
4
4
  function presenceTombstones() {
5
5
  const stamps = /* @__PURE__ */ new Map();
@@ -1,5 +1,5 @@
1
- import { S as SyncUnit, _ as withUserTokens, d as ResolvedTarget, f as SyncContext, h as UserTokens, o as ProviderPost, r as ProviderDelivery, y as SyncFn } from "./provider-DmSTp9lI.mjs";
2
- import { n as ChatSyncProvider } from "./chat-provider-BWHbChcQ.mjs";
1
+ import { S as SyncUnit, _ as withUserTokens, d as ResolvedTarget, f as SyncContext, h as UserTokens, o as ProviderPost, r as ProviderDelivery, y as SyncFn } from "./provider-Bm46LAdp.mjs";
2
+ import { n as ChatSyncProvider } from "./chat-provider-D6jVT4wS.mjs";
3
3
  import { z } from "zod";
4
4
  import { Adapter } from "chat";
5
5
  //#region src/sync/github.d.ts
@@ -1,5 +1,5 @@
1
- import { S as SyncUnit, f as SyncContext, y as SyncFn } from "./provider-DmSTp9lI.mjs";
2
- import { n as ChatSyncProvider, t as ChatInput } from "./chat-provider-BWHbChcQ.mjs";
1
+ import { S as SyncUnit, f as SyncContext, y as SyncFn } from "./provider-Bm46LAdp.mjs";
2
+ import { n as ChatSyncProvider, t as ChatInput } from "./chat-provider-D6jVT4wS.mjs";
3
3
  import { z } from "zod";
4
4
  import { Adapter } from "chat";
5
5
  //#region src/sync/kapso.d.ts
@@ -1,6 +1,6 @@
1
- import { mt as SourceRead } from "./client-BqAjk0Q4.mjs";
2
- import { S as SyncUnit, c as ReceivedEvent, d as ResolvedTarget, f as SyncContext, o as ProviderPost, r as ProviderDelivery, y as SyncFn } from "./provider-DmSTp9lI.mjs";
3
- import { n as ChatSyncProvider, t as ChatInput } from "./chat-provider-BWHbChcQ.mjs";
1
+ import { ht as SourceRead } from "./client-CjAatpV4.mjs";
2
+ import { S as SyncUnit, c as ReceivedEvent, d as ResolvedTarget, f as SyncContext, o as ProviderPost, r as ProviderDelivery, y as SyncFn } from "./provider-Bm46LAdp.mjs";
3
+ import { n as ChatSyncProvider, t as ChatInput } from "./chat-provider-D6jVT4wS.mjs";
4
4
  import { z } from "zod";
5
5
  import { Adapter } from "chat";
6
6
  //#region src/sync/linear.d.ts
@@ -37,6 +37,8 @@ const bodyOf = (description) => description?.trim() || null;
37
37
  * An issue's properties as board labels: `priority=high`, `project=v0-accessibility`, a label per
38
38
  * Linear label (`tag.bug`), and its assignee (`assignee.ada`). Only what the payload says: a
39
39
  * property it carries empty is unset, and one it names without its details is left as it was.
40
+ * Linear leaves an empty assignee or project out of the payload rather than sending `null`, so
41
+ * either one missing, with no ID either, is empty.
40
42
  * `priority` and `project` are single keys, so they're unset by name; `tag.` and `assignee.` are
41
43
  * prefixes the mirror owns, so a key under them that Linear doesn't have goes.
42
44
  */
@@ -47,7 +49,7 @@ function propertiesOf(data) {
47
49
  if (data.priority === 0 || data.priorityLabel === "No priority") unset.push("priority");
48
50
  else if (data.priorityLabel && slug(data.priorityLabel)) labels.priority = slug(data.priorityLabel).slice(0, 256);
49
51
  if (data.project?.name && slug(data.project.name)) labels.project = slug(data.project.name).slice(0, 256);
50
- else if (data.project === null || data.projectId === null) unset.push("project");
52
+ else if (!data.project && !data.projectId) unset.push("project");
51
53
  if (Array.isArray(data.labels)) {
52
54
  owns.push("tag.");
53
55
  for (const label of data.labels) {
@@ -59,7 +61,7 @@ function propertiesOf(data) {
59
61
  owns.push("assignee.");
60
62
  const tag = tagOf("assignee", handleOf(data.assignee));
61
63
  if (tag) labels[tag[0]] = tag[1];
62
- } else if (data.assignee === null || data.assigneeId === null) owns.push("assignee.");
64
+ } else if (!data.assigneeId) owns.push("assignee.");
63
65
  return {
64
66
  labels,
65
67
  unset,
@@ -1,6 +1,6 @@
1
- import { f as ExternalLink } from "./folds-ZkHM4M-v.mjs";
2
- import { C as channels, _ as withUserTokens, d as ResolvedTarget, f as SyncContext, h as UserTokens, o as ProviderPost, r as ProviderDelivery, y as SyncFn } from "./provider-DmSTp9lI.mjs";
3
- import { n as ChatSyncProvider, t as ChatInput } from "./chat-provider-BWHbChcQ.mjs";
1
+ import { f as ExternalLink } from "./folds-8wRRXjAt.mjs";
2
+ import { C as channels, _ as withUserTokens, d as ResolvedTarget, f as SyncContext, h as UserTokens, o as ProviderPost, r as ProviderDelivery, y as SyncFn } from "./provider-Bm46LAdp.mjs";
3
+ import { n as ChatSyncProvider, t as ChatInput } from "./chat-provider-D6jVT4wS.mjs";
4
4
  import { z } from "zod";
5
5
  import { Adapter } from "chat";
6
6
  //#region src/sync/slack.d.ts
@@ -1,2 +1,2 @@
1
- import { i as externalAuthor, n as ChatSyncProvider, r as ChatTransport, t as ChatInput } from "./chat-provider-BWHbChcQ.mjs";
1
+ import { i as externalAuthor, n as ChatSyncProvider, r as ChatTransport, t as ChatInput } from "./chat-provider-D6jVT4wS.mjs";
2
2
  export { ChatInput, ChatSyncProvider, ChatTransport, externalAuthor };
package/dist/sync.d.mts CHANGED
@@ -1,3 +1,3 @@
1
- import { d as ExternalFile, l as ExternalAuthor, u as ExternalEvent } from "./folds-ZkHM4M-v.mjs";
2
- import { A as SyncOverrides, C as channels, D as EventBase, E as render, M as SyncRoot, N as envelope, O as ProviderEvent, P as eventSchema, S as SyncUnit, T as mirror, _ as withUserTokens, a as ProviderOptions, b as SyncIn, c as ReceivedEvent, d as ResolvedTarget, f as SyncContext, g as connectUserTokens, h as UserTokens, i as ProviderFile, j as SyncResult, k as RootOverride, l as RenderInput, m as UnreadableError, n as FileDelivery, o as ProviderPost, p as SyncProvider, r as ProviderDelivery, s as Receive, u as Renderer, v as Sync, w as into, x as SyncOut, y as SyncFn } from "./provider-DmSTp9lI.mjs";
1
+ import { d as ExternalFile, l as ExternalAuthor, u as ExternalEvent } from "./folds-8wRRXjAt.mjs";
2
+ import { A as SyncOverrides, C as channels, D as EventBase, E as render, M as SyncRoot, N as envelope, O as ProviderEvent, P as eventSchema, S as SyncUnit, T as mirror, _ as withUserTokens, a as ProviderOptions, b as SyncIn, c as ReceivedEvent, d as ResolvedTarget, f as SyncContext, g as connectUserTokens, h as UserTokens, i as ProviderFile, j as SyncResult, k as RootOverride, l as RenderInput, m as UnreadableError, n as FileDelivery, o as ProviderPost, p as SyncProvider, r as ProviderDelivery, s as Receive, u as Renderer, v as Sync, w as into, x as SyncOut, y as SyncFn } from "./provider-Bm46LAdp.mjs";
3
3
  export { EventBase, type ExternalAuthor, ExternalEvent, type ExternalFile, type FileDelivery, type ProviderDelivery, type ProviderEvent, type ProviderFile, type ProviderOptions, type ProviderPost, type Receive, ReceivedEvent, type RenderInput, type Renderer, ResolvedTarget, type RootOverride, type Sync, type SyncContext, type SyncFn, type SyncIn, type SyncOut, SyncOverrides, SyncProvider, type SyncResult, type SyncRoot, type SyncUnit, UnreadableError, type UserTokens, channels, connectUserTokens, envelope, eventSchema, into, mirror, render, withUserTokens };
@@ -1,5 +1,5 @@
1
- import { l as unauthorized } from "./errors-CusN4x2l.mjs";
2
- import { f as markVerified, m as trustedIssuers, n as TOKENS, r as VERCEL_ISSUER, u as issuerName } from "./auth-JO22iIwr.mjs";
1
+ import { l as unauthorized } from "./errors-C_5rB8Iz.mjs";
2
+ import { f as markVerified, m as trustedIssuers, n as TOKENS, r as VERCEL_ISSUER, u as issuerName } from "./auth-BPinwfN0.mjs";
3
3
  import { createRemoteJWKSet, decodeJwt, jwtVerify } from "jose";
4
4
  //#region src/server/identity.ts
5
5
  let fromDisk;
@@ -1,5 +1,5 @@
1
- import { a as ExternalCopy, c as SyncedThread, g as BoardEvent, o as Message } from "./folds-ZkHM4M-v.mjs";
2
- import { t as A2Store } from "./store-D0MhBvg6-4Z2L0Kqd.mjs";
1
+ import { a as ExternalCopy, c as SyncedThread, g as BoardEvent, o as Message } from "./folds-8wRRXjAt.mjs";
2
+ import { t as A2Store } from "./store-DEzcHZOA-B-5vhxef.mjs";
3
3
  //#region src/store/types.d.ts
4
4
  /**
5
5
  * What a query matches, resolved by the board: handles are already actor and