@vercel/board 0.29.0 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -17
- package/dist/{a2-HUbQJ0RD.mjs → a2-DngWY2Eb.mjs} +741 -415
- package/dist/access-CY5xVMIK.mjs +242 -0
- package/dist/{access-CV96SYgr.d.mts → access-DPcrKIH_.d.mts} +6 -1
- package/dist/access.d.mts +4 -4
- package/dist/access.mjs +5 -4
- package/dist/{actors-DcJhFbwJ.mjs → actors-Bm-ojWWT.mjs} +2 -2
- package/dist/{auth-JO22iIwr.mjs → auth-CyO2aw5n.mjs} +126 -236
- package/dist/{auth-CU56Q2Xh.d.mts → auth-DLYSt_-A.d.mts} +32 -4
- package/dist/{backend-CPC_vyOo.d.mts → backend-Bob-5CM7.d.mts} +93 -42
- package/dist/backend-a2/blob-vercel.d.mts +1 -1
- package/dist/backend-a2/contract.d.mts +38 -98
- package/dist/backend-a2/contract.mjs +1 -1
- package/dist/backend-a2/scheduler-local.d.mts +1 -1
- package/dist/backend-a2/scheduler-local.mjs +1 -1
- package/dist/backend-a2/scheduler-qstash.d.mts +3 -3
- package/dist/backend-a2/scheduler-qstash.mjs +8 -8
- package/dist/backend-a2/scheduler-vercel.d.mts +3 -3
- package/dist/backend-a2/scheduler-vercel.mjs +6 -6
- package/dist/backend-a2/store-memory.d.mts +2 -2
- package/dist/backend-a2/store-memory.mjs +3 -3
- package/dist/backend-a2/store-postgres.d.mts +1 -1
- package/dist/backend-a2/store-postgres.mjs +34 -15
- package/dist/backend-a2/store-redis-http.d.mts +1 -1
- package/dist/backend-a2/store-redis-http.mjs +6 -6
- package/dist/backend-a2/store-redis.d.mts +2 -2
- package/dist/backend-a2/store-redis.mjs +5 -5
- package/dist/backend-a2/store-sqlite.d.mts +1 -1
- package/dist/backend-a2/store-sqlite.mjs +3 -3
- package/dist/backend-a2.d.mts +143 -242
- package/dist/backend-a2.mjs +2 -2
- package/dist/{backend-http-CqfKhrnn.d.mts → backend-http-BRrRbjRx.d.mts} +59 -45
- package/dist/{backend-http-CzIJMm58.mjs → backend-http-CvUKOn-m.mjs} +11 -10
- package/dist/{backend-http-Bmp0IgD3.mjs → backend-http-D8mUzuKQ.mjs} +2 -2
- package/dist/backend-http.d.mts +1 -1
- package/dist/backend-http.mjs +1 -1
- package/dist/backend-http.node.d.mts +1 -1
- package/dist/backend-http.node.mjs +1 -1
- package/dist/{backend-vercel-DQc_TaHp.mjs → backend-vercel-Ba8JDtqW.mjs} +3 -3
- package/dist/{backend-vercel-4tvcPKqX.d.mts → backend-vercel-BaSEUdwg.d.mts} +62 -47
- package/dist/{backend-vercel-BNauAs7w.mjs → backend-vercel-CmY9yZ9m.mjs} +279 -42
- package/dist/backend-vercel.d.mts +1 -1
- package/dist/backend-vercel.mjs +1 -1
- package/dist/backend-vercel.node.d.mts +1 -1
- package/dist/backend-vercel.node.mjs +1 -1
- package/dist/{blob-DmiQjrYy.d.mts → blob-Bx8QPWEd.d.mts} +2 -2
- package/dist/{blob-DdbpJqN1.mjs → blob-WbB2DJKn.mjs} +30 -11
- package/dist/{chat-provider-BWHbChcQ.d.mts → chat-provider-BChYrrA7.d.mts} +32 -28
- package/dist/{chat-provider-COtsU5jB.mjs → chat-provider-DkFp2hrh.mjs} +105 -60
- package/dist/cli-commands.d.mts +1 -1
- package/dist/cli-commands.mjs +1 -1
- package/dist/cli-embedded.d.mts +2 -2
- package/dist/cli-embedded.mjs +1 -1
- package/dist/cli.mjs +4 -4
- package/dist/{client-BqAjk0Q4.d.mts → client-COfYrgfV.d.mts} +240 -227
- package/dist/{commands-D6gvrOh3.d.mts → commands-DK4W3HCJ.d.mts} +47 -10
- package/dist/{commands-C3R1AWgm.mjs → commands-L1JSGz2Z.mjs} +212 -54
- package/dist/conformance-DK43HiHf.mjs +1000 -0
- package/dist/conformance.d.mts +8 -2
- package/dist/conformance.mjs +1 -1
- package/dist/{engine-DQxXk7dX.mjs → engine-DurYIRt8.mjs} +29 -210
- package/dist/{errors-DDktVeUa.d.mts → errors-2vGs49Db.d.mts} +1 -1
- package/dist/{client-D0Px7KzF.mjs → errors-CJXhhzvT.mjs} +132 -27
- package/dist/{provider-BaVmi4Hi.mjs → events-lujPA3gQ.mjs} +80 -17
- package/dist/{exports-BG-0Wyn-.mjs → exports-CWIdN0Ub.mjs} +195 -103
- package/dist/exports-FBOQWT7O.d.mts +5 -0
- package/dist/{folds-BDMSxBUf.mjs → folds-Cu9Q9zyQ.mjs} +3 -22
- package/dist/{folds-ZkHM4M-v.d.mts → folds-DLUzfibJ.d.mts} +15 -40
- package/dist/{index-D3VvNfh_.d.mts → index-Ho-ayyQL.d.mts} +2 -2
- package/dist/index.d.mts +7 -7
- package/dist/{index.default-rB8sJ9RX.mjs → index.default-BUcwDaAe.mjs} +1 -1
- package/dist/index.mjs +5 -6
- package/dist/index.node.d.mts +7 -7
- package/dist/index.node.mjs +3 -4
- package/dist/inspect/app.js +62 -61
- package/dist/inspect/engine.js +3 -3
- package/dist/{internal-CvsrprnU-CRY89I-b.mjs → internal-CvsrprnU-zZMpDiRY.mjs} +1 -1
- package/dist/{local-DhkrAqPP.mjs → local-C76Fy5ad.mjs} +1 -1
- package/dist/{main-CVBqe3VO.mjs → main-Dz-8komG.mjs} +251 -127
- package/dist/{middleware-CXjEeef4.mjs → middleware-BavYSDUa.mjs} +1 -1
- package/dist/{node-Zd_C-gxP.mjs → node-BgeGcwX0.mjs} +7 -3
- package/dist/{platform-B4TnJtWu-CwcTyKg2.mjs → platform-B4TnJtWu-Do3agKr5.mjs} +1 -1
- package/dist/{project-CBXlLftU.mjs → project-CQ4VUibA.mjs} +1 -1
- package/dist/{provider-DmSTp9lI.d.mts → provider-gynDUoyW.d.mts} +13 -43
- package/dist/{redis-tables-BJQVUspu.mjs → redis-tables-DHf85ixI.mjs} +40 -42
- package/dist/{reducer-CjmvZSAb-D_OSISmj.mjs → reducer-Bswr11ar-P324o9vn.mjs} +2 -2
- package/dist/{reducer-CYPHsSmd-BQIfozGi.d.mts → reducer-CYPHsSmd-BXjGiptm.d.mts} +1 -1
- package/dist/{reducers-DJzVpXwM.mjs → reducers-DcENwtwZ.mjs} +74 -77
- package/dist/{retryable-lazy-DZWmHpii-Bye-W8q7.mjs → retryable-lazy-DZWmHpii-DpTc5PIP.mjs} +1 -1
- package/dist/{scheduler-task-X1SToDjP-BVoWuInI.mjs → scheduler-task-X1SToDjP-D2Il2rln.mjs} +1 -1
- package/dist/{serve-G9RuaDSr.mjs → serve-CTmow-YH.mjs} +7 -7
- package/dist/{server-qgez0Xny-D5mLfqFQ.d.mts → server-B9gu0qi1-DI1WvcVK.d.mts} +10 -4
- package/dist/{server-BixV_byP.mjs → server-DG8D6VV0.mjs} +4 -4
- package/dist/{server-DtFrWxi3-Boa6gdWO.mjs → server-DX7mM6nm-D7N_7bug.mjs} +32 -23
- package/dist/{serving-B75Y4BF-.mjs → serving-DBFRo6U_.mjs} +1 -1
- package/dist/{session-clear-wHd5GCpZ-BnKSxReK.mjs → session-clear-XJYpmUpg-2q8l_FJR.mjs} +14 -2
- package/dist/{sql-D4Z_efJX.mjs → sql-CT5xVuGr.mjs} +2 -8
- package/dist/{sqlite-db-Bz2JkfCU.mjs → sqlite-db-0WeSOEZN.mjs} +1 -1
- package/dist/{store-D0MhBvg6-4Z2L0Kqd.d.mts → store-DEzcHZOA-B-5vhxef.d.mts} +12 -2
- package/dist/store-N8PXxDAS-DWWgv-Vz.mjs +5 -0
- package/dist/{store-codec-DwrWlgQx-CYxGW0aD.mjs → store-codec-pAG2oPgQ-SqDXlPBR.mjs} +4 -4
- package/dist/store-memory-4IBl0Ztu.mjs +2 -0
- package/dist/{store-memory-Bas9Uq5C.mjs → store-memory-B0PkVSuQ.mjs} +14 -7
- package/dist/{store-polling-BZt2Rf3D-BiEM6_HB.mjs → store-polling-BZt2Rf3D-Div-bJ_D.mjs} +2 -2
- package/dist/{store-presence-polling-JuAy2Ck2-CYpuK75X.mjs → store-presence-polling-JuAy2Ck2-Dh-g_KYM.mjs} +3 -3
- package/dist/{store-sqlite-CxxPCcCT.mjs → store-sqlite-D85t3tE7.mjs} +14 -7
- package/dist/store-sqlite-iBTYYKBj.mjs +2 -0
- package/dist/{stream-buffer-DrTyiIuo-BKy-vI14.mjs → stream-buffer-DrTyiIuo-Be10yOBR.mjs} +2 -2
- package/dist/{sync-kapso.d.mts → sync-chat-sdk.d.mts} +33 -37
- package/dist/sync-chat-sdk.mjs +44 -0
- package/dist/sync-github.d.mts +5 -18
- package/dist/sync-github.mjs +4 -70
- package/dist/sync-linear.d.mts +3 -3
- package/dist/sync-linear.mjs +6 -5
- package/dist/sync-slack.d.mts +7 -7
- package/dist/sync-slack.mjs +33 -54
- package/dist/sync.d.mts +3 -3
- package/dist/sync.mjs +2 -4
- package/dist/{tokens-CC3izSNr.mjs → tokens-Dnyd_y1n.mjs} +15 -6
- package/dist/{types-No0WdhE5.d.mts → types-CmrFjpml.d.mts} +2 -4
- package/dist/{watchers-hash-BDhLVkV5.mjs → watchers-hash-BjwlnGD9.mjs} +124 -115
- package/docs/01-board/01-mounting.md +2 -2
- package/docs/01-board/03-identity.md +5 -6
- package/docs/01-board/04-messages.md +96 -2
- package/docs/01-board/05-reading.md +2 -1
- package/docs/01-board/06-watchers.md +8 -6
- package/docs/01-board/08-middleware.md +6 -3
- package/docs/01-board/09-access.md +145 -14
- package/docs/02-sync/01-overview.md +19 -26
- package/docs/02-sync/02-functions.md +8 -9
- package/docs/02-sync/03-slack.md +5 -5
- package/docs/02-sync/04-github.md +2 -2
- package/docs/02-sync/06-providers.md +91 -62
- package/docs/03-guides/01-coding-agents.md +1 -1
- package/docs/03-guides/03-ci.md +7 -4
- package/docs/04-reference/01-cli.md +109 -51
- package/docs/04-reference/02-board.md +76 -28
- package/docs/04-reference/03-http.md +76 -38
- package/docs/04-reference/04-log.md +8 -11
- package/docs/04-reference/05-conformance.md +47 -7
- package/docs/index.md +2 -2
- package/package.json +7 -10
- package/sql/postgres/board.sql +1 -1
- package/sql/postgres/schema.sql +1 -1
- package/dist/conformance-DlnfuzEB.mjs +0 -556
- package/dist/errors-CusN4x2l.mjs +0 -88
- package/dist/events-qf5XG5VQ.mjs +0 -75
- package/dist/exports-mhAYiU4i.d.mts +0 -5
- package/dist/store-N8PXxDAS-BWBgzBHp.mjs +0 -5
- package/dist/store-memory-ZLiZbH3R.mjs +0 -2
- package/dist/store-sqlite-BmwL3pUR.mjs +0 -2
- package/dist/sync-kapso.mjs +0 -89
- package/dist/sync.chat.d.mts +0 -2
- package/dist/sync.chat.mjs +0 -2
- package/dist/users-yryHKFMo.mjs +0 -42
- package/docs/02-sync/05-whatsapp.md +0 -152
package/dist/sync-github.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as ChatSyncProvider } from "./chat-provider-
|
|
1
|
+
import { f as SyncContext, g as SyncFn, y as SyncUnit } from "./provider-gynDUoyW.mjs";
|
|
2
|
+
import { n as ChatSyncProvider } from "./chat-provider-BChYrrA7.mjs";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { Adapter } from "chat";
|
|
5
5
|
//#region src/sync/github.d.ts
|
|
@@ -432,9 +432,8 @@ export type GitHubRepo = SyncUnit<GitHubEvent> | {
|
|
|
432
432
|
};
|
|
433
433
|
export type GitHubOptions = {
|
|
434
434
|
/**
|
|
435
|
-
* A Vercel Connect connector (`'github/acme'`): board builds the GitHub adapter
|
|
436
|
-
*
|
|
437
|
-
* Or your own Chat SDK adapter, wrapped in `withUserTokens` to post as people.
|
|
435
|
+
* A Vercel Connect connector (`'github/acme'`): board builds the GitHub adapter.
|
|
436
|
+
* Or your own Chat SDK adapter.
|
|
438
437
|
*/
|
|
439
438
|
adapter: Adapter | string;
|
|
440
439
|
/**
|
|
@@ -459,18 +458,7 @@ export declare function github(app: string | GitHubOptions, sync: SyncFn<GitHubE
|
|
|
459
458
|
*/
|
|
460
459
|
export declare function repos(map: Record<string, GitHubRepo>): SyncFn<GitHubEvent>;
|
|
461
460
|
export declare class GitHubProvider extends ChatSyncProvider<GitHubEvent> {
|
|
462
|
-
private readonly body;
|
|
463
461
|
constructor(given: GitHubOptions, sync: SyncFn<GitHubEvent>);
|
|
464
|
-
whoAmI(token: string): Promise<{
|
|
465
|
-
id: string;
|
|
466
|
-
handle: string;
|
|
467
|
-
name: string;
|
|
468
|
-
avatar: string | null;
|
|
469
|
-
isBot: boolean;
|
|
470
|
-
}>;
|
|
471
|
-
postAs(token: string, target: string, kind: ResolvedTarget['kind'], post: ProviderPost): Promise<ProviderDelivery>;
|
|
472
|
-
editAs(token: string, thread: string, message: string, post: ProviderPost): Promise<void>;
|
|
473
|
-
deleteAs(token: string, thread: string, message: string): Promise<void>;
|
|
474
462
|
/**
|
|
475
463
|
* A thread's root is the PR or issue itself, not a comment: its copy has no comment ID
|
|
476
464
|
* (`root:<event>` or `lifecycle:<event>`), so its reactions go on the PR or issue.
|
|
@@ -478,5 +466,4 @@ export declare class GitHubProvider extends ChatSyncProvider<GitHubEvent> {
|
|
|
478
466
|
react(thread: string, message: string, emoji: string, added: boolean): Promise<void>;
|
|
479
467
|
event(context: SyncContext): GitHubEvent;
|
|
480
468
|
}
|
|
481
|
-
//#endregion
|
|
482
|
-
export { type UserTokens, withUserTokens };
|
|
469
|
+
//#endregion
|
package/dist/sync-github.mjs
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { r as withUserTokens, t as connectUserTokens } from "./users-yryHKFMo.mjs";
|
|
4
|
-
import { r as markdownOf, t as ChatSyncProvider } from "./chat-provider-COtsU5jB.mjs";
|
|
1
|
+
import { g as withRoutes, i as eventSchema, p as into, r as envelope } from "./events-lujPA3gQ.mjs";
|
|
2
|
+
import { n as markdownOf, t as ChatSyncProvider } from "./chat-provider-DkFp2hrh.mjs";
|
|
5
3
|
import { n as tagOf } from "./tags-BpFo6q0_.mjs";
|
|
6
4
|
import { z } from "zod";
|
|
7
5
|
import { connectGitHubAdapter } from "@vercel/connect/chat";
|
|
@@ -338,35 +336,6 @@ const GitHubEvent = z.discriminatedUnion("type", [
|
|
|
338
336
|
...prTypes.map(prLifecycle),
|
|
339
337
|
...issueTypes.map(issueLifecycle)
|
|
340
338
|
]);
|
|
341
|
-
/** `owner/repo:12`, `owner/repo:issue:3`, or `owner/repo:12:rc:345` (a review comment thread). */
|
|
342
|
-
function parseThread(thread) {
|
|
343
|
-
const match = /^([^/]+)\/([^:]+):(?:issue:)?(\d+)(?::rc:(\d+))?$/.exec(thread);
|
|
344
|
-
if (!match) throw new Error(`invalid GitHub thread: ${thread}`);
|
|
345
|
-
return {
|
|
346
|
-
owner: match[1],
|
|
347
|
-
repo: match[2],
|
|
348
|
-
number: Number(match[3]),
|
|
349
|
-
review: match[4] ? Number(match[4]) : null
|
|
350
|
-
};
|
|
351
|
-
}
|
|
352
|
-
/** GitHub's REST API with a person's own token: Chat SDK's adapter only holds the app's. */
|
|
353
|
-
async function asPerson(token, method, path, body) {
|
|
354
|
-
const response = await fetch(`https://api.github.com${path}`, {
|
|
355
|
-
method,
|
|
356
|
-
headers: {
|
|
357
|
-
authorization: `Bearer ${token}`,
|
|
358
|
-
accept: "application/vnd.github+json",
|
|
359
|
-
"x-github-api-version": "2022-11-28",
|
|
360
|
-
...body === void 0 ? {} : { "content-type": "application/json" }
|
|
361
|
-
},
|
|
362
|
-
...body === void 0 ? {} : { body: JSON.stringify(body) }
|
|
363
|
-
});
|
|
364
|
-
if (!response.ok) {
|
|
365
|
-
const detail = await response.text().catch(() => "");
|
|
366
|
-
throw Object.assign(/* @__PURE__ */ new Error(`GitHub ${method} ${path}: ${response.status} ${detail.slice(0, 200)}`), { data: { error: `github_${response.status}` } });
|
|
367
|
-
}
|
|
368
|
-
return response.status === 204 ? null : response.json();
|
|
369
|
-
}
|
|
370
339
|
/**
|
|
371
340
|
* Syncs GitHub with the board: `app` is a Vercel Connect connector
|
|
372
341
|
* (`'github/acme'`) or the options, and `sync` is what each event does, both
|
|
@@ -428,10 +397,9 @@ function fromConnector(connector, botUserId) {
|
|
|
428
397
|
detecting.logger?.warn("Could not detect the GitHub bot user ID", { error });
|
|
429
398
|
}
|
|
430
399
|
};
|
|
431
|
-
return
|
|
400
|
+
return adapter;
|
|
432
401
|
}
|
|
433
402
|
var GitHubProvider = class extends ChatSyncProvider {
|
|
434
|
-
body;
|
|
435
403
|
constructor(given, sync) {
|
|
436
404
|
const options = {
|
|
437
405
|
...given,
|
|
@@ -590,40 +558,6 @@ var GitHubProvider = class extends ChatSyncProvider {
|
|
|
590
558
|
};
|
|
591
559
|
}
|
|
592
560
|
}, sync);
|
|
593
|
-
const converter = options.adapter.formatConverter;
|
|
594
|
-
this.body = (post) => {
|
|
595
|
-
try {
|
|
596
|
-
return converter ? converter.renderPostable({ markdown: post.markdown }) : post.markdown;
|
|
597
|
-
} catch {
|
|
598
|
-
return post.markdown;
|
|
599
|
-
}
|
|
600
|
-
};
|
|
601
|
-
}
|
|
602
|
-
async whoAmI(token) {
|
|
603
|
-
const user = await asPerson(token, "GET", "/user");
|
|
604
|
-
if (!user.id) throw new Error("GitHub didn't say whose token this is");
|
|
605
|
-
return {
|
|
606
|
-
...author(user),
|
|
607
|
-
isBot: false
|
|
608
|
-
};
|
|
609
|
-
}
|
|
610
|
-
async postAs(token, target, kind, post) {
|
|
611
|
-
if (kind === "channel") throw new Error("github cannot start threads");
|
|
612
|
-
const { owner, repo, number, review } = parseThread(target);
|
|
613
|
-
const body = this.body(post);
|
|
614
|
-
const comment = await (review !== null ? asPerson(token, "POST", `/repos/${owner}/${repo}/pulls/${number}/comments/${review}/replies`, { body }) : asPerson(token, "POST", `/repos/${owner}/${repo}/issues/${number}/comments`, { body }));
|
|
615
|
-
return {
|
|
616
|
-
thread: target,
|
|
617
|
-
message: String(comment.id)
|
|
618
|
-
};
|
|
619
|
-
}
|
|
620
|
-
async editAs(token, thread, message, post) {
|
|
621
|
-
const { owner, repo, review } = parseThread(thread);
|
|
622
|
-
await asPerson(token, "PATCH", `/repos/${owner}/${repo}/${review !== null ? "pulls" : "issues"}/comments/${message}`, { body: this.body(post) });
|
|
623
|
-
}
|
|
624
|
-
async deleteAs(token, thread, message) {
|
|
625
|
-
const { owner, repo, review } = parseThread(thread);
|
|
626
|
-
await asPerson(token, "DELETE", `/repos/${owner}/${repo}/${review !== null ? "pulls" : "issues"}/comments/${message}`);
|
|
627
561
|
}
|
|
628
562
|
/**
|
|
629
563
|
* A thread's root is the PR or issue itself, not a comment: its copy has no comment ID
|
|
@@ -676,4 +610,4 @@ var GitHubProvider = class extends ChatSyncProvider {
|
|
|
676
610
|
}
|
|
677
611
|
};
|
|
678
612
|
//#endregion
|
|
679
|
-
export { GitHubEvent, GitHubPayload, GitHubProvider, github, repos
|
|
613
|
+
export { GitHubEvent, GitHubPayload, GitHubProvider, github, repos };
|
package/dist/sync-linear.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { mt as SourceRead } from "./client-
|
|
2
|
-
import {
|
|
3
|
-
import { n as ChatSyncProvider, t as ChatInput } from "./chat-provider-
|
|
1
|
+
import { mt as SourceRead } from "./client-COfYrgfV.mjs";
|
|
2
|
+
import { c as ReceivedEvent, d as ResolvedTarget, f as SyncContext, g as SyncFn, o as ProviderPost, r as ProviderDelivery, y as SyncUnit } from "./provider-gynDUoyW.mjs";
|
|
3
|
+
import { n as ChatSyncProvider, t as ChatInput } from "./chat-provider-BChYrrA7.mjs";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import { Adapter } from "chat";
|
|
6
6
|
//#region src/sync/linear.d.ts
|
package/dist/sync-linear.mjs
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { i as UnreadableError,
|
|
2
|
-
import {
|
|
3
|
-
import { r as markdownOf, t as ChatSyncProvider } from "./chat-provider-COtsU5jB.mjs";
|
|
1
|
+
import { f as channels, i as eventSchema, l as UnreadableError, r as envelope } from "./events-lujPA3gQ.mjs";
|
|
2
|
+
import { n as markdownOf, t as ChatSyncProvider } from "./chat-provider-DkFp2hrh.mjs";
|
|
4
3
|
import { n as tagOf, t as slug } from "./tags-BpFo6q0_.mjs";
|
|
5
4
|
import "zod";
|
|
6
5
|
import { connectLinearAdapter } from "@vercel/connect/chat";
|
|
@@ -37,6 +36,8 @@ const bodyOf = (description) => description?.trim() || null;
|
|
|
37
36
|
* An issue's properties as board labels: `priority=high`, `project=v0-accessibility`, a label per
|
|
38
37
|
* Linear label (`tag.bug`), and its assignee (`assignee.ada`). Only what the payload says: a
|
|
39
38
|
* property it carries empty is unset, and one it names without its details is left as it was.
|
|
39
|
+
* Linear leaves an empty assignee or project out of the payload rather than sending `null`, so
|
|
40
|
+
* either one missing, with no ID either, is empty.
|
|
40
41
|
* `priority` and `project` are single keys, so they're unset by name; `tag.` and `assignee.` are
|
|
41
42
|
* prefixes the mirror owns, so a key under them that Linear doesn't have goes.
|
|
42
43
|
*/
|
|
@@ -47,7 +48,7 @@ function propertiesOf(data) {
|
|
|
47
48
|
if (data.priority === 0 || data.priorityLabel === "No priority") unset.push("priority");
|
|
48
49
|
else if (data.priorityLabel && slug(data.priorityLabel)) labels.priority = slug(data.priorityLabel).slice(0, 256);
|
|
49
50
|
if (data.project?.name && slug(data.project.name)) labels.project = slug(data.project.name).slice(0, 256);
|
|
50
|
-
else if (data.project
|
|
51
|
+
else if (!data.project && !data.projectId) unset.push("project");
|
|
51
52
|
if (Array.isArray(data.labels)) {
|
|
52
53
|
owns.push("tag.");
|
|
53
54
|
for (const label of data.labels) {
|
|
@@ -59,7 +60,7 @@ function propertiesOf(data) {
|
|
|
59
60
|
owns.push("assignee.");
|
|
60
61
|
const tag = tagOf("assignee", handleOf(data.assignee));
|
|
61
62
|
if (tag) labels[tag[0]] = tag[1];
|
|
62
|
-
} else if (data.
|
|
63
|
+
} else if (!data.assigneeId) owns.push("assignee.");
|
|
63
64
|
return {
|
|
64
65
|
labels,
|
|
65
66
|
unset,
|
package/dist/sync-slack.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { f as ExternalLink } from "./folds-
|
|
2
|
-
import {
|
|
3
|
-
import { n as ChatSyncProvider, t as ChatInput } from "./chat-provider-
|
|
1
|
+
import { f as ExternalLink } from "./folds-DLUzfibJ.mjs";
|
|
2
|
+
import { b as channels, d as ResolvedTarget, f as SyncContext, g as SyncFn, o as ProviderPost, r as ProviderDelivery } from "./provider-gynDUoyW.mjs";
|
|
3
|
+
import { n as ChatSyncProvider, t as ChatInput } from "./chat-provider-BChYrrA7.mjs";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import { Adapter } from "chat";
|
|
6
6
|
//#region src/sync/slack.d.ts
|
|
@@ -165,6 +165,7 @@ type SlackMessage = {
|
|
|
165
165
|
files?: SlackFile[];
|
|
166
166
|
thread_ts?: string;
|
|
167
167
|
reply_count?: number;
|
|
168
|
+
attachments?: SlackAttachment[];
|
|
168
169
|
};
|
|
169
170
|
/** What Slack attaches to a message that links another: `is_msg_unfurl` marks a message link's. */
|
|
170
171
|
type SlackAttachment = {
|
|
@@ -343,9 +344,8 @@ export declare const SlackEvent: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
343
344
|
export type SlackEvent = z.infer<typeof SlackEvent>;
|
|
344
345
|
export type SlackOptions = {
|
|
345
346
|
/**
|
|
346
|
-
* A Vercel Connect connector (`'slack/acme'`): board builds the Slack adapter
|
|
347
|
-
* its Web API client
|
|
348
|
-
* Or your own Chat SDK adapter, wrapped in `withUserTokens` to post as people.
|
|
347
|
+
* A Vercel Connect connector (`'slack/acme'`): board builds the Slack adapter
|
|
348
|
+
* and its Web API client. Or your own Chat SDK adapter.
|
|
349
349
|
*/
|
|
350
350
|
adapter: Adapter | string;
|
|
351
351
|
/** Not needed with a connector. */
|
|
@@ -401,4 +401,4 @@ export declare class SlackProvider extends ChatSyncProvider<SlackEvent> {
|
|
|
401
401
|
event(context: SyncContext): SlackEvent;
|
|
402
402
|
}
|
|
403
403
|
//#endregion
|
|
404
|
-
export {
|
|
404
|
+
export { channels };
|
package/dist/sync-slack.mjs
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { m as MESSAGE_TEXT_MAX } from "./schemas-DBmUO6pr.mjs";
|
|
2
2
|
import "./external-D3p5T57R.mjs";
|
|
3
|
-
import { i as UnreadableError,
|
|
4
|
-
import {
|
|
5
|
-
import { r as withUserTokens, t as connectUserTokens } from "./users-yryHKFMo.mjs";
|
|
6
|
-
import { r as markdownOf, t as ChatSyncProvider } from "./chat-provider-COtsU5jB.mjs";
|
|
3
|
+
import { f as channels, i as eventSchema, l as UnreadableError, r as envelope } from "./events-lujPA3gQ.mjs";
|
|
4
|
+
import { n as markdownOf, t as ChatSyncProvider } from "./chat-provider-DkFp2hrh.mjs";
|
|
7
5
|
import { z } from "zod";
|
|
8
6
|
import { stringifyMarkdown } from "chat";
|
|
9
7
|
import { createSlackAdapter } from "@chat-adapter/slack";
|
|
@@ -236,13 +234,13 @@ const SLACK_CLIENT = {
|
|
|
236
234
|
},
|
|
237
235
|
timeout: 3e4
|
|
238
236
|
};
|
|
239
|
-
/** A Slack adapter
|
|
237
|
+
/** A Slack adapter and its client, from one Vercel Connect connector. */
|
|
240
238
|
function fromConnector(connector) {
|
|
241
239
|
const credentials = connectSlackAdapter(connector);
|
|
242
|
-
const adapter =
|
|
240
|
+
const adapter = createSlackAdapter({
|
|
243
241
|
...credentials,
|
|
244
242
|
webClientOptions: SLACK_CLIENT
|
|
245
|
-
})
|
|
243
|
+
});
|
|
246
244
|
const botToken = credentials.botToken;
|
|
247
245
|
const client = async () => adapter.withBotToken(typeof botToken === "function" ? await botToken() : botToken, () => adapter.webClient);
|
|
248
246
|
return {
|
|
@@ -263,7 +261,6 @@ var SlackProvider = class extends ChatSyncProvider {
|
|
|
263
261
|
...given,
|
|
264
262
|
adapter: given.adapter
|
|
265
263
|
};
|
|
266
|
-
const tokens = options.adapter;
|
|
267
264
|
let directClient;
|
|
268
265
|
if (!options.client) try {
|
|
269
266
|
directClient = options.adapter.webClient;
|
|
@@ -457,47 +454,45 @@ var SlackProvider = class extends ChatSyncProvider {
|
|
|
457
454
|
return null;
|
|
458
455
|
}
|
|
459
456
|
},
|
|
460
|
-
async fetchLink(link) {
|
|
457
|
+
async fetchLink(link, linker) {
|
|
461
458
|
const [, channel, thread] = link.thread.split(":");
|
|
462
459
|
const web = await client();
|
|
463
|
-
|
|
460
|
+
const replies = web?.conversations.replies;
|
|
461
|
+
if (!web || !replies || !channel || !thread) return {
|
|
464
462
|
snapshot: null,
|
|
465
463
|
unavailable: "no Slack client to read it with"
|
|
466
464
|
};
|
|
465
|
+
const one = async (channel, thread, ts) => (await replies({
|
|
466
|
+
channel,
|
|
467
|
+
ts: thread,
|
|
468
|
+
oldest: ts,
|
|
469
|
+
latest: ts,
|
|
470
|
+
inclusive: true,
|
|
471
|
+
limit: 1
|
|
472
|
+
})).messages?.find((m) => m.ts === ts);
|
|
467
473
|
let found;
|
|
474
|
+
let unavailable = "message_not_found";
|
|
468
475
|
try {
|
|
469
476
|
const info = (await web.conversations.info({ channel })).channel;
|
|
470
|
-
if (!info)
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
if (info.is_private || info.is_im || info.is_mpim) return {
|
|
475
|
-
snapshot: null,
|
|
476
|
-
unavailable: "private_channel"
|
|
477
|
-
};
|
|
478
|
-
if (!info.is_member) return {
|
|
479
|
-
snapshot: null,
|
|
480
|
-
unavailable: "not_in_channel"
|
|
481
|
-
};
|
|
482
|
-
const { messages } = await web.conversations.replies({
|
|
483
|
-
channel,
|
|
484
|
-
ts: thread,
|
|
485
|
-
oldest: link.message,
|
|
486
|
-
latest: link.message,
|
|
487
|
-
inclusive: true,
|
|
488
|
-
limit: 1
|
|
489
|
-
});
|
|
490
|
-
found = messages?.find((m) => m.ts === link.message);
|
|
477
|
+
if (!info) unavailable = "channel_not_found";
|
|
478
|
+
else if (info.is_private || info.is_im || info.is_mpim) unavailable = "private_channel";
|
|
479
|
+
else if (!info.is_member) unavailable = "not_in_channel";
|
|
480
|
+
else found = await one(channel, thread, link.message);
|
|
491
481
|
} catch (error) {
|
|
492
|
-
|
|
482
|
+
unavailable = slackError(error);
|
|
483
|
+
}
|
|
484
|
+
if (!found) {
|
|
485
|
+
const [, at, root] = linker.thread.split(":");
|
|
486
|
+
const linking = at && root ? await one(at, root, linker.message).catch(() => void 0) : void 0;
|
|
487
|
+
const unfurled = linking ? slackLinks("", linking.text ?? "", linking.attachments, mrkdwn).find((known) => known.url === link.url)?.snapshot : null;
|
|
488
|
+
return unfurled ? {
|
|
489
|
+
snapshot: unfurled,
|
|
490
|
+
unavailable: null
|
|
491
|
+
} : {
|
|
493
492
|
snapshot: null,
|
|
494
|
-
unavailable
|
|
493
|
+
unavailable
|
|
495
494
|
};
|
|
496
495
|
}
|
|
497
|
-
if (!found) return {
|
|
498
|
-
snapshot: null,
|
|
499
|
-
unavailable: "message_not_found"
|
|
500
|
-
};
|
|
501
496
|
return {
|
|
502
497
|
unavailable: null,
|
|
503
498
|
snapshot: {
|
|
@@ -645,22 +640,6 @@ var SlackProvider = class extends ChatSyncProvider {
|
|
|
645
640
|
groupThread: (thread) => thread,
|
|
646
641
|
isRoot: (thread, messageId) => thread.slice(thread.lastIndexOf(":") + 1) === messageId,
|
|
647
642
|
context: () => null,
|
|
648
|
-
...typeof tokens.withBotToken === "function" ? {
|
|
649
|
-
runAs: (token, fn) => tokens.withBotToken(token, fn),
|
|
650
|
-
async whoAmI(token) {
|
|
651
|
-
const me = await tokens.withBotToken(token, () => tokens.webClient.auth.test());
|
|
652
|
-
if (!me.user_id) throw new Error("Slack didn't say whose token this is");
|
|
653
|
-
const user = (await (await client().catch(() => void 0))?.users?.info({ user: me.user_id }).catch(() => void 0))?.user;
|
|
654
|
-
const handle = user?.profile?.display_name || user?.name || me.user || me.user_id;
|
|
655
|
-
return {
|
|
656
|
-
id: `slack:user:${me.user_id}`,
|
|
657
|
-
handle,
|
|
658
|
-
name: user?.profile?.real_name || user?.real_name || handle,
|
|
659
|
-
avatar: user?.profile?.image_72 ?? user?.profile?.image_48 ?? null,
|
|
660
|
-
isBot: false
|
|
661
|
-
};
|
|
662
|
-
}
|
|
663
|
-
} : {},
|
|
664
643
|
async resolveTarget(target) {
|
|
665
644
|
const at = target.indexOf(":");
|
|
666
645
|
const channel = await this.resolveChannel(at === -1 ? target : target.slice(0, at));
|
|
@@ -836,4 +815,4 @@ var SlackProvider = class extends ChatSyncProvider {
|
|
|
836
815
|
}
|
|
837
816
|
};
|
|
838
817
|
//#endregion
|
|
839
|
-
export { SlackEvent, SlackProvider, channels, forwardText, slack, slackFileName, slackIcon, slackLinks,
|
|
818
|
+
export { SlackEvent, SlackProvider, channels, forwardText, slack, slackFileName, slackIcon, slackLinks, withoutHtml, withoutLabel };
|
package/dist/sync.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { d as ExternalFile, l as ExternalAuthor, u as ExternalEvent } from "./folds-
|
|
2
|
-
import { A as
|
|
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,
|
|
1
|
+
import { d as ExternalFile, l as ExternalAuthor, u as ExternalEvent } from "./folds-DLUzfibJ.mjs";
|
|
2
|
+
import { A as envelope, C as render, D as SyncOverrides, E as RootOverride, O as SyncResult, S as mirror, T as ProviderEvent, _ as SyncIn, a as ProviderOptions, b as channels, c as ReceivedEvent, d as ResolvedTarget, f as SyncContext, g as SyncFn, h as Sync, i as ProviderFile, j as eventSchema, k as SyncRoot, 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 SyncOut, w as EventBase, x as into, y as SyncUnit } from "./provider-gynDUoyW.mjs";
|
|
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, channels, envelope, eventSchema, into, mirror, render };
|
package/dist/sync.mjs
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
1
|
import { n as ExternalEvent } from "./external-D3p5T57R.mjs";
|
|
2
|
-
import { c as
|
|
3
|
-
|
|
4
|
-
import { r as withUserTokens, t as connectUserTokens } from "./users-yryHKFMo.mjs";
|
|
5
|
-
export { EventBase, ExternalEvent, ReceivedEvent, ResolvedTarget, SyncOverrides, SyncProvider, UnreadableError, channels, connectUserTokens, envelope, eventSchema, into, mirror, render, withUserTokens };
|
|
2
|
+
import { c as SyncProvider, f as channels, h as render, i as eventSchema, l as UnreadableError, m as mirror, n as SyncOverrides, o as ReceivedEvent, p as into, r as envelope, s as ResolvedTarget, t as EventBase } from "./events-lujPA3gQ.mjs";
|
|
3
|
+
export { EventBase, ExternalEvent, ReceivedEvent, ResolvedTarget, SyncOverrides, SyncProvider, UnreadableError, channels, envelope, eventSchema, into, mirror, render };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { l as unauthorized } from "./errors-
|
|
2
|
-
import {
|
|
1
|
+
import { l as unauthorized } from "./errors-CJXhhzvT.mjs";
|
|
2
|
+
import { a as VERCEL_ISSUER, b as trustedIssuers, g as markVerified, i as TOKENS, m as issuerName, v as privateHost } from "./auth-CyO2aw5n.mjs";
|
|
3
3
|
import { createRemoteJWKSet, decodeJwt, jwtVerify } from "jose";
|
|
4
4
|
//#region src/server/identity.ts
|
|
5
5
|
let fromDisk;
|
|
@@ -95,13 +95,22 @@ function factsOf(issuer, iss, claims) {
|
|
|
95
95
|
}
|
|
96
96
|
const issuerMatches = (iss, accepted) => typeof accepted === "string" ? iss === accepted : accepted.test(iss);
|
|
97
97
|
const remoteKeys = /* @__PURE__ */ new Map();
|
|
98
|
+
/**
|
|
99
|
+
* An issuer's keys, by OIDC Discovery 1.0: its document under the issuer, naming that issuer
|
|
100
|
+
* (§4.3), and its keys at an https `jwks_uri` (§3), which must be on the internet, as a grant's
|
|
101
|
+
* issuer must. Like jose's own fetch of the keys, it follows no redirect.
|
|
102
|
+
*/
|
|
98
103
|
async function keysFor(iss) {
|
|
99
104
|
const cached = remoteKeys.get(iss);
|
|
100
105
|
if (cached) return cached;
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
const
|
|
106
|
+
const unknown = (why) => unauthorized(`cannot load keys for issuer ${iss}: ${why}`);
|
|
107
|
+
const response = await fetch(`${iss.replace(/\/+$/, "")}/.well-known/openid-configuration`, { redirect: "manual" });
|
|
108
|
+
if (response.status !== 200) throw unknown(`its discovery answered ${response.status}`);
|
|
109
|
+
const config = await response.json().catch(() => null);
|
|
110
|
+
if (config?.issuer !== iss) throw unknown("its discovery names another issuer");
|
|
111
|
+
const jwks = typeof config.jwks_uri === "string" ? URL.parse(config.jwks_uri) : null;
|
|
112
|
+
if (jwks?.protocol !== "https:" || privateHost(jwks.hostname)) throw unknown("its jwks_uri isn't an https URL on the internet");
|
|
113
|
+
const keys = createRemoteJWKSet(jwks);
|
|
105
114
|
remoteKeys.set(iss, keys);
|
|
106
115
|
return keys;
|
|
107
116
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as ExternalCopy, c as SyncedThread, g as BoardEvent, o as Message } from "./folds-
|
|
2
|
-
import { t as A2Store } from "./store-
|
|
1
|
+
import { a as ExternalCopy, c as SyncedThread, g as BoardEvent, o as Message } from "./folds-DLUzfibJ.mjs";
|
|
2
|
+
import { t as A2Store } from "./store-DEzcHZOA-B-5vhxef.mjs";
|
|
3
3
|
//#region src/store/types.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* What a query matches, resolved by the board: handles are already actor and
|
|
@@ -84,8 +84,6 @@ interface MessageTables {
|
|
|
84
84
|
messageOf(externalThread: string, platformMessage: string): Promise<number | null>;
|
|
85
85
|
/** Every platform thread a board thread lives in. */
|
|
86
86
|
externalThreads(): Promise<string[]>;
|
|
87
|
-
/** A person's own roots posted at or after `since` (epoch ms). */
|
|
88
|
-
recentRoots(principal: string, since: number): Promise<Message[]>;
|
|
89
87
|
/** The messages that carry an attachment, by ID. A deleted message carries none. */
|
|
90
88
|
withAttachment(attachment: string): Promise<Message[]>;
|
|
91
89
|
close(): Promise<void>;
|