@vercel/board 0.28.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 (139) hide show
  1. package/dist/{a2-B0_VlbtC.mjs → a2-D_28Pdip.mjs} +197 -259
  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-BLXVp4oZ.mjs → actors-xPiamLWk.mjs} +3 -3
  6. package/dist/{auth-lTkOgvcE.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 +3 -3
  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 +20 -7
  27. package/dist/backend-a2.mjs +2 -1
  28. package/dist/{backend-http-BvNFrvcY.mjs → backend-http-16SbvnAK.mjs} +2 -2
  29. package/dist/{backend-http-E7YU0qhn.d.mts → backend-http-3PoBYQoo.d.mts} +15 -3
  30. package/dist/{backend-http-CfLVYqmj.mjs → backend-http-BPaNYLWj.mjs} +4 -5
  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-ZKYTe3xa.d.mts → backend-n3hajfrD.d.mts} +12 -6
  36. package/dist/{backend-vercel-D87pIp2k.mjs → backend-vercel-C4Kee2-K.mjs} +260 -30
  37. package/dist/{backend-vercel-DTrDiSk5.mjs → backend-vercel-Kd8nvW5A.mjs} +3 -3
  38. package/dist/{backend-vercel-CIRObA0t.d.mts → backend-vercel-qznuDxnN.d.mts} +20 -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-B-9AvYis.d.mts → blob-CqILvdmr.d.mts} +2 -2
  44. package/dist/blob-DQK5prXT.mjs +182 -0
  45. package/dist/{chat-provider-DnHibqnM.mjs → chat-provider-COtsU5jB.mjs} +2 -2
  46. package/dist/{chat-provider-DsNEBQiA.d.mts → chat-provider-D6jVT4wS.d.mts} +5 -3
  47. package/dist/cli-commands.d.mts +1 -1
  48. package/dist/cli-commands.mjs +1 -1
  49. package/dist/cli-embedded.d.mts +2 -2
  50. package/dist/cli-embedded.mjs +1 -1
  51. package/dist/cli.mjs +5 -5
  52. package/dist/{client-xLxeDz0f.d.mts → client-CjAatpV4.d.mts} +67 -10
  53. package/dist/{commands-BFookFtn.mjs → commands-B5DHjZKK.mjs} +54 -10
  54. package/dist/{commands-D6gvrOh3.d.mts → commands-BtH69yqt.d.mts} +17 -0
  55. package/dist/{conformance-DlnfuzEB.mjs → conformance-C7fwIvmN.mjs} +258 -18
  56. package/dist/conformance.d.mts +1 -1
  57. package/dist/conformance.mjs +1 -1
  58. package/dist/{engine-Bfe6pcXb.mjs → engine-DkdkXQEy.mjs} +21 -13
  59. package/dist/{errors-CB4tnZGz.d.mts → errors-87TVtXeb.d.mts} +1 -1
  60. package/dist/{client-D0Px7KzF.mjs → errors-C_5rB8Iz.mjs} +104 -4
  61. package/dist/{events-CewD4kw7.mjs → events-qf5XG5VQ.mjs} +2 -2
  62. package/dist/{exports-CCzw2Vdw.mjs → exports-CG0P8Qi4.mjs} +59 -33
  63. package/dist/exports-CrGA5_yN.d.mts +5 -0
  64. package/dist/{external-BV_cUncs.mjs → external-D3p5T57R.mjs} +4 -2
  65. package/dist/{folds-jS9wlh9_.d.mts → folds-8wRRXjAt.d.mts} +4 -0
  66. package/dist/{folds-Dyjput8M.mjs → folds-DGYkMW19.mjs} +3 -2
  67. package/dist/{index-C05it0mC.d.mts → index-BygAXP7t.d.mts} +2 -2
  68. package/dist/index.d.mts +6 -6
  69. package/dist/{index.default-DmKxH_E6.mjs → index.default-DhkgpfR2.mjs} +1 -1
  70. package/dist/index.mjs +5 -6
  71. package/dist/index.node.d.mts +6 -6
  72. package/dist/index.node.mjs +3 -4
  73. package/dist/inspect/app.js +29 -29
  74. package/dist/inspect/engine.js +5 -5
  75. package/dist/{internal-CvsrprnU-CRY89I-b.mjs → internal-CvsrprnU-zZMpDiRY.mjs} +1 -1
  76. package/dist/{local-DhkrAqPP.mjs → local-C76Fy5ad.mjs} +1 -1
  77. package/dist/{main-eci7w-aP.mjs → main-D2s-QBOK.mjs} +76 -26
  78. package/dist/{middleware-ChKM1zuu.mjs → middleware-DlJQYiwV.mjs} +2 -2
  79. package/dist/{node-Zd_C-gxP.mjs → node-D8Rtg1su.mjs} +1 -1
  80. package/dist/{platform-B4TnJtWu-CwcTyKg2.mjs → platform-B4TnJtWu-Do3agKr5.mjs} +1 -1
  81. package/dist/{project-DMDST9kl.mjs → project-C_2xs57L.mjs} +1 -1
  82. package/dist/{provider-poIkXapd.mjs → provider-BaVmi4Hi.mjs} +3 -1
  83. package/dist/{provider-Cdg1qadh.d.mts → provider-Bm46LAdp.d.mts} +9 -2
  84. package/dist/{redis-tables-DN9PfIDi.mjs → redis-tables-BWJZHUGg.mjs} +41 -25
  85. package/dist/{reducer-CjmvZSAb-D_OSISmj.mjs → reducer-Bswr11ar-P324o9vn.mjs} +2 -2
  86. package/dist/{reducer-CYPHsSmd-BQIfozGi.d.mts → reducer-CYPHsSmd-BXjGiptm.d.mts} +1 -1
  87. package/dist/{reducers-BcmSs4qf.mjs → reducers-8jqLewgw.mjs} +5 -5
  88. package/dist/{retryable-lazy-DZWmHpii-Bye-W8q7.mjs → retryable-lazy-DZWmHpii-DpTc5PIP.mjs} +1 -1
  89. package/dist/{scheduler-task-X1SToDjP-BVoWuInI.mjs → scheduler-task-X1SToDjP-D2Il2rln.mjs} +1 -1
  90. package/dist/{schemas-Be08nyfW.mjs → schemas-DBmUO6pr.mjs} +2 -1
  91. package/dist/{serve-B09an9DQ.mjs → serve-lPoBDEds.mjs} +7 -6
  92. package/dist/{server-qgez0Xny-D5mLfqFQ.d.mts → server-B9gu0qi1-DI1WvcVK.d.mts} +10 -4
  93. package/dist/{server-DTX0prGr.mjs → server-D82a4uMe.mjs} +4 -4
  94. package/dist/{server-DtFrWxi3-Boa6gdWO.mjs → server-DX7mM6nm-D7N_7bug.mjs} +32 -23
  95. package/dist/{serving-CvOWEym2.mjs → serving-DKny38LK.mjs} +1 -1
  96. package/dist/{session-clear-wHd5GCpZ-BnKSxReK.mjs → session-clear-XJYpmUpg-2q8l_FJR.mjs} +14 -2
  97. package/dist/{sql-U9WTxrwJ.mjs → sql-Bj0fk6dn.mjs} +2 -2
  98. package/dist/{sqlite-db-Ds4majtT.mjs → sqlite-db-Dc8G78XV.mjs} +1 -1
  99. package/dist/{store-D0MhBvg6-4Z2L0Kqd.d.mts → store-DEzcHZOA-B-5vhxef.d.mts} +12 -2
  100. package/dist/store-N8PXxDAS-DWWgv-Vz.mjs +5 -0
  101. package/dist/{store-codec-DwrWlgQx-CYxGW0aD.mjs → store-codec-pAG2oPgQ-SqDXlPBR.mjs} +4 -4
  102. package/dist/store-memory-4IBl0Ztu.mjs +2 -0
  103. package/dist/{store-memory-Bas9Uq5C.mjs → store-memory-B0PkVSuQ.mjs} +14 -7
  104. package/dist/{store-polling-BZt2Rf3D-BiEM6_HB.mjs → store-polling-BZt2Rf3D-Div-bJ_D.mjs} +2 -2
  105. package/dist/{store-presence-polling-JuAy2Ck2-CYpuK75X.mjs → store-presence-polling-JuAy2Ck2-Dh-g_KYM.mjs} +3 -3
  106. package/dist/{store-sqlite-CxxPCcCT.mjs → store-sqlite-D85t3tE7.mjs} +14 -7
  107. package/dist/store-sqlite-iBTYYKBj.mjs +2 -0
  108. package/dist/{stream-buffer-DrTyiIuo-BKy-vI14.mjs → stream-buffer-DrTyiIuo-Be10yOBR.mjs} +2 -2
  109. package/dist/sync-github.d.mts +4 -2
  110. package/dist/sync-github.mjs +4 -14
  111. package/dist/sync-kapso.d.mts +3 -2
  112. package/dist/sync-kapso.mjs +3 -3
  113. package/dist/sync-linear.d.mts +12 -2
  114. package/dist/sync-linear.mjs +191 -9
  115. package/dist/sync-slack.d.mts +41 -5
  116. package/dist/sync-slack.mjs +70 -11
  117. package/dist/sync.chat.d.mts +1 -1
  118. package/dist/sync.chat.mjs +1 -1
  119. package/dist/sync.d.mts +2 -2
  120. package/dist/sync.mjs +3 -3
  121. package/dist/tags-BpFo6q0_.mjs +14 -0
  122. package/dist/{targets-C-wdR5wP.mjs → targets-Cgjs29T0.mjs} +1 -1
  123. package/dist/{tokens-BuCU-61R.mjs → tokens-C5_yGRlL.mjs} +2 -2
  124. package/dist/{types-aCAf6lGU.d.mts → types-shZmGZ-q.d.mts} +2 -2
  125. package/dist/{watchers-hash-7DJU9b-n.mjs → watchers-hash-B_5b0-ZG.mjs} +50 -19
  126. package/docs/01-board/04-messages.md +93 -0
  127. package/docs/01-board/08-middleware.md +5 -2
  128. package/docs/02-sync/03-slack.md +6 -2
  129. package/docs/02-sync/07-linear.md +28 -6
  130. package/docs/04-reference/01-cli.md +27 -12
  131. package/docs/04-reference/02-board.md +20 -5
  132. package/docs/04-reference/03-http.md +17 -6
  133. package/docs/04-reference/05-conformance.md +14 -3
  134. package/package.json +2 -2
  135. package/dist/errors-CusN4x2l.mjs +0 -88
  136. package/dist/exports-D22M68rk.d.mts +0 -5
  137. package/dist/store-N8PXxDAS-BWBgzBHp.mjs +0 -5
  138. package/dist/store-memory-ZLiZbH3R.mjs +0 -2
  139. package/dist/store-sqlite-BmwL3pUR.mjs +0 -2
