@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,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/internal-CvsrprnU.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/internal-CvsrprnU.js
2
2
  /**
3
3
  * A null-prototype record for maps keyed by caller-controlled strings
4
4
  * (participant ids, presence field names). On a normal object,
@@ -1,4 +1,4 @@
1
- import { i as deliverSchedulerClear, r as deliverSchedulerAppend } from "./server-DtFrWxi3-Boa6gdWO.mjs";
1
+ import { i as deliverSchedulerClear, r as deliverSchedulerAppend } from "./server-DX7mM6nm-D7N_7bug.mjs";
2
2
  //#region src/scheduler/local.ts
3
3
  /** The longest delay a timer takes: past it, `setTimeout` fires at once. */
4
4
  const MAX_DELAY = 2 ** 31 - 1;
@@ -1,14 +1,14 @@
1
1
  import { i as fileSize, n as DIRECT_UPLOAD_BYTES_MAX } from "./files-SniSmeEr.mjs";
2
2
  import { a as AttachmentId } from "./schemas-DBmUO6pr.mjs";
3
- import { d as VERSION, i as withMentions } from "./watchers-hash-BDhLVkV5.mjs";
3
+ import { d as VERSION, i as withMentions } from "./watchers-hash-B_5b0-ZG.mjs";
4
4
  import { n as displayEmoji, r as normalizeEmoji } from "./emoji-CTLpvH-A.mjs";
5
- import { t as BoardError } from "./client-D0Px7KzF.mjs";
6
- import { i as groups, n as filters$1, o as options, r as globalOptions, s as usage$1, t as commands } from "./commands-C3R1AWgm.mjs";
7
- import { a as handFetch, d as vercelProjectFile, n as boardUrl, o as handLogin, r as connect } from "./node-Zd_C-gxP.mjs";
8
- import { t as http } from "./backend-http-Bmp0IgD3.mjs";
9
- import { t as board } from "./server-BixV_byP.mjs";
10
- import { t as conformance } from "./conformance-DlnfuzEB.mjs";
11
- import { n as handTeam, r as vercel, t as credentialSource } from "./backend-vercel-DQc_TaHp.mjs";
5
+ import { u as BoardError } from "./errors-C_5rB8Iz.mjs";
6
+ import { i as groups, n as filters$1, o as options, r as globalOptions, s as usage$1, t as commands } from "./commands-B5DHjZKK.mjs";
7
+ import { a as handFetch, d as vercelProjectFile, n as boardUrl, o as handLogin, r as connect } from "./node-D8Rtg1su.mjs";
8
+ import { t as http } from "./backend-http-16SbvnAK.mjs";
9
+ import { t as board } from "./server-D82a4uMe.mjs";
10
+ import { t as conformance } from "./conformance-C7fwIvmN.mjs";
11
+ import { n as handTeam, r as vercel, t as credentialSource } from "./backend-vercel-Kd8nvW5A.mjs";
12
12
  import { t as displayText } from "./bots-CGkO76qH.mjs";
13
13
  import { spawn } from "node:child_process";
14
14
  import { readFile, stat, writeFile } from "node:fs/promises";
