@vercel/board 0.16.0 → 0.18.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 +27 -27
- package/dist/{a2-C41hD8SF.mjs → a2-ChRLRupa.mjs} +969 -25
- package/dist/access.d.mts +1 -1
- package/dist/access.mjs +3 -3
- package/dist/{actors-DjMeZpnU.mjs → actors-BOamkEuz.mjs} +3 -73
- package/dist/attempts-CLG840Oj.mjs +20 -0
- package/dist/{auth-COzc09sn.mjs → auth-Drg9FiC2.mjs} +225 -2
- package/dist/backend-B-SJ7p6p.d.mts +680 -0
- package/dist/backend-a2/contract.d.mts +873 -2
- package/dist/backend-a2/contract.mjs +2 -2
- 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 +78 -1
- package/dist/backend-a2/scheduler-qstash.mjs +521 -1
- package/dist/backend-a2/scheduler-vercel.d.mts +37 -1
- package/dist/backend-a2/scheduler-vercel.mjs +203 -1
- 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 +2850 -2
- package/dist/backend-a2/store-redis-http.d.mts +1 -1
- package/dist/backend-a2/store-redis-http.mjs +490 -2
- package/dist/backend-a2/store-redis.d.mts +10 -2
- package/dist/backend-a2/store-redis.mjs +51 -2
- 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 +2706 -3
- package/dist/backend-a2.mjs +1 -1
- package/dist/{backend-http-Bid7RIpC.d.mts → backend-http-7cNb8nJI.d.mts} +10 -3
- package/dist/{backend-http-0roEmjl0.mjs → backend-http-CMlL3yq3.mjs} +2 -2
- package/dist/{backend-http-BVRno-ca.mjs → backend-http-Ddzd5kTS.mjs} +32 -3
- 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-XCnQlxq6.d.mts → chat-provider-DNJQyajS.d.mts} +16 -4
- package/dist/{chat-provider-jFSeyNmB.mjs → chat-provider-YHy-WbrB.mjs} +15 -9
- package/dist/cli.mjs +30 -10
- package/dist/{client-DGDPaN7U.mjs → client-BA-J7usH.mjs} +10 -2
- package/dist/{conformance-DRR23YNy.mjs → conformance-CT5EeHeC.mjs} +5 -2
- package/dist/conformance.d.mts +1 -1
- package/dist/conformance.mjs +1 -1
- package/dist/{engine-Bir5s8ts.mjs → engine-D0oBUBEK.mjs} +249 -163
- package/dist/events-CewD4kw7.mjs +75 -0
- package/dist/{exports-Dvc1o52I.mjs → exports-CgjfMrQ-.mjs} +35 -32
- package/dist/exports-ZsgjzEnM.d.mts +4 -0
- package/dist/external-BV_cUncs.mjs +151 -0
- package/dist/folds-CRYY14kc.d.mts +534 -0
- package/dist/{reducers-mUPFuFJV.mjs → folds-Dyjput8M.mjs} +6 -73
- package/dist/ids-C6AYo1bu.mjs +31 -0
- package/dist/index.d.mts +4 -4
- package/dist/{index.default-Bkg77Pxn.mjs → index.default-C5Cpz3sa.mjs} +1 -1
- package/dist/index.mjs +5 -5
- package/dist/index.node.d.mts +4 -4
- package/dist/index.node.mjs +3 -3
- package/dist/inspect/app.js +31 -31
- package/dist/inspect/engine.js +5 -5
- package/dist/internal-CvsrprnU-CRY89I-b.mjs +203 -0
- package/dist/{local-Cr_dSjvs.mjs → local-DhkrAqPP.mjs} +1 -1
- package/dist/mentions-CB6ShY4R.mjs +72 -0
- package/dist/{targets-yM5JBUgr.mjs → middleware-CqaCwucP.mjs} +1 -33
- package/dist/platform-B4TnJtWu-CwcTyKg2.mjs +32 -0
- package/dist/{project-CFiArraX.mjs → project-DMDST9kl.mjs} +1 -1
- package/dist/{provider-BGjz-mDa.d.mts → provider-B0b9Qxw4.d.mts} +170 -40
- package/dist/provider-B3DpYSDq.mjs +220 -0
- package/dist/redis-tables-DN9PfIDi.mjs +3897 -0
- package/dist/reducer-CYPHsSmd-BQIfozGi.d.mts +170 -0
- package/dist/reducer-CjmvZSAb-D_OSISmj.mjs +74 -0
- package/dist/{contract-CuJmlrhw.mjs → reducers-BFmIXilu.mjs} +260 -287
- package/dist/retryable-lazy-DZWmHpii-Bye-W8q7.mjs +19 -0
- package/dist/scheduler-task-X1SToDjP-BVoWuInI.mjs +69 -0
- package/dist/{serve-BsOOc-6_.mjs → serve-BGYw0uNL.mjs} +5 -5
- package/dist/{server-jwPY7_wi.mjs → server-DPxBSogx.mjs} +4 -4
- package/dist/server-DtFrWxi3-Boa6gdWO.mjs +3602 -0
- package/dist/server-qgez0Xny-D5mLfqFQ.d.mts +385 -0
- package/dist/{serving-BNbzc96L.mjs → serving-CNkgUPW1.mjs} +1 -1
- package/dist/session-clear-wHd5GCpZ-BnKSxReK.mjs +51 -0
- package/dist/{sql-DbiEnqM0.mjs → sql-U9WTxrwJ.mjs} +2 -2
- package/dist/{sqlite-db-Cbj03vmp.mjs → sqlite-db-Ds4majtT.mjs} +1 -1
- package/dist/store-D0MhBvg6-4Z2L0Kqd.d.mts +530 -0
- package/dist/store-N8PXxDAS-BWBgzBHp.mjs +5 -0
- package/dist/store-codec-DwrWlgQx-CYxGW0aD.mjs +61 -0
- package/dist/store-memory-Bas9Uq5C.mjs +872 -0
- package/dist/store-memory-ZLiZbH3R.mjs +2 -0
- package/dist/store-polling-BZt2Rf3D-BiEM6_HB.mjs +148 -0
- package/dist/store-presence-polling-JuAy2Ck2-CYpuK75X.mjs +109 -0
- package/dist/store-sqlite-BmwL3pUR.mjs +2 -0
- package/dist/store-sqlite-CxxPCcCT.mjs +1053 -0
- package/dist/stream-buffer-DrTyiIuo-BKy-vI14.mjs +53 -0
- package/dist/sync-github.d.mts +24 -17
- package/dist/sync-github.mjs +89 -22
- package/dist/sync-kapso.d.mts +15 -13
- package/dist/sync-kapso.mjs +17 -14
- package/dist/sync-linear.d.mts +219 -0
- package/dist/sync-linear.mjs +311 -0
- package/dist/sync-slack.d.mts +12 -17
- package/dist/sync-slack.mjs +54 -42
- package/dist/sync.chat.d.mts +1 -1
- package/dist/sync.chat.mjs +1 -1
- package/dist/sync.d.mts +3 -3
- package/dist/sync.mjs +5 -4
- package/dist/targets-C-wdR5wP.mjs +33 -0
- package/dist/{tokens-DKLn5P9B.mjs → tokens-DhuzKzAl.mjs} +1 -1
- package/dist/{types-BHCjTZdB.d.mts → types-8yq2VnKI.d.mts} +2 -2
- package/dist/{users-Dls7_ANV.mjs → users-yryHKFMo.mjs} +2 -2
- package/dist/{watch-spec-W0c7ypHJ.mjs → watchers-hash-RLtnSF-t.mjs} +233 -28
- package/docs/01-board/01-mounting.md +1 -1
- package/docs/02-sync/01-overview.md +72 -48
- package/docs/02-sync/02-functions.md +398 -0
- package/docs/02-sync/03-slack.md +30 -25
- package/docs/02-sync/04-github.md +62 -26
- package/docs/02-sync/05-whatsapp.md +23 -19
- package/docs/02-sync/06-providers.md +60 -27
- package/docs/02-sync/07-linear.md +129 -0
- package/docs/03-guides/04-triage.md +1 -1
- package/docs/04-reference/01-cli.md +26 -6
- package/docs/04-reference/02-board.md +18 -5
- package/docs/04-reference/03-http.md +5 -2
- package/docs/04-reference/05-conformance.md +1 -1
- package/docs/index.md +5 -10
- package/package.json +31 -6
- package/dist/a2-D24cvwpN.d.mts +0 -3359
- package/dist/access-CJU2-vaa.mjs +0 -226
- package/dist/attempts-Bxp9KgPf.mjs +0 -919
- package/dist/exports-DLiE7fLY.d.mts +0 -4
- package/dist/provider-CuewcDNZ.mjs +0 -205
- package/dist/redis-tables-B35vv4CZ.mjs +0 -842
- package/dist/reducers-B_vUGQRp.d.mts +0 -1172
- package/dist/watchers-hash-CLjsa6od.mjs +0 -225
- package/docs/02-sync/02-callbacks.md +0 -265
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as AccessSummary } from "./access-CV96SYgr.mjs";
|
|
2
2
|
import { i as Attachment } from "./schemas-CWxs3ECJ.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { a as ExternalCopy, d as ExternalFile, f as ExternalLink, g as BoardEvent, l as ExternalAuthor, o as Message, p as Link, r as Channel, t as Actor, u as ExternalEvent } from "./folds-CRYY14kc.mjs";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
//#region src/api/routes.d.ts
|
|
6
6
|
/**
|
|
@@ -26,6 +26,8 @@ declare const Filters$1: z.ZodObject<{
|
|
|
26
26
|
from: z.ZodOptional<z.ZodString>;
|
|
27
27
|
text: z.ZodOptional<z.ZodString>;
|
|
28
28
|
}, z.core.$strip>;
|
|
29
|
+
/** The filters a query asks for, as the board parsed them. */
|
|
30
|
+
type ParsedFilters = z.output<typeof Filters$1>;
|
|
29
31
|
declare const MessagesQuery: z.ZodObject<{
|
|
30
32
|
channel: z.ZodOptional<z.ZodString>;
|
|
31
33
|
re: z.ZodOptional<z.ZodString>;
|
|
@@ -148,6 +150,10 @@ declare const SourceReadQuery: z.ZodObject<{
|
|
|
148
150
|
target: z.ZodString;
|
|
149
151
|
limit: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
150
152
|
}, z.core.$strip>;
|
|
153
|
+
/** A platform's link to a message or thread, such as a Slack permalink or a GitHub comment's URL. */
|
|
154
|
+
declare const LinkedQuery: z.ZodObject<{
|
|
155
|
+
url: z.ZodString;
|
|
156
|
+
}, z.core.$strip>;
|
|
151
157
|
declare const IdentityUnlinkBody: z.ZodObject<{
|
|
152
158
|
actor: z.ZodString;
|
|
153
159
|
}, z.core.$strip>;
|
|
@@ -468,6 +474,7 @@ declare const InboxPushBody: z.ZodObject<{
|
|
|
468
474
|
owns: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
469
475
|
reply: z.ZodNullable<z.ZodString>;
|
|
470
476
|
createRoot: z.ZodBoolean;
|
|
477
|
+
retitled: z.ZodOptional<z.ZodBoolean>;
|
|
471
478
|
author: z.ZodObject<{
|
|
472
479
|
id: z.ZodString;
|
|
473
480
|
handle: z.ZodString;
|
|
@@ -791,6 +798,25 @@ type MessagesPage = {
|
|
|
791
798
|
messages: MessageView[];
|
|
792
799
|
cursor: string;
|
|
793
800
|
};
|
|
801
|
+
/**
|
|
802
|
+
* Where a message's thread is synced: each target, the platform thread it is there, and this
|
|
803
|
+
* message's copy, with the platform's link to it when the sync that knows the platform runs here.
|
|
804
|
+
*/
|
|
805
|
+
type SyncedView = {
|
|
806
|
+
targets: {
|
|
807
|
+
/** As the thread's sync records it: `slack:C0123ABC`, `github:acme/www:12`. */
|
|
808
|
+
target: string;
|
|
809
|
+
/** The sync entry it belongs to: `slack`. */
|
|
810
|
+
key: string;
|
|
811
|
+
/** The platform thread this message's copy is in, or the one the target is, once it has one. */
|
|
812
|
+
thread: string | null;
|
|
813
|
+
/** This message's copy there, by the platform's ID: null when it has none. */
|
|
814
|
+
message: string | null;
|
|
815
|
+
url: string | null;
|
|
816
|
+
/** Why the message didn't reach it, when it didn't. */
|
|
817
|
+
undelivered: string | null;
|
|
818
|
+
}[];
|
|
819
|
+
};
|
|
794
820
|
type ThreadView = {
|
|
795
821
|
message: MessageView;
|
|
796
822
|
replies: MessageView[];
|
|
@@ -973,6 +999,19 @@ declare const routes: {
|
|
|
973
999
|
target: z.ZodString;
|
|
974
1000
|
}, z.core.$strip>;
|
|
975
1001
|
};
|
|
1002
|
+
/** Where the message's thread is synced, and its copy on each target: needs `read` where it is. */
|
|
1003
|
+
readonly synced: {
|
|
1004
|
+
readonly method: 'GET';
|
|
1005
|
+
readonly path: '/messages/:id/sync';
|
|
1006
|
+
};
|
|
1007
|
+
/** The board message a platform link names, from what the board synced: 404 `message_not_found` for one it didn't, or that the caller can't read. */
|
|
1008
|
+
readonly linked: {
|
|
1009
|
+
readonly method: 'GET';
|
|
1010
|
+
readonly path: '/links';
|
|
1011
|
+
readonly query: z.ZodObject<{
|
|
1012
|
+
url: z.ZodString;
|
|
1013
|
+
}, z.core.$strip>;
|
|
1014
|
+
};
|
|
976
1015
|
/** Ephemeral: shows typing in the thread's synced platform threads, and writes nothing to the log. Needs `post` where the thread is. */
|
|
977
1016
|
readonly typing: {
|
|
978
1017
|
readonly method: 'POST';
|
|
@@ -1141,6 +1180,7 @@ declare const routes: {
|
|
|
1141
1180
|
owns: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1142
1181
|
reply: z.ZodNullable<z.ZodString>;
|
|
1143
1182
|
createRoot: z.ZodBoolean;
|
|
1183
|
+
retitled: z.ZodOptional<z.ZodBoolean>;
|
|
1144
1184
|
author: z.ZodObject<{
|
|
1145
1185
|
id: z.ZodString;
|
|
1146
1186
|
handle: z.ZodString;
|
|
@@ -1752,11 +1792,22 @@ declare function createBoardClient(options: ClientOptions): {
|
|
|
1752
1792
|
* `status` replaces "Typing…" on Slack ("running tests…").
|
|
1753
1793
|
*/
|
|
1754
1794
|
typing: (id: string, status?: string) => Promise<string[]>;
|
|
1755
|
-
/**
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1795
|
+
/**
|
|
1796
|
+
* With a target, attaches the message's thread to it, backfilling it: attaching twice is a no-op.
|
|
1797
|
+
* Without one, where the thread is synced, and this message's copy on each target, with its link.
|
|
1798
|
+
*/
|
|
1799
|
+
sync: {
|
|
1800
|
+
(id: string): Promise<SyncedView>;
|
|
1801
|
+
(id: string, target: string): Promise<{
|
|
1802
|
+
target: string;
|
|
1803
|
+
attached: boolean;
|
|
1804
|
+
}>;
|
|
1805
|
+
};
|
|
1806
|
+
/**
|
|
1807
|
+
* The thread of the board message a platform link names (a Slack permalink, a GitHub comment's
|
|
1808
|
+
* URL), from what the board synced: the platform is never asked. 404 for one it didn't sync.
|
|
1809
|
+
*/
|
|
1810
|
+
linked: (url: string) => Promise<ThreadView>;
|
|
1760
1811
|
/** Raw platform events for a sync entry, newest first. */
|
|
1761
1812
|
inbox: (key: string, opts?: {
|
|
1762
1813
|
channel?: string;
|
|
@@ -2003,6 +2054,7 @@ declare function envelope(platform: string, key: string, event: ExternalEvent, r
|
|
|
2003
2054
|
owns?: string[] | undefined;
|
|
2004
2055
|
reply: string | null;
|
|
2005
2056
|
createRoot: boolean;
|
|
2057
|
+
retitled?: boolean | undefined;
|
|
2006
2058
|
author: {
|
|
2007
2059
|
id: string;
|
|
2008
2060
|
handle: string;
|
|
@@ -2145,6 +2197,7 @@ declare function eventSchema<P extends string, M extends string>(platform: P, me
|
|
|
2145
2197
|
owns: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
2146
2198
|
reply: z.ZodNullable<z.ZodString>;
|
|
2147
2199
|
createRoot: z.ZodBoolean;
|
|
2200
|
+
retitled: z.ZodOptional<z.ZodBoolean>;
|
|
2148
2201
|
author: z.ZodObject<{
|
|
2149
2202
|
id: z.ZodString;
|
|
2150
2203
|
handle: z.ZodString;
|
|
@@ -2181,6 +2234,88 @@ type SyncResult = {
|
|
|
2181
2234
|
message: string | null;
|
|
2182
2235
|
};
|
|
2183
2236
|
//#endregion
|
|
2237
|
+
//#region src/sync/fn.d.ts
|
|
2238
|
+
/** An event coming in from the platform. */
|
|
2239
|
+
type SyncIn<E extends ProviderEvent = ProviderEvent> = {
|
|
2240
|
+
direction: 'in';
|
|
2241
|
+
/** The sync entry's key: `slack` in `sync: { slack: slack(…) }`. */
|
|
2242
|
+
key: string;
|
|
2243
|
+
/** The platform channel it happened in, as the platform names it: `C0123ABC`, `owner/repo:pulls`, a phone number ID. */
|
|
2244
|
+
channel: string;
|
|
2245
|
+
/** The event, validated and frozen. */
|
|
2246
|
+
event: E;
|
|
2247
|
+
/** The board, as the platform user the event came from: its writes are theirs. */
|
|
2248
|
+
board: BoardClient;
|
|
2249
|
+
/**
|
|
2250
|
+
* Imports the event: into its board thread when the board syncs its platform thread, otherwise
|
|
2251
|
+
* as a new root in `channel`. Without a channel, an event in a thread the board doesn't sync
|
|
2252
|
+
* stays off it. Runs once: a second call answers what the first did.
|
|
2253
|
+
*/
|
|
2254
|
+
import(channel?: string, overrides?: SyncOverrides): Promise<SyncResult>;
|
|
2255
|
+
/** The platform's own link to the event's message, or null when it has none. Nothing is synced or joined. */
|
|
2256
|
+
permalink(): Promise<string | null>;
|
|
2257
|
+
/** A platform channel's ID from its name (`#dev` → `C0123ABC`), as `channel` names it. */
|
|
2258
|
+
resolve(name: string): Promise<string>;
|
|
2259
|
+
};
|
|
2260
|
+
/** A board event going out to the platform. */
|
|
2261
|
+
type SyncOut = {
|
|
2262
|
+
direction: 'out';
|
|
2263
|
+
key: string;
|
|
2264
|
+
/** The platform channel `target` is in, as the platform names it; null for a new root, which isn't on the platform yet. */
|
|
2265
|
+
channel: string | null;
|
|
2266
|
+
event: BoardEventView;
|
|
2267
|
+
/** The message the event is about, as it is now. */
|
|
2268
|
+
message: MessageView;
|
|
2269
|
+
/** Where it goes: a platform thread or channel the board thread syncs with (`slack:C0123ABC:1727000000.123456`), or null for a new root. */
|
|
2270
|
+
target: string | null;
|
|
2271
|
+
/**
|
|
2272
|
+
* Sends the event to `target`: a new thread's root and what's been said in it, a reply, an
|
|
2273
|
+
* edit, a delete, a reaction, or the copy a label change re-renders. A new root has no target
|
|
2274
|
+
* yet, so it sends nothing. Runs once: a second call answers what the first did.
|
|
2275
|
+
*/
|
|
2276
|
+
deliver(options?: {
|
|
2277
|
+
render?: Renderer;
|
|
2278
|
+
}): Promise<void>;
|
|
2279
|
+
/**
|
|
2280
|
+
* Syncs the message's thread with a platform channel (`#dev`, `C0123ABC`): the board starts a
|
|
2281
|
+
* thread there, and its root and replies follow. Never the channel it came from.
|
|
2282
|
+
*/
|
|
2283
|
+
start(channel: string): Promise<void>;
|
|
2284
|
+
resolve(name: string): Promise<string>;
|
|
2285
|
+
};
|
|
2286
|
+
type Sync<E extends ProviderEvent = ProviderEvent> = SyncIn<E> | SyncOut;
|
|
2287
|
+
/**
|
|
2288
|
+
* What every event does, both ways. Inbound, it calls `import` to bring the event onto the board;
|
|
2289
|
+
* outbound, `deliver` to send it to the platform, or `start` to open a new root's thread there.
|
|
2290
|
+
* One that calls neither does nothing. A throw is retried.
|
|
2291
|
+
*
|
|
2292
|
+
* The webhook keeps an event (stores it in the inbox for the function) when the board syncs its
|
|
2293
|
+
* thread, or when its channel is one that `channels`, `repos`, or `numbers` routes. A function of
|
|
2294
|
+
* your own at the top keeps every event the platform sends, so keep the helper outermost.
|
|
2295
|
+
*/
|
|
2296
|
+
type SyncFn<E extends ProviderEvent = ProviderEvent> = (sync: Sync<E>) => unknown;
|
|
2297
|
+
/** A sync function, or a board channel: what a string means is up to the helper that takes it. */
|
|
2298
|
+
type SyncUnit<E extends ProviderEvent = ProviderEvent> = string | SyncFn<E>;
|
|
2299
|
+
/**
|
|
2300
|
+
* A two-way mirror of a board channel: what comes in lands in `channel`, what's said on the
|
|
2301
|
+
* board goes out, and a new root in `channel` starts a thread in the platform channel.
|
|
2302
|
+
*/
|
|
2303
|
+
declare function mirror(channel: string): SyncFn;
|
|
2304
|
+
/** Imports into a board channel, and sends nothing back. */
|
|
2305
|
+
declare function into(channel: string): SyncFn;
|
|
2306
|
+
/** `inner`, delivering with `renderer` unless it passes its own. */
|
|
2307
|
+
declare function render<E extends ProviderEvent = ProviderEvent>(renderer: Renderer, inner: SyncFn<E>): SyncFn<E>;
|
|
2308
|
+
/**
|
|
2309
|
+
* Routes each event by its platform channel. Keys are platform channels, by name (`'#dev'`) or
|
|
2310
|
+
* ID (`'C0123ABC'`); values are a board channel to `mirror`, or a sync function. A new root goes
|
|
2311
|
+
* to every channel's function, with `channel` set to that one. A thread the board syncs outside
|
|
2312
|
+
* these channels (someone ran `vb sync` on it) stays synced both ways. A key the platform says
|
|
2313
|
+
* doesn't exist is skipped. While one can't be checked, an event outside the resolved channels
|
|
2314
|
+
* throws, so it's retried, rather than going past that key's function to the default. A new root
|
|
2315
|
+
* starts only in the channels that resolved.
|
|
2316
|
+
*/
|
|
2317
|
+
declare function channels<E extends ProviderEvent = ProviderEvent>(map: Record<string, SyncUnit<E>>): SyncFn<E>;
|
|
2318
|
+
//#endregion
|
|
2184
2319
|
//#region src/sync/users.d.ts
|
|
2185
2320
|
/**
|
|
2186
2321
|
* People's own platform tokens, so a board message they wrote reaches Slack or
|
|
@@ -2201,8 +2336,8 @@ type UserTokens = {
|
|
|
2201
2336
|
};
|
|
2202
2337
|
/**
|
|
2203
2338
|
* Gives an adapter people's tokens, for your own OAuth: `slack({ adapter:
|
|
2204
|
-
* withUserTokens(createSlackAdapter(...), { authorize, token }) })`. A
|
|
2205
|
-
* connector name (`
|
|
2339
|
+
* withUserTokens(createSlackAdapter(...), { authorize, token }) }, sync)`. A
|
|
2340
|
+
* Connect connector name (`slack('slack/acme', sync)`) does this for you.
|
|
2206
2341
|
*/
|
|
2207
2342
|
declare function withUserTokens<A extends object>(adapter: A, tokens: UserTokens): A;
|
|
2208
2343
|
/** Vercel Connect's user tokens for `connector`: the subject is the board's principal, so Connect binds the account to it. */
|
|
@@ -2218,32 +2353,12 @@ declare const ResolvedTarget: z.ZodObject<{
|
|
|
2218
2353
|
}>;
|
|
2219
2354
|
}, z.core.$strict>;
|
|
2220
2355
|
type ResolvedTarget = z.infer<typeof ResolvedTarget>;
|
|
2221
|
-
|
|
2222
|
-
sync(id: string, target: string): ReturnType<BoardClient['sync']>;
|
|
2223
|
-
sync(channel: string, event: E, overrides?: SyncOverrides): Promise<SyncResult>;
|
|
2224
|
-
};
|
|
2225
|
-
type SyncHandler<E extends ProviderEvent> = (args: {
|
|
2226
|
-
event: E;
|
|
2227
|
-
board: SyncClient<E>;
|
|
2228
|
-
/**
|
|
2229
|
-
* The platform's own link to the event's message (Slack's `chat.getPermalink`), fetched on
|
|
2230
|
-
* the first call and kept for the rest of the callback. Null when the event has no single
|
|
2231
|
-
* message or the platform has no links. It only reads the URL: nothing is synced or joined.
|
|
2232
|
-
*/
|
|
2233
|
-
permalink(): Promise<string | null>;
|
|
2234
|
-
}) => unknown;
|
|
2356
|
+
/** The fields a provider's `event` builds its typed event from. */
|
|
2235
2357
|
type SyncContext = {
|
|
2236
2358
|
id: string;
|
|
2237
2359
|
key: string;
|
|
2238
2360
|
event: ExternalEvent;
|
|
2239
2361
|
raw: unknown;
|
|
2240
|
-
board: BoardClient;
|
|
2241
|
-
client<E extends ProviderEvent>(event: E): SyncClient<E>;
|
|
2242
|
-
apply(channel: string, overrides?: SyncOverrides): Promise<SyncResult>;
|
|
2243
|
-
};
|
|
2244
|
-
type ProviderMapping = {
|
|
2245
|
-
channel?: string;
|
|
2246
|
-
run?: (context: SyncContext) => unknown;
|
|
2247
2362
|
};
|
|
2248
2363
|
type RenderInput = {
|
|
2249
2364
|
/** The message as clients see it: its IDs are refs. */
|
|
@@ -2254,16 +2369,19 @@ type RenderInput = {
|
|
|
2254
2369
|
label: string;
|
|
2255
2370
|
target: string;
|
|
2256
2371
|
};
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
run: SyncHandler<E>;
|
|
2260
|
-
};
|
|
2372
|
+
/** How a platform shows a board message: markdown, which the platform converts to its own format. */
|
|
2373
|
+
type Renderer = (input: RenderInput) => string;
|
|
2261
2374
|
type FileDelivery = {
|
|
2262
2375
|
message: string;
|
|
2263
2376
|
files: string[];
|
|
2264
2377
|
};
|
|
2265
2378
|
/** What a linked message said, or why the platform wouldn't say. */
|
|
2266
2379
|
type FetchedLink = Pick<Link, 'snapshot' | 'unavailable'>;
|
|
2380
|
+
/** Why a platform wouldn't read a channel or thread on demand. Its message is shown as is. */
|
|
2381
|
+
declare class UnreadableError extends Error {
|
|
2382
|
+
readonly code: string;
|
|
2383
|
+
constructor(code: string, message: string);
|
|
2384
|
+
}
|
|
2267
2385
|
/** A file to send: its bytes (a Node `Buffer` is one), its name, and its type. */
|
|
2268
2386
|
type ProviderFile = {
|
|
2269
2387
|
data: Uint8Array;
|
|
@@ -2293,7 +2411,6 @@ type ProviderOptions = {
|
|
|
2293
2411
|
canStartThreads?: boolean;
|
|
2294
2412
|
singleReaction?: boolean;
|
|
2295
2413
|
uploadsFiles?: boolean;
|
|
2296
|
-
render?: (input: RenderInput) => string;
|
|
2297
2414
|
/** People's own tokens, to post as them and to link accounts by signing in. */
|
|
2298
2415
|
users?: UserTokens | null;
|
|
2299
2416
|
};
|
|
@@ -2403,6 +2520,7 @@ declare const ReceivedEvent: z.ZodObject<{
|
|
|
2403
2520
|
owns: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
2404
2521
|
reply: z.ZodNullable<z.ZodString>;
|
|
2405
2522
|
createRoot: z.ZodBoolean;
|
|
2523
|
+
retitled: z.ZodOptional<z.ZodBoolean>;
|
|
2406
2524
|
author: z.ZodObject<{
|
|
2407
2525
|
id: z.ZodString;
|
|
2408
2526
|
handle: z.ZodString;
|
|
@@ -2421,11 +2539,11 @@ declare abstract class SyncProvider<E extends ProviderEvent = ProviderEvent> {
|
|
|
2421
2539
|
readonly canStartThreads: boolean;
|
|
2422
2540
|
readonly singleReaction: boolean;
|
|
2423
2541
|
readonly uploadsFiles: boolean;
|
|
2424
|
-
readonly
|
|
2542
|
+
private readonly fn;
|
|
2425
2543
|
/** People's tokens, when the adapter has them: messages they write post as them. */
|
|
2426
2544
|
readonly users: UserTokens | null;
|
|
2427
2545
|
protected readonly options: ProviderOptions;
|
|
2428
|
-
constructor(options: ProviderOptions);
|
|
2546
|
+
constructor(options: ProviderOptions, sync: SyncFn<E>);
|
|
2429
2547
|
abstract receive(key: string, request: Request, emit: Receive): Promise<Response>;
|
|
2430
2548
|
abstract resolveChannel(key: string): Promise<string>;
|
|
2431
2549
|
abstract resolveTarget(target: string): Promise<ResolvedTarget>;
|
|
@@ -2444,6 +2562,17 @@ declare abstract class SyncProvider<E extends ProviderEvent = ProviderEvent> {
|
|
|
2444
2562
|
permalink(_event: E): Promise<string | null>;
|
|
2445
2563
|
/** A linked message the platform didn't describe, read from the platform. */
|
|
2446
2564
|
fetchLink(_link: ExternalLink): Promise<FetchedLink>;
|
|
2565
|
+
/**
|
|
2566
|
+
* The message a URL of this platform's names, by its own thread and message IDs, or null for a
|
|
2567
|
+
* URL that isn't one. `message` is null for a link to a thread itself. It asks the platform
|
|
2568
|
+
* nothing: the board answers from what it synced (`vb read <url>`).
|
|
2569
|
+
*/
|
|
2570
|
+
locate(_url: string): {
|
|
2571
|
+
thread: string;
|
|
2572
|
+
message: string | null;
|
|
2573
|
+
} | null;
|
|
2574
|
+
/** The platform's URL for one of its messages, by its own IDs, or null when it has none (`vb sync <id>`). */
|
|
2575
|
+
url(_thread: string, _message: string): Promise<string | null>;
|
|
2447
2576
|
/**
|
|
2448
2577
|
* A channel or thread, read on demand for whoever asked: nothing is synced,
|
|
2449
2578
|
* stored, or joined. Throws `UnreadableError` for what it won't read.
|
|
@@ -2464,10 +2593,11 @@ declare abstract class SyncProvider<E extends ProviderEvent = ProviderEvent> {
|
|
|
2464
2593
|
deleteFiles(_ids: string[]): Promise<void>;
|
|
2465
2594
|
refusesFiles(_error: unknown): boolean;
|
|
2466
2595
|
uploadFiles(_thread: string, _files: ProviderFile[]): Promise<FileDelivery>;
|
|
2467
|
-
abstract event(context:
|
|
2468
|
-
sync
|
|
2596
|
+
abstract event(context: SyncContext): E;
|
|
2597
|
+
/** Runs the sync function the provider was made with: what every event does, both ways. */
|
|
2598
|
+
sync(sync: Sync<E>): unknown;
|
|
2599
|
+
/** The default rendering: `**${label}**: ${text}`. A `Renderer` passed to `deliver` replaces it. */
|
|
2469
2600
|
render(input: RenderInput): string;
|
|
2470
|
-
protected map(key: string, value: EventMapping<E>): void;
|
|
2471
2601
|
}
|
|
2472
2602
|
//#endregion
|
|
2473
|
-
export {
|
|
2603
|
+
export { Discovery as $, SyncFindInput as $t, SyncOverrides as A, Ref as At, ReplyOptions as B, SchedulesQueryInput as Bt, channels as C, MessagesQueryInput as Ct, EventBase as D, PostInput as Dt, render as E, PostBody as Et, BoardClient as F, ScheduleBody as Ft, Written as G, SourceReadQuery as Gt, ScheduleTiming as H, SignInQuery as Ht, BoardError as I, ScheduleBodyOutput as It, ActorView as J, SyncBody as Jt, duration as K, SyncAccountBody as Kt, Filters as L, ScheduleInput as Lt, SyncRoot as M, RegistrationView as Mt, envelope as N, ResolvedSyncTarget as Nt, ProviderEvent as O, REGISTERED_WATCHERS_MAX as Ot, eventSchema as P, RouteName as Pt, DeleteBody as Q, SyncCopiesView as Qt, PostOptions as R, ScheduleView as Rt, SyncUnit as S, MessagesQuery as St, mirror as T, PersonView as Tt, UploadInput as U, SourceMessage as Ut, ScheduleOptions as V, SchedulesQueryOutput as Vt, WaitOptions as W, SourceRead as Wt, BoardEventView as X, SyncCodeView as Xt, ApiError as Y, SyncCodeBody as Yt, ChannelView as Z, SyncCopiesQuery as Zt, withUserTokens as _, UploadStartBody as _n, MatchView as _t, ProviderOptions as a, SyncReceiptInput as an, IdentityUnlinkBody as at, SyncIn as b, MessageView as bt, ReceivedEvent as c, SyncUnlinkBody as cn, InboxEntry as ct, ResolvedTarget as d, ThreadView as dn, InboxPushBody as dt, SyncFindQuery as en, EditBody as et, SyncContext as f, ThreadsPage as fn, InboxQuery as ft, connectUserTokens as g, TypingResult as gn, LinkedQuery as gt, UserTokens as h, TypingBody as hn, LinkedAccount as ht, ProviderFile as i, SyncReceiptBody as in, FiltersInput as it, SyncResult as j, RegisterBody as jt, RootOverride as k, ReactBody as kt, RenderInput as l, SyncedView as ln, InboxItem as lt, UnreadableError as m, ThreadsQueryInput as mn, LinkView as mt, FileDelivery as n, SyncImportBody as nn, EventsQuery as nt, ProviderPost as o, SyncRootsQuery as on, IdentityView as ot, SyncProvider as p, ThreadsQuery as pn, LabelBody as pt, AckBody as q, SyncAccountInput as qt, ProviderDelivery as r, SyncImportInput as rn, EventsQueryInput as rt, Receive as s, SyncThreadView as sn, InboxAckBody as st, FetchedLink as t, SyncFindView as tn, EventsPage as tt, Renderer as u, ThreadSummaryView as un, InboxNextQuery as ut, Sync as v, UploadTicket as vn, MatchesQuery as vt, into as w, ParsedFilters as wt, SyncOut as x, MessagesPage as xt, SyncFn as y, routes as yn, Me as yt, ProfileOption as z, SchedulesQuery as zt };
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { n as ExternalEvent } from "./external-BV_cUncs.mjs";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
//#region src/sync/fn.ts
|
|
4
|
+
const ROUTES = Symbol.for("board.syncRoutes");
|
|
5
|
+
/** A helper's function, marked with the channels it routes. */
|
|
6
|
+
function withRoutes(fn, routes) {
|
|
7
|
+
Object.defineProperty(fn, ROUTES, {
|
|
8
|
+
value: routes,
|
|
9
|
+
enumerable: false,
|
|
10
|
+
configurable: true
|
|
11
|
+
});
|
|
12
|
+
return fn;
|
|
13
|
+
}
|
|
14
|
+
/** The channels a helper's function routes; undefined for a function of your own, which keeps everything. */
|
|
15
|
+
const routesOf = (fn) => fn[ROUTES];
|
|
16
|
+
/**
|
|
17
|
+
* A two-way mirror of a board channel: what comes in lands in `channel`, what's said on the
|
|
18
|
+
* board goes out, and a new root in `channel` starts a thread in the platform channel.
|
|
19
|
+
*/
|
|
20
|
+
function mirror(channel) {
|
|
21
|
+
return async (sync) => {
|
|
22
|
+
if (sync.direction === "in") return void await sync.import(channel);
|
|
23
|
+
if (sync.target !== null) return sync.deliver();
|
|
24
|
+
if (sync.channel !== null && sync.message.channel === channel) await sync.start(sync.channel);
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/** Imports into a board channel, and sends nothing back. */
|
|
28
|
+
function into(channel) {
|
|
29
|
+
return async (sync) => {
|
|
30
|
+
if (sync.direction === "in") await sync.import(channel);
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/** `inner`, delivering with `renderer` unless it passes its own. */
|
|
34
|
+
function render(renderer, inner) {
|
|
35
|
+
const fn = (sync) => inner(sync.direction === "in" ? sync : {
|
|
36
|
+
...sync,
|
|
37
|
+
deliver: (options = {}) => sync.deliver({
|
|
38
|
+
render: renderer,
|
|
39
|
+
...options
|
|
40
|
+
})
|
|
41
|
+
});
|
|
42
|
+
const routes = routesOf(inner);
|
|
43
|
+
return routes ? withRoutes(fn, routes) : fn;
|
|
44
|
+
}
|
|
45
|
+
/** What a thread the board syncs does outside the mapped channels: it stays synced, both ways. */
|
|
46
|
+
const follow = async (sync) => {
|
|
47
|
+
if (sync.direction === "in") await sync.import();
|
|
48
|
+
else await sync.deliver();
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Routes each event by its platform channel. Keys are platform channels, by name (`'#dev'`) or
|
|
52
|
+
* ID (`'C0123ABC'`); values are a board channel to `mirror`, or a sync function. A new root goes
|
|
53
|
+
* to every channel's function, with `channel` set to that one. A thread the board syncs outside
|
|
54
|
+
* these channels (someone ran `vb sync` on it) stays synced both ways. A key the platform says
|
|
55
|
+
* doesn't exist is skipped. While one can't be checked, an event outside the resolved channels
|
|
56
|
+
* throws, so it's retried, rather than going past that key's function to the default. A new root
|
|
57
|
+
* starts only in the channels that resolved.
|
|
58
|
+
*/
|
|
59
|
+
function channels(map) {
|
|
60
|
+
const units = Object.entries(map).map(([name, unit]) => [name, typeof unit === "string" ? mirror(unit) : unit]);
|
|
61
|
+
const resolved = async (resolve) => {
|
|
62
|
+
const ids = await Promise.allSettled(units.map(([name]) => resolve(name)));
|
|
63
|
+
const found = /* @__PURE__ */ new Map();
|
|
64
|
+
let unchecked;
|
|
65
|
+
ids.forEach((id, i) => {
|
|
66
|
+
if (id.status === "fulfilled") found.set(id.value, units[i][1]);
|
|
67
|
+
else if (!channelMissing(id.reason)) unchecked ??= { reason: id.reason };
|
|
68
|
+
});
|
|
69
|
+
return {
|
|
70
|
+
found,
|
|
71
|
+
unchecked
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
const fn = async (sync) => {
|
|
75
|
+
const { found, unchecked } = await resolved(sync.resolve);
|
|
76
|
+
if (sync.direction === "out" && sync.target === null) {
|
|
77
|
+
for (const [channel, unit] of found) await unit({
|
|
78
|
+
...sync,
|
|
79
|
+
channel
|
|
80
|
+
});
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const unit = found.get(sync.channel);
|
|
84
|
+
if (unit) return void await unit(sync);
|
|
85
|
+
if (unchecked) throw unchecked.reason;
|
|
86
|
+
await follow(sync);
|
|
87
|
+
};
|
|
88
|
+
return withRoutes(fn, async (channel, resolve) => (await resolved(resolve)).found.has(channel));
|
|
89
|
+
}
|
|
90
|
+
//#endregion
|
|
91
|
+
//#region src/sync/provider.ts
|
|
92
|
+
const ResolvedTarget = z.object({
|
|
93
|
+
target: z.string().min(1),
|
|
94
|
+
channel: z.string().min(1),
|
|
95
|
+
kind: z.enum(["channel", "thread"])
|
|
96
|
+
}).strict();
|
|
97
|
+
/** Why a platform wouldn't read a channel or thread on demand. Its message is shown as is. */
|
|
98
|
+
var UnreadableError = class extends Error {
|
|
99
|
+
code;
|
|
100
|
+
constructor(code, message) {
|
|
101
|
+
super(message);
|
|
102
|
+
this.code = code;
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* Whether `resolveChannel` failed because the platform has no such channel, so no event can be
|
|
107
|
+
* in it, rather than because it couldn't tell (a failed listing, a missing scope).
|
|
108
|
+
*/
|
|
109
|
+
const channelMissing = (error) => error instanceof UnreadableError && error.code === "channel_not_found";
|
|
110
|
+
const ReceivedEvent = z.object({
|
|
111
|
+
event: ExternalEvent,
|
|
112
|
+
raw: z.unknown(),
|
|
113
|
+
dedupe: z.string().min(1)
|
|
114
|
+
});
|
|
115
|
+
const routed = /* @__PURE__ */ new WeakMap();
|
|
116
|
+
/** The channels a provider's sync function routes, when a helper made it: the webhook keeps only theirs. */
|
|
117
|
+
const routesFor = (provider) => routed.get(provider);
|
|
118
|
+
var SyncProvider = class {
|
|
119
|
+
platform;
|
|
120
|
+
canStartThreads;
|
|
121
|
+
singleReaction;
|
|
122
|
+
uploadsFiles;
|
|
123
|
+
fn;
|
|
124
|
+
/** People's tokens, when the adapter has them: messages they write post as them. */
|
|
125
|
+
users;
|
|
126
|
+
options;
|
|
127
|
+
constructor(options, sync) {
|
|
128
|
+
if (typeof sync !== "function") throw new Error(`${options.platform} needs a sync function: what each event does, like channels({ '#dev': 'dev' })`);
|
|
129
|
+
this.fn = { run: sync };
|
|
130
|
+
const routes = routesOf(sync);
|
|
131
|
+
if (routes) routed.set(this, routes);
|
|
132
|
+
this.options = options;
|
|
133
|
+
this.users = options.users ?? null;
|
|
134
|
+
this.platform = options.platform;
|
|
135
|
+
this.canStartThreads = options.canStartThreads ?? false;
|
|
136
|
+
this.singleReaction = options.singleReaction ?? false;
|
|
137
|
+
this.uploadsFiles = options.uploadsFiles ?? false;
|
|
138
|
+
}
|
|
139
|
+
/** The platform account a person's token belongs to. */
|
|
140
|
+
async whoAmI(_token) {
|
|
141
|
+
throw new Error(`${this.platform} can't post as a person`);
|
|
142
|
+
}
|
|
143
|
+
/** `post`, as the person whose token this is. */
|
|
144
|
+
async postAs(_token, _target, _kind, _body) {
|
|
145
|
+
throw new Error(`${this.platform} can't post as a person`);
|
|
146
|
+
}
|
|
147
|
+
async editAs(_token, _thread, _message, _body) {}
|
|
148
|
+
async deleteAs(_token, _thread, _message) {}
|
|
149
|
+
async findByEmail(_email) {
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
mention(_actor) {
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
async fetchRoot(_thread) {
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
async fetchFile(_file) {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
/** The platform's own link to an event's message, or null when it has none. */
|
|
162
|
+
async permalink(_event) {
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
/** A linked message the platform didn't describe, read from the platform. */
|
|
166
|
+
async fetchLink(_link) {
|
|
167
|
+
return {
|
|
168
|
+
snapshot: null,
|
|
169
|
+
unavailable: `${this.platform} can't read it`
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* The message a URL of this platform's names, by its own thread and message IDs, or null for a
|
|
174
|
+
* URL that isn't one. `message` is null for a link to a thread itself. It asks the platform
|
|
175
|
+
* nothing: the board answers from what it synced (`vb read <url>`).
|
|
176
|
+
*/
|
|
177
|
+
locate(_url) {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
/** The platform's URL for one of its messages, by its own IDs, or null when it has none (`vb sync <id>`). */
|
|
181
|
+
async url(_thread, _message) {
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* A channel or thread, read on demand for whoever asked: nothing is synced,
|
|
186
|
+
* stored, or joined. Throws `UnreadableError` for what it won't read.
|
|
187
|
+
*/
|
|
188
|
+
async read(_target, _options) {
|
|
189
|
+
throw new UnreadableError("unsupported", `${this.platform} can't be read on demand`);
|
|
190
|
+
}
|
|
191
|
+
async edit(_thread, _message, _body) {}
|
|
192
|
+
async delete(_thread, _message) {}
|
|
193
|
+
async react(_thread, _message, _emoji, _added) {}
|
|
194
|
+
async startTyping(_thread, _latest, _status) {}
|
|
195
|
+
/**
|
|
196
|
+
* The channel whose inbox a thread's events land in (`slack:C0123ABC` for `slack:C0123ABC:1727.1234`),
|
|
197
|
+
* worked out without calling the platform. Null when the provider can't tell: a key's inbox then
|
|
198
|
+
* lists only the mapped channels'.
|
|
199
|
+
*/
|
|
200
|
+
inboxChannel(_key, _thread) {
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
203
|
+
async deleteFiles(_ids) {}
|
|
204
|
+
refusesFiles(_error) {
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
async uploadFiles(_thread, _files) {
|
|
208
|
+
throw new Error(`${this.platform} does not support file uploads`);
|
|
209
|
+
}
|
|
210
|
+
/** Runs the sync function the provider was made with: what every event does, both ways. */
|
|
211
|
+
sync(sync) {
|
|
212
|
+
return this.fn.run(sync);
|
|
213
|
+
}
|
|
214
|
+
/** The default rendering: `**${label}**: ${text}`. A `Renderer` passed to `deliver` replaces it. */
|
|
215
|
+
render(input) {
|
|
216
|
+
return `**${input.label}**: ${input.message.text}`;
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
//#endregion
|
|
220
|
+
export { channelMissing as a, into as c, withRoutes as d, UnreadableError as i, mirror as l, ResolvedTarget as n, routesFor as o, SyncProvider as r, channels as s, ReceivedEvent as t, render as u };
|