@vercel/board 0.18.1 → 0.20.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/dist/{a2-CW8jHGD_.mjs → a2-D__qQpe7.mjs} +37 -6
- package/dist/access.mjs +3 -3
- package/dist/{actors-BOamkEuz.mjs → actors-rPnEQLZu.mjs} +2 -2
- package/dist/{auth-Drg9FiC2.mjs → auth-5nLsx9qB.mjs} +1 -1
- package/dist/{backend-B-SJ7p6p.d.mts → backend-CWmd4UH-.d.mts} +8 -1
- package/dist/backend-a2.d.mts +22 -2
- package/dist/backend-a2.mjs +1 -1
- package/dist/{backend-http-7cNb8nJI.d.mts → backend-http-BfWQfvqB.d.mts} +22 -2
- package/dist/{backend-http-CDDS7MLI.mjs → backend-http-CG5y03UP.mjs} +25 -6
- package/dist/{backend-http-BjH8jMDi.mjs → backend-http-c-VHpUOs.mjs} +19 -6
- 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/{chat-provider-DNJQyajS.d.mts → chat-provider-D0k3y8zY.d.mts} +4 -1
- package/dist/{chat-provider-YHy-WbrB.mjs → chat-provider-DnHibqnM.mjs} +4 -1
- package/dist/cli-embedded.d.mts +47 -0
- package/dist/cli-embedded.mjs +64 -0
- package/dist/cli.mjs +73 -1661
- package/dist/{client-BA-J7usH.mjs → client-ClznIBMg.mjs} +2 -0
- package/dist/{conformance-CT5EeHeC.mjs → conformance-DQ9qVzWP.mjs} +47 -6
- package/dist/conformance.d.mts +1 -1
- package/dist/conformance.mjs +1 -1
- package/dist/{engine-D0oBUBEK.mjs → engine-kHfSOXnQ.mjs} +15 -4
- package/dist/{errors-DX3hpwWt.mjs → errors-CQ-fwxM3.mjs} +13 -1
- package/dist/{exports-CwsfgCul.mjs → exports-DqWJ7nzC.mjs} +15 -6
- package/dist/exports-ggfE9jNv.d.mts +4 -0
- package/dist/index-DsMPCv_K.d.mts +11 -0
- package/dist/index.d.mts +4 -4
- package/dist/{index.default-jkA7eFFe.mjs → index.default-C3luVnd-.mjs} +1 -1
- package/dist/index.mjs +6 -6
- package/dist/index.node.d.mts +4 -12
- package/dist/index.node.mjs +4 -4
- package/dist/inspect/app.js +93 -92
- package/dist/inspect/engine.js +4 -4
- package/dist/main-wB-VfTCL.mjs +1744 -0
- package/dist/{middleware-CqaCwucP.mjs → middleware-DUjyQP_a.mjs} +1 -1
- package/dist/{provider-B0b9Qxw4.d.mts → provider-D11Dfda0.d.mts} +91 -22
- package/dist/{provider-B3DpYSDq.mjs → provider-poIkXapd.mjs} +4 -0
- package/dist/{serve-Dpb7zMJ0.mjs → serve-AnApUWOR.mjs} +4 -4
- package/dist/{server-Bj1_ugXd.mjs → server-BqVickb5.mjs} +4 -4
- package/dist/{serving-CNkgUPW1.mjs → serving-B307gppu.mjs} +1 -1
- package/dist/sync-github.d.mts +2 -2
- package/dist/sync-github.mjs +2 -2
- package/dist/sync-kapso.d.mts +2 -2
- package/dist/sync-kapso.mjs +2 -2
- package/dist/sync-linear.d.mts +2 -2
- package/dist/sync-linear.mjs +2 -2
- package/dist/sync-slack.d.mts +11 -2
- package/dist/sync-slack.mjs +57 -17
- package/dist/sync.chat.d.mts +1 -1
- package/dist/sync.chat.mjs +1 -1
- package/dist/sync.d.mts +1 -1
- package/dist/sync.mjs +1 -1
- package/dist/{tokens-DhuzKzAl.mjs → tokens-DUXaXwOj.mjs} +2 -2
- package/dist/{watchers-hash-qlnbKQQ0.mjs → watchers-hash-DYwvkhdX.mjs} +38 -7
- package/docs/01-board/06-watchers.md +7 -0
- package/docs/02-sync/03-slack.md +14 -1
- package/docs/02-sync/06-providers.md +1 -0
- package/docs/04-reference/01-cli.md +55 -3
- package/docs/04-reference/02-board.md +8 -3
- package/docs/04-reference/03-http.md +7 -4
- package/package.json +5 -1
- package/dist/exports-ZsgjzEnM.d.mts +0 -4
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { m as MESSAGE_TEXT_MAX, p as Labels } from "./schemas-Be08nyfW.mjs";
|
|
2
|
-
import { t as HttpError } from "./errors-
|
|
2
|
+
import { t as HttpError } from "./errors-CQ-fwxM3.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. */
|
|
@@ -115,9 +115,27 @@ declare const InboxQuery: z.ZodObject<{
|
|
|
115
115
|
}, z.core.$strip>;
|
|
116
116
|
/** How many watchers one registration holds: the board matches every event against every tail. */
|
|
117
117
|
declare const REGISTERED_WATCHERS_MAX = 32;
|
|
118
|
-
/**
|
|
119
|
-
|
|
118
|
+
/**
|
|
119
|
+
* What a board on `http()` registers with the board it uses: its watchers, and where to wake it,
|
|
120
|
+
* at a URL or at a path on its own project, never both.
|
|
121
|
+
*/
|
|
122
|
+
declare const RegisterBody: z.ZodUnion<readonly [z.ZodObject<{
|
|
123
|
+
watch: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
124
|
+
tail: z.ZodString;
|
|
125
|
+
when: z.ZodDefault<z.ZodEnum<{
|
|
126
|
+
enters: "enters";
|
|
127
|
+
matches: "matches";
|
|
128
|
+
}>>;
|
|
129
|
+
}, z.core.$strip>>;
|
|
130
|
+
sync: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
131
|
+
key: z.ZodString;
|
|
132
|
+
platform: z.ZodString;
|
|
133
|
+
signIn: z.ZodDefault<z.ZodBoolean>;
|
|
134
|
+
}, z.core.$strip>>>;
|
|
120
135
|
url: z.ZodOptional<z.ZodNullable<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>>;
|
|
136
|
+
path: z.ZodOptional<z.ZodNull>;
|
|
137
|
+
branch: z.ZodOptional<z.ZodNull>;
|
|
138
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
121
139
|
watch: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
122
140
|
tail: z.ZodString;
|
|
123
141
|
when: z.ZodDefault<z.ZodEnum<{
|
|
@@ -130,7 +148,12 @@ declare const RegisterBody: z.ZodObject<{
|
|
|
130
148
|
platform: z.ZodString;
|
|
131
149
|
signIn: z.ZodDefault<z.ZodBoolean>;
|
|
132
150
|
}, z.core.$strip>>>;
|
|
133
|
-
|
|
151
|
+
url: z.ZodOptional<z.ZodNull>;
|
|
152
|
+
path: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
153
|
+
branch: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
154
|
+
}, z.core.$strip>]>;
|
|
155
|
+
/** A registration as a board on `http()` sends it: `{ url?, watch, sync? }` or `{ path, branch?, watch, sync? }`. */
|
|
156
|
+
type RegisterInput = z.input<typeof RegisterBody>;
|
|
134
157
|
/** A pull of the caller's matches: at most `limit`, waiting up to `wait` seconds for one. */
|
|
135
158
|
declare const MatchesQuery: z.ZodObject<{
|
|
136
159
|
limit: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
@@ -150,6 +173,10 @@ declare const SourceReadQuery: z.ZodObject<{
|
|
|
150
173
|
target: z.ZodString;
|
|
151
174
|
limit: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
152
175
|
}, z.core.$strip>;
|
|
176
|
+
/** A channel to add the board's app to, so it can be read on demand: `#name`, an ID, or a link into it. */
|
|
177
|
+
declare const SourceJoinBody: z.ZodObject<{
|
|
178
|
+
target: z.ZodString;
|
|
179
|
+
}, z.core.$strip>;
|
|
153
180
|
/** A platform's link to a message or thread, such as a Slack permalink or a GitHub comment's URL. */
|
|
154
181
|
declare const LinkedQuery: z.ZodObject<{
|
|
155
182
|
url: z.ZodString;
|
|
@@ -680,13 +707,19 @@ type Discovery = {
|
|
|
680
707
|
key: string;
|
|
681
708
|
platform: string;
|
|
682
709
|
}[];
|
|
710
|
+
/**
|
|
711
|
+
* Whether `POST /watchers` takes a `path`: the board wakes the caller's own Vercel project there,
|
|
712
|
+
* through its Deployment Protection. A board that can't find a project's deployments leaves it out.
|
|
713
|
+
*/
|
|
714
|
+
wake_by_path?: boolean;
|
|
683
715
|
};
|
|
684
|
-
/**
|
|
716
|
+
/**
|
|
717
|
+
* Watchers a board on `http()` registered here: one registration per principal, woken at a URL
|
|
718
|
+
* or at a path on its own project, never both.
|
|
719
|
+
*/
|
|
685
720
|
type RegistrationView = {
|
|
686
721
|
/** The principal that registered. Its watchers write as it, with their IDs as profiles. */
|
|
687
722
|
owner: string;
|
|
688
|
-
/** Where it's woken: `<url>/wake`. `null` when it pulls on its own. */
|
|
689
|
-
url: string | null;
|
|
690
723
|
watch: Record<string, {
|
|
691
724
|
tail: string;
|
|
692
725
|
when: 'matches' | 'enters';
|
|
@@ -699,7 +732,18 @@ type RegistrationView = {
|
|
|
699
732
|
}[];
|
|
700
733
|
/** Every wake-up carries it, so the board can tell its registration is stale. */
|
|
701
734
|
hash: string;
|
|
702
|
-
}
|
|
735
|
+
} & ({
|
|
736
|
+
/** Where it's woken: `<url>/wake`. `null` when it pulls on its own. */
|
|
737
|
+
url: string | null;
|
|
738
|
+
path?: undefined;
|
|
739
|
+
branch?: undefined;
|
|
740
|
+
} | {
|
|
741
|
+
url: null;
|
|
742
|
+
/** Where it's woken on its own Vercel project, on a board with `wake_by_path`. */
|
|
743
|
+
path: string;
|
|
744
|
+
/** The branch whose latest ready preview a preview's `path` wakes. */
|
|
745
|
+
branch?: string;
|
|
746
|
+
});
|
|
703
747
|
/** One match, leased to the registrant that pulled it. */
|
|
704
748
|
type MatchView = {
|
|
705
749
|
/** The match's ID, which its watcher's writes derive their IDs from. */
|
|
@@ -869,6 +913,12 @@ type SourceRead = {
|
|
|
869
913
|
/** The platform has more than `limit`: older messages in a channel, later replies in a thread. */
|
|
870
914
|
more: boolean;
|
|
871
915
|
};
|
|
916
|
+
/** A channel the board's app joined, or was already in (`joined: false`). */
|
|
917
|
+
type SourceJoin = {
|
|
918
|
+
channel: string;
|
|
919
|
+
name: string | null;
|
|
920
|
+
joined: boolean;
|
|
921
|
+
};
|
|
872
922
|
type ApiError = {
|
|
873
923
|
error: {
|
|
874
924
|
code: string;
|
|
@@ -1486,6 +1536,14 @@ declare const routes: {
|
|
|
1486
1536
|
limit: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
1487
1537
|
}, z.core.$strip>;
|
|
1488
1538
|
};
|
|
1539
|
+
/** Adds the app to a public channel so it can be read, where that sync runs and opted in with `join`. Full access only. */
|
|
1540
|
+
readonly joinSource: {
|
|
1541
|
+
readonly method: 'POST';
|
|
1542
|
+
readonly path: '/sources/:key/join';
|
|
1543
|
+
readonly body: z.ZodObject<{
|
|
1544
|
+
target: z.ZodString;
|
|
1545
|
+
}, z.core.$strip>;
|
|
1546
|
+
};
|
|
1489
1547
|
readonly webhook: {
|
|
1490
1548
|
readonly method: 'POST';
|
|
1491
1549
|
readonly path: '/webhooks/:key';
|
|
@@ -1577,8 +1635,23 @@ declare const routes: {
|
|
|
1577
1635
|
readonly register: {
|
|
1578
1636
|
readonly method: 'POST';
|
|
1579
1637
|
readonly path: '/watchers';
|
|
1580
|
-
readonly body: z.ZodObject<{
|
|
1638
|
+
readonly body: z.ZodUnion<readonly [z.ZodObject<{
|
|
1639
|
+
watch: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
1640
|
+
tail: z.ZodString;
|
|
1641
|
+
when: z.ZodDefault<z.ZodEnum<{
|
|
1642
|
+
enters: "enters";
|
|
1643
|
+
matches: "matches";
|
|
1644
|
+
}>>;
|
|
1645
|
+
}, z.core.$strip>>;
|
|
1646
|
+
sync: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1647
|
+
key: z.ZodString;
|
|
1648
|
+
platform: z.ZodString;
|
|
1649
|
+
signIn: z.ZodDefault<z.ZodBoolean>;
|
|
1650
|
+
}, z.core.$strip>>>;
|
|
1581
1651
|
url: z.ZodOptional<z.ZodNullable<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>>;
|
|
1652
|
+
path: z.ZodOptional<z.ZodNull>;
|
|
1653
|
+
branch: z.ZodOptional<z.ZodNull>;
|
|
1654
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
1582
1655
|
watch: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
1583
1656
|
tail: z.ZodString;
|
|
1584
1657
|
when: z.ZodDefault<z.ZodEnum<{
|
|
@@ -1591,7 +1664,10 @@ declare const routes: {
|
|
|
1591
1664
|
platform: z.ZodString;
|
|
1592
1665
|
signIn: z.ZodDefault<z.ZodBoolean>;
|
|
1593
1666
|
}, z.core.$strip>>>;
|
|
1594
|
-
|
|
1667
|
+
url: z.ZodOptional<z.ZodNull>;
|
|
1668
|
+
path: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
1669
|
+
branch: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1670
|
+
}, z.core.$strip>]>;
|
|
1595
1671
|
};
|
|
1596
1672
|
/** The caller's matches it can run now, each leased to it until it acks. */
|
|
1597
1673
|
readonly matches: {
|
|
@@ -1814,18 +1890,7 @@ declare function createBoardClient(options: ClientOptions): {
|
|
|
1814
1890
|
limit?: number;
|
|
1815
1891
|
}) => Promise<InboxEntry[]>;
|
|
1816
1892
|
/** Registers the caller's watchers, replacing its last registration: what a board on `http()` does. */
|
|
1817
|
-
register: (input:
|
|
1818
|
-
url?: string | null;
|
|
1819
|
-
watch: Record<string, {
|
|
1820
|
-
tail: string;
|
|
1821
|
-
when?: 'matches' | 'enters';
|
|
1822
|
-
}>;
|
|
1823
|
-
sync?: {
|
|
1824
|
-
key: string;
|
|
1825
|
-
platform: string;
|
|
1826
|
-
signIn?: boolean;
|
|
1827
|
-
}[];
|
|
1828
|
-
}) => Promise<RegistrationView>;
|
|
1893
|
+
register: (input: RegisterInput) => Promise<RegistrationView>;
|
|
1829
1894
|
/** Registered watchers: every one to `manage` everywhere, the caller's own to anyone else. */
|
|
1830
1895
|
watchers: () => Promise<RegistrationView[]>;
|
|
1831
1896
|
/** The caller's matches it can run now, each leased to it until it acks. `wait` holds the request up to that many seconds for one. */
|
|
@@ -1849,6 +1914,8 @@ declare function createBoardClient(options: ClientOptions): {
|
|
|
1849
1914
|
readSource: (key: string, target: string, opts?: {
|
|
1850
1915
|
limit?: number;
|
|
1851
1916
|
}) => Promise<SourceRead>;
|
|
1917
|
+
/** Adds the app to a public channel so `readSource` can read it, where the sync opted in with `join`. Full access only. */
|
|
1918
|
+
joinSource: (key: string, target: string) => Promise<SourceJoin>;
|
|
1852
1919
|
poll: (query?: Filters & {
|
|
1853
1920
|
after?: string;
|
|
1854
1921
|
wait?: number;
|
|
@@ -2580,6 +2647,8 @@ declare abstract class SyncProvider<E extends ProviderEvent = ProviderEvent> {
|
|
|
2580
2647
|
read(_target: string, _options: {
|
|
2581
2648
|
limit: number;
|
|
2582
2649
|
}): Promise<SourceRead>;
|
|
2650
|
+
/** Adds the board's app to a channel so `read` can read it, where the board opted in. Throws `UnreadableError` otherwise. */
|
|
2651
|
+
join(_target: string): Promise<SourceJoin>;
|
|
2583
2652
|
edit(_thread: string, _message: string, _body: ProviderPost): Promise<void>;
|
|
2584
2653
|
delete(_thread: string, _message: string): Promise<void>;
|
|
2585
2654
|
react(_thread: string, _message: string, _emoji: string, _added: boolean): Promise<void>;
|
|
@@ -2600,4 +2669,4 @@ declare abstract class SyncProvider<E extends ProviderEvent = ProviderEvent> {
|
|
|
2600
2669
|
render(input: RenderInput): string;
|
|
2601
2670
|
}
|
|
2602
2671
|
//#endregion
|
|
2603
|
-
export { Discovery as $,
|
|
2672
|
+
export { Discovery as $, SyncCodeView as $t, SyncOverrides as A, Ref as At, ReplyOptions as B, SchedulesQuery as Bt, channels as C, MessagesQueryInput as Ct, EventBase as D, PostInput as Dt, render as E, PostBody as Et, BoardClient as F, RouteName as Ft, Written as G, SourceJoinBody as Gt, ScheduleTiming as H, SchedulesQueryOutput as Ht, BoardError as I, ScheduleBody as It, ActorView as J, SourceReadQuery as Jt, duration as K, SourceMessage as Kt, Filters as L, ScheduleBodyOutput as Lt, SyncRoot as M, RegisterInput as Mt, envelope as N, RegistrationView as Nt, ProviderEvent as O, REGISTERED_WATCHERS_MAX as Ot, eventSchema as P, ResolvedSyncTarget as Pt, DeleteBody as Q, SyncCodeBody as Qt, PostOptions as R, ScheduleInput as Rt, SyncUnit as S, routes as Sn, MessagesQuery as St, mirror as T, PersonView as Tt, UploadInput as U, SignInQuery as Ut, ScheduleOptions as V, SchedulesQueryInput as Vt, WaitOptions as W, SourceJoin as Wt, BoardEventView as X, SyncAccountInput as Xt, ApiError as Y, SyncAccountBody as Yt, ChannelView as Z, SyncBody as Zt, withUserTokens as _, ThreadsQueryInput as _n, MatchView as _t, ProviderOptions as a, SyncImportBody as an, IdentityUnlinkBody as at, SyncIn as b, UploadStartBody as bn, MessageView as bt, ReceivedEvent as c, SyncReceiptInput as cn, InboxEntry as ct, ResolvedTarget as d, SyncUnlinkBody as dn, InboxPushBody as dt, SyncCopiesQuery as en, EditBody as et, SyncContext as f, SyncedView as fn, InboxQuery as ft, connectUserTokens as g, ThreadsQuery as gn, LinkedQuery as gt, UserTokens as h, ThreadsPage as hn, LinkedAccount as ht, ProviderFile as i, SyncFindView as in, FiltersInput as it, SyncResult as j, RegisterBody as jt, RootOverride as k, ReactBody as kt, RenderInput as l, SyncRootsQuery as ln, InboxItem as lt, UnreadableError as m, ThreadView as mn, LinkView as mt, FileDelivery as n, SyncFindInput as nn, EventsQuery as nt, ProviderPost as o, SyncImportInput as on, IdentityView as ot, SyncProvider as p, ThreadSummaryView as pn, LabelBody as pt, AckBody as q, SourceRead as qt, ProviderDelivery as r, SyncFindQuery as rn, EventsQueryInput as rt, Receive as s, SyncReceiptBody as sn, InboxAckBody as st, FetchedLink as t, SyncCopiesView as tn, EventsPage as tt, Renderer as u, SyncThreadView as un, InboxNextQuery as ut, Sync as v, TypingBody as vn, MatchesQuery as vt, into as w, ParsedFilters as wt, SyncOut as x, UploadTicket as xn, MessagesPage as xt, SyncFn as y, TypingResult as yn, Me as yt, ProfileOption as z, ScheduleView as zt };
|
|
@@ -188,6 +188,10 @@ var SyncProvider = class {
|
|
|
188
188
|
async read(_target, _options) {
|
|
189
189
|
throw new UnreadableError("unsupported", `${this.platform} can't be read on demand`);
|
|
190
190
|
}
|
|
191
|
+
/** Adds the board's app to a channel so `read` can read it, where the board opted in. Throws `UnreadableError` otherwise. */
|
|
192
|
+
async join(_target) {
|
|
193
|
+
throw new UnreadableError("unsupported", `${this.platform} can't join channels on demand`);
|
|
194
|
+
}
|
|
191
195
|
async edit(_thread, _message, _body) {}
|
|
192
196
|
async delete(_thread, _message) {}
|
|
193
197
|
async react(_thread, _message, _emoji, _added) {}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { o as localTokenFile } from "./backend-http-
|
|
2
|
-
import { t as board } from "./server-
|
|
3
|
-
import { t as oidcTokens } from "./tokens-
|
|
4
|
-
import { n as fsBlob, t as a2 } from "./a2-
|
|
1
|
+
import { o as localTokenFile } from "./backend-http-c-VHpUOs.mjs";
|
|
2
|
+
import { t as board } from "./server-BqVickb5.mjs";
|
|
3
|
+
import { t as oidcTokens } from "./tokens-DUXaXwOj.mjs";
|
|
4
|
+
import { n as fsBlob, t as a2 } from "./a2-D__qQpe7.mjs";
|
|
5
5
|
import { t as localScheduler } from "./local-DhkrAqPP.mjs";
|
|
6
6
|
import { mkdir, rm, writeFile } from "node:fs/promises";
|
|
7
7
|
import { userInfo } from "node:os";
|
|
@@ -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-DqWJ7nzC.mjs";
|
|
2
|
+
import { t as http } from "./backend-http-c-VHpUOs.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-BjH8jMDi.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-kHfSOXnQ.mjs"),
|
|
13
|
+
serving: () => import("./serving-B307gppu.mjs")
|
|
14
14
|
});
|
|
15
15
|
}
|
|
16
16
|
//#endregion
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as ownTeamId, n as discoveryIdentity, r as ownProjectId, t as oidcTokens } from "./tokens-
|
|
1
|
+
import { i as ownTeamId, n as discoveryIdentity, r as ownProjectId, t as oidcTokens } from "./tokens-DUXaXwOj.mjs";
|
|
2
2
|
export { discoveryIdentity, oidcTokens, ownProjectId, ownTeamId };
|
package/dist/sync-github.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as SyncUnit, _ as withUserTokens, d as ResolvedTarget, f as SyncContext, h as UserTokens, o as ProviderPost, r as ProviderDelivery, y as SyncFn } from "./provider-
|
|
2
|
-
import { n as ChatSyncProvider } from "./chat-provider-
|
|
1
|
+
import { S as SyncUnit, _ as withUserTokens, d as ResolvedTarget, f as SyncContext, h as UserTokens, o as ProviderPost, r as ProviderDelivery, y as SyncFn } from "./provider-D11Dfda0.mjs";
|
|
2
|
+
import { n as ChatSyncProvider } from "./chat-provider-D0k3y8zY.mjs";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { Adapter } from "chat";
|
|
5
5
|
//#region src/sync/github.d.ts
|
package/dist/sync-github.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { c as into, d as withRoutes } from "./provider-
|
|
1
|
+
import { c as into, d as withRoutes } from "./provider-poIkXapd.mjs";
|
|
2
2
|
import { i as eventSchema, r as envelope } from "./events-CewD4kw7.mjs";
|
|
3
3
|
import { r as withUserTokens, t as connectUserTokens } from "./users-yryHKFMo.mjs";
|
|
4
|
-
import { r as markdownOf, t as ChatSyncProvider } from "./chat-provider-
|
|
4
|
+
import { r as markdownOf, t as ChatSyncProvider } from "./chat-provider-DnHibqnM.mjs";
|
|
5
5
|
import { z } from "zod";
|
|
6
6
|
import { connectGitHubAdapter } from "@vercel/connect/chat";
|
|
7
7
|
import { createGitHubAdapter } from "@chat-adapter/github";
|
package/dist/sync-kapso.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as SyncUnit, f as SyncContext, y as SyncFn } from "./provider-
|
|
2
|
-
import { n as ChatSyncProvider, t as ChatInput } from "./chat-provider-
|
|
1
|
+
import { S as SyncUnit, f as SyncContext, y as SyncFn } from "./provider-D11Dfda0.mjs";
|
|
2
|
+
import { n as ChatSyncProvider, t as ChatInput } from "./chat-provider-D0k3y8zY.mjs";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { Adapter } from "chat";
|
|
5
5
|
//#region src/sync/kapso.d.ts
|
package/dist/sync-kapso.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { s as channels } from "./provider-
|
|
1
|
+
import { s as channels } from "./provider-poIkXapd.mjs";
|
|
2
2
|
import { i as eventSchema, r as envelope } from "./events-CewD4kw7.mjs";
|
|
3
|
-
import { r as markdownOf, t as ChatSyncProvider } from "./chat-provider-
|
|
3
|
+
import { r as markdownOf, t as ChatSyncProvider } from "./chat-provider-DnHibqnM.mjs";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
//#region src/sync/kapso.ts
|
|
6
6
|
const decode = (id) => id.split(":").map((part) => Buffer.from(part, "base64url").toString("utf8")).join(":");
|
package/dist/sync-linear.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as SyncUnit, c as ReceivedEvent, d as ResolvedTarget, f as SyncContext, o as ProviderPost, r as ProviderDelivery, y as SyncFn } from "./provider-
|
|
2
|
-
import { n as ChatSyncProvider, t as ChatInput } from "./chat-provider-
|
|
1
|
+
import { S as SyncUnit, c as ReceivedEvent, d as ResolvedTarget, f as SyncContext, o as ProviderPost, r as ProviderDelivery, y as SyncFn } from "./provider-D11Dfda0.mjs";
|
|
2
|
+
import { n as ChatSyncProvider, t as ChatInput } from "./chat-provider-D0k3y8zY.mjs";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { Adapter } from "chat";
|
|
5
5
|
//#region src/sync/linear.d.ts
|
package/dist/sync-linear.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { i as UnreadableError, s as channels } from "./provider-
|
|
1
|
+
import { i as UnreadableError, s as channels } from "./provider-poIkXapd.mjs";
|
|
2
2
|
import { i as eventSchema, r as envelope } from "./events-CewD4kw7.mjs";
|
|
3
|
-
import { r as markdownOf, t as ChatSyncProvider } from "./chat-provider-
|
|
3
|
+
import { r as markdownOf, t as ChatSyncProvider } from "./chat-provider-DnHibqnM.mjs";
|
|
4
4
|
import "zod";
|
|
5
5
|
import { connectLinearAdapter } from "@vercel/connect/chat";
|
|
6
6
|
import { createLinearAdapter } from "@chat-adapter/linear";
|
package/dist/sync-slack.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { f as ExternalLink } from "./folds-CRYY14kc.mjs";
|
|
2
|
-
import { C as channels, _ as withUserTokens, d as ResolvedTarget, f as SyncContext, h as UserTokens, o as ProviderPost, r as ProviderDelivery, y as SyncFn } from "./provider-
|
|
3
|
-
import { n as ChatSyncProvider, t as ChatInput } from "./chat-provider-
|
|
2
|
+
import { C as channels, _ as withUserTokens, d as ResolvedTarget, f as SyncContext, h as UserTokens, o as ProviderPost, r as ProviderDelivery, y as SyncFn } from "./provider-D11Dfda0.mjs";
|
|
3
|
+
import { n as ChatSyncProvider, t as ChatInput } from "./chat-provider-D0k3y8zY.mjs";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import { Adapter } from "chat";
|
|
6
6
|
//#region src/sync/slack.d.ts
|
|
@@ -46,6 +46,10 @@ export type SlackClient = {
|
|
|
46
46
|
messages?: SlackMessage[];
|
|
47
47
|
has_more?: boolean;
|
|
48
48
|
}>;
|
|
49
|
+
/** Adds the app to a public channel, for `vb sources <key> join`; needs `channels:join`. */
|
|
50
|
+
join?(args: {
|
|
51
|
+
channel: string;
|
|
52
|
+
}): Promise<unknown>;
|
|
49
53
|
};
|
|
50
54
|
users?: {
|
|
51
55
|
info(args: {
|
|
@@ -320,6 +324,11 @@ export type SlackOptions = {
|
|
|
320
324
|
adapter: Adapter | string;
|
|
321
325
|
/** Not needed with a connector. */
|
|
322
326
|
client?: () => Promise<SlackClient>;
|
|
327
|
+
/**
|
|
328
|
+
* Lets `vb sources <key> join` add the app to a public channel, so it can be read on demand
|
|
329
|
+
* without syncing it. Off by default; the app needs `channels:join`.
|
|
330
|
+
*/
|
|
331
|
+
join?: boolean;
|
|
323
332
|
};
|
|
324
333
|
/**
|
|
325
334
|
* Syncs a Slack workspace with the board: `app` is a Vercel Connect connector
|
package/dist/sync-slack.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { m as MESSAGE_TEXT_MAX } from "./schemas-Be08nyfW.mjs";
|
|
2
2
|
import "./external-BV_cUncs.mjs";
|
|
3
|
-
import { i as UnreadableError, s as channels } from "./provider-
|
|
3
|
+
import { i as UnreadableError, s as channels } from "./provider-poIkXapd.mjs";
|
|
4
4
|
import { i as eventSchema, r as envelope } from "./events-CewD4kw7.mjs";
|
|
5
5
|
import { r as withUserTokens, t as connectUserTokens } from "./users-yryHKFMo.mjs";
|
|
6
|
-
import { r as markdownOf, t as ChatSyncProvider } from "./chat-provider-
|
|
6
|
+
import { r as markdownOf, t as ChatSyncProvider } from "./chat-provider-DnHibqnM.mjs";
|
|
7
7
|
import { z } from "zod";
|
|
8
8
|
import { stringifyMarkdown } from "chat";
|
|
9
9
|
import { createSlackAdapter } from "@chat-adapter/slack";
|
|
@@ -318,6 +318,26 @@ var SlackProvider = class extends ChatSyncProvider {
|
|
|
318
318
|
if (!found) throw new UnreadableError("channel_not_found", publicOnly ? `no public Slack channel named #${name} (the app lacks groups:read, so a private channel needs its ID)` : `no Slack channel named #${name} (a private channel shows up once the app is invited)`);
|
|
319
319
|
return found;
|
|
320
320
|
}
|
|
321
|
+
async function targetOf(web, target) {
|
|
322
|
+
const link = new RegExp(PERMALINK.source).exec(target);
|
|
323
|
+
if (link) {
|
|
324
|
+
const [, id, seconds, micros, query] = link;
|
|
325
|
+
return {
|
|
326
|
+
channel: id,
|
|
327
|
+
thread: /[?&]thread_ts=(\d+\.\d+)/.exec(query?.replaceAll("&", "&") ?? "")?.[1] ?? `${seconds}.${micros}`
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
if (target.startsWith("#")) return {
|
|
331
|
+
channel: (await find(web, target.slice(1))).id,
|
|
332
|
+
thread: null
|
|
333
|
+
};
|
|
334
|
+
const parsed = /^([A-Z0-9]+)(?::(\d+\.\d+))?$/.exec(target);
|
|
335
|
+
if (!parsed) throw new UnreadableError("invalid_target", `not a Slack channel, thread, or message link: ${target} (try #name, C0123, C0123:1727000000.123456, or a permalink)`);
|
|
336
|
+
return {
|
|
337
|
+
channel: parsed[1],
|
|
338
|
+
thread: parsed[2] ?? null
|
|
339
|
+
};
|
|
340
|
+
}
|
|
321
341
|
const avatars = /* @__PURE__ */ new Map();
|
|
322
342
|
function avatarOf(user) {
|
|
323
343
|
let promise = avatars.get(user);
|
|
@@ -488,20 +508,9 @@ var SlackProvider = class extends ChatSyncProvider {
|
|
|
488
508
|
async read(target, { limit }) {
|
|
489
509
|
const web = await client();
|
|
490
510
|
if (!web) throw new UnreadableError("no_client", "no Slack client to read it with");
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
if (link) {
|
|
495
|
-
const [, id, seconds, micros, query] = link;
|
|
496
|
-
channel = id;
|
|
497
|
-
thread = /[?&]thread_ts=(\d+\.\d+)/.exec(query?.replaceAll("&", "&") ?? "")?.[1] ?? `${seconds}.${micros}`;
|
|
498
|
-
} else if (target.startsWith("#")) channel = (await find(web, target.slice(1))).id;
|
|
499
|
-
else {
|
|
500
|
-
const parsed = /^([A-Z0-9]+)(?::(\d+\.\d+))?$/.exec(target);
|
|
501
|
-
if (!parsed) throw new UnreadableError("invalid_target", `not a Slack channel, thread, or message link: ${target} (try #name, C0123, C0123:1727000000.123456, or a permalink)`);
|
|
502
|
-
channel = parsed[1];
|
|
503
|
-
thread = parsed[2] ?? null;
|
|
504
|
-
}
|
|
511
|
+
const parsed = await targetOf(web, target);
|
|
512
|
+
const channel = parsed.channel;
|
|
513
|
+
let thread = parsed.thread;
|
|
505
514
|
let found;
|
|
506
515
|
let more = false;
|
|
507
516
|
let name = null;
|
|
@@ -512,7 +521,7 @@ var SlackProvider = class extends ChatSyncProvider {
|
|
|
512
521
|
const label = name ? `#${name}` : channel;
|
|
513
522
|
if (info.is_private || info.is_im || info.is_mpim) throw new UnreadableError("private_channel", `${label} is private: the board only reads public channels on demand`);
|
|
514
523
|
if (info.is_ext_shared) throw new UnreadableError("shared_channel", `${label} is shared with another organization: the board doesn't read those on demand`);
|
|
515
|
-
if (!info.is_member) throw new UnreadableError("not_in_channel", `the app isn't in ${label}: someone needs to add it (it won't join on its own)`);
|
|
524
|
+
if (!info.is_member) throw new UnreadableError("not_in_channel", options.join ? `the app isn't in ${label}: join it first with \`vb sources <key> join ${label}\`, which adds the app there` : `the app isn't in ${label}: someone needs to add it (it won't join on its own)`);
|
|
516
525
|
if (thread) {
|
|
517
526
|
const replies = web.conversations.replies;
|
|
518
527
|
if (!replies) throw new UnreadableError("no_client", "this Slack client can't read threads");
|
|
@@ -562,6 +571,37 @@ var SlackProvider = class extends ChatSyncProvider {
|
|
|
562
571
|
more: more || found.length > limit
|
|
563
572
|
};
|
|
564
573
|
},
|
|
574
|
+
async join(target) {
|
|
575
|
+
if (!options.join) throw new UnreadableError("join_disabled", "this board doesn't join Slack channels: it needs `join: true` on slack()");
|
|
576
|
+
const web = await client();
|
|
577
|
+
if (!web) throw new UnreadableError("no_client", "no Slack client to join with");
|
|
578
|
+
const { channel } = await targetOf(web, target);
|
|
579
|
+
try {
|
|
580
|
+
const info = (await web.conversations.info({ channel })).channel;
|
|
581
|
+
if (!info) throw new UnreadableError("channel_not_found", `no Slack channel ${channel}`);
|
|
582
|
+
const name = info.name ?? null;
|
|
583
|
+
const label = name ? `#${name}` : channel;
|
|
584
|
+
if (info.is_private || info.is_im || info.is_mpim) throw new UnreadableError("private_channel", `${label} is private: the app can only be invited there`);
|
|
585
|
+
if (info.is_ext_shared) throw new UnreadableError("shared_channel", `${label} is shared with another organization: the board doesn't join those`);
|
|
586
|
+
if (info.is_member) return {
|
|
587
|
+
channel,
|
|
588
|
+
name,
|
|
589
|
+
joined: false
|
|
590
|
+
};
|
|
591
|
+
if (!web.conversations.join) throw new UnreadableError("no_client", "this Slack client can't join channels");
|
|
592
|
+
await web.conversations.join({ channel });
|
|
593
|
+
return {
|
|
594
|
+
channel,
|
|
595
|
+
name,
|
|
596
|
+
joined: true
|
|
597
|
+
};
|
|
598
|
+
} catch (error) {
|
|
599
|
+
if (error instanceof UnreadableError) throw error;
|
|
600
|
+
const code = slackError(error).split(",")[0];
|
|
601
|
+
if (code === "missing_scope") throw new UnreadableError(code, "the Slack app can't join channels: it needs the channels:join scope");
|
|
602
|
+
throw new UnreadableError(code, `Slack refused to join ${target}: ${slackError(error)}`);
|
|
603
|
+
}
|
|
604
|
+
},
|
|
565
605
|
intercept(key, _headers, body) {
|
|
566
606
|
let event;
|
|
567
607
|
try {
|
package/dist/sync.chat.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as externalAuthor, n as ChatSyncProvider, r as ChatTransport, t as ChatInput } from "./chat-provider-
|
|
1
|
+
import { i as externalAuthor, n as ChatSyncProvider, r as ChatTransport, t as ChatInput } from "./chat-provider-D0k3y8zY.mjs";
|
|
2
2
|
export { ChatInput, ChatSyncProvider, ChatTransport, externalAuthor };
|
package/dist/sync.chat.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as externalAuthor, t as ChatSyncProvider } from "./chat-provider-
|
|
1
|
+
import { n as externalAuthor, t as ChatSyncProvider } from "./chat-provider-DnHibqnM.mjs";
|
|
2
2
|
export { ChatSyncProvider, externalAuthor };
|
package/dist/sync.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { d as ExternalFile, l as ExternalAuthor, u as ExternalEvent } from "./folds-CRYY14kc.mjs";
|
|
2
|
-
import { A as SyncOverrides, C as channels, D as EventBase, E as render, M as SyncRoot, N as envelope, O as ProviderEvent, P as eventSchema, S as SyncUnit, T as mirror, _ as withUserTokens, a as ProviderOptions, b as SyncIn, c as ReceivedEvent, d as ResolvedTarget, f as SyncContext, g as connectUserTokens, h as UserTokens, i as ProviderFile, j as SyncResult, k as RootOverride, l as RenderInput, m as UnreadableError, n as FileDelivery, o as ProviderPost, p as SyncProvider, r as ProviderDelivery, s as Receive, u as Renderer, v as Sync, w as into, x as SyncOut, y as SyncFn } from "./provider-
|
|
2
|
+
import { A as SyncOverrides, C as channels, D as EventBase, E as render, M as SyncRoot, N as envelope, O as ProviderEvent, P as eventSchema, S as SyncUnit, T as mirror, _ as withUserTokens, a as ProviderOptions, b as SyncIn, c as ReceivedEvent, d as ResolvedTarget, f as SyncContext, g as connectUserTokens, h as UserTokens, i as ProviderFile, j as SyncResult, k as RootOverride, l as RenderInput, m as UnreadableError, n as FileDelivery, o as ProviderPost, p as SyncProvider, r as ProviderDelivery, s as Receive, u as Renderer, v as Sync, w as into, x as SyncOut, y as SyncFn } from "./provider-D11Dfda0.mjs";
|
|
3
3
|
export { EventBase, type ExternalAuthor, ExternalEvent, type ExternalFile, type FileDelivery, type ProviderDelivery, type ProviderEvent, type ProviderFile, type ProviderOptions, type ProviderPost, type Receive, ReceivedEvent, type RenderInput, type Renderer, ResolvedTarget, type RootOverride, type Sync, type SyncContext, type SyncFn, type SyncIn, type SyncOut, SyncOverrides, SyncProvider, type SyncResult, type SyncRoot, type SyncUnit, UnreadableError, type UserTokens, channels, connectUserTokens, envelope, eventSchema, into, mirror, render, withUserTokens };
|
package/dist/sync.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as ExternalEvent } from "./external-BV_cUncs.mjs";
|
|
2
|
-
import { c as into, i as UnreadableError, l as mirror, n as ResolvedTarget, r as SyncProvider, s as channels, t as ReceivedEvent, u as render } from "./provider-
|
|
2
|
+
import { c as into, i as UnreadableError, l as mirror, n as ResolvedTarget, r as SyncProvider, s as channels, t as ReceivedEvent, u as render } from "./provider-poIkXapd.mjs";
|
|
3
3
|
import { i as eventSchema, n as SyncOverrides, r as envelope, t as EventBase } from "./events-CewD4kw7.mjs";
|
|
4
4
|
import { r as withUserTokens, t as connectUserTokens } from "./users-yryHKFMo.mjs";
|
|
5
5
|
export { EventBase, ExternalEvent, ReceivedEvent, ResolvedTarget, SyncOverrides, SyncProvider, UnreadableError, channels, connectUserTokens, envelope, eventSchema, into, mirror, render, withUserTokens };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { l as unauthorized } from "./errors-
|
|
2
|
-
import { f as markVerified, m as trustedIssuers, n as TOKENS, r as VERCEL_ISSUER, u as issuerName } from "./auth-
|
|
1
|
+
import { l as unauthorized } from "./errors-CQ-fwxM3.mjs";
|
|
2
|
+
import { f as markVerified, m as trustedIssuers, n as TOKENS, r as VERCEL_ISSUER, u as issuerName } from "./auth-5nLsx9qB.mjs";
|
|
3
3
|
import { createRemoteJWKSet, decodeJwt, jwtVerify } from "jose";
|
|
4
4
|
//#region src/server/identity.ts
|
|
5
5
|
let fromDisk;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { n as DIRECT_UPLOAD_BYTES_MAX, t as ATTACHMENT_BYTES_MAX } from "./files-SniSmeEr.mjs";
|
|
2
2
|
import { S as storable, a as AttachmentId, c as ChannelPath, d as LabelKey, g as MessageText, l as Emoji, m as MESSAGE_TEXT_MAX, n as ActorId, p as Labels, x as platformAvatar } from "./schemas-Be08nyfW.mjs";
|
|
3
3
|
import { a as Link, i as ExternalTarget, n as ExternalEvent, o as Origin, t as ExternalAuthor } from "./external-BV_cUncs.mjs";
|
|
4
|
-
import { r as badRequest, t as HttpError } from "./errors-
|
|
4
|
+
import { r as badRequest, t as HttpError } from "./errors-CQ-fwxM3.mjs";
|
|
5
5
|
import { z } from "zod";
|
|
6
6
|
//#region src/api/routes.ts
|
|
7
7
|
/**
|
|
@@ -114,10 +114,8 @@ const InboxQuery = z.object({
|
|
|
114
114
|
channel: z.string().optional(),
|
|
115
115
|
limit: z.coerce.number().int().min(1).max(500).optional()
|
|
116
116
|
});
|
|
117
|
-
/** What
|
|
118
|
-
const
|
|
119
|
-
/** Without one, the board pulls on its own instead of being woken. */
|
|
120
|
-
url: z.string().url().max(500).refine((url) => /^https:\/\//.test(url), "wake-ups go over https").transform((url) => url.replace(/\/+$/, "")).nullable().optional(),
|
|
117
|
+
/** What every registration carries: its watchers' tails, and its sync entries. */
|
|
118
|
+
const Registering = z.object({
|
|
121
119
|
watch: z.record(z.string().max(100), z.object({
|
|
122
120
|
tail: z.string().max(1e3),
|
|
123
121
|
when: z.enum(["matches", "enters"]).default("matches")
|
|
@@ -132,6 +130,30 @@ const RegisterBody = z.object({
|
|
|
132
130
|
signIn: z.boolean().default(false)
|
|
133
131
|
})).max(32).optional()
|
|
134
132
|
});
|
|
133
|
+
/**
|
|
134
|
+
* What a board on `http()` registers with the board it uses: its watchers, and where to wake it,
|
|
135
|
+
* at a URL or at a path on its own project, never both.
|
|
136
|
+
*/
|
|
137
|
+
const RegisterBody = z.union([Registering.extend({
|
|
138
|
+
/** Without one, the board pulls on its own instead of being woken. */
|
|
139
|
+
url: z.string().url().max(500).refine((url) => /^https:\/\//.test(url), "wake-ups go over https").transform((url) => url.replace(/\/+$/, "")).nullable().optional(),
|
|
140
|
+
path: z.null({ error: "register a url or a path, not both" }).optional(),
|
|
141
|
+
branch: z.null({ error: "a branch goes with a path" }).optional()
|
|
142
|
+
}), Registering.extend({
|
|
143
|
+
url: z.null({ error: "register a url or a path, not both" }).optional(),
|
|
144
|
+
/**
|
|
145
|
+
* Where to wake the caller on its own Vercel project, on a board whose discovery says
|
|
146
|
+
* `wake_by_path`. The board takes the project and environment from the caller's token and
|
|
147
|
+
* finds the deployment, so a project can only register itself, and anyone else gets 403
|
|
148
|
+
* `not_a_project`.
|
|
149
|
+
*/
|
|
150
|
+
path: z.string().max(300).regex(/^\/[^?#]*$/, "a path starts with / and has no query or fragment").transform((path) => path.replace(/(.)\/+$/, "$1")),
|
|
151
|
+
/**
|
|
152
|
+
* From a preview: the branch whose latest ready preview is woken, since a token says which
|
|
153
|
+
* project and environment called but not which deployment. Production names none.
|
|
154
|
+
*/
|
|
155
|
+
branch: z.string().min(1).max(255).nullable().optional()
|
|
156
|
+
})]);
|
|
135
157
|
/** A pull of the caller's matches: at most `limit`, waiting up to `wait` seconds for one. */
|
|
136
158
|
const MatchesQuery = z.object({
|
|
137
159
|
limit: z.coerce.number().int().min(1).max(50).optional(),
|
|
@@ -151,6 +173,8 @@ const SourceReadQuery = z.object({
|
|
|
151
173
|
target: z.string().min(1).max(4e3),
|
|
152
174
|
limit: z.coerce.number().int().min(1).max(200).optional()
|
|
153
175
|
});
|
|
176
|
+
/** A channel to add the board's app to, so it can be read on demand: `#name`, an ID, or a link into it. */
|
|
177
|
+
const SourceJoinBody = z.object({ target: z.string().min(1).max(4e3) });
|
|
154
178
|
/** A platform's link to a message or thread, such as a Slack permalink or a GitHub comment's URL. */
|
|
155
179
|
const LinkedQuery = z.object({ url: z.string().url().max(4e3) });
|
|
156
180
|
const IdentityUnlinkBody = z.object({ actor: z.string().min(1).max(256) });
|
|
@@ -538,6 +562,12 @@ const routes = {
|
|
|
538
562
|
path: "/sources/:key/read",
|
|
539
563
|
query: SourceReadQuery
|
|
540
564
|
},
|
|
565
|
+
/** Adds the app to a public channel so it can be read, where that sync runs and opted in with `join`. Full access only. */
|
|
566
|
+
joinSource: {
|
|
567
|
+
method: "POST",
|
|
568
|
+
path: "/sources/:key/join",
|
|
569
|
+
body: SourceJoinBody
|
|
570
|
+
},
|
|
541
571
|
webhook: {
|
|
542
572
|
method: "POST",
|
|
543
573
|
path: "/webhooks/:key"
|
|
@@ -631,7 +661,7 @@ const routes = {
|
|
|
631
661
|
const SYNC = "@sync";
|
|
632
662
|
//#endregion
|
|
633
663
|
//#region src/version.ts
|
|
634
|
-
const VERSION = "0.
|
|
664
|
+
const VERSION = "0.20.0";
|
|
635
665
|
//#endregion
|
|
636
666
|
//#region src/server/routing.ts
|
|
637
667
|
/** board()'s own routes: the files it serves, and sync's, which run where board() does. */
|
|
@@ -687,6 +717,7 @@ const METHODS = [
|
|
|
687
717
|
"syncUnlink",
|
|
688
718
|
"typing",
|
|
689
719
|
"readSource",
|
|
720
|
+
"joinSource",
|
|
690
721
|
"synced",
|
|
691
722
|
"linked"
|
|
692
723
|
];
|
|
@@ -989,4 +1020,4 @@ function canonicalWatchers(watch, sync = []) {
|
|
|
989
1020
|
return JSON.stringify(canonical);
|
|
990
1021
|
}
|
|
991
1022
|
//#endregion
|
|
992
|
-
export { ScheduleBody as A,
|
|
1023
|
+
export { ScheduleBody as A, SyncImportBody as B, LinkedQuery as C, ReactBody as D, PostBody as E, SyncAccountBody as F, TypingBody as G, SyncRootsQuery as H, SyncBody as I, UploadStartBody as K, SyncCodeBody as L, SignInQuery as M, SourceJoinBody as N, Ref as O, SourceReadQuery as P, SyncCopiesQuery as R, LabelBody as S, MessagesQuery as T, SyncUnlinkBody as U, SyncReceiptBody as V, ThreadsQuery as W, IdentityUnlinkBody as _, withMentions as a, InboxPushBody as b, openapi as c, readJson as d, VERSION as f, EventsQuery as g, EditBody as h, FILTER_FLAGS as i, SchedulesQuery as j, RegisterBody as k, queryObject as l, AckBody as m, compileWatcher as n, METHODS as o, SYNC as p, routes as q, hasCriteria as r, createRouter as s, canonicalWatchers as t, readCapped as u, InboxAckBody as v, MatchesQuery as w, InboxQuery as x, InboxNextQuery as y, SyncFindQuery as z };
|
|
@@ -236,6 +236,13 @@ export const GET = team.fetch, POST = team.fetch
|
|
|
236
236
|
makes this board pull with its own credentials. One that Deployment
|
|
237
237
|
Protection stops answers 401, and the other board tries less often until
|
|
238
238
|
this board pulls or registers.
|
|
239
|
+
- **On a board whose discovery says `wake_by_path`,** this board registers
|
|
240
|
+
its mount path on its own project instead of its URL, and its wake-ups get
|
|
241
|
+
through Deployment Protection with nothing to set up. Only on Vercel, from
|
|
242
|
+
production or a preview of a branch, which it names: the other board finds
|
|
243
|
+
the deployment from this project's token and that branch. Anywhere else
|
|
244
|
+
(development, a custom environment, a preview made with `vercel deploy`), it
|
|
245
|
+
registers its URL.
|
|
239
246
|
- **Retries need the other board's scheduler,** as its own watchers do.
|
|
240
247
|
Without one there, nothing waits on a clock: a retry, a lease that ran out,
|
|
241
248
|
and a wake-up that didn't get there (once its back-off is over) each wait
|