@@ -83,7 +83,7 @@ function embed(link, pad) {
83
83
  /** One message as a block: header line, indented text, reactions. */
84
84
  function formatMessage(message, options = {}) {
85
85
  const pad = options.reply ? " " : " ";
86
- const head = `${options.reply ? " ↳ " : ""}#${message.id} ${authorName(message)} · ${ago(message.createdAt)}${message.editedAt ? " (edited)" : ""}${message.schedule ? ` · scheduled s${message.schedule.id}` : ""}${labels(message)}`;
86
+ const head = `${options.reply ? " ↳ " : ""}#${message.id} ${authorName(message)} · ${ago(message.createdAt)}${message.editedAt ? " (edited)" : ""}${message.schedule ? ` · scheduled ${message.schedule.id}` : ""}${labels(message)}`;
87
87
  const body = message.deleted ? `${pad}(message removed)` : indent(displayText(message.text, message.by.actor), pad);
88
88
  const files = (message.attachments ?? []).map((a) => `${pad}file ${a.name} · ${a.type} · ${fileSize(a.size)} · ${a.id}`);
89
89
  const links = message.deleted ? [] : (message.links ?? []).flatMap((link) => embed(link, pad));
@@ -193,7 +193,7 @@ function formatSchedule(schedule, options = {}) {
193
193
  const sent = schedule.sent > 0 ? ` · ${schedule.sent} sent` : "";
194
194
  const files = schedule.attachments.length ? ` · ${schedule.attachments.length} ${schedule.attachments.length === 1 ? "file" : "files"}` : "";
195
195
  const text = displayText(schedule.text, schedule.by.actor);
196
- return [`${pad}s${schedule.id} ${where} · ${repeat}${stop} · ${when}${sent}${files} · by ${authorName(schedule)}`, indent(text || "(no text)", `${pad} `)].join("\n");
196
+ return [`${pad}${schedule.id} ${where} · ${repeat}${stop} · ${when}${sent}${files} · by ${authorName(schedule)}`, indent(text || "(no text)", `${pad} `)].join("\n");
197
197
  }
198
198
  /** One line per live event, for `tail` and `wait`. */
199
199
  function formatEvent(event) {
@@ -859,11 +859,18 @@ const tooLarge = (path) => new Failed({
859
859
  const isMessageRef = (value) => /^#[^\s/]+$/.test(value) || /^\d+$/.test(value);
860
860
  /** A message's ID as it's passed back: bare when it's a number, `#<id>` when it could be a channel's name. */
861
861
  const messageRef = (id) => /^\d+$/.test(id) ? id : `#${id}`;
862
- function labelPairs(values) {
862
+ /** `--if-revision N`, as an edit or a delete takes it. */
863
+ function ifRevision() {
864
+ const given = flags["if-revision"];
865
+ if (given === void 0) return {};
866
+ if (!/^[1-9]\d{0,15}$/.test(given)) throw usage(`--if-revision takes the message's revision, a number, and ${given} isn't one.`);
867
+ return { revision: Number(given) };
868
+ }
869
+ function labelPairs(values, wrong = "Labels look like key=value, and {value} isn't one.") {
863
870
  const pairs = {};
864
871
  for (const value of values ?? []) {
865
872
  const at = value.indexOf("=");
866
- if (at <= 0) throw usage(`Labels look like key=value, and ${value} isn't one.`);
873
+ if (at <= 0) throw usage(wrong.replace("{value}", value));
867
874
  pairs[value.slice(0, at)] = value.slice(at + 1);
868
875
  }
869
876
  return pairs;
@@ -895,12 +902,11 @@ async function attachments(board) {
895
902
  }));
896
903
  return uploaded;
897
904
  }
898
- /** `s12` or `12`. */
905
+ /** A schedule's ID as the board gave it: `s12`, or `sch_…` on Vercel's board. */
899
906
  function scheduleId(value) {
900
- const id = value?.replace(/^s(?=\d)/i, "") ?? "";
901
907
  if (value === void 0) throw usage("Missing the schedule ID, like s12.", { reason: "missing_arguments" });
902
- if (!/^[^\s/]+$/.test(id)) throw usage(`${value} isn't a schedule ID like s12.`);
903
- return id;
908
+ if (!/^[^\s/]+$/.test(value)) throw usage(`${value} isn't a schedule ID like s12.`);
909
+ return value;
904
910
  }
905
911
  /** A time flag: anything `Date` reads, as ISO. */
906
912
  function instant(flag, value) {
@@ -1121,7 +1127,37 @@ function failureOf(error) {
1121
1127
  details: []
1122
1128
  } : theirs("not_found", specific("not_found"), `Can't ${doing()}.`);
1123
1129
  }
1124
- if (status === 409) return theirs("conflict", specific("conflict"), `Can't ${doing()}.`);
1130
+ if (status === 409) {
1131
+ const { args } = current;
1132
+ const newer = code === "newer_message" && flags.after !== void 0 && args[0] !== void 0;
1133
+ const labeled = code === "label_conflict" && (flags.if !== void 0 || flags["if-unset"] !== void 0) && args[0] !== void 0;
1134
+ const changed = code === "revision_conflict" && flags["if-revision"] !== void 0 && args[0] !== void 0;
1135
+ return theirs("conflict", specific("conflict"), `Can't ${doing()}.`, newer ? [{
1136
+ instruction: `Read what came after ${ref(flags.after)}`,
1137
+ argv: [
1138
+ ...cli(),
1139
+ "read",
1140
+ args[0].replace(/^#/, ""),
1141
+ "--after",
1142
+ flags.after.replace(/^#/, "")
1143
+ ]
1144
+ }] : labeled ? [{
1145
+ instruction: "See its labels now",
1146
+ argv: [
1147
+ ...cli(),
1148
+ "read",
1149
+ args[0].replace(/^#/, "")
1150
+ ]
1151
+ }] : changed ? [{
1152
+ instruction: "Read it as it is now",
1153
+ argv: [
1154
+ ...cli(),
1155
+ "read",
1156
+ args[0].replace(/^#/, ""),
1157
+ "--json"
1158
+ ]
1159
+ }] : []);
1160
+ }
1125
1161
  if (status === 413) return theirs("limit", "payload_too_large", `Can't ${doing()}. It's too large for the board.`);
1126
1162
  if (status === 429) return theirs("rate_limit", "rate_limited", "Too many requests to the board. Try again in a minute.");
1127
1163
  if (status === 501) return theirs("platform", specific("not_supported"), `Can't ${doing()}. This board doesn't support it.`);
@@ -1506,6 +1542,7 @@ async function run(command, args) {
1506
1542
  ]
1507
1543
  }] });
1508
1544
  if (flags.sync?.length && flags["no-sync"]) throw usage("Can't use --sync with --no-sync.");
1545
+ if (re === void 0 && flags.after !== void 0) throw usage("Can't use --after on a new thread. It's for replies: the thread's newest message.");
1509
1546
  const board = client();
1510
1547
  const content = body === void 0 && flags.attach?.length ? "" : await text(body);
1511
1548
  const files = await attachments(board);
@@ -1519,7 +1556,10 @@ async function run(command, args) {
1519
1556
  const message = re === void 0 ? await board.post(target, {
1520
1557
  ...options,
1521
1558
  ...flags.sync?.length ? { sync: flags.sync } : {}
1522
- }) : await board.reply(re, options);
1559
+ }) : await board.reply(re, {
1560
+ ...options,
1561
+ ...flags.after !== void 0 ? { after: messageId(flags.after) } : {}
1562
+ });
1523
1563
  warnUnknownMentions(message.unknownMentions);
1524
1564
  printMessage(message);
1525
1565
  return 0;
@@ -1533,7 +1573,8 @@ async function run(command, args) {
1533
1573
  text: content,
1534
1574
  ...files.length ? { attachments: files } : {},
1535
1575
  ...flags["idempotency-key"] ? { id: flags["idempotency-key"] } : {},
1536
- ...flags["no-sync"] ? { noSync: true } : {}
1576
+ ...flags["no-sync"] ? { noSync: true } : {},
1577
+ ...flags.after !== void 0 ? { after: messageId(flags.after) } : {}
1537
1578
  });
1538
1579
  warnUnknownMentions(message.unknownMentions);
1539
1580
  printMessage(message);
@@ -1546,7 +1587,7 @@ async function run(command, args) {
1546
1587
  schedule,
1547
1588
  outcome: canceled ? "canceled" : "unchanged"
1548
1589
  });
1549
- else out(canceled ? `canceled s${schedule.id}` : `s${schedule.id} is already ${schedule.state}`);
1590
+ else out(canceled ? `canceled ${schedule.id}` : `${schedule.id} is already ${schedule.state}`);
1550
1591
  return 0;
1551
1592
  }
