@vercel/board 0.28.0 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{a2-B0_VlbtC.mjs → a2-D_28Pdip.mjs} +197 -259
- package/dist/access-CQ39gqEV.mjs +226 -0
- package/dist/access.d.mts +1 -1
- package/dist/access.mjs +3 -3
- package/dist/{actors-BLXVp4oZ.mjs → actors-xPiamLWk.mjs} +3 -3
- package/dist/{auth-lTkOgvcE.mjs → auth-BPinwfN0.mjs} +3 -226
- package/dist/backend-a2/blob-vercel.d.mts +1 -1
- package/dist/backend-a2/contract.d.mts +2 -2
- package/dist/backend-a2/contract.mjs +3 -3
- 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 +20 -7
- package/dist/backend-a2.mjs +2 -1
- package/dist/{backend-http-BvNFrvcY.mjs → backend-http-16SbvnAK.mjs} +2 -2
- package/dist/{backend-http-E7YU0qhn.d.mts → backend-http-3PoBYQoo.d.mts} +15 -3
- package/dist/{backend-http-CfLVYqmj.mjs → backend-http-BPaNYLWj.mjs} +4 -5
- 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-ZKYTe3xa.d.mts → backend-n3hajfrD.d.mts} +12 -6
- package/dist/{backend-vercel-D87pIp2k.mjs → backend-vercel-C4Kee2-K.mjs} +260 -30
- package/dist/{backend-vercel-DTrDiSk5.mjs → backend-vercel-Kd8nvW5A.mjs} +3 -3
- package/dist/{backend-vercel-CIRObA0t.d.mts → backend-vercel-qznuDxnN.d.mts} +20 -5
- 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-B-9AvYis.d.mts → blob-CqILvdmr.d.mts} +2 -2
- package/dist/blob-DQK5prXT.mjs +182 -0
- package/dist/{chat-provider-DnHibqnM.mjs → chat-provider-COtsU5jB.mjs} +2 -2
- package/dist/{chat-provider-DsNEBQiA.d.mts → chat-provider-D6jVT4wS.d.mts} +5 -3
- 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 +5 -5
- package/dist/{client-xLxeDz0f.d.mts → client-CjAatpV4.d.mts} +67 -10
- package/dist/{commands-BFookFtn.mjs → commands-B5DHjZKK.mjs} +54 -10
- package/dist/{commands-D6gvrOh3.d.mts → commands-BtH69yqt.d.mts} +17 -0
- package/dist/{conformance-DlnfuzEB.mjs → conformance-C7fwIvmN.mjs} +258 -18
- package/dist/conformance.d.mts +1 -1
- package/dist/conformance.mjs +1 -1
- package/dist/{engine-Bfe6pcXb.mjs → engine-DkdkXQEy.mjs} +21 -13
- package/dist/{errors-CB4tnZGz.d.mts → errors-87TVtXeb.d.mts} +1 -1
- package/dist/{client-D0Px7KzF.mjs → errors-C_5rB8Iz.mjs} +104 -4
- package/dist/{events-CewD4kw7.mjs → events-qf5XG5VQ.mjs} +2 -2
- package/dist/{exports-CCzw2Vdw.mjs → exports-CG0P8Qi4.mjs} +59 -33
- package/dist/exports-CrGA5_yN.d.mts +5 -0
- package/dist/{external-BV_cUncs.mjs → external-D3p5T57R.mjs} +4 -2
- package/dist/{folds-jS9wlh9_.d.mts → folds-8wRRXjAt.d.mts} +4 -0
- package/dist/{folds-Dyjput8M.mjs → folds-DGYkMW19.mjs} +3 -2
- package/dist/{index-C05it0mC.d.mts → index-BygAXP7t.d.mts} +2 -2
- package/dist/index.d.mts +6 -6
- package/dist/{index.default-DmKxH_E6.mjs → index.default-DhkgpfR2.mjs} +1 -1
- package/dist/index.mjs +5 -6
- package/dist/index.node.d.mts +6 -6
- package/dist/index.node.mjs +3 -4
- package/dist/inspect/app.js +29 -29
- package/dist/inspect/engine.js +5 -5
- 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-eci7w-aP.mjs → main-D2s-QBOK.mjs} +76 -26
- package/dist/{middleware-ChKM1zuu.mjs → middleware-DlJQYiwV.mjs} +2 -2
- package/dist/{node-Zd_C-gxP.mjs → node-D8Rtg1su.mjs} +1 -1
- package/dist/{platform-B4TnJtWu-CwcTyKg2.mjs → platform-B4TnJtWu-Do3agKr5.mjs} +1 -1
- package/dist/{project-DMDST9kl.mjs → project-C_2xs57L.mjs} +1 -1
- package/dist/{provider-poIkXapd.mjs → provider-BaVmi4Hi.mjs} +3 -1
- package/dist/{provider-Cdg1qadh.d.mts → provider-Bm46LAdp.d.mts} +9 -2
- package/dist/{redis-tables-DN9PfIDi.mjs → redis-tables-BWJZHUGg.mjs} +41 -25
- 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-BcmSs4qf.mjs → reducers-8jqLewgw.mjs} +5 -5
- 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/{schemas-Be08nyfW.mjs → schemas-DBmUO6pr.mjs} +2 -1
- package/dist/{serve-B09an9DQ.mjs → serve-lPoBDEds.mjs} +7 -6
- package/dist/{server-qgez0Xny-D5mLfqFQ.d.mts → server-B9gu0qi1-DI1WvcVK.d.mts} +10 -4
- package/dist/{server-DTX0prGr.mjs → server-D82a4uMe.mjs} +4 -4
- package/dist/{server-DtFrWxi3-Boa6gdWO.mjs → server-DX7mM6nm-D7N_7bug.mjs} +32 -23
- package/dist/{serving-CvOWEym2.mjs → serving-DKny38LK.mjs} +1 -1
- package/dist/{session-clear-wHd5GCpZ-BnKSxReK.mjs → session-clear-XJYpmUpg-2q8l_FJR.mjs} +14 -2
- package/dist/{sql-U9WTxrwJ.mjs → sql-Bj0fk6dn.mjs} +2 -2
- package/dist/{sqlite-db-Ds4majtT.mjs → sqlite-db-Dc8G78XV.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-github.d.mts +4 -2
- package/dist/sync-github.mjs +4 -14
- package/dist/sync-kapso.d.mts +3 -2
- package/dist/sync-kapso.mjs +3 -3
- package/dist/sync-linear.d.mts +12 -2
- package/dist/sync-linear.mjs +191 -9
- package/dist/sync-slack.d.mts +41 -5
- package/dist/sync-slack.mjs +70 -11
- package/dist/sync.chat.d.mts +1 -1
- package/dist/sync.chat.mjs +1 -1
- package/dist/sync.d.mts +2 -2
- package/dist/sync.mjs +3 -3
- package/dist/tags-BpFo6q0_.mjs +14 -0
- package/dist/{targets-C-wdR5wP.mjs → targets-Cgjs29T0.mjs} +1 -1
- package/dist/{tokens-BuCU-61R.mjs → tokens-C5_yGRlL.mjs} +2 -2
- package/dist/{types-aCAf6lGU.d.mts → types-shZmGZ-q.d.mts} +2 -2
- package/dist/{watchers-hash-7DJU9b-n.mjs → watchers-hash-B_5b0-ZG.mjs} +50 -19
- package/docs/01-board/04-messages.md +93 -0
- package/docs/01-board/08-middleware.md +5 -2
- package/docs/02-sync/03-slack.md +6 -2
- package/docs/02-sync/07-linear.md +28 -6
- package/docs/04-reference/01-cli.md +27 -12
- package/docs/04-reference/02-board.md +20 -5
- package/docs/04-reference/03-http.md +17 -6
- package/docs/04-reference/05-conformance.md +14 -3
- package/package.json +2 -2
- package/dist/errors-CusN4x2l.mjs +0 -88
- package/dist/exports-D22M68rk.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
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { r as IMPORT_BYTES_MAX } from "./files-SniSmeEr.mjs";
|
|
2
|
+
import { _ as RemoteWatcherId } from "./schemas-DBmUO6pr.mjs";
|
|
3
|
+
import { a as METHODS, d as VERSION, k as RegisterBody, n as compileWatcher, t as canonicalWatchers } from "./watchers-hash-B_5b0-ZG.mjs";
|
|
4
|
+
import { a as forbidden, f as duration, o as json, r as badRequest, s as notFound, t as HttpError } from "./errors-C_5rB8Iz.mjs";
|
|
3
5
|
import { o as sha256, r as derivedId } from "./wait-until-Dw4XrIDQ.mjs";
|
|
4
|
-
import { a as
|
|
5
|
-
import {
|
|
6
|
+
import { a as wakePath, i as registrant, n as callerProfile, t as PROJECTS_OWN } from "./backend-http-BPaNYLWj.mjs";
|
|
7
|
+
import { o as mediaType, r as fileName } from "./blob-DQK5prXT.mjs";
|
|
6
8
|
//#region src/server/backend-vercel.ts
|
|
7
9
|
const PROFILE = /^[A-Za-z][A-Za-z0-9-]{0,31}$/;
|
|
8
10
|
const SESSION = /^[A-Za-z0-9_.:-]{1,128}$/;
|
|
@@ -17,14 +19,13 @@ const PAGE_MAX = 100;
|
|
|
17
19
|
const WAIT_MAX_S = 25;
|
|
18
20
|
/** Pages a filtered read of one channel scans for matches before it answers with what it found. */
|
|
19
21
|
const SCAN_PAGES = 10;
|
|
20
|
-
/**
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
};
|
|
22
|
+
/** A file as the board names it. */
|
|
23
|
+
const fileOf = ({ id, name, type, size }) => ({
|
|
24
|
+
id,
|
|
25
|
+
name,
|
|
26
|
+
type,
|
|
27
|
+
size
|
|
28
|
+
});
|
|
28
29
|
const notSupported = (what) => new HttpError(501, "not_supported", `Vercel's boards don't support ${what} yet`);
|
|
29
30
|
/** What a caller board() verified may do. Null for this deployment's own code, which may do what its credentials may. */
|
|
30
31
|
const accessOf = (caller) => "identity" in caller ? caller.identity.principal.access : null;
|
|
@@ -65,6 +66,13 @@ const authorOf = (actor) => ({
|
|
|
65
66
|
profile: actor.profile?.name ?? null,
|
|
66
67
|
session: actor.session ?? null
|
|
67
68
|
});
|
|
69
|
+
/** Who cancels a schedule when no one did: the API, once its creator can no longer post it, as a2()'s scheduler. */
|
|
70
|
+
const SCHEDULER = {
|
|
71
|
+
actor: "board:schedule",
|
|
72
|
+
principal: "board:schedule",
|
|
73
|
+
profile: null,
|
|
74
|
+
session: null
|
|
75
|
+
};
|
|
68
76
|
/** The API names nobody, so an actor's handle is its profile, or a short form of its principal. */
|
|
69
77
|
function actorView(actor) {
|
|
70
78
|
const { principal } = actor;
|
|
@@ -81,14 +89,15 @@ function actorView(actor) {
|
|
|
81
89
|
}
|
|
82
90
|
/**
|
|
83
91
|
* Vercel's board for your team, in Vercel's API: this deployment keeps nothing and reads and writes
|
|
84
|
-
* it as itself, its people as themselves. Messages, threads, reactions, labels,
|
|
85
|
-
* changes work; what the API keeps none of yet (
|
|
92
|
+
* it as itself, its people as themselves. Messages, threads, reactions, labels, a channel's
|
|
93
|
+
* changes, schedules, files, and watchers work; what the API keeps none of yet (sync) answers 501.
|
|
86
94
|
*/
|
|
87
95
|
function createVercel(options, environment) {
|
|
88
96
|
const origin = (options.api ?? "https://api.vercel.com").replace(/\/+$/, "");
|
|
89
97
|
if (!/^https:\/\/[^/]+$|^http:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/.test(origin)) throw new Error(`vercel: ${origin} isn't Vercel's API: pass an https origin`);
|
|
90
98
|
if (!options.fetch && !environment) throw new Error("vercel: pass a fetch that sends credentials: outside Node there's no environment to find them in");
|
|
91
99
|
const doFetch = options.fetch ?? environment.fetch();
|
|
100
|
+
const filesFetch = options.files ?? fetch;
|
|
92
101
|
let binding = null;
|
|
93
102
|
/** This board's own code's names, which a caller here never takes as its profile. */
|
|
94
103
|
const own = /* @__PURE__ */ new Set();
|
|
@@ -318,10 +327,42 @@ function createVercel(options, environment) {
|
|
|
318
327
|
editedAt: message.editedAt === void 0 ? null : iso(message.editedAt),
|
|
319
328
|
deleted: message.deletedAt !== void 0,
|
|
320
329
|
undelivered: {},
|
|
321
|
-
attachments: [],
|
|
330
|
+
attachments: message.attachments ?? [],
|
|
322
331
|
links: [],
|
|
323
332
|
version: message.version,
|
|
324
|
-
|
|
333
|
+
revision: message.revision,
|
|
334
|
+
author: await nameOf(who, message.createdBy),
|
|
335
|
+
...message.schedule ? { schedule: {
|
|
336
|
+
id: message.schedule.id,
|
|
337
|
+
n: message.schedule.n
|
|
338
|
+
} } : {}
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
async function scheduleView(who, schedule) {
|
|
342
|
+
const { canceled } = schedule;
|
|
343
|
+
return {
|
|
344
|
+
id: schedule.id,
|
|
345
|
+
channel: (await channelById(who, schedule.channelId)).name,
|
|
346
|
+
re: schedule.threadId === void 0 ? null : idAt(schedule.threadId, 1),
|
|
347
|
+
text: schedule.text,
|
|
348
|
+
labels: { ...schedule.labels },
|
|
349
|
+
noSync: false,
|
|
350
|
+
attachments: [],
|
|
351
|
+
first: iso(schedule.firstAt),
|
|
352
|
+
every: schedule.every ?? null,
|
|
353
|
+
until: schedule.until === void 0 ? null : iso(schedule.until),
|
|
354
|
+
times: schedule.times ?? null,
|
|
355
|
+
sent: schedule.sent,
|
|
356
|
+
next: schedule.nextAt === null ? null : iso(schedule.nextAt),
|
|
357
|
+
last: schedule.lastMessageId ?? null,
|
|
358
|
+
state: schedule.state,
|
|
359
|
+
canceled: canceled ? {
|
|
360
|
+
by: canceled.by ? authorOf(canceled.by) : SCHEDULER,
|
|
361
|
+
reason: canceled.reason === "disabled" ? "revoked" : canceled.reason
|
|
362
|
+
} : null,
|
|
363
|
+
by: authorOf(schedule.createdBy),
|
|
364
|
+
author: await nameOf(who, schedule.createdBy),
|
|
365
|
+
createdAt: iso(schedule.createdAt)
|
|
325
366
|
};
|
|
326
367
|
}
|
|
327
368
|
const positions = /* @__PURE__ */ new Map();
|
|
@@ -560,7 +601,7 @@ function createVercel(options, environment) {
|
|
|
560
601
|
by,
|
|
561
602
|
origin: null,
|
|
562
603
|
from: null,
|
|
563
|
-
attachments:
|
|
604
|
+
attachments: message.attachments,
|
|
564
605
|
links: []
|
|
565
606
|
};
|
|
566
607
|
break;
|
|
@@ -786,6 +827,22 @@ function createVercel(options, environment) {
|
|
|
786
827
|
function checkCaller(method, caller) {
|
|
787
828
|
if ("identity" in caller && PROJECTS_OWN.has(method)) throw forbidden(`this board's callers act as its project on Vercel's board, which can't tell them apart: ${method} is the project's own to do there`);
|
|
788
829
|
}
|
|
830
|
+
/**
|
|
831
|
+
* The API owns messages and schedules by principal, and sees every caller here as this project:
|
|
832
|
+
* a caller that is the project (its own deployment's token) changes what it wrote, as on any
|
|
833
|
+
* board, and anyone else would be changing what the project wrote for others.
|
|
834
|
+
*/
|
|
835
|
+
/** Whether a caller is this project: the deployment's own code, or a caller verified as its principal. */
|
|
836
|
+
const isProject = async (caller, who) => !("identity" in caller) || caller.identity.principal.id === principalId((await self(who)).actor.principal);
|
|
837
|
+
async function checkOwner(what, caller, who) {
|
|
838
|
+
if (!await isProject(caller, who)) throw forbidden(`this board's callers act as its project on Vercel's board, which owns what any of them wrote: only the project itself may ${what} there`);
|
|
839
|
+
}
|
|
840
|
+
/** A file is no use until a post or an import carries it, so uploading takes `post` or `sync` somewhere, as on a2(). */
|
|
841
|
+
async function checkUploader(caller, who) {
|
|
842
|
+
await checkOwner("upload", caller, who);
|
|
843
|
+
const access = accessOf(caller);
|
|
844
|
+
if (access && !access.anywhere("post") && !access.anywhere("sync")) throw forbidden("this token can't post anywhere, so it can't upload");
|
|
845
|
+
}
|
|
789
846
|
const meOf = (identity) => {
|
|
790
847
|
const { principal, author, actor } = identity;
|
|
791
848
|
return {
|
|
@@ -965,8 +1022,6 @@ function createVercel(options, environment) {
|
|
|
965
1022
|
});
|
|
966
1023
|
const methods = {
|
|
967
1024
|
...Object.fromEntries(METHODS.map((method) => [method, async () => {
|
|
968
|
-
const unkept = UNKEPT[method];
|
|
969
|
-
if (unkept) throw new HttpError(501, unkept[0], unkept[1]);
|
|
970
1025
|
throw notSupported(method === "register" || method === "watchers" || method === "matches" || method === "ack" ? "watchers" : method);
|
|
971
1026
|
}])),
|
|
972
1027
|
async discovery() {
|
|
@@ -1144,12 +1199,83 @@ function createVercel(options, environment) {
|
|
|
1144
1199
|
})
|
|
1145
1200
|
};
|
|
1146
1201
|
},
|
|
1202
|
+
async upload(caller, { data, name, type }) {
|
|
1203
|
+
const who = whoOf(caller);
|
|
1204
|
+
await checkUploader(caller, who);
|
|
1205
|
+
if (data.byteLength === 0) throw new HttpError(400, "bad_request", "the file is empty");
|
|
1206
|
+
if (data.byteLength > 26214400) throw new HttpError(413, "too_large", `attachments are at most ${IMPORT_BYTES_MAX / 1024 / 1024} MB`);
|
|
1207
|
+
const bytes = new Uint8Array(data);
|
|
1208
|
+
const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", bytes));
|
|
1209
|
+
const started = await api(who, "POST", await onBoard(who, "/attachments"), { body: {
|
|
1210
|
+
operationId: operationId(),
|
|
1211
|
+
name: fileName(name),
|
|
1212
|
+
type: mediaType(type),
|
|
1213
|
+
size: data.byteLength,
|
|
1214
|
+
sha256: btoa(String.fromCharCode(...digest))
|
|
1215
|
+
} });
|
|
1216
|
+
const put = await filesFetch(started.upload.url, {
|
|
1217
|
+
method: started.upload.method,
|
|
1218
|
+
headers: started.upload.headers,
|
|
1219
|
+
body: bytes,
|
|
1220
|
+
redirect: "error"
|
|
1221
|
+
});
|
|
1222
|
+
if (!put.ok) throw new HttpError(502, "upload_failed", `the upload to Vercel's storage answered ${put.status}`);
|
|
1223
|
+
const { attachment } = await api(who, "POST", await onBoard(who, `/attachments/${encodeURIComponent(started.attachment.id)}/complete`));
|
|
1224
|
+
return { attachment: fileOf(attachment) };
|
|
1225
|
+
},
|
|
1226
|
+
async uploadStart(caller, { name, type, size, sha256 }) {
|
|
1227
|
+
const who = whoOf(caller);
|
|
1228
|
+
await checkUploader(caller, who);
|
|
1229
|
+
if (sha256 === void 0) throw new HttpError(400, "invalid_request", "Vercel's API signs a direct upload for its bytes' SHA-256: send `sha256`, as board's client does");
|
|
1230
|
+
const started = await api(who, "POST", await onBoard(who, "/attachments"), { body: {
|
|
1231
|
+
operationId: operationId(),
|
|
1232
|
+
name: fileName(name ?? null),
|
|
1233
|
+
type: mediaType(type ?? null),
|
|
1234
|
+
size,
|
|
1235
|
+
sha256
|
|
1236
|
+
} });
|
|
1237
|
+
return {
|
|
1238
|
+
id: started.attachment.id,
|
|
1239
|
+
url: started.upload.url,
|
|
1240
|
+
headers: started.upload.headers,
|
|
1241
|
+
expiresAt: iso(started.upload.expiresAt)
|
|
1242
|
+
};
|
|
1243
|
+
},
|
|
1244
|
+
async uploadFinish(caller, { id }) {
|
|
1245
|
+
const who = whoOf(caller);
|
|
1246
|
+
await checkUploader(caller, who);
|
|
1247
|
+
const { attachment } = await api(who, "POST", await onBoard(who, `/attachments/${encodeURIComponent(id)}/complete`));
|
|
1248
|
+
return { attachment: fileOf(attachment) };
|
|
1249
|
+
},
|
|
1250
|
+
async attachment(caller, { id }, signal) {
|
|
1251
|
+
const who = whoOf(caller);
|
|
1252
|
+
const access = accessOf(caller);
|
|
1253
|
+
const found = await api(who, "GET", await onBoard(who, `/attachments/${encodeURIComponent(id)}`), signal ? { signal } : {});
|
|
1254
|
+
if (access && !found.attachment.messageId) {
|
|
1255
|
+
if (!await isProject(caller, who)) throw notFound(`no attachment: ${id}`, "attachment_not_found");
|
|
1256
|
+
} else if (access) {
|
|
1257
|
+
const { message } = await readableMessage(who, access, found.attachment.messageId, signal).catch((error) => {
|
|
1258
|
+
if (error instanceof HttpError && error.status === 404) throw notFound(`no attachment: ${id}`, "attachment_not_found");
|
|
1259
|
+
throw error;
|
|
1260
|
+
});
|
|
1261
|
+
if (message.deletedAt !== void 0) throw notFound(`no attachment: ${id}`, "attachment_not_found");
|
|
1262
|
+
}
|
|
1263
|
+
const response = await filesFetch(found.url, {
|
|
1264
|
+
redirect: "error",
|
|
1265
|
+
...signal ? { signal } : {}
|
|
1266
|
+
});
|
|
1267
|
+
if (!response.ok || !response.body) throw new HttpError(502, "download_failed", `Vercel's storage answered ${response.status}`);
|
|
1268
|
+
return {
|
|
1269
|
+
attachment: fileOf(found.attachment),
|
|
1270
|
+
data: response.body
|
|
1271
|
+
};
|
|
1272
|
+
},
|
|
1147
1273
|
async post(caller, input, signal) {
|
|
1148
1274
|
checkCaller("post", caller);
|
|
1149
|
-
if (input.attachments?.length) throw new HttpError(501, "no_files", "Vercel's boards keep no files yet");
|
|
1150
1275
|
if (input.sync?.length) throw notSupported("sync");
|
|
1151
1276
|
const who = whoOf(caller);
|
|
1152
1277
|
const access = accessOf(caller);
|
|
1278
|
+
if (input.attachments?.length) await checkOwner("post files", caller, who);
|
|
1153
1279
|
const labeled = Object.keys(input.labels ?? {}).length > 0;
|
|
1154
1280
|
const clientId = input.id !== void 0 ? await postId(caller, input.id) : void 0;
|
|
1155
1281
|
let made;
|
|
@@ -1163,7 +1289,8 @@ function createVercel(options, environment) {
|
|
|
1163
1289
|
channelId: channel.id,
|
|
1164
1290
|
text: input.text,
|
|
1165
1291
|
...input.labels && Object.keys(input.labels).length ? { labels: input.labels } : {},
|
|
1166
|
-
...clientId ? { clientId } : {}
|
|
1292
|
+
...clientId ? { clientId } : {},
|
|
1293
|
+
...input.attachments?.length ? { attachments: input.attachments } : {}
|
|
1167
1294
|
},
|
|
1168
1295
|
signal
|
|
1169
1296
|
});
|
|
@@ -1171,14 +1298,25 @@ function createVercel(options, environment) {
|
|
|
1171
1298
|
const { thread, message: to, channel } = await readableMessage(who, access, input.re, signal);
|
|
1172
1299
|
need(access, "post", channel.name);
|
|
1173
1300
|
if (labeled) need(access, "label", channel.name);
|
|
1301
|
+
const after = input.after === void 0 ? void 0 : locate(input.after);
|
|
1302
|
+
if (after !== void 0 && after?.threadId !== thread.id) {
|
|
1303
|
+
const landed = clientId ? await api(who, "GET", await onBoard(who, `/posts/${encodeURIComponent(clientId)}`), { signal }).catch(() => null) : null;
|
|
1304
|
+
if (landed?.thread.id === thread.id) return { message: await view(who, landed.message, channel.name) };
|
|
1305
|
+
throw badRequest(`after: ${input.after} isn't in ${input.re}'s thread`, "invalid_after");
|
|
1306
|
+
}
|
|
1174
1307
|
made = await api(who, "POST", await onBoard(who, `/threads/${encodeURIComponent(thread.id)}/messages`), {
|
|
1175
1308
|
body: {
|
|
1176
1309
|
operationId: operationId(),
|
|
1177
1310
|
text: input.text,
|
|
1178
1311
|
...to.sequence > 1 ? { replyTo: to.sequence } : {},
|
|
1179
|
-
...clientId ? { clientId } : {}
|
|
1312
|
+
...clientId ? { clientId } : {},
|
|
1313
|
+
...input.attachments?.length ? { attachments: input.attachments } : {},
|
|
1314
|
+
...after ? { after: after.sequence } : {}
|
|
1180
1315
|
},
|
|
1181
1316
|
signal
|
|
1317
|
+
}).catch((error) => {
|
|
1318
|
+
if (error instanceof HttpError && error.code === "newer_message") throw new HttpError(409, "newer_message", `a message came after ${input.after}`);
|
|
1319
|
+
throw error;
|
|
1182
1320
|
});
|
|
1183
1321
|
if (input.labels && Object.keys(input.labels).length) {
|
|
1184
1322
|
const labeled = await api(who, "POST", await onBoard(who, `/threads/${encodeURIComponent(thread.id)}/messages/${made.message.sequence}/labels`), {
|
|
@@ -1210,27 +1348,35 @@ function createVercel(options, environment) {
|
|
|
1210
1348
|
if (access && !access.readable(channel.name)) throw notFound(`no post of yours has id ${id}`, "post_not_found");
|
|
1211
1349
|
return { message: await view(who, found.message, channel.name) };
|
|
1212
1350
|
},
|
|
1213
|
-
async edit(caller, { id, text }, signal) {
|
|
1214
|
-
checkCaller("edit", caller);
|
|
1351
|
+
async edit(caller, { id, text, revision }, signal) {
|
|
1215
1352
|
const who = whoOf(caller);
|
|
1353
|
+
await checkOwner("edit", caller, who);
|
|
1216
1354
|
const at = locate(id);
|
|
1217
1355
|
if (!at) throw notFound(`message not found: ${id}`, "message_not_found");
|
|
1356
|
+
const access = accessOf(caller);
|
|
1357
|
+
if (access) need(access, "post", (await readableMessage(who, access, id, signal)).channel.name);
|
|
1218
1358
|
await api(who, "PATCH", await onBoard(who, `/threads/${encodeURIComponent(at.threadId)}/messages/${at.sequence}`), {
|
|
1219
1359
|
body: {
|
|
1220
1360
|
operationId: operationId(),
|
|
1221
|
-
text
|
|
1361
|
+
text,
|
|
1362
|
+
...revision !== void 0 ? { revision } : {}
|
|
1222
1363
|
},
|
|
1223
1364
|
signal
|
|
1224
1365
|
});
|
|
1225
1366
|
return { ok: true };
|
|
1226
1367
|
},
|
|
1227
|
-
async delete(caller, { id }, signal) {
|
|
1228
|
-
checkCaller("delete", caller);
|
|
1368
|
+
async delete(caller, { id, revision }, signal) {
|
|
1229
1369
|
const who = whoOf(caller);
|
|
1370
|
+
await checkOwner("delete", caller, who);
|
|
1230
1371
|
const at = locate(id);
|
|
1231
1372
|
if (!at) throw notFound(`message not found: ${id}`, "message_not_found");
|
|
1373
|
+
const access = accessOf(caller);
|
|
1374
|
+
if (access) need(access, "post", (await readableMessage(who, access, id, signal)).channel.name);
|
|
1232
1375
|
await api(who, "POST", await onBoard(who, `/threads/${encodeURIComponent(at.threadId)}/messages/${at.sequence}/delete`), {
|
|
1233
|
-
body: {
|
|
1376
|
+
body: {
|
|
1377
|
+
operationId: operationId(),
|
|
1378
|
+
...revision !== void 0 ? { revision } : {}
|
|
1379
|
+
},
|
|
1234
1380
|
signal
|
|
1235
1381
|
});
|
|
1236
1382
|
return { ok: true };
|
|
@@ -1252,7 +1398,7 @@ function createVercel(options, environment) {
|
|
|
1252
1398
|
});
|
|
1253
1399
|
return { ok: true };
|
|
1254
1400
|
},
|
|
1255
|
-
async label(caller, { id, set, unset }, signal) {
|
|
1401
|
+
async label(caller, { id, set, unset, if: expected }, signal) {
|
|
1256
1402
|
checkCaller("label", caller);
|
|
1257
1403
|
const who = whoOf(caller);
|
|
1258
1404
|
const at = locate(id);
|
|
@@ -1263,12 +1409,95 @@ function createVercel(options, environment) {
|
|
|
1263
1409
|
body: {
|
|
1264
1410
|
operationId: operationId(),
|
|
1265
1411
|
...set ? { set } : {},
|
|
1266
|
-
...unset ? { unset } : {}
|
|
1412
|
+
...unset ? { unset } : {},
|
|
1413
|
+
...expected && Object.keys(expected).length ? { if: expected } : {}
|
|
1267
1414
|
},
|
|
1268
1415
|
signal
|
|
1269
1416
|
});
|
|
1270
1417
|
return { ok: true };
|
|
1271
1418
|
},
|
|
1419
|
+
async schedule(caller, input, signal) {
|
|
1420
|
+
if (input.attachments?.length) throw notSupported("files on scheduled messages");
|
|
1421
|
+
const who = whoOf(caller);
|
|
1422
|
+
await checkOwner("schedule", caller, who);
|
|
1423
|
+
const access = accessOf(caller);
|
|
1424
|
+
const labels = input.labels && Object.keys(input.labels).length ? input.labels : void 0;
|
|
1425
|
+
let target;
|
|
1426
|
+
if (input.channel !== void 0) {
|
|
1427
|
+
need(access, "post", input.channel);
|
|
1428
|
+
if (labels) need(access, "label", input.channel);
|
|
1429
|
+
target = { channelId: (await channelToPost(who, input.channel)).id };
|
|
1430
|
+
} else {
|
|
1431
|
+
if (labels) throw notSupported("labels on a scheduled reply");
|
|
1432
|
+
const { thread, channel } = await readableMessage(who, access, input.re, signal);
|
|
1433
|
+
need(access, "post", channel.name);
|
|
1434
|
+
target = { threadId: thread.id };
|
|
1435
|
+
}
|
|
1436
|
+
const ms = (value) => Math.round(duration(value));
|
|
1437
|
+
const firstAt = input.at !== void 0 ? Date.parse(input.at) : Date.now() + ms(input.in ?? input.every);
|
|
1438
|
+
const until = input.until !== void 0 ? Date.parse(input.until) : input.for !== void 0 ? firstAt + ms(input.for) : void 0;
|
|
1439
|
+
const { schedule } = await api(who, "POST", await onBoard(who, "/schedules"), {
|
|
1440
|
+
body: {
|
|
1441
|
+
operationId: operationId(),
|
|
1442
|
+
...target,
|
|
1443
|
+
text: input.text,
|
|
1444
|
+
...labels ? { labels } : {},
|
|
1445
|
+
firstAt,
|
|
1446
|
+
...input.every !== void 0 ? { every: ms(input.every) } : {},
|
|
1447
|
+
...until !== void 0 ? { until } : {},
|
|
1448
|
+
...input.times !== void 0 ? { times: input.times } : {}
|
|
1449
|
+
},
|
|
1450
|
+
signal
|
|
1451
|
+
});
|
|
1452
|
+
return { schedule: await scheduleView(who, schedule) };
|
|
1453
|
+
},
|
|
1454
|
+
async schedules(caller, query, signal) {
|
|
1455
|
+
const who = whoOf(caller);
|
|
1456
|
+
const access = accessOf(caller);
|
|
1457
|
+
const filter = { state: query.all ? void 0 : "pending" };
|
|
1458
|
+
if (query.re !== void 0) {
|
|
1459
|
+
const found = await readableMessage(who, access, query.re, signal).catch((error) => {
|
|
1460
|
+
if (error instanceof HttpError && error.status === 404) return null;
|
|
1461
|
+
throw error;
|
|
1462
|
+
});
|
|
1463
|
+
if (!found) return { schedules: [] };
|
|
1464
|
+
filter.threadId = found.thread.id;
|
|
1465
|
+
}
|
|
1466
|
+
if (query.channel !== void 0) {
|
|
1467
|
+
const channel = await channelNamed(who, query.channel);
|
|
1468
|
+
if (!channel) return { schedules: [] };
|
|
1469
|
+
filter.channelId = channel.id;
|
|
1470
|
+
}
|
|
1471
|
+
const me = query.by === "me" ? await actorOf(who) : void 0;
|
|
1472
|
+
const by = me ?? query.by;
|
|
1473
|
+
if (by?.startsWith("vercel:")) filter.createdBy = by;
|
|
1474
|
+
const created = (actor) => by === void 0 || (me ? actor.id === me : [
|
|
1475
|
+
actor.id,
|
|
1476
|
+
principalId(actor.principal),
|
|
1477
|
+
actor.profile?.name
|
|
1478
|
+
].includes(by));
|
|
1479
|
+
const listed = await all(who, await onBoard(who, "/schedules"), "schedules", filter, signal);
|
|
1480
|
+
return { schedules: (await Promise.all(listed.filter((schedule) => created(schedule.createdBy)).map((schedule) => scheduleView(who, schedule)))).filter((schedule) => access === null || access.readable(schedule.channel)) };
|
|
1481
|
+
},
|
|
1482
|
+
async cancelSchedule(caller, { id }, signal) {
|
|
1483
|
+
const who = whoOf(caller);
|
|
1484
|
+
await checkOwner("cancelSchedule", caller, who);
|
|
1485
|
+
const access = accessOf(caller);
|
|
1486
|
+
if (access) {
|
|
1487
|
+
const found = (await all(who, await onBoard(who, "/schedules"), "schedules", {}, signal)).find((schedule) => schedule.id === id);
|
|
1488
|
+
const channel = found && await channelById(who, found.channelId);
|
|
1489
|
+
if (!channel || !access.readable(channel.name)) throw notFound(`no schedule: ${id}`, "schedule_not_found");
|
|
1490
|
+
need(access, "post", channel.name);
|
|
1491
|
+
}
|
|
1492
|
+
const { schedule, canceled } = await api(who, "POST", await onBoard(who, `/schedules/${encodeURIComponent(id)}/cancel`), {
|
|
1493
|
+
body: { operationId: operationId() },
|
|
1494
|
+
signal
|
|
1495
|
+
});
|
|
1496
|
+
return {
|
|
1497
|
+
schedule: await scheduleView(who, schedule),
|
|
1498
|
+
canceled
|
|
1499
|
+
};
|
|
1500
|
+
},
|
|
1272
1501
|
async events(caller, query, signal) {
|
|
1273
1502
|
checkCaller("events", caller);
|
|
1274
1503
|
const who = whoOf(caller);
|
|
@@ -1341,6 +1570,7 @@ function createVercel(options, environment) {
|
|
|
1341
1570
|
}])),
|
|
1342
1571
|
routes: runner.routes,
|
|
1343
1572
|
keeps: false,
|
|
1573
|
+
sendsSchedulesHere: false,
|
|
1344
1574
|
bind(next) {
|
|
1345
1575
|
if (binding) throw new Error("vercel: this backend already serves a board: create one vercel() per board()");
|
|
1346
1576
|
if (Object.values(next.subscriptions).map((subscription) => subscription.kind).includes("sync")) throw new Error("vercel: Vercel's boards don't run sync yet: leave `sync` out");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { t as HttpError } from "./errors-
|
|
2
|
-
import { c as loginHanded, d as vercelProjectFile, i as environmentProfile, t as asYou, u as vercelLogin } from "./node-
|
|
3
|
-
import { t as createVercel } from "./backend-vercel-
|
|
1
|
+
import { t as HttpError } from "./errors-C_5rB8Iz.mjs";
|
|
2
|
+
import { c as loginHanded, d as vercelProjectFile, i as environmentProfile, t as asYou, u as vercelLogin } from "./node-D8Rtg1su.mjs";
|
|
3
|
+
import { t as createVercel } from "./backend-vercel-C4Kee2-K.mjs";
|
|
4
4
|
import { readFile } from "node:fs/promises";
|
|
5
5
|
import { decodeJwt } from "jose";
|
|
6
6
|
import { getVercelOidcToken } from "@vercel/oidc";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { t as Actor, x as Attachment } from "./folds-
|
|
2
|
-
import { A as InboxItem,
|
|
3
|
-
import { i as Caller, n as BackendRoute, r as BoardBinding } from "./backend-
|
|
1
|
+
import { t as Actor, x as Attachment } from "./folds-8wRRXjAt.mjs";
|
|
2
|
+
import { A as InboxItem, Ct as SyncCopiesView, D as IdentityView, Et as SyncFindView, H as MessageView, It as ThreadView, L as LinkedAccount, Lt as ThreadsPage, Mt as SyncThreadView, Pt as SyncedView, S as EventsPage, U as MessagesPage, Ut as UploadTicket, V as Me, b as Discovery, ft as SourceJoin, ht as SourceRead, k as InboxEntry, o as ProfileOption, q as PersonView, st as ScheduleView, tt as RegistrationView, v as ChannelView, xt as SyncCodeView, z as MatchView } from "./client-CjAatpV4.mjs";
|
|
3
|
+
import { i as Caller, n as BackendRoute, r as BoardBinding } from "./backend-n3hajfrD.mjs";
|
|
4
4
|
//#region src/server/backend-vercel.d.ts
|
|
5
5
|
type VercelOptions = {
|
|
6
6
|
/** The team whose board it is: its ID (`team_…`) or its slug. In Node, by default your deployment's, or `VERCEL_ORG_ID`. */
|
|
@@ -14,6 +14,8 @@ type VercelOptions = {
|
|
|
14
14
|
* a deployment's OIDC token, or your `vercel login`. Elsewhere, pass one that sends them.
|
|
15
15
|
*/
|
|
16
16
|
fetch?: typeof fetch;
|
|
17
|
+
/** How files reach Vercel's storage, on URLs the API signs: `fetch` by default, never with credentials. */
|
|
18
|
+
files?: typeof fetch;
|
|
17
19
|
};
|
|
18
20
|
/** What finds the API's credentials and the team, in the Node build. A browser has none. */
|
|
19
21
|
type VercelEnvironment = {
|
|
@@ -29,8 +31,8 @@ type VercelEnvironment = {
|
|
|
29
31
|
};
|
|
30
32
|
/**
|
|
31
33
|
* Vercel's board for your team, in Vercel's API: this deployment keeps nothing and reads and writes
|
|
32
|
-
* it as itself, its people as themselves. Messages, threads, reactions, labels,
|
|
33
|
-
* changes work; what the API keeps none of yet (
|
|
34
|
+
* it as itself, its people as themselves. Messages, threads, reactions, labels, a channel's
|
|
35
|
+
* changes, schedules, files, and watchers work; what the API keeps none of yet (sync) answers 501.
|
|
34
36
|
*/
|
|
35
37
|
declare function createVercel(options: VercelOptions, environment: VercelEnvironment | null): {
|
|
36
38
|
discovery: (caller: Caller, input: {
|
|
@@ -94,6 +96,7 @@ declare function createVercel(options: VercelOptions, environment: VercelEnviron
|
|
|
94
96
|
})[] | undefined;
|
|
95
97
|
id?: string | undefined;
|
|
96
98
|
attachments?: string[] | undefined;
|
|
99
|
+
after?: string | undefined;
|
|
97
100
|
}, signal: AbortSignal) => Promise<{
|
|
98
101
|
message: MessageView;
|
|
99
102
|
unknownMentions?: string[];
|
|
@@ -107,12 +110,15 @@ declare function createVercel(options: VercelOptions, environment: VercelEnviron
|
|
|
107
110
|
id: string;
|
|
108
111
|
} & {
|
|
109
112
|
text: string;
|
|
113
|
+
revision?: number | undefined;
|
|
110
114
|
}, signal: AbortSignal) => Promise<{
|
|
111
115
|
ok: true;
|
|
112
116
|
unknownMentions?: string[];
|
|
113
117
|
}>;
|
|
114
118
|
delete: (caller: Caller, input: {
|
|
115
119
|
id: string;
|
|
120
|
+
} & {
|
|
121
|
+
revision?: number | undefined;
|
|
116
122
|
}, signal: AbortSignal) => Promise<{
|
|
117
123
|
ok: true;
|
|
118
124
|
}>;
|
|
@@ -129,6 +135,7 @@ declare function createVercel(options: VercelOptions, environment: VercelEnviron
|
|
|
129
135
|
} & {
|
|
130
136
|
set?: Record<string, string> | undefined;
|
|
131
137
|
unset?: string[] | undefined;
|
|
138
|
+
if?: Record<string, string | null> | undefined;
|
|
132
139
|
}, signal: AbortSignal) => Promise<{
|
|
133
140
|
ok: true;
|
|
134
141
|
}>;
|
|
@@ -180,6 +187,7 @@ declare function createVercel(options: VercelOptions, environment: VercelEnviron
|
|
|
180
187
|
name?: string | null | undefined;
|
|
181
188
|
type?: string | null | undefined;
|
|
182
189
|
size: number;
|
|
190
|
+
sha256?: string | undefined;
|
|
183
191
|
}, signal: AbortSignal) => Promise<UploadTicket>;
|
|
184
192
|
uploadFinish: (caller: Caller, input: {
|
|
185
193
|
id: string;
|
|
@@ -257,6 +265,7 @@ declare function createVercel(options: VercelOptions, environment: VercelEnviron
|
|
|
257
265
|
} & {
|
|
258
266
|
target: string;
|
|
259
267
|
limit?: number | undefined;
|
|
268
|
+
after?: string | undefined;
|
|
260
269
|
}, signal: AbortSignal) => Promise<SourceRead>;
|
|
261
270
|
joinSource: (caller: Caller, input: {
|
|
262
271
|
key: string;
|
|
@@ -312,6 +321,7 @@ declare function createVercel(options: VercelOptions, environment: VercelEnviron
|
|
|
312
321
|
message: string | null;
|
|
313
322
|
}[] | undefined;
|
|
314
323
|
id?: string | undefined;
|
|
324
|
+
after?: string | undefined;
|
|
315
325
|
} | {
|
|
316
326
|
author: {
|
|
317
327
|
id: string;
|
|
@@ -333,6 +343,7 @@ declare function createVercel(options: VercelOptions, environment: VercelEnviron
|
|
|
333
343
|
channel: string;
|
|
334
344
|
thread: string;
|
|
335
345
|
} | undefined;
|
|
346
|
+
revision?: number | undefined;
|
|
336
347
|
} | {
|
|
337
348
|
author: {
|
|
338
349
|
id: string;
|
|
@@ -348,6 +359,7 @@ declare function createVercel(options: VercelOptions, environment: VercelEnviron
|
|
|
348
359
|
} | undefined;
|
|
349
360
|
message?: string | undefined;
|
|
350
361
|
op: "delete";
|
|
362
|
+
revision?: number | undefined;
|
|
351
363
|
} | {
|
|
352
364
|
author: {
|
|
353
365
|
id: string;
|
|
@@ -382,6 +394,7 @@ declare function createVercel(options: VercelOptions, environment: VercelEnviron
|
|
|
382
394
|
op: "labels";
|
|
383
395
|
set?: Record<string, string> | undefined;
|
|
384
396
|
unset?: string[] | undefined;
|
|
397
|
+
if?: Record<string, string | null> | undefined;
|
|
385
398
|
} | {
|
|
386
399
|
author: {
|
|
387
400
|
id: string;
|
|
@@ -574,6 +587,7 @@ declare function createVercel(options: VercelOptions, environment: VercelEnviron
|
|
|
574
587
|
type: string;
|
|
575
588
|
title: string;
|
|
576
589
|
url: string | null;
|
|
590
|
+
body?: string | null | undefined;
|
|
577
591
|
labels: Record<string, string>;
|
|
578
592
|
unset: string[];
|
|
579
593
|
owns?: string[] | undefined;
|
|
@@ -644,6 +658,7 @@ declare function createVercel(options: VercelOptions, environment: VercelEnviron
|
|
|
644
658
|
}>;
|
|
645
659
|
routes: BackendRoute[];
|
|
646
660
|
keeps: boolean;
|
|
661
|
+
sendsSchedulesHere: boolean;
|
|
647
662
|
bind(next: BoardBinding): void;
|
|
648
663
|
/** Registers this board's watchers with Vercel's API now, as `POST /watchers` does. */
|
|
649
664
|
registerWatchers: () => Promise<RegistrationView>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as VercelOptions, t as VercelBackend } from "./backend-vercel-
|
|
1
|
+
import { n as VercelOptions, t as VercelBackend } from "./backend-vercel-qznuDxnN.mjs";
|
|
2
2
|
//#region src/backend-vercel/index.default.d.ts
|
|
3
3
|
/**
|
|
4
4
|
* Your team's board, in Vercel's API. Outside Node there's no environment to find credentials or
|
package/dist/backend-vercel.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as createVercel } from "./backend-vercel-
|
|
1
|
+
import { t as createVercel } from "./backend-vercel-C4Kee2-K.mjs";
|
|
2
2
|
//#region src/backend-vercel/index.default.ts
|
|
3
3
|
/**
|
|
4
4
|
* Your team's board, in Vercel's API. Outside Node there's no environment to find credentials or
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as VercelOptions, t as VercelBackend } from "./backend-vercel-
|
|
1
|
+
import { n as VercelOptions, t as VercelBackend } from "./backend-vercel-qznuDxnN.mjs";
|
|
2
2
|
//#region src/backend-vercel/index.d.ts
|
|
3
3
|
/** Where `token` comes from, in words: what `vb whoami` says. */
|
|
4
4
|
export declare function credentialSource(): string;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as handTeam, r as vercel, t as credentialSource } from "./backend-vercel-
|
|
1
|
+
import { n as handTeam, r as vercel, t as credentialSource } from "./backend-vercel-Kd8nvW5A.mjs";
|
|
2
2
|
export { credentialSource, handTeam, vercel };
|