@@ -0,0 +1,182 @@
1
+ import { n as DIRECT_UPLOAD_BYTES_MAX, t as ATTACHMENT_BYTES_MAX } from "./files-SniSmeEr.mjs";
2
+ import { i as Attachment } from "./schemas-DBmUO6pr.mjs";
3
+ import { r as badRequest, s as notFound, t as HttpError } from "./errors-C_5rB8Iz.mjs";
4
+ import { randomBytes } from "node:crypto";
5
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
6
+ import { dirname, join } from "node:path";
7
+ //#region src/server/blob.ts
8
+ /** Files in memory, for tests: forgets everything when the process ends. */
9
+ function memoryBlob() {
10
+ const files = /* @__PURE__ */ new Map();
11
+ return {
12
+ put: async (key, data, contentType) => void files.set(key, {
13
+ data: data.slice(),
14
+ contentType
15
+ }),
16
+ get: async (key) => files.get(key) ?? null
17
+ };
18
+ }
19
+ /** Files on disk, for development and `vb serve`: under `dir`, `.a2/attachments` by default. */
20
+ function fsBlob(dir = ".a2/attachments") {
21
+ const path = (key) => join(dir, ...key.split("/"));
22
+ return {
23
+ async put(key, data, contentType) {
24
+ await mkdir(dirname(path(key)), { recursive: true });
25
+ await writeFile(path(key), data);
26
+ await writeFile(`${path(key)}.type`, contentType);
27
+ },
28
+ async get(key) {
29
+ try {
30
+ const [data, contentType] = await Promise.all([readFile(path(key)), readFile(`${path(key)}.type`, "utf8")]);
31
+ return {
32
+ data: new Uint8Array(data),
33
+ contentType
34
+ };
35
+ } catch {
36
+ return null;
37
+ }
38
+ }
39
+ };
40
+ }
41
+ const dataKey = (id) => `board/attachments/${id}`;
42
+ /** A direct upload the board signed, until it's finished: what it's called, and who may finish it. */
43
+ const ticketKey = (id) => `board/uploads/${id}.json`;
44
+ const metaKey = (id) => `board/attachments/${id}.json`;
45
+ /** `shot.png`, as the board stores a name: no paths, no control characters. */
46
+ function fileName(name) {
47
+ return (name ?? "").split(/[\\/]/).pop().replace(/[\u0000-\u001f\u007f]/g, "").trim().slice(0, 255) || "file";
48
+ }
49
+ /** `image/png`, or `application/octet-stream` when the type isn't one. */
50
+ function mediaType(type) {
51
+ const value = (type ?? "").split(";")[0].trim().toLowerCase();
52
+ return /^[a-z0-9][a-z0-9!#$&^_.+-]*\/[a-z0-9][a-z0-9!#$&^_.+-]*$/.test(value) && value.length <= 255 ? value : "application/octet-stream";
53
+ }
54
+ /** A board without a blob store keeps no files: every file route says so. */
55
+ const noBlob = () => new HttpError(501, "no_files", "this board keeps no files: pass `blob` to `a2()`");
56
+ /** 128 random bits, base64url, drawn again when they'd start with `-`, which a command line reads as a flag. */
57
+ function attachmentId() {
58
+ for (;;) {
59
+ const id = randomBytes(16).toString("base64url");
60
+ if (!id.startsWith("-")) return id;
61
+ }
62
+ }
63
+ /**
64
+ * Stores an upload under a fresh ID, with its metadata beside it. `uploadedBy`
65
+ * is the principal that sent it, who can read it before any message carries it.
66
+ * `max` is the most it can be: `ATTACHMENT_BYTES_MAX` unless the board's own sync imports it.
67
+ */
68
+ async function writeUpload(blob, input, max = ATTACHMENT_BYTES_MAX) {
69
+ if (!blob) throw noBlob();
70
+ if (input.data.byteLength === 0) throw badRequest("the file is empty");
71
+ if (input.data.byteLength > max) throw new HttpError(413, "too_large", `attachments are at most ${max / 1024 / 1024} MB`);
72
+ const attachment = {
73
+ id: attachmentId(),
74
+ name: fileName(input.name),
75
+ type: mediaType(input.type),
76
+ size: input.data.byteLength
77
+ };
78
+ await blob.put(dataKey(attachment.id), input.data, attachment.type);
79
+ const meta = input.uploadedBy === void 0 ? attachment : {
80
+ ...attachment,
81
+ uploadedBy: input.uploadedBy
82
+ };
83
+ await blob.put(metaKey(attachment.id), new TextEncoder().encode(JSON.stringify(meta)), "application/json");
84
+ return attachment;
85
+ }
86
+ async function bytes(data) {
87
+ return data instanceof Uint8Array ? data : new Uint8Array(await new Response(data).arrayBuffer());
88
+ }
89
+ const attachmentNotFound = (id) => notFound(`no attachment: ${id}`, "attachment_not_found");
90
+ /**
91
+ * An upload's metadata, as the board recorded it, never what a request says,
92
+ * and who uploaded it: null for files the board imported itself, or stored
93
+ * before it recorded that.
94
+ */
95
+ async function readUpload(blob, id) {
96
+ if (!blob) throw noBlob();
97
+ const found = Attachment.shape.id.safeParse(id).success ? await blob.get(metaKey(id)) : null;
98
+ if (!found) throw attachmentNotFound(id);
99
+ const meta = JSON.parse(new TextDecoder().decode(await bytes(found.data)));
100
+ return {
101
+ attachment: Attachment.parse(meta),
102
+ uploadedBy: typeof meta.uploadedBy === "string" ? meta.uploadedBy : null
103
+ };
104
+ }
105
+ /** An attachment's bytes as the store keeps them, a stream or the bytes, for board() to serve. */
106
+ async function attachmentBody(blob, id) {
107
+ if (!blob) throw noBlob();
108
+ const found = await blob.get(dataKey(id));
109
+ if (!found) throw attachmentNotFound(id);
110
+ return found.data;
111
+ }
112
+ /** How long a direct upload's URL takes bytes: long enough for 100 MB on a slow link. */
113
+ const DIRECT_UPLOAD_TTL_MS = 18e5;
114
+ const noDirectUploads = () => new HttpError(501, "no_direct_uploads", `this board's blob store can't take direct uploads, so files are at most ${ATTACHMENT_BYTES_MAX / 1024 / 1024} MB`);
115
+ /**
116
+ * Starts a direct upload: a fresh ID, and a URL in the store to `PUT` its bytes to. The board
117
+ * keeps what the request said the file is until `finishUpload` checks the store has it.
118
+ */
119
+ async function startUpload(blob, input) {
120
+ if (!blob) throw noBlob();
121
+ if (!blob.uploadUrl || !blob.head) throw noDirectUploads();
122
+ if (input.size > 104857600) throw new HttpError(413, "too_large", `direct uploads are at most ${DIRECT_UPLOAD_BYTES_MAX / 1024 / 1024} MB`);
123
+ const expires = new Date(Date.now() + DIRECT_UPLOAD_TTL_MS);
124
+ const ticket = {
125
+ id: attachmentId(),
126
+ name: fileName(input.name),
127
+ type: mediaType(input.type),
128
+ size: input.size,
129
+ uploadedBy: input.uploadedBy,
130
+ expiresAt: expires.toISOString()
131
+ };
132
+ await blob.put(ticketKey(ticket.id), new TextEncoder().encode(JSON.stringify(ticket)), "application/json");
133
+ const { url, headers } = await blob.uploadUrl(dataKey(ticket.id), {
134
+ contentType: ticket.type,
135
+ maxBytes: ticket.size,
136
+ expiresAt: expires
137
+ });
138
+ return {
139
+ id: ticket.id,
140
+ url,
141
+ headers: {
142
+ ...headers,
143
+ "content-type": ticket.type
144
+ },
145
+ expiresAt: ticket.expiresAt
146
+ };
147
+ }
148
+ /**
149
+ * Finishes a direct upload: once the store has exactly the bytes its start said, the board records
150
+ * the attachment, as `writeUpload` does. Only its uploader may finish it; a second finish answers
151
+ * the same attachment. It never reads the record before writing it: a store with a cache (Vercel
152
+ * Blob's CDN) would keep that miss, and the post that names the file would find nothing.
153
+ */
154
+ async function finishUpload(blob, id, principal) {
155
+ if (!blob) throw noBlob();
156
+ const found = Attachment.shape.id.safeParse(id).success ? await blob.get(ticketKey(id)) : null;
157
+ const ticket = found ? JSON.parse(new TextDecoder().decode(await bytes(found.data))) : null;
158
+ if (!ticket || ticket.uploadedBy !== principal) throw notFound(`no upload: ${id}`, "upload_not_found");
159
+ if (!blob.head) throw noDirectUploads();
160
+ const stored = await blob.head(dataKey(id));
161
+ if (!stored) throw new HttpError(409, "not_uploaded", `nothing's been uploaded for ${id} yet: PUT the file to its URL first`);
162
+ if (stored.size !== ticket.size) throw badRequest(`the store has ${stored.size} bytes for ${id}, but its upload said ${ticket.size}`, "size_mismatch");
163
+ const attachment = {
164
+ id,
165
+ name: ticket.name,
166
+ type: ticket.type,
167
+ size: stored.size
168
+ };
169
+ try {
170
+ await blob.put(metaKey(id), new TextEncoder().encode(JSON.stringify({
171
+ ...attachment,
172
+ uploadedBy: principal
173
+ })), "application/json");
174
+ } catch (error) {
175
+ const done = await blob.get(metaKey(id)).catch(() => null);
176
+ if (!done) throw error;
177
+ return Attachment.parse(JSON.parse(new TextDecoder().decode(await bytes(done.data))));
178
+ }
179
+ return attachment;
180
+ }
181
+ //#endregion
182
+ export { fsBlob as a, readUpload as c, finishUpload as i, startUpload as l, attachmentNotFound as n, mediaType as o, fileName as r, memoryBlob as s, attachmentBody as t, writeUpload as u };
@@ -1,5 +1,5 @@
1
- import "./external-BV_cUncs.mjs";
2
- import { n as ResolvedTarget, r as SyncProvider } from "./provider-poIkXapd.mjs";
1
+ import "./external-D3p5T57R.mjs";
2
+ import { n as ResolvedTarget, r as SyncProvider } from "./provider-BaVmi4Hi.mjs";
3
3
  import { n as userTokensOf } from "./users-yryHKFMo.mjs";
4
4
  import { AsyncLocalStorage } from "node:async_hooks";
5
5
  import { Chat, stringifyMarkdown } from "chat";
@@ -1,6 +1,6 @@
1
- import { d as ExternalFile, f as ExternalLink, l as ExternalAuthor, t as Actor } from "./folds-jS9wlh9_.mjs";
2
- import { dt as SourceJoin, mt as SourceRead } from "./client-xLxeDz0f.mjs";
3
- import { M as SyncRoot, O as ProviderEvent, a as ProviderOptions, c as ReceivedEvent, d as ResolvedTarget, i as ProviderFile, n as FileDelivery, o as ProviderPost, p as SyncProvider, r as ProviderDelivery, s as Receive, t as FetchedLink, y as SyncFn } from "./provider-Cdg1qadh.mjs";
1
+ import { d as ExternalFile, f as ExternalLink, l as ExternalAuthor, t as Actor } from "./folds-8wRRXjAt.mjs";
2
+ import { ft as SourceJoin, ht as SourceRead } from "./client-CjAatpV4.mjs";
3
+ import { M as SyncRoot, O as ProviderEvent, a as ProviderOptions, c as ReceivedEvent, d as ResolvedTarget, i as ProviderFile, n as FileDelivery, o as ProviderPost, p as SyncProvider, r as ProviderDelivery, s as Receive, t as FetchedLink, y as SyncFn } from "./provider-Bm46LAdp.mjs";
4
4
  import { Adapter, Author, FileUpload, Message, ReactionEvent } from "chat";
5
5
  //#region src/sync/types.d.ts
6
6
  declare function externalAuthor(platform: string, author: Author): ExternalAuthor;
@@ -45,6 +45,7 @@ type ChatTransport = Omit<ProviderOptions, 'uploadsFiles'> & {
45
45
  /** A channel or thread, read on demand without syncing it. */
46
46
  read?(target: string, options: {
47
47
  limit: number;
48
+ after: string | null;
48
49
  }): Promise<SourceRead>;
49
50
  /** Adds the app to a channel so `read` can read it. */
50
51
  join?(target: string): Promise<SourceJoin>;
@@ -126,6 +127,7 @@ declare abstract class ChatSyncProvider<E extends ProviderEvent = ProviderEvent>
126
127
  url(thread: string, message: string): Promise<string | null>;
127
128
  read(target: string, options: {
128
129
  limit: number;
130
+ after: string | null;
129
131
  }): Promise<SourceRead>;
130
132
  join(target: string): Promise<SourceJoin>;
131
133
  fetchFile(file: ExternalFile): Promise<Uint8Array | null>;
@@ -1,2 +1,2 @@
1
- import { a as OptionName, c as globalOptions, d as options, f as usage, i as CliOption, l as groups, n as CliCommand, o as commands, r as CliExample, s as filters, t as CliArgument, u as option } from "./commands-D6gvrOh3.mjs";
1
+ import { a as OptionName, c as globalOptions, d as options, f as usage, i as CliOption, l as groups, n as CliCommand, o as commands, r as CliExample, s as filters, t as CliArgument, u as option } from "./commands-BtH69yqt.mjs";
2
2
  export { CliArgument, CliCommand, CliExample, CliOption, OptionName, commands, filters, globalOptions, groups, option, options, usage };
@@ -1,2 +1,2 @@
1
- import { a as option, i as groups, n as filters, o as options, r as globalOptions, s as usage, t as commands } from "./commands-BFookFtn.mjs";
1
+ import { a as option, i as groups, n as filters, o as options, r as globalOptions, s as usage, t as commands } from "./commands-B5DHjZKK.mjs";
2
2
  export { commands, filters, globalOptions, groups, option, options, usage };
@@ -1,5 +1,5 @@
1
- import { d as Board } from "./backend-ZKYTe3xa.mjs";
2
- import "./index-C05it0mC.mjs";
1
+ import { d as Board } from "./backend-n3hajfrD.mjs";
2
+ import "./index-BygAXP7t.mjs";
3
3
  //#region src/cli/failure.d.ts
4
4
  /**
5
5
  * What kind of failure it is, which fixes the exit code: 2 for `usage` and `missing_input`, 130
@@ -1,4 +1,4 @@
1
- import { a as commandLine, c as failureLines, i as mainWith, l as formatFailure, n as commandWord, o as exitCode, r as main, s as failureDocument, t as Failed } from "./main-eci7w-aP.mjs";
1
+ import { a as commandLine, c as failureLines, i as mainWith, l as formatFailure, n as commandWord, o as exitCode, r as main, s as failureDocument, t as Failed } from "./main-D2s-QBOK.mjs";
2
2
  //#region src/cli/embedded.ts
3
3
  /**
4
4
  * Board's CLI as `appName` names it in help, usage, and errors (`vercel board`). With no board
package/dist/cli.mjs CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { t as ATTACHMENT_BYTES_MAX } from "./files-SniSmeEr.mjs";
3
- import "./schemas-Be08nyfW.mjs";
4
- import { a as option } from "./commands-BFookFtn.mjs";
5
- import { l as projectDir } from "./node-Zd_C-gxP.mjs";
6
- import { r as main, u as who } from "./main-eci7w-aP.mjs";
3
+ import "./schemas-DBmUO6pr.mjs";
4
+ import { a as option } from "./commands-B5DHjZKK.mjs";
5
+ import { l as projectDir } from "./node-D8Rtg1su.mjs";
6
+ import { r as main, u as who } from "./main-D2s-QBOK.mjs";
7
7
  import { randomBytes, timingSafeEqual } from "node:crypto";
8
8
  import { appendFile, readFile } from "node:fs/promises";
9
9
  import { join } from "node:path";
@@ -661,7 +661,7 @@ const local = {
661
661
  if (args.length > 0) throw usage("serve takes no arguments: pass its port with --port, and its directory with --dir.");
662
662
  const port = portFlag();
663
663
  const root = projectDir();
664
- const { localHandle, serveLocal } = await import("./serve-B09an9DQ.mjs");
664
+ const { localHandle, serveLocal } = await import("./serve-lPoBDEds.mjs");
665
665
  const handle = flags.handle ?? process.env.BOARD_HANDLE;
666
666
  const local = await serveLocal({
667
667
  dir: flags.dir ?? join(root, ".board"),
@@ -1,10 +1,11 @@
1
1
  import { n as AccessSummary } from "./access-CV96SYgr.mjs";
2
- import { a as ExternalCopy, g as BoardEvent, o as Message, p as Link, r as Channel, t as Actor, u as ExternalEvent, x as Attachment } from "./folds-jS9wlh9_.mjs";
2
+ import { a as ExternalCopy, g as BoardEvent, o as Message, p as Link, r as Channel, t as Actor, u as ExternalEvent, x as Attachment } from "./folds-8wRRXjAt.mjs";
3
3
  import { z } from "zod";
4
4
  //#region src/api/routes.d.ts
5
5
  /**
6
6
  * A message's, schedule's, or cursor's ID: a string clients pass back as they got it, and never
7
- * parse, compare, or count with. Each backend picks its own; a board on `a2()` writes decimals.
7
+ * parse, compare, or count with. Each backend picks its own; a board on `a2()` writes decimals,
8
+ * and `s12` for a schedule.
8
9
  */
9
10
  declare const Ref: z.ZodString;
10
11
  /** A sync target as the board that syncs it resolved it: a platform channel to start a thread in, or a thread to join. */
@@ -78,6 +79,7 @@ declare const PostBody: z.ZodObject<{
78
79
  }, z.core.$strip>]>>>;
79
80
  id: z.ZodOptional<z.ZodString>;
80
81
  attachments: z.ZodOptional<z.ZodArray<z.ZodString>>;
82
+ after: z.ZodOptional<z.ZodString>;
81
83
  }, z.core.$strip>;
