@vercel/board 0.29.0 → 0.31.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.
- package/README.md +8 -17
- package/dist/{a2-HUbQJ0RD.mjs → a2-DngWY2Eb.mjs} +741 -415
- package/dist/access-CY5xVMIK.mjs +242 -0
- package/dist/{access-CV96SYgr.d.mts → access-DPcrKIH_.d.mts} +6 -1
- package/dist/access.d.mts +4 -4
- package/dist/access.mjs +5 -4
- package/dist/{actors-DcJhFbwJ.mjs → actors-Bm-ojWWT.mjs} +2 -2
- package/dist/{auth-JO22iIwr.mjs → auth-CyO2aw5n.mjs} +126 -236
- package/dist/{auth-CU56Q2Xh.d.mts → auth-DLYSt_-A.d.mts} +32 -4
- package/dist/{backend-CPC_vyOo.d.mts → backend-Bob-5CM7.d.mts} +93 -42
- package/dist/backend-a2/blob-vercel.d.mts +1 -1
- package/dist/backend-a2/contract.d.mts +38 -98
- package/dist/backend-a2/contract.mjs +1 -1
- package/dist/backend-a2/scheduler-local.d.mts +1 -1
- package/dist/backend-a2/scheduler-local.mjs +1 -1
- package/dist/backend-a2/scheduler-qstash.d.mts +3 -3
- package/dist/backend-a2/scheduler-qstash.mjs +8 -8
- package/dist/backend-a2/scheduler-vercel.d.mts +3 -3
- package/dist/backend-a2/scheduler-vercel.mjs +6 -6
- package/dist/backend-a2/store-memory.d.mts +2 -2
- package/dist/backend-a2/store-memory.mjs +3 -3
- package/dist/backend-a2/store-postgres.d.mts +1 -1
- package/dist/backend-a2/store-postgres.mjs +34 -15
- package/dist/backend-a2/store-redis-http.d.mts +1 -1
- package/dist/backend-a2/store-redis-http.mjs +6 -6
- package/dist/backend-a2/store-redis.d.mts +2 -2
- package/dist/backend-a2/store-redis.mjs +5 -5
- package/dist/backend-a2/store-sqlite.d.mts +1 -1
- package/dist/backend-a2/store-sqlite.mjs +3 -3
- package/dist/backend-a2.d.mts +143 -242
- package/dist/backend-a2.mjs +2 -2
- package/dist/{backend-http-CqfKhrnn.d.mts → backend-http-BRrRbjRx.d.mts} +59 -45
- package/dist/{backend-http-CzIJMm58.mjs → backend-http-CvUKOn-m.mjs} +11 -10
- package/dist/{backend-http-Bmp0IgD3.mjs → backend-http-D8mUzuKQ.mjs} +2 -2
- package/dist/backend-http.d.mts +1 -1
- package/dist/backend-http.mjs +1 -1
- package/dist/backend-http.node.d.mts +1 -1
- package/dist/backend-http.node.mjs +1 -1
- package/dist/{backend-vercel-DQc_TaHp.mjs → backend-vercel-Ba8JDtqW.mjs} +3 -3
- package/dist/{backend-vercel-4tvcPKqX.d.mts → backend-vercel-BaSEUdwg.d.mts} +62 -47
- package/dist/{backend-vercel-BNauAs7w.mjs → backend-vercel-CmY9yZ9m.mjs} +279 -42
- package/dist/backend-vercel.d.mts +1 -1
- package/dist/backend-vercel.mjs +1 -1
- package/dist/backend-vercel.node.d.mts +1 -1
- package/dist/backend-vercel.node.mjs +1 -1
- package/dist/{blob-DmiQjrYy.d.mts → blob-Bx8QPWEd.d.mts} +2 -2
- package/dist/{blob-DdbpJqN1.mjs → blob-WbB2DJKn.mjs} +30 -11
- package/dist/{chat-provider-BWHbChcQ.d.mts → chat-provider-BChYrrA7.d.mts} +32 -28
- package/dist/{chat-provider-COtsU5jB.mjs → chat-provider-DkFp2hrh.mjs} +105 -60
- package/dist/cli-commands.d.mts +1 -1
- package/dist/cli-commands.mjs +1 -1
- package/dist/cli-embedded.d.mts +2 -2
- package/dist/cli-embedded.mjs +1 -1
- package/dist/cli.mjs +4 -4
- package/dist/{client-BqAjk0Q4.d.mts → client-COfYrgfV.d.mts} +240 -227
- package/dist/{commands-D6gvrOh3.d.mts → commands-DK4W3HCJ.d.mts} +47 -10
- package/dist/{commands-C3R1AWgm.mjs → commands-L1JSGz2Z.mjs} +212 -54
- package/dist/conformance-DK43HiHf.mjs +1000 -0
- package/dist/conformance.d.mts +8 -2
- package/dist/conformance.mjs +1 -1
- package/dist/{engine-DQxXk7dX.mjs → engine-DurYIRt8.mjs} +29 -210
- package/dist/{errors-DDktVeUa.d.mts → errors-2vGs49Db.d.mts} +1 -1
- package/dist/{client-D0Px7KzF.mjs → errors-CJXhhzvT.mjs} +132 -27
- package/dist/{provider-BaVmi4Hi.mjs → events-lujPA3gQ.mjs} +80 -17
- package/dist/{exports-BG-0Wyn-.mjs → exports-CWIdN0Ub.mjs} +195 -103
- package/dist/exports-FBOQWT7O.d.mts +5 -0
- package/dist/{folds-BDMSxBUf.mjs → folds-Cu9Q9zyQ.mjs} +3 -22
- package/dist/{folds-ZkHM4M-v.d.mts → folds-DLUzfibJ.d.mts} +15 -40
- package/dist/{index-D3VvNfh_.d.mts → index-Ho-ayyQL.d.mts} +2 -2
- package/dist/index.d.mts +7 -7
- package/dist/{index.default-rB8sJ9RX.mjs → index.default-BUcwDaAe.mjs} +1 -1
- package/dist/index.mjs +5 -6
- package/dist/index.node.d.mts +7 -7
- package/dist/index.node.mjs +3 -4
- package/dist/inspect/app.js +62 -61
- package/dist/inspect/engine.js +3 -3
- package/dist/{internal-CvsrprnU-CRY89I-b.mjs → internal-CvsrprnU-zZMpDiRY.mjs} +1 -1
- package/dist/{local-DhkrAqPP.mjs → local-C76Fy5ad.mjs} +1 -1
- package/dist/{main-CVBqe3VO.mjs → main-Dz-8komG.mjs} +251 -127
- package/dist/{middleware-CXjEeef4.mjs → middleware-BavYSDUa.mjs} +1 -1
- package/dist/{node-Zd_C-gxP.mjs → node-BgeGcwX0.mjs} +7 -3
- package/dist/{platform-B4TnJtWu-CwcTyKg2.mjs → platform-B4TnJtWu-Do3agKr5.mjs} +1 -1
- package/dist/{project-CBXlLftU.mjs → project-CQ4VUibA.mjs} +1 -1
- package/dist/{provider-DmSTp9lI.d.mts → provider-gynDUoyW.d.mts} +13 -43
- package/dist/{redis-tables-BJQVUspu.mjs → redis-tables-DHf85ixI.mjs} +40 -42
- package/dist/{reducer-CjmvZSAb-D_OSISmj.mjs → reducer-Bswr11ar-P324o9vn.mjs} +2 -2
- package/dist/{reducer-CYPHsSmd-BQIfozGi.d.mts → reducer-CYPHsSmd-BXjGiptm.d.mts} +1 -1
- package/dist/{reducers-DJzVpXwM.mjs → reducers-DcENwtwZ.mjs} +74 -77
- package/dist/{retryable-lazy-DZWmHpii-Bye-W8q7.mjs → retryable-lazy-DZWmHpii-DpTc5PIP.mjs} +1 -1
- package/dist/{scheduler-task-X1SToDjP-BVoWuInI.mjs → scheduler-task-X1SToDjP-D2Il2rln.mjs} +1 -1
- package/dist/{serve-G9RuaDSr.mjs → serve-CTmow-YH.mjs} +7 -7
- package/dist/{server-qgez0Xny-D5mLfqFQ.d.mts → server-B9gu0qi1-DI1WvcVK.d.mts} +10 -4
- package/dist/{server-BixV_byP.mjs → server-DG8D6VV0.mjs} +4 -4
- package/dist/{server-DtFrWxi3-Boa6gdWO.mjs → server-DX7mM6nm-D7N_7bug.mjs} +32 -23
- package/dist/{serving-B75Y4BF-.mjs → serving-DBFRo6U_.mjs} +1 -1
- package/dist/{session-clear-wHd5GCpZ-BnKSxReK.mjs → session-clear-XJYpmUpg-2q8l_FJR.mjs} +14 -2
- package/dist/{sql-D4Z_efJX.mjs → sql-CT5xVuGr.mjs} +2 -8
- package/dist/{sqlite-db-Bz2JkfCU.mjs → sqlite-db-0WeSOEZN.mjs} +1 -1
- package/dist/{store-D0MhBvg6-4Z2L0Kqd.d.mts → store-DEzcHZOA-B-5vhxef.d.mts} +12 -2
- package/dist/store-N8PXxDAS-DWWgv-Vz.mjs +5 -0
- package/dist/{store-codec-DwrWlgQx-CYxGW0aD.mjs → store-codec-pAG2oPgQ-SqDXlPBR.mjs} +4 -4
- package/dist/store-memory-4IBl0Ztu.mjs +2 -0
- package/dist/{store-memory-Bas9Uq5C.mjs → store-memory-B0PkVSuQ.mjs} +14 -7
- package/dist/{store-polling-BZt2Rf3D-BiEM6_HB.mjs → store-polling-BZt2Rf3D-Div-bJ_D.mjs} +2 -2
- package/dist/{store-presence-polling-JuAy2Ck2-CYpuK75X.mjs → store-presence-polling-JuAy2Ck2-Dh-g_KYM.mjs} +3 -3
- package/dist/{store-sqlite-CxxPCcCT.mjs → store-sqlite-D85t3tE7.mjs} +14 -7
- package/dist/store-sqlite-iBTYYKBj.mjs +2 -0
- package/dist/{stream-buffer-DrTyiIuo-BKy-vI14.mjs → stream-buffer-DrTyiIuo-Be10yOBR.mjs} +2 -2
- package/dist/{sync-kapso.d.mts → sync-chat-sdk.d.mts} +33 -37
- package/dist/sync-chat-sdk.mjs +44 -0
- package/dist/sync-github.d.mts +5 -18
- package/dist/sync-github.mjs +4 -70
- package/dist/sync-linear.d.mts +3 -3
- package/dist/sync-linear.mjs +6 -5
- package/dist/sync-slack.d.mts +7 -7
- package/dist/sync-slack.mjs +33 -54
- package/dist/sync.d.mts +3 -3
- package/dist/sync.mjs +2 -4
- package/dist/{tokens-CC3izSNr.mjs → tokens-Dnyd_y1n.mjs} +15 -6
- package/dist/{types-No0WdhE5.d.mts → types-CmrFjpml.d.mts} +2 -4
- package/dist/{watchers-hash-BDhLVkV5.mjs → watchers-hash-BjwlnGD9.mjs} +124 -115
- package/docs/01-board/01-mounting.md +2 -2
- package/docs/01-board/03-identity.md +5 -6
- package/docs/01-board/04-messages.md +96 -2
- package/docs/01-board/05-reading.md +2 -1
- package/docs/01-board/06-watchers.md +8 -6
- package/docs/01-board/08-middleware.md +6 -3
- package/docs/01-board/09-access.md +145 -14
- package/docs/02-sync/01-overview.md +19 -26
- package/docs/02-sync/02-functions.md +8 -9
- package/docs/02-sync/03-slack.md +5 -5
- package/docs/02-sync/04-github.md +2 -2
- package/docs/02-sync/06-providers.md +91 -62
- package/docs/03-guides/01-coding-agents.md +1 -1
- package/docs/03-guides/03-ci.md +7 -4
- package/docs/04-reference/01-cli.md +109 -51
- package/docs/04-reference/02-board.md +76 -28
- package/docs/04-reference/03-http.md +76 -38
- package/docs/04-reference/04-log.md +8 -11
- package/docs/04-reference/05-conformance.md +47 -7
- package/docs/index.md +2 -2
- package/package.json +7 -10
- package/sql/postgres/board.sql +1 -1
- package/sql/postgres/schema.sql +1 -1
- package/dist/conformance-DlnfuzEB.mjs +0 -556
- package/dist/errors-CusN4x2l.mjs +0 -88
- package/dist/events-qf5XG5VQ.mjs +0 -75
- package/dist/exports-mhAYiU4i.d.mts +0 -5
- package/dist/store-N8PXxDAS-BWBgzBHp.mjs +0 -5
- package/dist/store-memory-ZLiZbH3R.mjs +0 -2
- package/dist/store-sqlite-BmwL3pUR.mjs +0 -2
- package/dist/sync-kapso.mjs +0 -89
- package/dist/sync.chat.d.mts +0 -2
- package/dist/sync.chat.mjs +0 -2
- package/dist/users-yryHKFMo.mjs +0 -42
- package/docs/02-sync/05-whatsapp.md +0 -152
|
@@ -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-
|
|
2
|
-
import {
|
|
1
|
+
import { d as ExternalFile, f as ExternalLink, l as ExternalAuthor, p as Link, t as Actor, u as ExternalEvent } from "./folds-DLUzfibJ.mjs";
|
|
2
|
+
import { U as MessageView, _ as BoardEventView, dt as SourceJoin, mt as SourceRead, t as BoardClient } from "./client-COfYrgfV.mjs";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
//#region src/sync/events.d.ts
|
|
5
5
|
declare const EventBase: z.ZodObject<{
|
|
@@ -401,33 +401,6 @@ declare function render<E extends ProviderEvent = ProviderEvent>(renderer: Rende
|
|
|
401
401
|
*/
|
|
402
402
|
declare function channels<E extends ProviderEvent = ProviderEvent>(map: Record<string, SyncUnit<E>>): SyncFn<E>;
|
|
403
403
|
//#endregion
|
|
404
|
-
//#region src/sync/users.d.ts
|
|
405
|
-
/**
|
|
406
|
-
* People's own platform tokens, so a board message they wrote reaches Slack or
|
|
407
|
-
* GitHub as them, and signing in proves an account is theirs. The board never
|
|
408
|
-
* stores a token: it asks for one at each delivery, and a person without one
|
|
409
|
-
* (never signed in, revoked, expired) is delivered as the bot, as before.
|
|
410
|
-
*/
|
|
411
|
-
type UserTokens = {
|
|
412
|
-
/**
|
|
413
|
-
* A sign-in URL that binds whoever completes it to `principal`. Show it only to them. With
|
|
414
|
-
* `callback`, the platform sends them there once they've approved.
|
|
415
|
-
*/
|
|
416
|
-
authorize(principal: string, options?: {
|
|
417
|
-
callback?: string;
|
|
418
|
-
}): Promise<string>;
|
|
419
|
-
/** `principal`'s token on the platform, or null when they haven't signed in. */
|
|
420
|
-
token(principal: string): Promise<string | null>;
|
|
421
|
-
};
|
|
422
|
-
/**
|
|
423
|
-
* Gives an adapter people's tokens, for your own OAuth: `slack({ adapter:
|
|
424
|
-
* withUserTokens(createSlackAdapter(...), { authorize, token }) }, sync)`. A
|
|
425
|
-
* Connect connector name (`slack('slack/acme', sync)`) does this for you.
|
|
426
|
-
*/
|
|
427
|
-
declare function withUserTokens<A extends object>(adapter: A, tokens: UserTokens): A;
|
|
428
|
-
/** Vercel Connect's user tokens for `connector`: the subject is the board's principal, so Connect binds the account to it. */
|
|
429
|
-
declare function connectUserTokens(connector: string): UserTokens;
|
|
430
|
-
//#endregion
|
|
431
404
|
//#region src/sync/provider.d.ts
|
|
432
405
|
declare const ResolvedTarget: z.ZodObject<{
|
|
433
406
|
target: z.ZodString;
|
|
@@ -449,7 +422,7 @@ type RenderInput = {
|
|
|
449
422
|
/** The message as clients see it: its IDs are refs. */
|
|
450
423
|
message: Readonly<MessageView>;
|
|
451
424
|
author: Readonly<Actor> | null;
|
|
452
|
-
/** How this platform mentions an actor
|
|
425
|
+
/** How this platform mentions an actor when it's one of its own (`<@U123>`); null for anyone else. */
|
|
453
426
|
mentionOf: (actor: string) => string | null;
|
|
454
427
|
label: string;
|
|
455
428
|
target: string;
|
|
@@ -498,8 +471,6 @@ type ProviderOptions = {
|
|
|
498
471
|
uploadsFiles?: boolean;
|
|
499
472
|
/** Whether a new thread's root can carry its files in the same message as its text. */
|
|
500
473
|
startsThreadsWithFiles?: boolean;
|
|
501
|
-
/** People's own tokens, to post as them and to link accounts by signing in. */
|
|
502
|
-
users?: UserTokens | null;
|
|
503
474
|
};
|
|
504
475
|
declare const ReceivedEvent: z.ZodObject<{
|
|
505
476
|
event: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
@@ -629,28 +600,27 @@ declare abstract class SyncProvider<E extends ProviderEvent = ProviderEvent> {
|
|
|
629
600
|
readonly uploadsFiles: boolean;
|
|
630
601
|
readonly startsThreadsWithFiles: boolean;
|
|
631
602
|
private readonly fn;
|
|
632
|
-
/** People's tokens, when the adapter has them: messages they write post as them. */
|
|
633
|
-
readonly users: UserTokens | null;
|
|
634
603
|
protected readonly options: ProviderOptions;
|
|
635
604
|
constructor(options: ProviderOptions, sync: SyncFn<E>);
|
|
636
605
|
abstract receive(key: string, request: Request, emit: Receive): Promise<Response>;
|
|
637
606
|
abstract resolveChannel(key: string): Promise<string>;
|
|
638
607
|
abstract resolveTarget(target: string): Promise<ResolvedTarget>;
|
|
639
608
|
abstract post(target: string, kind: ResolvedTarget['kind'], body: ProviderPost): Promise<ProviderDelivery>;
|
|
640
|
-
/** The platform account a person's token belongs to. */
|
|
641
|
-
whoAmI(_token: string): Promise<ExternalAuthor>;
|
|
642
|
-
/** `post`, as the person whose token this is. */
|
|
643
|
-
postAs(_token: string, _target: string, _kind: ResolvedTarget['kind'], _body: ProviderPost): Promise<ProviderDelivery>;
|
|
644
|
-
editAs(_token: string, _thread: string, _message: string, _body: ProviderPost): Promise<void>;
|
|
645
|
-
deleteAs(_token: string, _thread: string, _message: string): Promise<void>;
|
|
646
609
|
findByEmail(_email: string): Promise<ExternalAuthor | null>;
|
|
647
610
|
mention(_actor: Actor): string | null;
|
|
648
611
|
fetchRoot(_thread: string): Promise<SyncRoot | null>;
|
|
649
612
|
fetchFile(_file: ExternalFile): Promise<Uint8Array | null>;
|
|
650
613
|
/** The platform's own link to an event's message, or null when it has none. */
|
|
651
614
|
permalink(_event: E): Promise<string | null>;
|
|
652
|
-
/**
|
|
653
|
-
|
|
615
|
+
/**
|
|
616
|
+
* A linked message the platform didn't describe, read from the platform. `linker` is the
|
|
617
|
+
* platform message that links it, by its own IDs: what the platform says about the link may be
|
|
618
|
+
* there by now.
|
|
619
|
+
*/
|
|
620
|
+
fetchLink(_link: ExternalLink, _linker: {
|
|
621
|
+
thread: string;
|
|
622
|
+
message: string;
|
|
623
|
+
}): Promise<FetchedLink>;
|
|
654
624
|
/**
|
|
655
625
|
* The message a URL of this platform's names, by its own thread and message IDs, or null for a
|
|
656
626
|
* URL that isn't one. `message` is null for a link to a thread itself. It asks the platform
|
|
@@ -692,4 +662,4 @@ declare abstract class SyncProvider<E extends ProviderEvent = ProviderEvent> {
|
|
|
692
662
|
render(input: RenderInput): string;
|
|
693
663
|
}
|
|
694
664
|
//#endregion
|
|
695
|
-
export {
|
|
665
|
+
export { envelope as A, render as C, SyncOverrides as D, RootOverride as E, SyncResult as O, mirror as S, ProviderEvent as T, SyncIn as _, ProviderOptions as a, channels as b, ReceivedEvent as c, ResolvedTarget as d, SyncContext as f, SyncFn as g, Sync as h, ProviderFile as i, eventSchema as j, SyncRoot as k, RenderInput as l, UnreadableError as m, FileDelivery as n, ProviderPost as o, SyncProvider as p, ProviderDelivery as r, Receive as s, FetchedLink as t, Renderer as u, SyncOut as v, EventBase as w, into as x, SyncUnit as y };
|
|
@@ -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 {
|
|
4
|
-
import { m as nullProtoRecord, n as NOTIFY_TIMINGS, v as stateTailReaders } from "./internal-CvsrprnU-
|
|
5
|
-
import { i as presenceTombstones, n as isSerializedEvent, r as parseSerializedEvent, t as bufferedEvents } from "./stream-buffer-DrTyiIuo-
|
|
6
|
-
import { i as streamActivities, n as defaultSleep, r as pollingStream, t as createStreamActivity } from "./store-polling-BZt2Rf3D-
|
|
7
|
-
import { t as retryableLazy } from "./retryable-lazy-DZWmHpii-
|
|
8
|
-
import { i as syncReads, n as project, r as projectSync, t as concernedMessageId } from "./project-
|
|
9
|
-
import { i as idempotentReplay, n as decodeCause } from "./store-codec-
|
|
10
|
-
import { t as pollPresence } from "./store-presence-polling-JuAy2Ck2-
|
|
11
|
-
//#region ../../node_modules/.pnpm/experimental-a2@0.
|
|
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-CQ4VUibA.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 '',
|
|
649
|
-
* event: id, type, payloadJson, causeJson or '',
|
|
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[
|
|
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[
|
|
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 =
|
|
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 =
|
|
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 === "
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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);
|
|
@@ -3262,12 +3278,6 @@ local out = {}
|
|
|
3262
3278
|
for i = 1, #KEYS do out[i] = redis.call('HGETALL', KEYS[i]) end
|
|
3263
3279
|
return out
|
|
3264
3280
|
`;
|
|
3265
|
-
/** A person's roots posted at or after ARGV[1]. KEYS: messages, their roots by creation time. */
|
|
3266
|
-
const RECENT = `
|
|
3267
|
-
local ids = redis.call('ZRANGEBYSCORE', KEYS[2], ARGV[1], '+inf')
|
|
3268
|
-
if #ids == 0 then return {} end
|
|
3269
|
-
return redis.call('HMGET', KEYS[1], unpack(ids))
|
|
3270
|
-
`;
|
|
3271
3281
|
/**
|
|
3272
3282
|
* What an event reads before it applies, in one script so it reads the primary,
|
|
3273
3283
|
* where the position check runs: a replica can lag it. Nothing, when the
|
|
@@ -3396,8 +3406,6 @@ function redisTables(send, prefix, options = {}) {
|
|
|
3396
3406
|
mention: (actor) => `${p}:i:mn:${actor}`,
|
|
3397
3407
|
attachment: (id) => `${p}:i:at:${id}`,
|
|
3398
3408
|
from: (from) => `${p}:i:f:${from}`,
|
|
3399
|
-
/** A person's roots, by when they were posted: for the echo check. */
|
|
3400
|
-
rootsBy: (principal) => `${p}:rr:${principal}`,
|
|
3401
3409
|
label: (token) => `${p}:i:${token}`,
|
|
3402
3410
|
copies: (id) => `${p}:cp:${id}`
|
|
3403
3411
|
};
|
|
@@ -3506,7 +3514,6 @@ function redisTables(send, prefix, options = {}) {
|
|
|
3506
3514
|
re: m.re,
|
|
3507
3515
|
c: m.channel,
|
|
3508
3516
|
t: m.text.toLowerCase(),
|
|
3509
|
-
ca: Date.parse(m.createdAt),
|
|
3510
3517
|
d: m.deleted
|
|
3511
3518
|
};
|
|
3512
3519
|
out.push([
|
|
@@ -3561,12 +3568,6 @@ function redisTables(send, prefix, options = {}) {
|
|
|
3561
3568
|
id,
|
|
3562
3569
|
id
|
|
3563
3570
|
]);
|
|
3564
|
-
else out.push([
|
|
3565
|
-
"ZADD",
|
|
3566
|
-
k.rootsBy(m.by.principal),
|
|
3567
|
-
String(meta.ca),
|
|
3568
|
-
id
|
|
3569
|
-
]);
|
|
3570
3571
|
}
|
|
3571
3572
|
if (change.message.terms) {
|
|
3572
3573
|
const old = read.message;
|
|
@@ -3887,9 +3888,6 @@ function redisTables(send, prefix, options = {}) {
|
|
|
3887
3888
|
return message ? [message] : [];
|
|
3888
3889
|
});
|
|
3889
3890
|
},
|
|
3890
|
-
async recentRoots(principal, since) {
|
|
3891
|
-
return (await evaluate(RECENT, [k.messages, k.rootsBy(principal)], [since])).map((row) => parse(row)).sort((a, b) => a.id - b.id);
|
|
3892
|
-
},
|
|
3893
3891
|
async close() {}
|
|
3894
3892
|
};
|
|
3895
3893
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
//#region ../../node_modules/.pnpm/experimental-a2@0.
|
|
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.
|
|
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-
|
|
5
|
-
import { n as foldMessages, t as foldActors } from "./folds-
|
|
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-Cu9Q9zyQ.mjs";
|
|
6
6
|
import { z } from "zod";
|
|
7
|
-
//#region ../../node_modules/.pnpm/experimental-a2@0.
|
|
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);
|
|
@@ -80,6 +80,14 @@ const boardEvents = {
|
|
|
80
80
|
*/
|
|
81
81
|
importedBy: ActorId.optional()
|
|
82
82
|
}),
|
|
83
|
+
/**
|
|
84
|
+
* A channel made before anything posted to it. A post makes one too, with no event of its own:
|
|
85
|
+
* this is only for one that's empty. It names no message, so it carries no `id`.
|
|
86
|
+
*/
|
|
87
|
+
"channel.created": z.object({
|
|
88
|
+
channel: ChannelPath,
|
|
89
|
+
by: Author
|
|
90
|
+
}),
|
|
83
91
|
/** A message's links changed: an edit linked something new, or the platform sent what a link says. */
|
|
84
92
|
"message.linked": z.object({
|
|
85
93
|
id: MessageId,
|
|
@@ -138,9 +146,7 @@ const boardEvents = {
|
|
|
138
146
|
target: ExternalTarget,
|
|
139
147
|
external: z.object({
|
|
140
148
|
thread: ExternalTarget,
|
|
141
|
-
message: z.string().min(1).max(300)
|
|
142
|
-
/** Posted with its author's own platform token, so it shows as them. Older receipts have none. */
|
|
143
|
-
asUser: z.literal(true).optional()
|
|
149
|
+
message: z.string().min(1).max(300)
|
|
144
150
|
}),
|
|
145
151
|
/**
|
|
146
152
|
* (server) The principal of the sync elsewhere that recorded it: its copy is that sync's to
|
|
@@ -179,22 +185,6 @@ const boardEvents = {
|
|
|
179
185
|
* signs in, whatever its ID or kind, so sync never writes as it. Others have none.
|
|
180
186
|
*/
|
|
181
187
|
host: z.literal(true).optional()
|
|
182
|
-
}),
|
|
183
|
-
/**
|
|
184
|
-
* A platform actor (`slack:user:U0456`) is the same person as a principal
|
|
185
|
-
* (`vercel:user:…`): for display, `--by`, and mentions, never for permissions.
|
|
186
|
-
* `method` says how it was proved: a one-time code posted from that account,
|
|
187
|
-
* or the account's own sign-in (`consent`).
|
|
188
|
-
*/
|
|
189
|
-
"actor.linked": z.object({
|
|
190
|
-
actor: ActorId,
|
|
191
|
-
to: ActorId,
|
|
192
|
-
method: z.enum(["code", "consent"]),
|
|
193
|
-
by: Author
|
|
194
|
-
}),
|
|
195
|
-
"actor.unlinked": z.object({
|
|
196
|
-
actor: ActorId,
|
|
197
|
-
by: Author
|
|
198
188
|
})
|
|
199
189
|
};
|
|
200
190
|
const BOARD_SESSION = "board";
|
|
@@ -328,7 +318,9 @@ const StoredPrincipal = z.object({
|
|
|
328
318
|
/** The board's own Vercel team, as the board knew it when it verified the token. */
|
|
329
319
|
team: z.string().max(200).optional()
|
|
330
320
|
}).optional(),
|
|
331
|
-
scope: z.string().max(SCOPE_MAX).optional()
|
|
321
|
+
scope: z.string().max(SCOPE_MAX).optional(),
|
|
322
|
+
/** The board token it came with: what it stores stops when the token does. */
|
|
323
|
+
token: z.string().min(1).max(64).optional()
|
|
332
324
|
});
|
|
333
325
|
/** A watcher as a board on `http()` registers it: its tail, and when it runs. */
|
|
334
326
|
const WatcherSpec = z.object({
|
|
@@ -350,11 +342,13 @@ const registryContract = contract({
|
|
|
350
342
|
/** Where to wake it: `<url>/wake`. Without one, it pulls on its own. */
|
|
351
343
|
url: z.string().url().max(500).nullable(),
|
|
352
344
|
watch: z.record(RemoteWatcherId, WatcherSpec),
|
|
353
|
-
/**
|
|
345
|
+
/**
|
|
346
|
+
* Its sync entries: with any, its sync subscribes too, to every post, change, and thread sync
|
|
347
|
+
* where it may sync. Older registrations have none.
|
|
348
|
+
*/
|
|
354
349
|
sync: z.array(z.object({
|
|
355
350
|
key: z.string().min(1).max(64),
|
|
356
|
-
platform: z.string().min(1).max(64)
|
|
357
|
-
signIn: z.boolean()
|
|
351
|
+
platform: z.string().min(1).max(64)
|
|
358
352
|
})).max(32).optional(),
|
|
359
353
|
/** `watchersHash(watch)`, which every wake-up carries so the board can tell it's stale. */
|
|
360
354
|
hash: z.string().min(1).max(100)
|
|
@@ -444,31 +438,53 @@ const schedulesContract = contract({
|
|
|
444
438
|
}
|
|
445
439
|
});
|
|
446
440
|
const SCHEDULES_SESSION = "schedules";
|
|
441
|
+
const Grant = z.union([z.literal("all"), z.array(z.string().min(1).max(16)).max(8)]);
|
|
442
|
+
/** A `can`, as config writes it: board() checks it before it's kept. */
|
|
443
|
+
const Can = z.union([Grant, z.record(z.string().min(1).max(300), Grant)]);
|
|
444
|
+
const ClaimValue = z.string().min(1).max(1e3);
|
|
447
445
|
/**
|
|
448
|
-
*
|
|
449
|
-
*
|
|
446
|
+
* Who the board trusts beside its code's rules, outside the board log: grants, and the tokens it
|
|
447
|
+
* issued, of which only a hash is kept. Session `access`. A grant's and a token's ID is the index
|
|
448
|
+
* of the event that made it.
|
|
450
449
|
*/
|
|
451
|
-
const
|
|
452
|
-
name: "board-
|
|
450
|
+
const accessContract = contract({
|
|
451
|
+
name: "board-access",
|
|
453
452
|
events: {
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
453
|
+
/** A grant, or a new `can` for the grant with this issuer and claims. */
|
|
454
|
+
"grant.set": z.object({
|
|
455
|
+
issuer: z.string().min(1).max(1e3),
|
|
456
|
+
claims: z.record(z.string().min(1).max(200), z.union([ClaimValue, z.array(ClaimValue).min(1).max(32)])),
|
|
457
|
+
can: Can,
|
|
458
|
+
by: ActorId
|
|
459
|
+
}),
|
|
460
|
+
"grant.revoked": z.object({
|
|
461
|
+
id: z.number().int().positive(),
|
|
462
|
+
by: ActorId
|
|
463
|
+
}),
|
|
464
|
+
"token.minted": z.object({
|
|
465
|
+
/** The secret's SHA-256, hex. */
|
|
466
|
+
hash: z.string().regex(/^[0-9a-f]{64}$/),
|
|
467
|
+
name: z.string().min(1).max(64),
|
|
468
|
+
/** Who it acts as, its scope narrowed to what the token may do. */
|
|
469
|
+
minter: StoredPrincipal,
|
|
470
|
+
profile: z.string().min(1).max(32).nullable(),
|
|
471
|
+
avatar: z.string().max(2048).nullable(),
|
|
472
|
+
session: z.string().min(1).max(128).nullable(),
|
|
473
|
+
/** A person's handle and name when they minted it. */
|
|
474
|
+
handle: Handle.nullable(),
|
|
475
|
+
personName: z.string().min(1).max(128).nullable(),
|
|
476
|
+
expiresAt: Millis,
|
|
477
|
+
/** The token it was minted with, which it stops with. */
|
|
478
|
+
parent: z.number().int().positive().nullable(),
|
|
479
|
+
by: ActorId
|
|
461
480
|
}),
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
actor: ActorId,
|
|
466
|
-
/** The message that used it (`externalMessageKey`): only a retry of that one claims it again. */
|
|
467
|
-
message: z.string().max(1024).optional()
|
|
481
|
+
"token.revoked": z.object({
|
|
482
|
+
id: z.number().int().positive(),
|
|
483
|
+
by: ActorId
|
|
468
484
|
})
|
|
469
485
|
}
|
|
470
486
|
});
|
|
471
|
-
const
|
|
487
|
+
const ACCESS_SESSION = "access";
|
|
472
488
|
//#endregion
|
|
473
489
|
//#region src/contract/reducers.ts
|
|
474
490
|
const messagesReducer = reducer({
|
|
@@ -487,19 +503,24 @@ reducer({
|
|
|
487
503
|
if (event.type === "message.posted") setOwn(state, event.id, event.index);
|
|
488
504
|
return state;
|
|
489
505
|
});
|
|
506
|
+
const emptyChannel = (path) => ({
|
|
507
|
+
path,
|
|
508
|
+
lastIndex: 0,
|
|
509
|
+
messages: 0,
|
|
510
|
+
threads: 0
|
|
511
|
+
});
|
|
490
512
|
const channelsReducer = reducer({
|
|
491
513
|
contract: boardContract,
|
|
492
|
-
name: "board.channels.
|
|
514
|
+
name: "board.channels.v2",
|
|
493
515
|
initialState: {}
|
|
494
516
|
}).fold((state, event) => {
|
|
517
|
+
if (event.type === "channel.created") {
|
|
518
|
+
if (!own(state, event.payload.channel)) setOwn(state, event.payload.channel, emptyChannel(event.payload.channel));
|
|
519
|
+
return state;
|
|
520
|
+
}
|
|
495
521
|
if (event.type !== "message.posted") return state;
|
|
496
522
|
const { channel, re } = event.payload;
|
|
497
|
-
const entry = own(state, channel) ?? setOwn(state, channel,
|
|
498
|
-
path: channel,
|
|
499
|
-
lastIndex: 0,
|
|
500
|
-
messages: 0,
|
|
501
|
-
threads: 0
|
|
502
|
-
});
|
|
523
|
+
const entry = own(state, channel) ?? setOwn(state, channel, emptyChannel(channel));
|
|
503
524
|
entry.lastIndex = event.index;
|
|
504
525
|
entry.messages += 1;
|
|
505
526
|
if (re === null) entry.threads += 1;
|
|
@@ -510,32 +531,8 @@ const actorsReducer = reducer({
|
|
|
510
531
|
name: "board.actors.v2",
|
|
511
532
|
initialState: {
|
|
512
533
|
byId: {},
|
|
513
|
-
byHandle: {}
|
|
514
|
-
links: {}
|
|
534
|
+
byHandle: {}
|
|
515
535
|
}
|
|
516
536
|
}).fold(foldActors);
|
|
517
|
-
const identityCodesReducer = reducer({
|
|
518
|
-
contract: identityContract,
|
|
519
|
-
name: "board.identity-codes.v1",
|
|
520
|
-
initialState: {}
|
|
521
|
-
}).fold((state, event) => {
|
|
522
|
-
if (event.type === "identity.code_issued") {
|
|
523
|
-
const { hash, principal, sync, expiresAt } = event.payload;
|
|
524
|
-
state[hash] ??= {
|
|
525
|
-
principal,
|
|
526
|
-
sync,
|
|
527
|
-
expiresAt,
|
|
528
|
-
usedBy: null,
|
|
529
|
-
usedIn: null
|
|
530
|
-
};
|
|
531
|
-
} else if (event.type === "identity.code_used") {
|
|
532
|
-
const code = state[event.payload.hash];
|
|
533
|
-
if (code && code.usedBy === null) {
|
|
534
|
-
code.usedBy = event.payload.actor;
|
|
535
|
-
code.usedIn = event.payload.message ?? null;
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
return state;
|
|
539
|
-
});
|
|
540
537
|
//#endregion
|
|
541
|
-
export {
|
|
538
|
+
export { INBOXES_SESSION as a, accessContract as c, inboxSession as d, registryContract as f, BOARD_SESSION as g, watchSession as h, ACCESS_SESSION as i, boardContract as l, watchContract as m, channelsReducer as n, REGISTRY_SESSION as o, schedulesContract as p, messagesReducer as r, SCHEDULES_SESSION as s, actorsReducer as t, inboxContract as u };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region ../../node_modules/.pnpm/experimental-a2@0.
|
|
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.
|
|
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 {
|
|
2
|
-
import { s as localTokenFile } from "./node-
|
|
3
|
-
import { t as board } from "./server-
|
|
4
|
-
import { t as oidcTokens } from "./tokens-
|
|
5
|
-
import { t as a2 } from "./a2-
|
|
6
|
-
import { a as fsBlob } from "./blob-
|
|
7
|
-
import { t as localScheduler } from "./local-
|
|
1
|
+
import { u as BoardError } from "./errors-CJXhhzvT.mjs";
|
|
2
|
+
import { s as localTokenFile } from "./node-BgeGcwX0.mjs";
|
|
3
|
+
import { t as board } from "./server-DG8D6VV0.mjs";
|
|
4
|
+
import { t as oidcTokens } from "./tokens-Dnyd_y1n.mjs";
|
|
5
|
+
import { t as a2 } from "./a2-DngWY2Eb.mjs";
|
|
6
|
+
import { a as fsBlob } from "./blob-WbB2DJKn.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-
|
|
2
|
-
import { r as Event } from "./store-
|
|
3
|
-
//#region ../../node_modules/.pnpm/experimental-a2@0.
|
|
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.
|
|
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-
|
|
2
|
-
import { t as http } from "./backend-http-
|
|
1
|
+
import { t as createBoard } from "./exports-CWIdN0Ub.mjs";
|
|
2
|
+
import { t as http } from "./backend-http-D8mUzuKQ.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-
|
|
13
|
-
serving: () => import("./serving-
|
|
12
|
+
sync: () => import("./engine-DurYIRt8.mjs"),
|
|
13
|
+
serving: () => import("./serving-DBFRo6U_.mjs")
|
|
14
14
|
});
|
|
15
15
|
}
|
|
16
16
|
//#endregion
|