@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
package/dist/sync-kapso.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as SyncUnit, f as SyncContext, y as SyncFn } from "./provider-
|
|
2
|
-
import { n as ChatSyncProvider, t as ChatInput } from "./chat-provider-
|
|
1
|
+
import { S as SyncUnit, f as SyncContext, y as SyncFn } from "./provider-Bm46LAdp.mjs";
|
|
2
|
+
import { n as ChatSyncProvider, t as ChatInput } from "./chat-provider-D6jVT4wS.mjs";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { Adapter } from "chat";
|
|
5
5
|
//#region src/sync/kapso.d.ts
|
|
@@ -127,6 +127,7 @@ export declare const WhatsAppEvent: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
127
127
|
type: z.ZodString;
|
|
128
128
|
title: z.ZodString;
|
|
129
129
|
url: z.ZodNullable<z.ZodString>;
|
|
130
|
+
body: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
130
131
|
labels: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
131
132
|
unset: z.ZodArray<z.ZodString>;
|
|
132
133
|
owns: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
package/dist/sync-kapso.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { s as channels } from "./provider-
|
|
2
|
-
import { i as eventSchema, r as envelope } from "./events-
|
|
3
|
-
import { r as markdownOf, t as ChatSyncProvider } from "./chat-provider-
|
|
1
|
+
import { s as channels } from "./provider-BaVmi4Hi.mjs";
|
|
2
|
+
import { i as eventSchema, r as envelope } from "./events-qf5XG5VQ.mjs";
|
|
3
|
+
import { r as markdownOf, t as ChatSyncProvider } from "./chat-provider-COtsU5jB.mjs";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
//#region src/sync/kapso.ts
|
|
6
6
|
const decode = (id) => id.split(":").map((part) => Buffer.from(part, "base64url").toString("utf8")).join(":");
|
package/dist/sync-linear.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { ht as SourceRead } from "./client-CjAatpV4.mjs";
|
|
2
|
+
import { S as SyncUnit, c as ReceivedEvent, d as ResolvedTarget, f as SyncContext, o as ProviderPost, r as ProviderDelivery, y as SyncFn } from "./provider-Bm46LAdp.mjs";
|
|
3
|
+
import { n as ChatSyncProvider, t as ChatInput } from "./chat-provider-D6jVT4wS.mjs";
|
|
3
4
|
import { z } from "zod";
|
|
4
5
|
import { Adapter } from "chat";
|
|
5
6
|
//#region src/sync/linear.d.ts
|
|
@@ -127,6 +128,7 @@ export declare const LinearEvent: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
127
128
|
type: z.ZodString;
|
|
128
129
|
title: z.ZodString;
|
|
129
130
|
url: z.ZodNullable<z.ZodString>;
|
|
131
|
+
body: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
130
132
|
labels: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
131
133
|
unset: z.ZodArray<z.ZodString>;
|
|
132
134
|
owns: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
@@ -174,6 +176,14 @@ export declare class LinearProvider extends ChatSyncProvider<LinearEvent> {
|
|
|
174
176
|
* webhook sets up: anything else (a delivery, a root fetched on a later pull) asks for one here.
|
|
175
177
|
*/
|
|
176
178
|
private api;
|
|
179
|
+
/**
|
|
180
|
+
* A project's or team's issues, newest first, or one issue and its comments, read on demand:
|
|
181
|
+
* nothing is synced or stored. `next` pages past a read's `limit`.
|
|
182
|
+
*/
|
|
183
|
+
read(target: string, { limit, after }: {
|
|
184
|
+
limit: number;
|
|
185
|
+
after: string | null;
|
|
186
|
+
}): Promise<SourceRead>;
|
|
177
187
|
resolveChannel(key: string): Promise<string>;
|
|
178
188
|
/**
|
|
179
189
|
* `ENG` is a team; `ENG:<uuid>`, a bare UUID, or `ENG-12` is an issue, by its team and UUID:
|
package/dist/sync-linear.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { i as UnreadableError, s as channels } from "./provider-
|
|
2
|
-
import { i as eventSchema, r as envelope } from "./events-
|
|
3
|
-
import { r as markdownOf, t as ChatSyncProvider } from "./chat-provider-
|
|
1
|
+
import { i as UnreadableError, s as channels } from "./provider-BaVmi4Hi.mjs";
|
|
2
|
+
import { i as eventSchema, r as envelope } from "./events-qf5XG5VQ.mjs";
|
|
3
|
+
import { r as markdownOf, t as ChatSyncProvider } from "./chat-provider-COtsU5jB.mjs";
|
|
4
|
+
import { n as tagOf, t as slug } from "./tags-BpFo6q0_.mjs";
|
|
4
5
|
import "zod";
|
|
5
6
|
import { connectLinearAdapter } from "@vercel/connect/chat";
|
|
6
7
|
import { createLinearAdapter } from "@chat-adapter/linear";
|
|
@@ -30,6 +31,43 @@ const author = (user, isBot) => ({
|
|
|
30
31
|
});
|
|
31
32
|
/** `ENG` from `ENG-123`, or from a Linear URL that names an issue (`…/issue/ENG-123/…`). */
|
|
32
33
|
const teamOf = (identifierOrUrl) => /(?:^|\/issue\/)([A-Z0-9_]+)-\d+/i.exec(identifierOrUrl ?? "")?.[1]?.toUpperCase() ?? null;
|
|
34
|
+
/** An issue's description, or null when it has none. */
|
|
35
|
+
const bodyOf = (description) => description?.trim() || null;
|
|
36
|
+
/**
|
|
37
|
+
* An issue's properties as board labels: `priority=high`, `project=v0-accessibility`, a label per
|
|
38
|
+
* Linear label (`tag.bug`), and its assignee (`assignee.ada`). Only what the payload says: a
|
|
39
|
+
* property it carries empty is unset, and one it names without its details is left as it was.
|
|
40
|
+
* Linear leaves an empty assignee or project out of the payload rather than sending `null`, so
|
|
41
|
+
* either one missing, with no ID either, is empty.
|
|
42
|
+
* `priority` and `project` are single keys, so they're unset by name; `tag.` and `assignee.` are
|
|
43
|
+
* prefixes the mirror owns, so a key under them that Linear doesn't have goes.
|
|
44
|
+
*/
|
|
45
|
+
function propertiesOf(data) {
|
|
46
|
+
const labels = {};
|
|
47
|
+
const unset = [];
|
|
48
|
+
const owns = [];
|
|
49
|
+
if (data.priority === 0 || data.priorityLabel === "No priority") unset.push("priority");
|
|
50
|
+
else if (data.priorityLabel && slug(data.priorityLabel)) labels.priority = slug(data.priorityLabel).slice(0, 256);
|
|
51
|
+
if (data.project?.name && slug(data.project.name)) labels.project = slug(data.project.name).slice(0, 256);
|
|
52
|
+
else if (!data.project && !data.projectId) unset.push("project");
|
|
53
|
+
if (Array.isArray(data.labels)) {
|
|
54
|
+
owns.push("tag.");
|
|
55
|
+
for (const label of data.labels) {
|
|
56
|
+
const tag = tagOf("tag", label.name);
|
|
57
|
+
if (tag) labels[tag[0]] = tag[1];
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (data.assignee) {
|
|
61
|
+
owns.push("assignee.");
|
|
62
|
+
const tag = tagOf("assignee", handleOf(data.assignee));
|
|
63
|
+
if (tag) labels[tag[0]] = tag[1];
|
|
64
|
+
} else if (!data.assigneeId) owns.push("assignee.");
|
|
65
|
+
return {
|
|
66
|
+
labels,
|
|
67
|
+
unset,
|
|
68
|
+
owns
|
|
69
|
+
};
|
|
70
|
+
}
|
|
33
71
|
/** The copy of an issue the board opened: the issue itself, not a comment. */
|
|
34
72
|
const OPENED = "issue";
|
|
35
73
|
/** A root's copy: one the board opened, or imported (`lifecycle:<event>`, `root:<event>`). Comment IDs are UUIDs. */
|
|
@@ -52,6 +90,51 @@ function titleOf(markdown) {
|
|
|
52
90
|
function stateOf(state) {
|
|
53
91
|
return state?.type ?? state?.name?.toLowerCase() ?? null;
|
|
54
92
|
}
|
|
93
|
+
const ISSUE_FIELDS = `id identifier title description url createdAt priority priorityLabel
|
|
94
|
+
state { name } assignee { name displayName url } creator { name displayName url } project { name }
|
|
95
|
+
labels(first: 10) { nodes { name } }`;
|
|
96
|
+
const ISSUES_PER_PAGE = 100;
|
|
97
|
+
const DESCRIPTION_IN_LIST = 1500;
|
|
98
|
+
const MAX_COMMENTS = 1e3;
|
|
99
|
+
/** What a read names: a project (by its link), a team (by its key), or an issue (by its ID or link). */
|
|
100
|
+
function readTargetOf(target) {
|
|
101
|
+
const project = /\/project\/(?:[^/?#]*-)?([0-9a-f]{8,})(?:[/?#]|$)/i.exec(target);
|
|
102
|
+
if (project) return {
|
|
103
|
+
kind: "project",
|
|
104
|
+
slugId: project[1]
|
|
105
|
+
};
|
|
106
|
+
const issue = /(?:^|\/issue\/)([A-Z0-9_]+-\d+)(?:[/?#]|$)/i.exec(target.trim());
|
|
107
|
+
if (issue) return {
|
|
108
|
+
kind: "issue",
|
|
109
|
+
id: issue[1].toUpperCase()
|
|
110
|
+
};
|
|
111
|
+
if (/^[A-Z0-9_]+$/i.test(target.trim())) return {
|
|
112
|
+
kind: "team",
|
|
113
|
+
key: target.trim().toUpperCase()
|
|
114
|
+
};
|
|
115
|
+
throw new UnreadableError("invalid_target", `can't read ${target} from Linear: name a project by its link, a team by its key (ENG), or an issue (ENG-123)`);
|
|
116
|
+
}
|
|
117
|
+
/** An issue as a read shows it: its title, its properties on one line, its link, and what it says. */
|
|
118
|
+
function issueMessage(issue, descriptionMax) {
|
|
119
|
+
const properties = [
|
|
120
|
+
issue.state?.name,
|
|
121
|
+
issue.priority ? issue.priorityLabel : void 0,
|
|
122
|
+
issue.assignee ? `assigned to ${handleOf(issue.assignee)}` : "unassigned",
|
|
123
|
+
issue.project?.name,
|
|
124
|
+
...(issue.labels?.nodes ?? []).map((label) => label.name)
|
|
125
|
+
].filter(Boolean);
|
|
126
|
+
const description = bodyOf(issue.description);
|
|
127
|
+
const shown = description && descriptionMax !== null && description.length > descriptionMax ? `${description.slice(0, descriptionMax)}…` : description;
|
|
128
|
+
return {
|
|
129
|
+
id: issue.identifier,
|
|
130
|
+
thread: issue.identifier,
|
|
131
|
+
author: handleOf(issue.creator ?? void 0) ?? "unknown",
|
|
132
|
+
text: [`${issue.identifier}: ${issue.title}\n${properties.join(" · ")}\n${issue.url}`, shown].filter(Boolean).join("\n\n"),
|
|
133
|
+
createdAt: issue.createdAt,
|
|
134
|
+
replies: issue.comments?.nodes.length ?? 0,
|
|
135
|
+
files: []
|
|
136
|
+
};
|
|
137
|
+
}
|
|
55
138
|
var LinearProvider = class extends ChatSyncProvider {
|
|
56
139
|
linear;
|
|
57
140
|
teamIds = /* @__PURE__ */ new Map();
|
|
@@ -133,13 +216,14 @@ var LinearProvider = class extends ChatSyncProvider {
|
|
|
133
216
|
const { data } = payload;
|
|
134
217
|
const created = payload.action === "create";
|
|
135
218
|
if (!created && payload.action !== "update") return [];
|
|
136
|
-
const retitled = payload.action === "update" && payload.updatedFrom?.title !== void 0;
|
|
219
|
+
const retitled = payload.action === "update" && (payload.updatedFrom?.title !== void 0 || payload.updatedFrom?.description !== void 0);
|
|
137
220
|
const team = data.team?.key ?? teamOf(data.identifier);
|
|
138
221
|
const state = stateOf(data.state);
|
|
139
222
|
const bot = adapter.defaultBotUserId;
|
|
140
223
|
const own = payload.actor?.id !== void 0 && payload.actor.id === bot;
|
|
141
224
|
const opens = created ? !own : !own && (bot === null || data.creatorId !== bot) && payload.actor?.type === "user" && !data.archivedAt;
|
|
142
225
|
const delivery = headers.get("linear-delivery") ?? `${payload.webhookId}:${payload.webhookTimestamp}`;
|
|
226
|
+
const properties = propertiesOf(data);
|
|
143
227
|
return [{
|
|
144
228
|
event: {
|
|
145
229
|
kind: "lifecycle",
|
|
@@ -148,11 +232,14 @@ var LinearProvider = class extends ChatSyncProvider {
|
|
|
148
232
|
type: created ? "issue.created" : "issue.updated",
|
|
149
233
|
title: `${data.identifier}: ${data.title}`,
|
|
150
234
|
url: data.url ?? payload.url ?? null,
|
|
235
|
+
body: bodyOf(data.description),
|
|
151
236
|
labels: {
|
|
152
237
|
issue: data.identifier,
|
|
153
|
-
...state ? { state } : {}
|
|
238
|
+
...state ? { state } : {},
|
|
239
|
+
...properties.labels
|
|
154
240
|
},
|
|
155
|
-
unset:
|
|
241
|
+
unset: properties.unset,
|
|
242
|
+
owns: properties.owns,
|
|
156
243
|
reply: null,
|
|
157
244
|
createRoot: opens,
|
|
158
245
|
...retitled ? { retitled: true } : {},
|
|
@@ -173,6 +260,84 @@ var LinearProvider = class extends ChatSyncProvider {
|
|
|
173
260
|
await this.ready();
|
|
174
261
|
return this.linear.isConnectMode() ? this.linear.withConnectClient(void 0, fn) : fn();
|
|
175
262
|
}
|
|
263
|
+
/**
|
|
264
|
+
* A project's or team's issues, newest first, or one issue and its comments, read on demand:
|
|
265
|
+
* nothing is synced or stored. `next` pages past a read's `limit`.
|
|
266
|
+
*/
|
|
267
|
+
async read(target, { limit, after }) {
|
|
268
|
+
const wanted = readTargetOf(target);
|
|
269
|
+
const query = (text, variables) => this.api(async () => (await this.client().client.rawRequest(text, variables)).data);
|
|
270
|
+
if (wanted.kind === "issue") {
|
|
271
|
+
let issue = null;
|
|
272
|
+
const comments = [];
|
|
273
|
+
let cursor = null;
|
|
274
|
+
do {
|
|
275
|
+
const data = await query(`query BoardReadIssue($id: String!, $first: Int!, $after: String) { issue(id: $id) { ${ISSUE_FIELDS}
|
|
276
|
+
comments(first: $first, after: $after) { nodes { id body createdAt user { name displayName url } } pageInfo { hasNextPage endCursor } } } }`, {
|
|
277
|
+
id: wanted.id,
|
|
278
|
+
first: ISSUES_PER_PAGE,
|
|
279
|
+
after: cursor
|
|
280
|
+
});
|
|
281
|
+
if (!data?.issue) throw new UnreadableError("channel_not_found", `no Linear issue ${wanted.id}`);
|
|
282
|
+
issue = data.issue;
|
|
283
|
+
comments.push(...issue.comments?.nodes ?? []);
|
|
284
|
+
const page = issue.comments?.pageInfo;
|
|
285
|
+
cursor = page?.hasNextPage ? page.endCursor ?? null : null;
|
|
286
|
+
} while (cursor !== null && comments.length < MAX_COMMENTS);
|
|
287
|
+
comments.sort((a, b) => a.createdAt.localeCompare(b.createdAt));
|
|
288
|
+
const from = after === null ? 0 : Math.max(0, Number.parseInt(after, 10) || 0);
|
|
289
|
+
const shown = comments.slice(from, from + Math.min(limit, ISSUES_PER_PAGE));
|
|
290
|
+
const to = from + shown.length;
|
|
291
|
+
return {
|
|
292
|
+
channel: teamOf(issue.identifier) ?? wanted.id,
|
|
293
|
+
name: null,
|
|
294
|
+
thread: issue.identifier,
|
|
295
|
+
messages: [...from === 0 ? [{
|
|
296
|
+
...issueMessage(issue, null),
|
|
297
|
+
replies: comments.length
|
|
298
|
+
}] : [], ...shown.map((comment) => ({
|
|
299
|
+
id: comment.id,
|
|
300
|
+
thread: issue.identifier,
|
|
301
|
+
author: handleOf(comment.user ?? void 0) ?? "unknown",
|
|
302
|
+
text: comment.body ?? "",
|
|
303
|
+
createdAt: comment.createdAt,
|
|
304
|
+
replies: 0,
|
|
305
|
+
files: []
|
|
306
|
+
}))],
|
|
307
|
+
more: to < comments.length,
|
|
308
|
+
next: to < comments.length ? String(to) : null
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
let filter;
|
|
312
|
+
let channel;
|
|
313
|
+
let name;
|
|
314
|
+
if (wanted.kind === "project") {
|
|
315
|
+
const project = (await query("query BoardReadProject($slugId: String!) { projects(filter: { slugId: { eq: $slugId } }, first: 1) { nodes { id name url } } }", { slugId: wanted.slugId }))?.projects.nodes[0];
|
|
316
|
+
if (!project) throw new UnreadableError("channel_not_found", `no Linear project ${target}`);
|
|
317
|
+
filter = { project: { id: { eq: project.id } } };
|
|
318
|
+
channel = project.url;
|
|
319
|
+
name = project.name;
|
|
320
|
+
} else {
|
|
321
|
+
await this.team(wanted.key);
|
|
322
|
+
filter = { team: { key: { eq: wanted.key } } };
|
|
323
|
+
channel = wanted.key;
|
|
324
|
+
name = null;
|
|
325
|
+
}
|
|
326
|
+
const issues = (await query(`query BoardReadIssues($filter: IssueFilter, $first: Int!, $after: String) {
|
|
327
|
+
issues(filter: $filter, first: $first, after: $after) { nodes { ${ISSUE_FIELDS} comments(first: 20) { nodes { id createdAt } } } pageInfo { hasNextPage endCursor } } }`, {
|
|
328
|
+
filter,
|
|
329
|
+
first: Math.min(limit, ISSUES_PER_PAGE),
|
|
330
|
+
after
|
|
331
|
+
}))?.issues;
|
|
332
|
+
return {
|
|
333
|
+
channel,
|
|
334
|
+
name,
|
|
335
|
+
thread: null,
|
|
336
|
+
messages: (issues?.nodes ?? []).map((issue) => issueMessage(issue, DESCRIPTION_IN_LIST)),
|
|
337
|
+
more: issues?.pageInfo.hasNextPage ?? false,
|
|
338
|
+
next: issues?.pageInfo.hasNextPage ? issues.pageInfo.endCursor ?? null : null
|
|
339
|
+
};
|
|
340
|
+
}
|
|
176
341
|
async resolveChannel(key) {
|
|
177
342
|
await this.team(key);
|
|
178
343
|
return key.toUpperCase();
|
|
@@ -207,10 +372,26 @@ var LinearProvider = class extends ChatSyncProvider {
|
|
|
207
372
|
async fetchRoot(thread) {
|
|
208
373
|
return this.api(async () => {
|
|
209
374
|
const issue = await this.client().issue(parseThread(thread).issue);
|
|
210
|
-
const [state, creator] = await Promise.all([
|
|
375
|
+
const [state, creator, project, assignee, tags] = await Promise.all([
|
|
376
|
+
issue.state,
|
|
377
|
+
issue.creator,
|
|
378
|
+
issue.project,
|
|
379
|
+
issue.assignee,
|
|
380
|
+
issue.labels?.()
|
|
381
|
+
]);
|
|
211
382
|
const found = stateOf(state);
|
|
383
|
+
const properties = propertiesOf({
|
|
384
|
+
id: issue.id,
|
|
385
|
+
identifier: issue.identifier,
|
|
386
|
+
title: issue.title,
|
|
387
|
+
priority: issue.priority,
|
|
388
|
+
priorityLabel: issue.priorityLabel,
|
|
389
|
+
project,
|
|
390
|
+
assignee,
|
|
391
|
+
labels: tags?.nodes
|
|
392
|
+
});
|
|
212
393
|
return {
|
|
213
|
-
text: `${issue.identifier}: ${issue.title}\n${issue.url}`,
|
|
394
|
+
text: [`${issue.identifier}: ${issue.title}\n${issue.url}`, bodyOf(issue.description)].filter(Boolean).join("\n\n"),
|
|
214
395
|
raw: { issue: {
|
|
215
396
|
id: issue.id,
|
|
216
397
|
identifier: issue.identifier,
|
|
@@ -220,7 +401,8 @@ var LinearProvider = class extends ChatSyncProvider {
|
|
|
220
401
|
author: author(creator, false),
|
|
221
402
|
labels: {
|
|
222
403
|
issue: issue.identifier,
|
|
223
|
-
...found ? { state: found } : {}
|
|
404
|
+
...found ? { state: found } : {},
|
|
405
|
+
...properties.labels
|
|
224
406
|
}
|
|
225
407
|
};
|
|
226
408
|
});
|
package/dist/sync-slack.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { f as ExternalLink } from "./folds-
|
|
2
|
-
import { C as channels, _ as withUserTokens, d as ResolvedTarget, f as SyncContext, h as UserTokens, o as ProviderPost, r as ProviderDelivery, y as SyncFn } from "./provider-
|
|
3
|
-
import { n as ChatSyncProvider, t as ChatInput } from "./chat-provider-
|
|
1
|
+
import { f as ExternalLink } from "./folds-8wRRXjAt.mjs";
|
|
2
|
+
import { C as channels, _ as withUserTokens, d as ResolvedTarget, f as SyncContext, h as UserTokens, o as ProviderPost, r as ProviderDelivery, y as SyncFn } from "./provider-Bm46LAdp.mjs";
|
|
3
|
+
import { n as ChatSyncProvider, t as ChatInput } from "./chat-provider-D6jVT4wS.mjs";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import { Adapter } from "chat";
|
|
6
6
|
//#region src/sync/slack.d.ts
|
|
@@ -67,6 +67,31 @@ export type SlackClient = {
|
|
|
67
67
|
delete(args: {
|
|
68
68
|
file: string;
|
|
69
69
|
}): Promise<unknown>;
|
|
70
|
+
/** Uploads files and shares them in one message, with `initial_comment` as its text; needs `files:write`. */
|
|
71
|
+
uploadV2?(args: {
|
|
72
|
+
channel_id: string;
|
|
73
|
+
initial_comment: string;
|
|
74
|
+
file_uploads: {
|
|
75
|
+
file: Buffer;
|
|
76
|
+
filename: string;
|
|
77
|
+
}[];
|
|
78
|
+
}): Promise<{
|
|
79
|
+
files?: {
|
|
80
|
+
files?: {
|
|
81
|
+
id?: string;
|
|
82
|
+
}[];
|
|
83
|
+
}[];
|
|
84
|
+
}>;
|
|
85
|
+
/** Where a file was shared (`shares`), to find the message an upload made; needs `files:read`. */
|
|
86
|
+
info?(args: {
|
|
87
|
+
file: string;
|
|
88
|
+
}): Promise<{
|
|
89
|
+
file?: {
|
|
90
|
+
shares?: Partial<Record<'public' | 'private', Record<string, {
|
|
91
|
+
ts?: string;
|
|
92
|
+
}[]>>>;
|
|
93
|
+
};
|
|
94
|
+
}>;
|
|
70
95
|
};
|
|
71
96
|
/** Posts an agent's message under its own name; needs `chat:write.customize` for `username` and `icon_url`. */
|
|
72
97
|
chat?: {
|
|
@@ -296,6 +321,7 @@ export declare const SlackEvent: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
296
321
|
type: z.ZodString;
|
|
297
322
|
title: z.ZodString;
|
|
298
323
|
url: z.ZodNullable<z.ZodString>;
|
|
324
|
+
body: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
299
325
|
labels: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
300
326
|
unset: z.ZodArray<z.ZodString>;
|
|
301
327
|
owns: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
@@ -339,7 +365,7 @@ export type SlackOptions = {
|
|
|
339
365
|
export declare function slack(app: string | SlackOptions, sync: SyncFn<SlackEvent>): SlackProvider;
|
|
340
366
|
export declare class SlackProvider extends ChatSyncProvider<SlackEvent> {
|
|
341
367
|
private readonly web;
|
|
342
|
-
private
|
|
368
|
+
private scopes;
|
|
343
369
|
constructor(given: SlackOptions, sync: SyncFn<SlackEvent>);
|
|
344
370
|
/**
|
|
345
371
|
* An agent's message goes out under its own name (`clever-lemur via vboard-factory`), and its
|
|
@@ -347,11 +373,21 @@ export declare class SlackProvider extends ChatSyncProvider<SlackEvent> {
|
|
|
347
373
|
* `**name**: ` label dropped. Without `chat:write.customize` it posts as the app, label and all.
|
|
348
374
|
*/
|
|
349
375
|
post(target: string, kind: ResolvedTarget['kind'], body: ProviderPost): Promise<ProviderDelivery>;
|
|
376
|
+
/**
|
|
377
|
+
* A new thread whose root shows its files under its text, as one message: Slack makes
|
|
378
|
+
* that message from an upload's `initial_comment`, and names it only on the file, a
|
|
379
|
+
* moment later. A file upload can't set a username, so it goes out as the app, label and all.
|
|
380
|
+
* Null, before anything is sent, where the client can't, or the app can't read files
|
|
381
|
+
* (`files:read`) to find that message.
|
|
382
|
+
*/
|
|
383
|
+
private postWithFiles;
|
|
350
384
|
/** An edit keeps the label out only where the message went out under the agent's name. */
|
|
351
385
|
edit(thread: string, message: string, body: ProviderPost): Promise<void>;
|
|
352
386
|
private postNamed;
|
|
353
|
-
/** Whether the app may set a message's username and icon (`chat:write.customize`)
|
|
387
|
+
/** Whether the app may set a message's username and icon (`chat:write.customize`). */
|
|
354
388
|
private canCustomize;
|
|
389
|
+
/** Whether the app has a scope, from its scopes, asked once. */
|
|
390
|
+
private hasScope;
|
|
355
391
|
/** Whether a message Slack has went out under `name`. */
|
|
356
392
|
private sentAs;
|
|
357
393
|
/**
|
package/dist/sync-slack.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { m as MESSAGE_TEXT_MAX } from "./schemas-
|
|
2
|
-
import "./external-
|
|
3
|
-
import { i as UnreadableError, s as channels } from "./provider-
|
|
4
|
-
import { i as eventSchema, r as envelope } from "./events-
|
|
1
|
+
import { m as MESSAGE_TEXT_MAX } from "./schemas-DBmUO6pr.mjs";
|
|
2
|
+
import "./external-D3p5T57R.mjs";
|
|
3
|
+
import { i as UnreadableError, s as channels } from "./provider-BaVmi4Hi.mjs";
|
|
4
|
+
import { i as eventSchema, r as envelope } from "./events-qf5XG5VQ.mjs";
|
|
5
5
|
import { r as withUserTokens, t as connectUserTokens } from "./users-yryHKFMo.mjs";
|
|
6
|
-
import { r as markdownOf, t as ChatSyncProvider } from "./chat-provider-
|
|
6
|
+
import { r as markdownOf, t as ChatSyncProvider } from "./chat-provider-COtsU5jB.mjs";
|
|
7
7
|
import { z } from "zod";
|
|
8
8
|
import { stringifyMarkdown } from "chat";
|
|
9
9
|
import { createSlackAdapter } from "@chat-adapter/slack";
|
|
@@ -220,6 +220,8 @@ const SlackEvent = eventSchema("slack", "message");
|
|
|
220
220
|
function slack(app, sync) {
|
|
221
221
|
return new SlackProvider(typeof app === "string" ? { adapter: app } : app, sync);
|
|
222
222
|
}
|
|
223
|
+
/** How many times to look for the message an upload made, about 15 seconds in all. */
|
|
224
|
+
const SHARE_POLLS = 10;
|
|
223
225
|
/**
|
|
224
226
|
* Slack's client retries 10 times over about 30 minutes by default, which outlives any function:
|
|
225
227
|
* here a call gets 3 more tries. Each still waits out Slack's `Retry-After` (about a minute at
|
|
@@ -250,7 +252,7 @@ function fromConnector(connector) {
|
|
|
250
252
|
}
|
|
251
253
|
var SlackProvider = class extends ChatSyncProvider {
|
|
252
254
|
web;
|
|
253
|
-
|
|
255
|
+
scopes;
|
|
254
256
|
constructor(given, sync) {
|
|
255
257
|
const connected = typeof given.adapter === "string" ? fromConnector(given.adapter) : null;
|
|
256
258
|
const options = connected ? {
|
|
@@ -386,6 +388,7 @@ var SlackProvider = class extends ChatSyncProvider {
|
|
|
386
388
|
platform: "slack",
|
|
387
389
|
adapter: options.adapter,
|
|
388
390
|
canStartThreads: true,
|
|
391
|
+
startsThreadsWithFiles: true,
|
|
389
392
|
async uploadFiles(thread, files) {
|
|
390
393
|
const sent = await options.adapter.postMessage(thread, {
|
|
391
394
|
markdown: "",
|
|
@@ -681,8 +684,60 @@ var SlackProvider = class extends ChatSyncProvider {
|
|
|
681
684
|
...given,
|
|
682
685
|
markdown: withoutHtml(given.markdown)
|
|
683
686
|
};
|
|
687
|
+
if (kind === "channel" && post.files?.length && post.markdown.trim()) {
|
|
688
|
+
const sent = await this.postWithFiles(target, post.markdown, post.files);
|
|
689
|
+
if (sent) return sent;
|
|
690
|
+
const { files: _files, ...text } = post;
|
|
691
|
+
return (as ? await this.postNamed(target, as, text.markdown) : null) ?? super.post(target, kind, text);
|
|
692
|
+
}
|
|
684
693
|
return (as && !post.files?.length ? await this.postNamed(target, as, post.markdown) : null) ?? super.post(target, kind, post);
|
|
685
694
|
}
|
|
695
|
+
/**
|
|
696
|
+
* A new thread whose root shows its files under its text, as one message: Slack makes
|
|
697
|
+
* that message from an upload's `initial_comment`, and names it only on the file, a
|
|
698
|
+
* moment later. A file upload can't set a username, so it goes out as the app, label and all.
|
|
699
|
+
* Null, before anything is sent, where the client can't, or the app can't read files
|
|
700
|
+
* (`files:read`) to find that message.
|
|
701
|
+
*/
|
|
702
|
+
async postWithFiles(target, markdown, files) {
|
|
703
|
+
const adapter = await this.ready();
|
|
704
|
+
const web = await this.web();
|
|
705
|
+
const toMrkdwn = adapter.formatConverter?.toResponseUrlText;
|
|
706
|
+
if (!web?.files?.uploadV2 || !web.files.info || !toMrkdwn || !await this.hasScope(web, "files:read")) return null;
|
|
707
|
+
const threadId = this.toChat(target);
|
|
708
|
+
const { channel } = adapter.decodeThreadId(threadId);
|
|
709
|
+
const message = { markdown };
|
|
710
|
+
const resolved = await adapter.resolveMessageMentions?.(message, threadId) ?? message;
|
|
711
|
+
const ids = ((await web.files.uploadV2({
|
|
712
|
+
channel_id: channel,
|
|
713
|
+
initial_comment: toMrkdwn.call(adapter.formatConverter, resolved),
|
|
714
|
+
file_uploads: files.map((file) => ({
|
|
715
|
+
file: Buffer.from(file.data),
|
|
716
|
+
filename: slackFileName(file.filename, file.mimeType)
|
|
717
|
+
}))
|
|
718
|
+
})).files?.[0]?.files ?? []).map((file) => file.id).filter((id) => !!id);
|
|
719
|
+
const found = async () => {
|
|
720
|
+
for (let attempt = 0; attempt < SHARE_POLLS; attempt++) {
|
|
721
|
+
const shares = (await web.files.info({ file: ids[0] })).file?.shares;
|
|
722
|
+
const ts = shares?.public?.[channel]?.[0]?.ts ?? shares?.private?.[channel]?.[0]?.ts;
|
|
723
|
+
if (ts) return ts;
|
|
724
|
+
await new Promise((resolve) => setTimeout(resolve, Math.min(250 * 2 ** attempt, 2e3)));
|
|
725
|
+
}
|
|
726
|
+
throw new Error("never shared");
|
|
727
|
+
};
|
|
728
|
+
if (!ids[0]) throw new Error("slack: files.uploadV2 returned no file IDs");
|
|
729
|
+
let ts;
|
|
730
|
+
try {
|
|
731
|
+
ts = await found();
|
|
732
|
+
} catch (error) {
|
|
733
|
+
throw new Error(`slack: couldn't find the message uploading ${ids[0]} made in ${channel} (${slackError(error)})`);
|
|
734
|
+
}
|
|
735
|
+
return {
|
|
736
|
+
thread: this.toNative(`${adapter.name}:${channel}:${ts}`),
|
|
737
|
+
message: ts,
|
|
738
|
+
files: ids
|
|
739
|
+
};
|
|
740
|
+
}
|
|
686
741
|
/** An edit keeps the label out only where the message went out under the agent's name. */
|
|
687
742
|
async edit(thread, message, body) {
|
|
688
743
|
const { as, ...given } = body;
|
|
@@ -720,14 +775,18 @@ var SlackProvider = class extends ChatSyncProvider {
|
|
|
720
775
|
message: sent.ts
|
|
721
776
|
};
|
|
722
777
|
}
|
|
723
|
-
/** Whether the app may set a message's username and icon (`chat:write.customize`)
|
|
778
|
+
/** Whether the app may set a message's username and icon (`chat:write.customize`). */
|
|
724
779
|
canCustomize(web) {
|
|
725
|
-
this.
|
|
726
|
-
|
|
780
|
+
return this.hasScope(web, "chat:write.customize");
|
|
781
|
+
}
|
|
782
|
+
/** Whether the app has a scope, from its scopes, asked once. */
|
|
783
|
+
async hasScope(web, scope) {
|
|
784
|
+
this.scopes ??= (async () => (await web.auth?.test())?.response_metadata?.scopes ?? [])().catch((error) => {
|
|
785
|
+
this.scopes = void 0;
|
|
727
786
|
console.warn(`[board] slack: couldn't check the app's scopes (${slackError(error)}); posting as the app`);
|
|
728
|
-
return
|
|
787
|
+
return [];
|
|
729
788
|
});
|
|
730
|
-
return this.
|
|
789
|
+
return (await this.scopes).includes(scope);
|
|
731
790
|
}
|
|
732
791
|
/** Whether a message Slack has went out under `name`. */
|
|
733
792
|
async sentAs(thread, message, name) {
|
package/dist/sync.chat.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as externalAuthor, n as ChatSyncProvider, r as ChatTransport, t as ChatInput } from "./chat-provider-
|
|
1
|
+
import { i as externalAuthor, n as ChatSyncProvider, r as ChatTransport, t as ChatInput } from "./chat-provider-D6jVT4wS.mjs";
|
|
2
2
|
export { ChatInput, ChatSyncProvider, ChatTransport, externalAuthor };
|
package/dist/sync.chat.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as externalAuthor, t as ChatSyncProvider } from "./chat-provider-
|
|
1
|
+
import { n as externalAuthor, t as ChatSyncProvider } from "./chat-provider-COtsU5jB.mjs";
|
|
2
2
|
export { ChatSyncProvider, externalAuthor };
|
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 SyncOverrides, C as channels, D as EventBase, E as render, M as SyncRoot, N as envelope, O as ProviderEvent, P as eventSchema, S as SyncUnit, T as mirror, _ as withUserTokens, a as ProviderOptions, b as SyncIn, c as ReceivedEvent, d as ResolvedTarget, f as SyncContext, g as connectUserTokens, h as UserTokens, i as ProviderFile, j as SyncResult, k as RootOverride, l as RenderInput, m as UnreadableError, n as FileDelivery, o as ProviderPost, p as SyncProvider, r as ProviderDelivery, s as Receive, u as Renderer, v as Sync, w as into, x as SyncOut, y as SyncFn } from "./provider-
|
|
1
|
+
import { d as ExternalFile, l as ExternalAuthor, u as ExternalEvent } from "./folds-8wRRXjAt.mjs";
|
|
2
|
+
import { A as SyncOverrides, C as channels, D as EventBase, E as render, M as SyncRoot, N as envelope, O as ProviderEvent, P as eventSchema, S as SyncUnit, T as mirror, _ as withUserTokens, a as ProviderOptions, b as SyncIn, c as ReceivedEvent, d as ResolvedTarget, f as SyncContext, g as connectUserTokens, h as UserTokens, i as ProviderFile, j as SyncResult, k as RootOverride, l as RenderInput, m as UnreadableError, n as FileDelivery, o as ProviderPost, p as SyncProvider, r as ProviderDelivery, s as Receive, u as Renderer, v as Sync, w as into, x as SyncOut, y as SyncFn } from "./provider-Bm46LAdp.mjs";
|
|
3
3
|
export { EventBase, type ExternalAuthor, ExternalEvent, type ExternalFile, type FileDelivery, type ProviderDelivery, type ProviderEvent, type ProviderFile, type ProviderOptions, type ProviderPost, type Receive, ReceivedEvent, type RenderInput, type Renderer, ResolvedTarget, type RootOverride, type Sync, type SyncContext, type SyncFn, type SyncIn, type SyncOut, SyncOverrides, SyncProvider, type SyncResult, type SyncRoot, type SyncUnit, UnreadableError, type UserTokens, channels, connectUserTokens, envelope, eventSchema, into, mirror, render, withUserTokens };
|
package/dist/sync.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as ExternalEvent } from "./external-
|
|
2
|
-
import { c as into, i as UnreadableError, l as mirror, n as ResolvedTarget, r as SyncProvider, s as channels, t as ReceivedEvent, u as render } from "./provider-
|
|
3
|
-
import { i as eventSchema, n as SyncOverrides, r as envelope, t as EventBase } from "./events-
|
|
1
|
+
import { n as ExternalEvent } from "./external-D3p5T57R.mjs";
|
|
2
|
+
import { c as into, i as UnreadableError, l as mirror, n as ResolvedTarget, r as SyncProvider, s as channels, t as ReceivedEvent, u as render } from "./provider-BaVmi4Hi.mjs";
|
|
3
|
+
import { i as eventSchema, n as SyncOverrides, r as envelope, t as EventBase } from "./events-qf5XG5VQ.mjs";
|
|
4
4
|
import { r as withUserTokens, t as connectUserTokens } from "./users-yryHKFMo.mjs";
|
|
5
5
|
export { EventBase, ExternalEvent, ReceivedEvent, ResolvedTarget, SyncOverrides, SyncProvider, UnreadableError, channels, connectUserTokens, envelope, eventSchema, into, mirror, render, withUserTokens };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/sync/tags.ts
|
|
2
|
+
/** `good first issue` → `good-first-issue`: the part of a label key a name gives. Empty when nothing's left. */
|
|
3
|
+
const slug = (name) => name.normalize("NFKD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9_.-]+/g, "-").replace(/^[-_.]+|-+$/g, "");
|
|
4
|
+
/**
|
|
5
|
+
* A platform's label or assignee as a board label: `bug` → `tag.bug=bug`,
|
|
6
|
+
* `julianbenegas` → `assignee.julianbenegas=julianbenegas`. The keys don't
|
|
7
|
+
* name the platform, so a filter like `--label tag.bug` holds for any of them.
|
|
8
|
+
*/
|
|
9
|
+
function tagOf(prefix, name) {
|
|
10
|
+
const key = name ? slug(name) : "";
|
|
11
|
+
return key ? [`${prefix}.${key}`.slice(0, 64), name.slice(0, 256)] : null;
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
export { tagOf as n, slug as t };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { l as isThreadTarget } from "./external-
|
|
1
|
+
import { l as isThreadTarget } from "./external-D3p5T57R.mjs";
|
|
2
2
|
import { n as replaceMentions, t as extractMentions } from "./mentions-CB6ShY4R.mjs";
|
|
3
3
|
//#region src/server/targets.ts
|
|
4
4
|
/** A target as a post or a receipt names it, resolved: a plain one's kind goes by its shape. */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { l as unauthorized } from "./errors-
|
|
2
|
-
import { f as markVerified, m as trustedIssuers, n as TOKENS, r as VERCEL_ISSUER, u as issuerName } from "./auth-
|
|
1
|
+
import { l as unauthorized } from "./errors-C_5rB8Iz.mjs";
|
|
2
|
+
import { f as markVerified, m as trustedIssuers, n as TOKENS, r as VERCEL_ISSUER, u as issuerName } from "./auth-BPinwfN0.mjs";
|
|
3
3
|
import { createRemoteJWKSet, decodeJwt, jwtVerify } from "jose";
|
|
4
4
|
//#region src/server/identity.ts
|
|
5
5
|
let fromDisk;
|
|
@@ -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-8wRRXjAt.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
|