1552
1593
  const [target, body] = args;
@@ -1630,14 +1671,14 @@ async function run(command, args) {
1630
1671
  case "hook": return 0;
1631
1672
  case "edit": {
1632
1673
  const id = messageId(args[0]);
1633
- const { unknownMentions } = await client().edit(id, await text(args[1]));
1674
+ const { unknownMentions } = await client().edit(id, await text(args[1]), ifRevision());
1634
1675
  warnUnknownMentions(unknownMentions);
1635
1676
  printDone(id, "edited");
1636
1677
  return 0;
1637
1678
  }
1638
1679
  case "delete": {
1639
1680
  const id = messageId(args[0]);
1640
- await client().delete(id);
1681
+ await client().delete(id, ifRevision());
1641
1682
  printDone(id, "deleted");
1642
1683
  return 0;
1643
1684
  }
@@ -1659,9 +1700,15 @@ async function run(command, args) {
1659
1700
  const set = labelPairs(args.slice(1));
1660
1701
  const unset = flags.unset ?? [];
1661
1702
  if (Object.keys(set).length === 0 && unset.length === 0) throw usage("Missing the labels: k=v to set one, --unset k to remove one.", { reason: "missing_arguments" });
1703
+ const expected = labelPairs(flags.if, "--if takes key=value, and {value} isn't one. For a label that mustn't be set, --if-unset key.");
1704
+ for (const key of flags["if-unset"] ?? []) {
1705
+ if (Object.hasOwn(expected, key)) throw usage(`Can't use --if ${key}=… with --if-unset ${key}.`);
1706
+ expected[key] = null;
1707
+ }
1662
1708
  await client().label(id, {
1663
1709
  set,
1664
- unset
1710
+ unset,
1711
+ ...Object.keys(expected).length ? { if: expected } : {}
1665
1712
  });
1666
1713
  printDone(id, "labeled");
1667
1714
  return 0;
@@ -1,5 +1,5 @@
1
1
  import { m as MESSAGE_TEXT_MAX, p as Labels } from "./schemas-DBmUO6pr.mjs";
2
- import { t as HttpError } from "./errors-CusN4x2l.mjs";
2
+ import { t as HttpError } from "./errors-C_5rB8Iz.mjs";
3
3
  import { z } from "zod";
4
4
  //#region src/server/middleware.ts
5
5
  /** A write the middleware didn't let through: the API answers 422 with what it responded. */
@@ -1,4 +1,4 @@
1
- import { t as BoardError } from "./client-D0Px7KzF.mjs";
1
+ import { u as BoardError } from "./errors-C_5rB8Iz.mjs";
2
2
  import { execFile } from "node:child_process";
3
3
  import { createHash } from "node:crypto";
4
4
  import { mkdir, readFile, readdir, stat, unlink, writeFile } from "node:fs/promises";
@@ -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/platform-B4TnJtWu.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/platform-B4TnJtWu.js
2
2
  const SYMBOL_FOR_REQ_CONTEXT = Symbol.for("@vercel/request-context");
3
3
  function requestContext() {
4
4
  try {
@@ -1,5 +1,5 @@
1
1
  import { n as setOwn, t as own } from "./own-OwgPWdmh.mjs";
2
- import { n as foldMessages, r as foldSync } from "./folds-BDMSxBUf.mjs";
2
+ import { n as foldMessages, r as foldSync } from "./folds-DGYkMW19.mjs";
3
3
  //#region src/store/project.ts
4
4
  /** The message an event concerns, if any. */
5
5
  function concernedMessageId(event) {
@@ -1,5 +1,5 @@
1
- import { d as ExternalFile, f as ExternalLink, l as ExternalAuthor, p as Link, t as Actor, u as ExternalEvent } from "./folds-ZkHM4M-v.mjs";
2
- import { V as MessageView, _ as BoardEventView, dt as SourceJoin, mt as SourceRead, t as BoardClient } from "./client-BqAjk0Q4.mjs";
1
+ import { d as ExternalFile, f as ExternalLink, l as ExternalAuthor, p as Link, t as Actor, u as ExternalEvent } from "./folds-8wRRXjAt.mjs";
2
+ import { H as MessageView, _ as BoardEventView, ft as SourceJoin, ht as SourceRead, t as BoardClient } from "./client-CjAatpV4.mjs";
3
3
  import { z } from "zod";
4
4
  //#region src/sync/events.d.ts
5
5
  declare const EventBase: z.ZodObject<{
@@ -1,14 +1,14 @@
1
1
  import { c as externalMessageKey } from "./external-D3p5T57R.mjs";
2
2
  import { n as setOwn } from "./own-OwgPWdmh.mjs";
3
- import { n as CLEAR_EVENT_TYPE, o as sessionClearedError, s as supersededAttemptError, t as A2Error } from "./session-clear-wHd5GCpZ-BnKSxReK.mjs";
4
- import { m as nullProtoRecord, n as NOTIFY_TIMINGS, v as stateTailReaders } from "./internal-CvsrprnU-CRY89I-b.mjs";
5
- import { i as presenceTombstones, n as isSerializedEvent, r as parseSerializedEvent, t as bufferedEvents } from "./stream-buffer-DrTyiIuo-BKy-vI14.mjs";
6
- import { i as streamActivities, n as defaultSleep, r as pollingStream, t as createStreamActivity } from "./store-polling-BZt2Rf3D-BiEM6_HB.mjs";
7
- import { t as retryableLazy } from "./retryable-lazy-DZWmHpii-Bye-W8q7.mjs";
8
- import { i as syncReads, n as project, r as projectSync, t as concernedMessageId } from "./project-CBXlLftU.mjs";
9
- import { i as idempotentReplay, n as decodeCause } from "./store-codec-DwrWlgQx-CYxGW0aD.mjs";
10
- import { t as pollPresence } from "./store-presence-polling-JuAy2Ck2-CYpuK75X.mjs";
11
- //#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-redis-notify-CsJw_hfD.js
3
+ 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";
4
+ import { m as nullProtoRecord, n as NOTIFY_TIMINGS, v as stateTailReaders } from "./internal-CvsrprnU-zZMpDiRY.mjs";
5
+ import { i as presenceTombstones, n as isSerializedEvent, r as parseSerializedEvent, t as bufferedEvents } from "./stream-buffer-DrTyiIuo-Be10yOBR.mjs";
6
+ import { i as streamActivities, n as defaultSleep, r as pollingStream, t as createStreamActivity } from "./store-polling-BZt2Rf3D-Div-bJ_D.mjs";
7
+ import { t as retryableLazy } from "./retryable-lazy-DZWmHpii-DpTc5PIP.mjs";
8
+ import { i as syncReads, n as project, r as projectSync, t as concernedMessageId } from "./project-C_2xs57L.mjs";
9
+ import { i as idempotentReplay, n as decodeCause } from "./store-codec-pAG2oPgQ-SqDXlPBR.mjs";
10
+ import { t as pollPresence } from "./store-presence-polling-JuAy2Ck2-Dh-g_KYM.mjs";
11
+ //#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-redis-notify-ys_-VrSP.js
12
12
  const key = ({ participant, field }) => JSON.stringify([participant, field]);
13
13
  function presenceRecovery({ read, deliver, isActive }) {
14
14
  const fields = /* @__PURE__ */ new Map();
@@ -645,11 +645,12 @@ end
645
645
  `;
646
646
  /**
647
647
  * KEYS: counter.
648
- * ARGV: sessionId, nowMs, n, served consumers, origin index or '', then per
649
- * event: id, type, payloadJson, causeJson or '', targets.
648
+ * ARGV: sessionId, nowMs, n, served consumers, origin index or '',
649
+ * ifLastIndex or '', then per event: id, type, payloadJson, causeJson or '',
650
+ * targets.
650
651
  * Returns ['empty', hasPending] | ['ok', firstIndex, hasPending] |
651
- * ['dup', hasPending, ...indexes] | ['partial', count] |
652
- * ['superseded', position] | ['cleared', originIndex] |
652
+ * ['dup', hasPending, head, ...indexes] | ['partial', count, head] |
653
+ * ['superseded', position] | ['cleared', originIndex] | ['moved', head] |
653
654
  * ['index', type, after].
654
655
  */
655
656
  const APPEND_LUA = `${BASE_LUA}${CURSOR_LUA}
@@ -657,7 +658,7 @@ local now, n = ARGV[2], tonumber(ARGV[3])
657
658
  use_served(ARGV[4])
658
659
  if n == 0 then return { 'empty', has_pending() } end
659
660
  local ids = {}
660
- for i = 1, n do ids[i] = ARGV[5 + (i - 1) * 5 + 1] end
661
+ for i = 1, n do ids[i] = ARGV[6 + (i - 1) * 5 + 1] end
661
662
  local owners = owners_of(read_bounds(ids))
662
663
  local base = total
663
664
  local dups = {}
@@ -665,18 +666,18 @@ for i = 1, n do
665
666
  if owners[i] then dups[#dups + 1] = owners[i] end
666
667
  end
667
668
  if #dups == n then
668
- local res = { 'dup', has_pending() }
669
+ local res = { 'dup', has_pending(), tostring(total) }
669
670
  for i = 1, #dups do res[#res + 1] = dups[i] end
670
671
  return res
671
672
  end
672
- if #dups > 0 then return { 'partial', tostring(#dups) } end
673
+ if #dups > 0 then return { 'partial', tostring(#dups), tostring(total) } end
673
674
  local origin = ARGV[5]
674
675
  if origin ~= '' and tonumber(origin) <= boundary then return { 'cleared', origin } end
675
676
  -- The attempt-currency fence: a cause's head row must still be its cursor's
676
677
  -- head, at that attempt, not dead-lettered.
677
678
  local refs, fenced = {}, {}
678
679
  for i = 1, n do
679
- local raw = ARGV[5 + (i - 1) * 5 + 4]
680
+ local raw = ARGV[6 + (i - 1) * 5 + 4]
680
681
  if raw ~= '' then
681
682
  local cause = cjson.decode(raw)
682
683
  local index = tonumber(cause.index)
@@ -696,16 +697,18 @@ for k, cause in ipairs(fenced) do
696
697
  end
697
698
  if served_has(cause.consumer) then pending_fast = true end
698
699
  end
700
+ local expected = ARGV[6]
701
+ if expected ~= '' and tonumber(expected) ~= total then return { 'moved', tostring(total) } end
699
702
  local batch = {}
700
703
  for i = 1, n do
701
- local o = 5 + (i - 1) * 5
704
+ local o = 6 + (i - 1) * 5
702
705
  batch[i] = { idx = base + i, type = ARGV[o + 2], targets = targets_of(ARGV[o + 5]) }
703
706
  end
704
707
  local planned, missing, after = plan(batch, base)
705
708
  if not planned then return { 'index', missing, tostring(after) } end
706
709
  local marks = {}
707
710
  for i = 1, n do
708
- local o = 5 + (i - 1) * 5
711
+ local o = 6 + (i - 1) * 5
709
712
  local field = tostring(base + i)
710
713
  redis.call('XADD', LOG, field .. '-0',
711
714
  'id', ARGV[o + 1], 'type', ARGV[o + 2], 'payload', ARGV[o + 3],
@@ -2040,6 +2043,12 @@ function createRedisStoreCore(options) {
2040
2043
  const suppliedIds = events.filter((e) => e.id !== void 0).map((e) => e.id);
2041
2044
  if (new Set(suppliedIds).size !== suppliedIds.length) throw new A2Error("PARTIAL_DUPLICATE_BATCH", "batch contains the same event id more than once");
2042
2045
  const now = clock.now().getTime();
2046
+ const ifLastIndex = appendOptions?.ifLastIndex;
2047
+ const conditionalAt = (head) => ifLastIndex === void 0 ? void 0 : {
2048
+ sessionId,
2049
+ ifLastIndex,
2050
+ head: Number(head)
2051
+ };
2043
2052
  const withIds = events.map((e) => ({
2044
2053
  id: e.id ?? generateId(),
2045
2054
  type: e.type,
@@ -2054,6 +2063,7 @@ function createRedisStoreCore(options) {
2054
2063
  withIds.length,
2055
2064
  servedArg(appendOptions?.consumers),
2056
2065
  appendOptions?.originIndex ?? "",
2066
+ ifLastIndex ?? "",
2057
2067
  ...withIds.flatMap((e, i) => [
2058
2068
  e.id,
2059
2069
  e.type,
@@ -2069,13 +2079,14 @@ function createRedisStoreCore(options) {
2069
2079
  };
2070
2080
  if (verdict === "cleared") throw sessionClearedError(`scheduled work from event ${reply[1]} was cleared in session '${sessionId}'`);
2071
2081
  if (verdict === "superseded") throw supersededAttemptError(sessionId, withIds[Number(reply[1]) - 1].cause);
2072
- if (verdict === "partial") throw new A2Error("PARTIAL_DUPLICATE_BATCH", `batch mixes ${reply[1]} already-appended and ${events.length - Number(reply[1])} fresh events`);
2082
+ if (verdict === "moved") throw lastIndexMismatchError(sessionId, ifLastIndex, Number(reply[1]));
2083
+ if (verdict === "partial") throw duplicateBatchError(`batch mixes ${reply[1]} already-appended and ${events.length - Number(reply[1])} fresh events`, conditionalAt(reply[2]));
2073
2084
  if (verdict === "dup") {
2074
2085
  const hasPending = reply[1] === "1";
2075
- const firstIndex = Math.min(...reply.slice(2).map(Number));
2086
+ const firstIndex = Math.min(...reply.slice(3).map(Number));
2076
2087
  const { rows: existing, clearIndex } = await retryAfterGap(() => readBoundedRange(sessionId, firstIndex - 1, firstIndex + events.length - 1));
2077
2088
  if (firstIndex < clearIndex) throw new A2Error("STORE_UNAVAILABLE", `session '${sessionId}' was cleared while an append retry replayed; retry it`);
2078
- const replayed = idempotentReplay(events, existing);
2089
+ const replayed = idempotentReplay(events, existing, conditionalAt(reply[2]));
2079
2090
  await publish(notifyChannel(sessionId), wakeMessage(firstIndex + events.length - 1, now, []));
2080
2091
  return {
2081
2092
  events: replayed,
@@ -2674,11 +2685,16 @@ function createRedisNotifyStore(options) {
2674
2685
  */
2675
2686
  let subscriberGate = null;
2676
2687
  const gatedSubscriber = () => {
2677
- subscriberGate ??= getSubscriber().then(async (conn) => {
2688
+ if (subscriberGate) return subscriberGate;
2689
+ const gate = getSubscriber().then(async (conn) => {
2678
2690
  await conn.call("echo", "ready");
2679
2691
  return conn;
2680
2692
  });
2681
- return subscriberGate;
2693
+ subscriberGate = gate;
2694
+ gate.catch(() => {
2695
+ if (subscriberGate === gate) subscriberGate = null;
2696
+ });
2697
+ return gate;
2682
2698
  };
2683
2699
  const acquireChannel = async (channel) => {
2684
2700
  const existing = subscriptions.get(channel);
@@ -1,5 +1,5 @@
1
- import { a as isSessionCleared } 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/reducer-CjmvZSAb.js
1
+ import { o as isSessionCleared } 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/reducer-Bswr11ar.js
3
3
  /**
4
4
  * Run a Standard Schema validator, requiring a synchronous result.
5
5
  * Validators must be synchronous (specs/a2-api.md §1) — an async one is
@@ -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/reducer-CYPHsSmd.d.ts
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/reducer-CYPHsSmd.d.ts
2
2
  //#region src/standard-schema.d.ts
3
3
  /**
4
4
  * The Standard Schema interface, vendored per the spec's guidance
@@ -1,10 +1,10 @@
1
1
  import { S as storable, _ as RemoteWatcherId, c as ChannelPath, d as LabelKey, g as MessageText, h as MessageId, i as Attachment, l as Emoji, n as ActorId, o as Author, p as Labels, u as Handle, v as SCOPE_MAX, y as SeenActorKind } from "./schemas-DBmUO6pr.mjs";
2
2
  import { a as Link, i as ExternalTarget, n as ExternalEvent, o as Origin } from "./external-D3p5T57R.mjs";
3
3
  import { n as setOwn, t as own } from "./own-OwgPWdmh.mjs";
4
- import { a as reducer, i as makeReducerBuilder, t as assertSyncSchema } from "./reducer-CjmvZSAb-D_OSISmj.mjs";
5
- import { n as foldMessages, t as foldActors } from "./folds-BDMSxBUf.mjs";
4
+ import { a as reducer, i as makeReducerBuilder, t as assertSyncSchema } from "./reducer-Bswr11ar-P324o9vn.mjs";
5
+ import { n as foldMessages, t as foldActors } from "./folds-DGYkMW19.mjs";
6
6
  import { z } from "zod";
7
- //#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/contract-CWukt01d.js
7
+ //#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/contract-DqfBSIqJ.js
8
8
  function contract(options) {
9
9
  for (const type of Object.keys(options.events ?? {})) if (type.startsWith("a2.")) throw new TypeError(`contract '${String(options.name)}': event types starting with 'a2.' are reserved`);
10
10
  return defineContract(options);
@@ -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/retryable-lazy-DZWmHpii.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/retryable-lazy-DZWmHpii.js
2
2
  const retryableLazy = (initialize) => {
3
3
  let current = null;
4
4
  const get = () => {
@@ -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/scheduler-task-X1SToDjP.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/scheduler-task-X1SToDjP.js
2
2
  const recordOf = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
3
3
  const validName = (value) => typeof value === "string" && value.length > 0;
4
4
  const validDueAt = (value) => typeof value === "number" && Number.isInteger(value) && value % 1e3 === 0;
@@ -1,10 +1,10 @@
1
- import { t as BoardError } from "./client-D0Px7KzF.mjs";
2
- import { s as localTokenFile } from "./node-Zd_C-gxP.mjs";
3
- import { t as board } from "./server-BixV_byP.mjs";
4
- import { t as oidcTokens } from "./tokens-CC3izSNr.mjs";
5
- import { t as a2 } from "./a2-HUbQJ0RD.mjs";
6
- import { a as fsBlob } from "./blob-DdbpJqN1.mjs";
7
- import { t as localScheduler } from "./local-DhkrAqPP.mjs";
1
+ import { u as BoardError } from "./errors-C_5rB8Iz.mjs";
2
+ import { s as localTokenFile } from "./node-D8Rtg1su.mjs";
3
+ import { t as board } from "./server-D82a4uMe.mjs";
4
+ import { t as oidcTokens } from "./tokens-C5_yGRlL.mjs";
5
+ import { t as a2 } from "./a2-D_28Pdip.mjs";
6
+ import { a as fsBlob } from "./blob-DQK5prXT.mjs";
7
+ import { t as localScheduler } from "./local-C76Fy5ad.mjs";
8
8
  import { mkdir, rm, writeFile } from "node:fs/promises";
9
9
  import { userInfo } from "node:os";
10
10
  import { dirname, join, resolve } from "node:path";
@@ -1,6 +1,6 @@
1
- import { a as PresenceDefs, c as PresenceSnapshot, d as WithPresence, i as EventDefs, l as Reducer, n as Contract, o as PresenceMap, r as ContractEvent, s as PresencePatch, t as AppendInput, u as RegisteredReducer } from "./reducer-CYPHsSmd-BQIfozGi.mjs";
2
- import { r as Event } from "./store-D0MhBvg6-4Z2L0Kqd.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/session-clear-D1PFe7xl.d.ts
1
+ import { a as PresenceDefs, c as PresenceSnapshot, d as WithPresence, i as EventDefs, l as Reducer, n as Contract, o as PresenceMap, r as ContractEvent, s as PresencePatch, t as AppendInput, u as RegisteredReducer } from "./reducer-CYPHsSmd-BXjGiptm.mjs";
2
+ import { r as Event } from "./store-DEzcHZOA-B-5vhxef.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/session-clear-vfonou9S.d.ts
4
4
  //#region src/session-clear.d.ts
5
5
  /** Reserved type of the marker a clear appends. */
6
6
  declare const CLEAR_EVENT_TYPE = "a2.cleared";
@@ -10,7 +10,7 @@ type SessionCleared = Event & {
10
10
  payload: null;
11
11
  };
12
12
  //#endregion
13
- //#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-qgez0Xny.d.ts
13
+ //#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-B9gu0qi1.d.ts
14
14
  //#region src/session-socket.d.ts
15
15
  /**
16
16
  * The structural socket `sessionsSocket` speaks against — satisfied
@@ -148,6 +148,12 @@ type SessionDispatch<D extends EventDefs> = (...events: AppendInput<D>[]) => Pro
148
148
  type SessionAppend<D extends EventDefs> = SessionDispatch<D> & {
149
149
  /** Commit, then hand pending work directly to configured scheduler. */
150
150
  dispatch: SessionDispatch<D>;
151
+ /**
152
+ * Append only while `index` is the session's head, checked in the same
153
+ * atomic step as the write. Otherwise nothing is written and it throws
154
+ * `LAST_INDEX_MISMATCH`, with the head as `details.index`.
155
+ */
156
+ ifLastIndex(index: number, ...events: AppendInput<D>[]): Promise<ContractEvent<D>[]>;
151
157
  };
152
158
  type ConsumerAppend<D extends EventDefs> = (name: string, ...events: AppendInput<D>[]) => Promise<ContractEvent<D>[]>;
153
159
  type ScheduleDelay = `${number}${"ms" | "s" | "m" | "h" | "d"}`;
@@ -1,5 +1,5 @@
1
- import { t as createBoard } from "./exports-BG-0Wyn-.mjs";
2
- import { t as http } from "./backend-http-Bmp0IgD3.mjs";
1
+ import { t as createBoard } from "./exports-CG0P8Qi4.mjs";
2
+ import { t as http } from "./backend-http-16SbvnAK.mjs";
3
3
  //#region src/server/index.ts
4
4
  /**
5
5
  * The handle on a board. With a `backend`, the board lives there: `a2()` keeps it in this
@@ -9,8 +9,8 @@ import { t as http } from "./backend-http-Bmp0IgD3.mjs";
9
9
  function board(options = {}) {
10
10
  return createBoard(options, {
11
11
  http: () => http(),
12
- sync: () => import("./engine-DQxXk7dX.mjs"),
13
- serving: () => import("./serving-B75Y4BF-.mjs")
12
+ sync: () => import("./engine-DkdkXQEy.mjs"),
13
+ serving: () => import("./serving-DKny38LK.mjs")
14
14
  });
15
15
  }
16
16
  //#endregion