82
84
  /**
83
85
  * A message to post later, as the caller: once (`in` or `at`), or repeating
@@ -171,6 +173,7 @@ declare const AckBody: z.ZodObject<{
171
173
  declare const SourceReadQuery: z.ZodObject<{
172
174
  target: z.ZodString;
173
175
  limit: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
176
+ after: z.ZodOptional<z.ZodString>;
174
177
  }, z.core.$strip>;
175
178
  /** A channel to add the board's app to, so it can be read on demand: `#name`, an ID, or a link into it. */
176
179
  declare const SourceJoinBody: z.ZodObject<{
@@ -231,6 +234,7 @@ declare const SyncImportBody: z.ZodDiscriminatedUnion<[z.ZodObject<{
231
234
  message: z.ZodNullable<z.ZodString>;
232
235
  }, z.core.$strip>>>;
233
236
  id: z.ZodOptional<z.ZodString>;
237
+ after: z.ZodOptional<z.ZodString>;
234
238
  }, z.core.$strip>, z.ZodObject<{
235
239
  author: z.ZodObject<{
236
240
  id: z.ZodString;
@@ -252,6 +256,7 @@ declare const SyncImportBody: z.ZodDiscriminatedUnion<[z.ZodObject<{
252
256
  channel: z.ZodString;
253
257
  thread: z.ZodString;
254
258
  }, z.core.$strip>>;
259
+ revision: z.ZodOptional<z.ZodNumber>;
255
260
  }, z.core.$strip>, z.ZodObject<{
256
261
  author: z.ZodObject<{
257
262
  id: z.ZodString;
@@ -267,6 +272,7 @@ declare const SyncImportBody: z.ZodDiscriminatedUnion<[z.ZodObject<{
267
272
  }, z.core.$strip>>;
268
273
  message: z.ZodOptional<z.ZodString>;
269
274
  op: z.ZodLiteral<"delete">;
275
+ revision: z.ZodOptional<z.ZodNumber>;
270
276
  }, z.core.$strip>, z.ZodObject<{
271
277
  author: z.ZodObject<{
272
278
  id: z.ZodString;
@@ -301,6 +307,7 @@ declare const SyncImportBody: z.ZodDiscriminatedUnion<[z.ZodObject<{
301
307
  op: z.ZodLiteral<"labels">;
302
308
  set: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
303
309
  unset: z.ZodOptional<z.ZodArray<z.ZodString>>;
310
+ if: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNullable<z.ZodString>>>;
304
311
  }, z.core.$strip>, z.ZodObject<{
305
312
  author: z.ZodObject<{
306
313
  id: z.ZodString;
@@ -495,6 +502,7 @@ declare const InboxPushBody: z.ZodObject<{
495
502
  type: z.ZodString;
496
503
  title: z.ZodString;
497
504
  url: z.ZodNullable<z.ZodString>;
505
+ body: z.ZodOptional<z.ZodNullable<z.ZodString>>;
498
506
  labels: z.ZodRecord<z.ZodString, z.ZodString>;
499
507
  unset: z.ZodArray<z.ZodString>;
500
508
  owns: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -551,11 +559,15 @@ declare const SignInQuery: z.ZodObject<{
551
559
  declare const SyncUnlinkBody: z.ZodObject<{
552
560
  account: z.ZodString;
553
561
  }, z.core.$strip>;
554
- /** A direct upload, before its bytes: what the file will be called, its type, and its exact size. */
562
+ /**
563
+ * A direct upload, before its bytes: what the file will be called, its type, its exact size, and
564
+ * the SHA-256 of its bytes, in base64, for a store that signs its URL for them (Vercel's).
565
+ */
555
566
  declare const UploadStartBody: z.ZodObject<{
556
567
  name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
557
568
  type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
558
569
  size: z.ZodNumber;
570
+ sha256: z.ZodOptional<z.ZodString>;
559
571
  }, z.core.$strip>;
560
572
  /** Where to send a direct upload's bytes: `PUT` the file to `url` with `headers` (its `content-type` included), before `expiresAt`, then finish it. */
561
573
  type UploadTicket = {
@@ -566,8 +578,11 @@ type UploadTicket = {
566
578
  };
567
579
  declare const EditBody: z.ZodObject<{
568
580
  text: z.ZodString;
581
+ revision: z.ZodOptional<z.ZodNumber>;
569
582
  }, z.core.$strip>;
570
- declare const DeleteBody: z.ZodOptional<z.ZodObject<{}, z.core.$strip>>;
583
+ declare const DeleteBody: z.ZodOptional<z.ZodObject<{
584
+ revision: z.ZodOptional<z.ZodNumber>;
585
+ }, z.core.$strip>>;
571
586
  /** `status`: what Slack shows in place of "Typing…" (WhatsApp and GitHub ignore it). */
572
587
  declare const TypingBody: z.ZodOptional<z.ZodObject<{
573
588
  status: z.ZodOptional<z.ZodString>;
@@ -576,9 +591,12 @@ declare const ReactBody: z.ZodObject<{
576
591
  emoji: z.ZodString;
577
592
  remove: z.ZodOptional<z.ZodBoolean>;
578
593
  }, z.core.$strip>;
594
+ /** At most this many labels in a label write's `if`. */
595
+ declare const LABEL_CONDITIONS_MAX = 16;
579
596
  declare const LabelBody: z.ZodObject<{
580
597
  set: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
581
598
  unset: z.ZodOptional<z.ZodArray<z.ZodString>>;
599
+ if: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNullable<z.ZodString>>>;
582
600
  }, z.core.$strip>;
583
601
  type FiltersInput = z.input<typeof Filters$1>;
584
602
  type SyncImportInput = z.input<typeof SyncImportBody>;
@@ -653,7 +671,7 @@ type ActorView = Pick<Actor, 'kind' | 'handle' | 'name' | 'avatar'> & {
653
671
  person?: PersonView;
654
672
  };
655
673
  /** A message as clients see it: its IDs are refs, and `version` says which of two views of it is newer. */
656
- type MessageView = Omit<Message, 'id' | 're' | 'replyTo' | 'links' | 'schedule' | 'version'> & {
674
+ type MessageView = Omit<Message, 'id' | 're' | 'replyTo' | 'links' | 'schedule' | 'version' | 'revision'> & {
657
675
  id: string;
658
676
  /** The thread's root, or null for a root. */
659
677
  re: string | null;
@@ -661,6 +679,11 @@ type MessageView = Omit<Message, 'id' | 're' | 'replyTo' | 'links' | 'schedule'
661
679
  replyTo: string | null;
662
680
  /** Grows with each change to this message: of two views of it, the one with the higher version is newer. */
663
681
  version: number;
682
+ /**
683
+ * Changes with each edit and delete, and only then: what an edit or a delete passes as `revision`
684
+ * to change it only if no one has since.
685
+ */
686
+ revision: number;
664
687
  links: LinkView[];
665
688
  /** Set when a schedule posted it: the schedule's ID and which send this was, from 0. */
666
689
  schedule?: {
@@ -911,6 +934,8 @@ type SourceRead = {
911
934
  messages: SourceMessage[];
912
935
  /** The platform has more than `limit`: older messages in a channel, later replies in a thread. */
913
936
  more: boolean;
937
+ /** Where to pick up, as `after`, when the platform can page past `limit`. */
938
+ next?: string | null;
914
939
  };
915
940
  /** A channel the board's app joined, or was already in (`joined: false`). */
916
941
  type SourceJoin = {
@@ -1012,6 +1037,7 @@ declare const routes: {
1012
1037
  }, z.core.$strip>]>>>;
1013
1038
  id: z.ZodOptional<z.ZodString>;
1014
1039
  attachments: z.ZodOptional<z.ZodArray<z.ZodString>>;
1040
+ after: z.ZodOptional<z.ZodString>;
1015
1041
  }, z.core.$strip>;
1016
1042
  };
1017
1043
  readonly edit: {
@@ -1019,12 +1045,15 @@ declare const routes: {
1019
1045
  readonly path: '/messages/:id/edit';
1020
1046
  readonly body: z.ZodObject<{
1021
1047
  text: z.ZodString;
1048
+ revision: z.ZodOptional<z.ZodNumber>;
1022
1049
  }, z.core.$strip>;
1023
1050
  };
1024
1051
  readonly delete: {
1025
1052
  readonly method: 'POST';
1026
1053
  readonly path: '/messages/:id/delete';
1027
- readonly body: z.ZodOptional<z.ZodObject<{}, z.core.$strip>>;
1054
+ readonly body: z.ZodOptional<z.ZodObject<{
1055
+ revision: z.ZodOptional<z.ZodNumber>;
1056
+ }, z.core.$strip>>;
1028
1057
  };
1029
1058
  readonly react: {
1030
1059
  readonly method: 'POST';
@@ -1040,6 +1069,7 @@ declare const routes: {
1040
1069
  readonly body: z.ZodObject<{
1041
1070
  set: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1042
1071
  unset: z.ZodOptional<z.ZodArray<z.ZodString>>;
1072
+ if: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNullable<z.ZodString>>>;
1043
1073
  }, z.core.$strip>;
1044
1074
  };
1045
1075
  /** Attaches the thread to a sync target, recording a `thread` receipt: needs `sync` where the thread is. */
@@ -1226,6 +1256,7 @@ declare const routes: {
1226
1256
  type: z.ZodString;
1227
1257
  title: z.ZodString;
1228
1258
  url: z.ZodNullable<z.ZodString>;
1259
+ body: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1229
1260
  labels: z.ZodRecord<z.ZodString, z.ZodString>;
1230
1261
  unset: z.ZodArray<z.ZodString>;
1231
1262
  owns: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -1308,6 +1339,7 @@ declare const routes: {
1308
1339
  message: z.ZodNullable<z.ZodString>;
1309
1340
  }, z.core.$strip>>>;
1310
1341
  id: z.ZodOptional<z.ZodString>;
1342
+ after: z.ZodOptional<z.ZodString>;
1311
1343
  }, z.core.$strip>, z.ZodObject<{
1312
1344
  author: z.ZodObject<{
1313
1345
  id: z.ZodString;
@@ -1329,6 +1361,7 @@ declare const routes: {
1329
1361
  channel: z.ZodString;
1330
1362
  thread: z.ZodString;
1331
1363
  }, z.core.$strip>>;
1364
+ revision: z.ZodOptional<z.ZodNumber>;
1332
1365
  }, z.core.$strip>, z.ZodObject<{
1333
1366
  author: z.ZodObject<{
1334
1367
  id: z.ZodString;
@@ -1344,6 +1377,7 @@ declare const routes: {
1344
1377
  }, z.core.$strip>>;
1345
1378
  message: z.ZodOptional<z.ZodString>;
1346
1379
  op: z.ZodLiteral<"delete">;
1380
+ revision: z.ZodOptional<z.ZodNumber>;
1347
1381
  }, z.core.$strip>, z.ZodObject<{
1348
1382
  author: z.ZodObject<{
1349
1383
  id: z.ZodString;
@@ -1378,6 +1412,7 @@ declare const routes: {
1378
1412
  op: z.ZodLiteral<"labels">;
1379
1413
  set: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1380
1414
  unset: z.ZodOptional<z.ZodArray<z.ZodString>>;
1415
+ if: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNullable<z.ZodString>>>;
1381
1416
  }, z.core.$strip>, z.ZodObject<{
1382
1417
  author: z.ZodObject<{
1383
1418
  id: z.ZodString;
@@ -1535,6 +1570,7 @@ declare const routes: {
1535
1570
  readonly query: z.ZodObject<{
1536
1571
  target: z.ZodString;
1537
1572
  limit: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
1573
+ after: z.ZodOptional<z.ZodString>;
1538
1574
  }, z.core.$strip>;
1539
1575
  };
1540
1576
  /** Adds the app to a public channel so it can be read, where that sync runs and opted in with `join`. Full access only. */
@@ -1586,6 +1622,7 @@ declare const routes: {
1586
1622
  name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1587
1623
  type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1588
1624
  size: z.ZodNumber;
1625
+ sha256: z.ZodOptional<z.ZodString>;
1589
1626
  }, z.core.$strip>;
1590
1627
  };
1591
1628
  /** After the `PUT`: the board checks what landed in the store and records the attachment. */
@@ -1760,7 +1797,13 @@ type PostOptions = {
1760
1797
  /** Files from `upload`, or their IDs. */
1761
1798
  attachments?: (Attachment | string)[];
1762
1799
  };
1763
- type ReplyOptions = Omit<PostOptions, 'sync'>;
1800
+ type ReplyOptions = Omit<PostOptions, 'sync'> & {
1801
+ /**
1802
+ * Posts only while this is the thread's newest message: the ID of the last one you read. If
1803
+ * another has come after it, nothing is posted, and it throws a 409 `newer_message`.
1804
+ */
1805
+ after?: string;
1806
+ };
1764
1807
  /**
1765
1808
  * When a scheduled message goes out: once `in` a while or `at` a time, or
1766
1809
  * `every` so often (first at `at`, `in`, or one `every` from now), stopping
@@ -1859,11 +1902,19 @@ declare function createBoardClient(options: ClientOptions): {
1859
1902
  download: (id: string, opts?: {
1860
1903
  signal?: AbortSignal;
1861
1904
  }) => Promise<Response>;
1862
- edit: (id: string, text: string) => Promise<{
1905
+ /**
1906
+ * `revision` is the message's as you read it: if it's been edited or deleted since, nothing
1907
+ * changes, and it throws a 409 `revision_conflict`.
1908
+ */
1909
+ edit: (id: string, text: string, opts?: {
1910
+ revision?: number;
1911
+ }) => Promise<{
1863
1912
  ok: true;
1864
1913
  unknownMentions?: string[];
1865
1914
  }>;
1866
- delete: (id: string) => Promise<{
1915
+ delete: (id: string, opts?: {
1916
+ revision?: number;
1917
+ }) => Promise<{
1867
1918
  ok: true;
1868
1919
  }>;
1869
1920
  /** `emoji` is a short name, `:name:`, or the character itself. */
@@ -1872,9 +1923,14 @@ declare function createBoardClient(options: ClientOptions): {
1872
1923
  }) => Promise<{
1873
1924
  ok: true;
1874
1925
  }>;
1926
+ /**
1927
+ * `if` is what the labels must be now, a value or null for one that mustn't be set: if one
1928
+ * isn't, nothing changes, and it throws a 409 `label_conflict`.
1929
+ */
1875
1930
  label: (id: string, change: {
1876
1931
  set?: Record<string, string>;
1877
1932
  unset?: string[];
1933
+ if?: Record<string, string | null>;
1878
1934
  }) => Promise<{
1879
1935
  ok: true;
1880
1936
  }>;
@@ -1930,6 +1986,7 @@ declare function createBoardClient(options: ClientOptions): {
1930
1986
  */
1931
1987
  readSource: (key: string, target: string, opts?: {
1932
1988
  limit?: number;
1989
+ after?: string;
1933
1990
  }) => Promise<SourceRead>;
1934
1991
  /** Adds the app to a public channel so `readSource` can read it, where the sync opted in with `join`. Full access only. */
1935
1992
  joinSource: (key: string, target: string) => Promise<SourceJoin>;
@@ -2002,4 +2059,4 @@ declare function createBoardClient(options: ClientOptions): {
2002
2059
  }, opts?: WaitOptions): Promise<BoardEventView | null>;
2003
2060
  };
2004
2061
  //#endregion
2005
- export { RegisterInput as $, InboxItem as A, SyncRootsQuery as At, Me as B, TypingResult as Bt, EventsQuery as C, SyncFindInput as Ct, IdentityView as D, SyncImportInput as Dt, IdentityUnlinkBody as E, SyncImportBody as Et, LinkView as F, ThreadView as Ft, ParsedFilters as G, MessagesPage as H, UploadTicket as Ht, LinkedAccount as I, ThreadsPage as It, PostInput as J, PersonView as K, LinkedQuery as L, ThreadsQuery as Lt, InboxPushBody as M, SyncUnlinkBody as Mt, InboxQuery as N, SyncedView as Nt, InboxAckBody as O, SyncReceiptBody as Ot, LabelBody as P, ThreadSummaryView as Pt, RegisterBody as Q, MatchView as R, ThreadsQueryInput as Rt, EventsPage as S, SyncCopiesView as St, FiltersInput as T, SyncFindView as Tt, MessagesQuery as U, routes as Ut, MessageView as V, UploadStartBody as Vt, MessagesQueryInput as W, ReactBody as X, REGISTERED_WATCHERS_MAX as Y, Ref as Z, BoardEventView as _, SyncAccountInput as _t, PostOptions as a, ScheduleInput as at, Discovery as b, SyncCodeView as bt, ScheduleOptions as c, SchedulesQueryInput as ct, WaitOptions as d, SourceJoin as dt, RegistrationView as et, Written as f, SourceJoinBody as ft, ApiError as g, SyncAccountBody as gt, ActorView as h, SourceReadQuery as ht, Filters as i, ScheduleBodyOutput as it, InboxNextQuery as j, SyncThreadView as jt, InboxEntry as k, SyncReceiptInput as kt, ScheduleTiming as l, SchedulesQueryOutput as lt, AckBody as m, SourceRead as mt, BoardError as n, RouteName as nt, ProfileOption as o, ScheduleView as ot, duration as p, SourceMessage as pt, PostBody as q, ErrorOrigin as r, ScheduleBody as rt, ReplyOptions as s, SchedulesQuery as st, BoardClient as t, ResolvedSyncTarget as tt, UploadInput as u, SignInQuery as ut, ChannelView as v, SyncBody as vt, EventsQueryInput as w, SyncFindQuery as wt, EditBody as x, SyncCopiesQuery as xt, DeleteBody as y, SyncCodeBody as yt, MatchesQuery as z, TypingBody as zt };
2062
+ export { RegisterBody as $, InboxItem as A, SyncReceiptInput as At, MatchesQuery as B, TypingBody as Bt, EventsQuery as C, SyncCopiesView as Ct, IdentityView as D, SyncImportBody as Dt, IdentityUnlinkBody as E, SyncFindView as Et, LabelBody as F, ThreadSummaryView as Ft, MessagesQueryInput as G, MessageView as H, UploadStartBody as Ht, LinkView as I, ThreadView as It, PostBody as J, ParsedFilters as K, LinkedAccount as L, ThreadsPage as Lt, InboxPushBody as M, SyncThreadView as Mt, InboxQuery as N, SyncUnlinkBody as Nt, InboxAckBody as O, SyncImportInput as Ot, LABEL_CONDITIONS_MAX as P, SyncedView as Pt, Ref as Q, LinkedQuery as R, ThreadsQuery as Rt, EventsPage as S, SyncCopiesQuery as St, FiltersInput as T, SyncFindQuery as Tt, MessagesPage as U, UploadTicket as Ut, Me as V, TypingResult as Vt, MessagesQuery as W, routes as Wt, REGISTERED_WATCHERS_MAX as X, PostInput as Y, ReactBody as Z, BoardEventView as _, SyncAccountBody as _t, PostOptions as a, ScheduleBodyOutput as at, Discovery as b, SyncCodeBody as bt, ScheduleOptions as c, SchedulesQuery as ct, WaitOptions as d, SignInQuery as dt, RegisterInput as et, Written as f, SourceJoin as ft, ApiError as g, SourceReadQuery as gt, ActorView as h, SourceRead as ht, Filters as i, ScheduleBody as it, InboxNextQuery as j, SyncRootsQuery as jt, InboxEntry as k, SyncReceiptBody as kt, ScheduleTiming as l, SchedulesQueryInput as lt, AckBody as m, SourceMessage as mt, BoardError as n, ResolvedSyncTarget as nt, ProfileOption as o, ScheduleInput as ot, duration as p, SourceJoinBody as pt, PersonView as q, ErrorOrigin as r, RouteName as rt, ReplyOptions as s, ScheduleView as st, BoardClient as t, RegistrationView as tt, UploadInput as u, SchedulesQueryOutput as ut, ChannelView as v, SyncAccountInput as vt, EventsQueryInput as w, SyncFindInput as wt, EditBody as x, SyncCodeView as xt, DeleteBody as y, SyncBody as yt, MatchView as z, ThreadsQueryInput as zt };