@vercel/board 0.0.0 → 0.16.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 +180 -0
- package/dist/a2-C41hD8SF.mjs +3045 -0
- package/dist/a2-D24cvwpN.d.mts +3359 -0
- package/dist/access-CJU2-vaa.mjs +226 -0
- package/dist/access-CV96SYgr.d.mts +32 -0
- package/dist/access.d.mts +30 -0
- package/dist/access.mjs +4 -0
- package/dist/actors-DjMeZpnU.mjs +224 -0
- package/dist/attempts-Bxp9KgPf.mjs +919 -0
- package/dist/auth-COzc09sn.mjs +276 -0
- package/dist/auth-CU56Q2Xh.d.mts +204 -0
- package/dist/backend-a2/blob-vercel.d.mts +8 -0
- package/dist/backend-a2/blob-vercel.mjs +81 -0
- package/dist/backend-a2/contract.d.mts +18 -0
- package/dist/backend-a2/contract.mjs +5 -0
- package/dist/backend-a2/scheduler-local.d.mts +11 -0
- package/dist/backend-a2/scheduler-local.mjs +2 -0
- package/dist/backend-a2/scheduler-qstash.d.mts +2 -0
- package/dist/backend-a2/scheduler-qstash.mjs +2 -0
- package/dist/backend-a2/scheduler-vercel.d.mts +2 -0
- package/dist/backend-a2/scheduler-vercel.mjs +2 -0
- package/dist/backend-a2/store-memory.d.mts +11 -0
- package/dist/backend-a2/store-memory.mjs +19 -0
- package/dist/backend-a2/store-postgres.d.mts +38 -0
- package/dist/backend-a2/store-postgres.mjs +110 -0
- package/dist/backend-a2/store-redis-http.d.mts +17 -0
- package/dist/backend-a2/store-redis-http.mjs +32 -0
- package/dist/backend-a2/store-redis.d.mts +23 -0
- package/dist/backend-a2/store-redis.mjs +39 -0
- package/dist/backend-a2/store-sqlite.d.mts +12 -0
- package/dist/backend-a2/store-sqlite.mjs +31 -0
- package/dist/backend-a2.d.mts +4 -0
- package/dist/backend-a2.mjs +2 -0
- package/dist/backend-http-0roEmjl0.mjs +613 -0
- package/dist/backend-http-BVRno-ca.mjs +469 -0
- package/dist/backend-http-Bid7RIpC.d.mts +630 -0
- package/dist/backend-http.d.mts +10 -0
- package/dist/backend-http.mjs +2 -0
- package/dist/backend-http.node.d.mts +10 -0
- package/dist/backend-http.node.mjs +2 -0
- package/dist/blob-C0J3wbGv.d.mts +39 -0
- package/dist/bots-CGkO76qH.mjs +67 -0
- package/dist/chat-provider-XCnQlxq6.d.mts +140 -0
- package/dist/chat-provider-jFSeyNmB.mjs +389 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +2252 -0
- package/dist/client-DGDPaN7U.mjs +380 -0
- package/dist/conformance-DRR23YNy.mjs +512 -0
- package/dist/conformance.d.mts +30 -0
- package/dist/conformance.mjs +2 -0
- package/dist/contract-CuJmlrhw.mjs +566 -0
- package/dist/emoji-CTLpvH-A.mjs +445 -0
- package/dist/engine-Bir5s8ts.mjs +1449 -0
- package/dist/errors-DX3hpwWt.mjs +64 -0
- package/dist/exports-DLiE7fLY.d.mts +4 -0
- package/dist/exports-Dvc1o52I.mjs +1285 -0
- package/dist/files-SniSmeEr.mjs +47 -0
- package/dist/index.d.mts +13 -0
- package/dist/index.default-Bkg77Pxn.mjs +12 -0
- package/dist/index.mjs +19 -0
- package/dist/index.node.d.mts +14 -0
- package/dist/index.node.mjs +5 -0
- package/dist/inspect/app.js +416 -0
- package/dist/inspect/engine.js +5 -0
- package/dist/local-Cr_dSjvs.mjs +44 -0
- package/dist/own-OwgPWdmh.mjs +15 -0
- package/dist/project-CFiArraX.mjs +124 -0
- package/dist/provider-BGjz-mDa.d.mts +2473 -0
- package/dist/provider-CuewcDNZ.mjs +205 -0
- package/dist/redis-tables-B35vv4CZ.mjs +842 -0
- package/dist/reducers-B_vUGQRp.d.mts +1172 -0
- package/dist/reducers-mUPFuFJV.mjs +293 -0
- package/dist/schemas-Be08nyfW.mjs +74 -0
- package/dist/schemas-CWxs3ECJ.d.mts +50 -0
- package/dist/serve-BsOOc-6_.mjs +170 -0
- package/dist/server-jwPY7_wi.mjs +17 -0
- package/dist/serving-BNbzc96L.mjs +2 -0
- package/dist/sql-DbiEnqM0.mjs +571 -0
- package/dist/sqlite-db-Cbj03vmp.mjs +70 -0
- package/dist/sync-github.d.mts +473 -0
- package/dist/sync-github.mjs +603 -0
- package/dist/sync-kapso.d.mts +175 -0
- package/dist/sync-kapso.mjs +86 -0
- package/dist/sync-slack.d.mts +364 -0
- package/dist/sync-slack.mjs +728 -0
- package/dist/sync.chat.d.mts +2 -0
- package/dist/sync.chat.mjs +2 -0
- package/dist/sync.d.mts +3 -0
- package/dist/sync.mjs +4 -0
- package/dist/targets-yM5JBUgr.mjs +94 -0
- package/dist/tokens-DKLn5P9B.mjs +256 -0
- package/dist/types-BHCjTZdB.d.mts +104 -0
- package/dist/users-Dls7_ANV.mjs +42 -0
- package/dist/watch-spec-W0c7ypHJ.mjs +787 -0
- package/dist/watchers-hash-CLjsa6od.mjs +225 -0
- package/docs/01-board/01-mounting.md +506 -0
- package/docs/01-board/02-database.md +258 -0
- package/docs/01-board/03-identity.md +264 -0
- package/docs/01-board/04-messages.md +192 -0
- package/docs/01-board/05-reading.md +177 -0
- package/docs/01-board/06-watchers.md +249 -0
- package/docs/01-board/07-schedules.md +133 -0
- package/docs/01-board/08-middleware.md +139 -0
- package/docs/01-board/09-access.md +501 -0
- package/docs/01-quickstart.md +196 -0
- package/docs/02-sync/01-overview.md +290 -0
- package/docs/02-sync/02-callbacks.md +265 -0
- package/docs/02-sync/03-slack.md +248 -0
- package/docs/02-sync/04-github.md +201 -0
- package/docs/02-sync/05-whatsapp.md +148 -0
- package/docs/02-sync/06-providers.md +228 -0
- package/docs/03-guides/01-coding-agents.md +226 -0
- package/docs/03-guides/02-inspector.md +104 -0
- package/docs/03-guides/03-ci.md +251 -0
- package/docs/03-guides/04-triage.md +233 -0
- package/docs/03-guides/05-agent-factory.md +142 -0
- package/docs/04-reference/01-cli.md +606 -0
- package/docs/04-reference/02-board.md +579 -0
- package/docs/04-reference/03-http.md +489 -0
- package/docs/04-reference/04-log.md +250 -0
- package/docs/04-reference/05-conformance.md +97 -0
- package/docs/index.md +186 -0
- package/package.json +168 -1
- package/sql/postgres/board.sql +145 -0
- package/sql/postgres/notifications.sql +24 -0
- package/sql/postgres/schema.sql +451 -0
package/package.json
CHANGED
|
@@ -1 +1,168 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"name": "@vercel/board",
|
|
3
|
+
"version": "0.16.0",
|
|
4
|
+
"description": "A message board you mount in one route: one durable log, verified authors, live tail, and two-way sync.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=22.18"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"docs",
|
|
13
|
+
"sql",
|
|
14
|
+
"README.md"
|
|
15
|
+
],
|
|
16
|
+
"bin": {
|
|
17
|
+
"board": "./dist/cli.mjs",
|
|
18
|
+
"vb": "./dist/cli.mjs"
|
|
19
|
+
},
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"types": "./dist/index.d.mts",
|
|
23
|
+
"node": "./dist/index.node.mjs",
|
|
24
|
+
"default": "./dist/index.mjs"
|
|
25
|
+
},
|
|
26
|
+
"./access": {
|
|
27
|
+
"types": "./dist/access.d.mts",
|
|
28
|
+
"default": "./dist/access.mjs"
|
|
29
|
+
},
|
|
30
|
+
"./conformance": {
|
|
31
|
+
"types": "./dist/conformance.d.mts",
|
|
32
|
+
"default": "./dist/conformance.mjs"
|
|
33
|
+
},
|
|
34
|
+
"./backend-a2": {
|
|
35
|
+
"types": "./dist/backend-a2.d.mts",
|
|
36
|
+
"default": "./dist/backend-a2.mjs"
|
|
37
|
+
},
|
|
38
|
+
"./backend-a2/contract": {
|
|
39
|
+
"types": "./dist/backend-a2/contract.d.mts",
|
|
40
|
+
"default": "./dist/backend-a2/contract.mjs"
|
|
41
|
+
},
|
|
42
|
+
"./backend-a2/blob-vercel": {
|
|
43
|
+
"types": "./dist/backend-a2/blob-vercel.d.mts",
|
|
44
|
+
"default": "./dist/backend-a2/blob-vercel.mjs"
|
|
45
|
+
},
|
|
46
|
+
"./backend-a2/store-postgres": {
|
|
47
|
+
"types": "./dist/backend-a2/store-postgres.d.mts",
|
|
48
|
+
"default": "./dist/backend-a2/store-postgres.mjs"
|
|
49
|
+
},
|
|
50
|
+
"./backend-a2/store-redis": {
|
|
51
|
+
"types": "./dist/backend-a2/store-redis.d.mts",
|
|
52
|
+
"default": "./dist/backend-a2/store-redis.mjs"
|
|
53
|
+
},
|
|
54
|
+
"./backend-a2/store-redis-http": {
|
|
55
|
+
"types": "./dist/backend-a2/store-redis-http.d.mts",
|
|
56
|
+
"default": "./dist/backend-a2/store-redis-http.mjs"
|
|
57
|
+
},
|
|
58
|
+
"./backend-a2/store-sqlite": {
|
|
59
|
+
"types": "./dist/backend-a2/store-sqlite.d.mts",
|
|
60
|
+
"default": "./dist/backend-a2/store-sqlite.mjs"
|
|
61
|
+
},
|
|
62
|
+
"./backend-a2/store-memory": {
|
|
63
|
+
"types": "./dist/backend-a2/store-memory.d.mts",
|
|
64
|
+
"default": "./dist/backend-a2/store-memory.mjs"
|
|
65
|
+
},
|
|
66
|
+
"./backend-a2/scheduler-vercel": {
|
|
67
|
+
"types": "./dist/backend-a2/scheduler-vercel.d.mts",
|
|
68
|
+
"default": "./dist/backend-a2/scheduler-vercel.mjs"
|
|
69
|
+
},
|
|
70
|
+
"./backend-a2/scheduler-qstash": {
|
|
71
|
+
"types": "./dist/backend-a2/scheduler-qstash.d.mts",
|
|
72
|
+
"default": "./dist/backend-a2/scheduler-qstash.mjs"
|
|
73
|
+
},
|
|
74
|
+
"./backend-a2/scheduler-local": {
|
|
75
|
+
"types": "./dist/backend-a2/scheduler-local.d.mts",
|
|
76
|
+
"default": "./dist/backend-a2/scheduler-local.mjs"
|
|
77
|
+
},
|
|
78
|
+
"./backend-http": {
|
|
79
|
+
"types": "./dist/backend-http.d.mts",
|
|
80
|
+
"node": "./dist/backend-http.node.mjs",
|
|
81
|
+
"default": "./dist/backend-http.mjs"
|
|
82
|
+
},
|
|
83
|
+
"./sync": {
|
|
84
|
+
"types": "./dist/sync.d.mts",
|
|
85
|
+
"default": "./dist/sync.mjs"
|
|
86
|
+
},
|
|
87
|
+
"./sync/chat": {
|
|
88
|
+
"types": "./dist/sync.chat.d.mts",
|
|
89
|
+
"default": "./dist/sync.chat.mjs"
|
|
90
|
+
},
|
|
91
|
+
"./sync-slack": {
|
|
92
|
+
"types": "./dist/sync-slack.d.mts",
|
|
93
|
+
"default": "./dist/sync-slack.mjs"
|
|
94
|
+
},
|
|
95
|
+
"./sync-github": {
|
|
96
|
+
"types": "./dist/sync-github.d.mts",
|
|
97
|
+
"default": "./dist/sync-github.mjs"
|
|
98
|
+
},
|
|
99
|
+
"./sync-kapso": {
|
|
100
|
+
"types": "./dist/sync-kapso.d.mts",
|
|
101
|
+
"default": "./dist/sync-kapso.mjs"
|
|
102
|
+
},
|
|
103
|
+
"./package.json": "./package.json"
|
|
104
|
+
},
|
|
105
|
+
"dependencies": {
|
|
106
|
+
"@chat-adapter/github": "^4.41.1",
|
|
107
|
+
"@chat-adapter/slack": "^4.41.1",
|
|
108
|
+
"@vercel/connect": "^2.3.4",
|
|
109
|
+
"@vercel/oidc": "^3.8.9",
|
|
110
|
+
"chat": "^4.41.1",
|
|
111
|
+
"experimental-a2": "0.22.0",
|
|
112
|
+
"jose": "^6.2.12",
|
|
113
|
+
"zod": "^4.6.5"
|
|
114
|
+
},
|
|
115
|
+
"peerDependencies": {
|
|
116
|
+
"@upstash/qstash": "^2.11.0",
|
|
117
|
+
"@vercel/blob": "^2.8.0",
|
|
118
|
+
"@vercel/queue": "*",
|
|
119
|
+
"ioredis": "^5.4.0",
|
|
120
|
+
"pg": "^8.11.0"
|
|
121
|
+
},
|
|
122
|
+
"devDependencies": {
|
|
123
|
+
"@base-ui/react": "^1.8.0",
|
|
124
|
+
"@chat-adapter/tests": "^4.41.1",
|
|
125
|
+
"@electric-sql/pglite": "0.3.15",
|
|
126
|
+
"@kapso/chat-adapter": "^0.1.1",
|
|
127
|
+
"@types/node": "^26.6.3",
|
|
128
|
+
"@types/pg": "8.15.5",
|
|
129
|
+
"@types/react": "^19.3.0",
|
|
130
|
+
"@types/react-dom": "^19.3.0",
|
|
131
|
+
"@vercel/blob": "^2.8.0",
|
|
132
|
+
"ai": "^7.0.130",
|
|
133
|
+
"ioredis": "5.11.1",
|
|
134
|
+
"lucide-react": "^1.49.0",
|
|
135
|
+
"pg": "^8.16.3",
|
|
136
|
+
"react": "^19.3.0",
|
|
137
|
+
"react-dom": "^19.3.0",
|
|
138
|
+
"react-markdown": "^10.1.0",
|
|
139
|
+
"remark-breaks": "^4.0.0",
|
|
140
|
+
"remark-gfm": "^4.0.1",
|
|
141
|
+
"tsdown": "^0.23.0",
|
|
142
|
+
"typescript": "^7.0.2",
|
|
143
|
+
"vitest": "^5.0.3"
|
|
144
|
+
},
|
|
145
|
+
"peerDependenciesMeta": {
|
|
146
|
+
"@upstash/qstash": {
|
|
147
|
+
"optional": true
|
|
148
|
+
},
|
|
149
|
+
"@vercel/blob": {
|
|
150
|
+
"optional": true
|
|
151
|
+
},
|
|
152
|
+
"@vercel/queue": {
|
|
153
|
+
"optional": true
|
|
154
|
+
},
|
|
155
|
+
"ioredis": {
|
|
156
|
+
"optional": true
|
|
157
|
+
},
|
|
158
|
+
"pg": {
|
|
159
|
+
"optional": true
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
"scripts": {
|
|
163
|
+
"build": "tsdown && node scripts/schema.ts",
|
|
164
|
+
"typecheck": "tsc --noEmit",
|
|
165
|
+
"test": "vitest run",
|
|
166
|
+
"pretest": "tsdown --log-level warn"
|
|
167
|
+
}
|
|
168
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
-- board's tables, which live next to A2's. schema.sql holds both: apply that.
|
|
2
|
+
|
|
3
|
+
create table if not exists board_positions (
|
|
4
|
+
consumer text primary key,
|
|
5
|
+
log_index bigint not null
|
|
6
|
+
);
|
|
7
|
+
--> statement-breakpoint
|
|
8
|
+
create table if not exists board_messages (
|
|
9
|
+
id bigint primary key,
|
|
10
|
+
event_id text not null unique,
|
|
11
|
+
channel text not null,
|
|
12
|
+
re bigint,
|
|
13
|
+
by_actor text not null,
|
|
14
|
+
by_principal text not null,
|
|
15
|
+
by_profile text,
|
|
16
|
+
from_key text,
|
|
17
|
+
no_sync boolean not null,
|
|
18
|
+
text_lower text not null,
|
|
19
|
+
deleted boolean not null,
|
|
20
|
+
created_at bigint not null,
|
|
21
|
+
replies integer not null default 0,
|
|
22
|
+
at bigint,
|
|
23
|
+
data text not null
|
|
24
|
+
);
|
|
25
|
+
--> statement-breakpoint
|
|
26
|
+
create index if not exists board_messages_channel on board_messages (channel, id);
|
|
27
|
+
--> statement-breakpoint
|
|
28
|
+
create index if not exists board_messages_re on board_messages (re, id);
|
|
29
|
+
--> statement-breakpoint
|
|
30
|
+
create index if not exists board_messages_by_actor on board_messages (by_actor, id);
|
|
31
|
+
--> statement-breakpoint
|
|
32
|
+
create index if not exists board_messages_by_principal on board_messages (by_principal, id);
|
|
33
|
+
--> statement-breakpoint
|
|
34
|
+
create index if not exists board_threads_at on board_messages (at) where re is null;
|
|
35
|
+
--> statement-breakpoint
|
|
36
|
+
create index if not exists board_threads_channel on board_messages (channel, at) where re is null;
|
|
37
|
+
--> statement-breakpoint
|
|
38
|
+
create table if not exists board_versions (
|
|
39
|
+
log_index bigint primary key,
|
|
40
|
+
message_id bigint not null,
|
|
41
|
+
data text not null
|
|
42
|
+
);
|
|
43
|
+
--> statement-breakpoint
|
|
44
|
+
create index if not exists board_versions_message on board_versions (message_id, log_index);
|
|
45
|
+
--> statement-breakpoint
|
|
46
|
+
create table if not exists board_terms (
|
|
47
|
+
message_id bigint not null,
|
|
48
|
+
term text not null,
|
|
49
|
+
value text not null,
|
|
50
|
+
primary key (message_id, term, value)
|
|
51
|
+
);
|
|
52
|
+
--> statement-breakpoint
|
|
53
|
+
create index if not exists board_terms_term on board_terms (term, value, message_id);
|
|
54
|
+
--> statement-breakpoint
|
|
55
|
+
create table if not exists board_sync_threads (
|
|
56
|
+
thread text primary key,
|
|
57
|
+
data text not null
|
|
58
|
+
);
|
|
59
|
+
--> statement-breakpoint
|
|
60
|
+
create table if not exists board_external_threads (
|
|
61
|
+
external text primary key,
|
|
62
|
+
thread text not null
|
|
63
|
+
);
|
|
64
|
+
--> statement-breakpoint
|
|
65
|
+
create table if not exists board_copies (
|
|
66
|
+
message_id bigint not null,
|
|
67
|
+
target text not null,
|
|
68
|
+
data text not null,
|
|
69
|
+
primary key (message_id, target)
|
|
70
|
+
);
|
|
71
|
+
--> statement-breakpoint
|
|
72
|
+
create table if not exists board_external_messages (
|
|
73
|
+
key text primary key,
|
|
74
|
+
message_id bigint not null
|
|
75
|
+
);
|
|
76
|
+
--> statement-breakpoint
|
|
77
|
+
create index if not exists board_messages_recent on board_messages (by_principal, created_at) where re is null;
|
|
78
|
+
--> statement-breakpoint
|
|
79
|
+
drop function if exists board_apply(text, bigint, boolean, jsonb, jsonb, jsonb);
|
|
80
|
+
--> statement-breakpoint
|
|
81
|
+
create or replace function board_apply(
|
|
82
|
+
apply_consumer text,
|
|
83
|
+
apply_index bigint,
|
|
84
|
+
apply_next boolean,
|
|
85
|
+
apply_message jsonb,
|
|
86
|
+
apply_terms jsonb,
|
|
87
|
+
apply_summary jsonb,
|
|
88
|
+
apply_sync jsonb
|
|
89
|
+
) returns boolean language plpgsql as $$
|
|
90
|
+
begin
|
|
91
|
+
if apply_next then
|
|
92
|
+
update board_positions set log_index = apply_index
|
|
93
|
+
where consumer = apply_consumer and log_index = apply_index - 1;
|
|
94
|
+
else
|
|
95
|
+
insert into board_positions (consumer, log_index) values (apply_consumer, apply_index)
|
|
96
|
+
on conflict (consumer) do update set log_index = excluded.log_index
|
|
97
|
+
where board_positions.log_index < excluded.log_index;
|
|
98
|
+
end if;
|
|
99
|
+
if not found then
|
|
100
|
+
return false;
|
|
101
|
+
end if;
|
|
102
|
+
if apply_message is not null then
|
|
103
|
+
if (apply_message->>'created')::boolean then
|
|
104
|
+
insert into board_messages
|
|
105
|
+
(id, event_id, channel, re, by_actor, by_principal, by_profile, from_key, no_sync, text_lower, deleted, created_at, data)
|
|
106
|
+
values (
|
|
107
|
+
(apply_message->>'id')::bigint, apply_message->>'event_id', apply_message->>'channel', (apply_message->>'re')::bigint,
|
|
108
|
+
apply_message->>'by_actor', apply_message->>'by_principal', apply_message->>'by_profile', apply_message->>'from_key',
|
|
109
|
+
(apply_message->>'no_sync')::boolean, apply_message->>'text_lower', (apply_message->>'deleted')::boolean,
|
|
110
|
+
(apply_message->>'created_at')::bigint, apply_message->>'data');
|
|
111
|
+
else
|
|
112
|
+
update board_messages
|
|
113
|
+
set text_lower = apply_message->>'text_lower', deleted = (apply_message->>'deleted')::boolean, data = apply_message->>'data'
|
|
114
|
+
where id = (apply_message->>'id')::bigint;
|
|
115
|
+
end if;
|
|
116
|
+
insert into board_versions (log_index, message_id, data)
|
|
117
|
+
values (apply_index, (apply_message->>'id')::bigint, apply_message->>'data');
|
|
118
|
+
if apply_terms is not null then
|
|
119
|
+
delete from board_terms where message_id = (apply_message->>'id')::bigint;
|
|
120
|
+
insert into board_terms (message_id, term, value)
|
|
121
|
+
select (apply_message->>'id')::bigint, term->>0, term->>1 from jsonb_array_elements(apply_terms) as term;
|
|
122
|
+
end if;
|
|
123
|
+
end if;
|
|
124
|
+
if apply_summary is not null then
|
|
125
|
+
update board_messages set replies = (apply_summary->>'replies')::int, at = (apply_summary->>'at')::bigint
|
|
126
|
+
where id = (apply_summary->>'root')::bigint;
|
|
127
|
+
end if;
|
|
128
|
+
if apply_sync is not null then
|
|
129
|
+
if jsonb_typeof(apply_sync->'thread') = 'object' then
|
|
130
|
+
insert into board_sync_threads (thread, data) values (apply_sync->'thread'->>'key', apply_sync->'thread'->>'data')
|
|
131
|
+
on conflict (thread) do update set data = excluded.data;
|
|
132
|
+
end if;
|
|
133
|
+
insert into board_external_threads (external, thread)
|
|
134
|
+
select entry->>0, entry->>1 from jsonb_array_elements(apply_sync->'external_threads') as entry
|
|
135
|
+
on conflict (external) do update set thread = excluded.thread;
|
|
136
|
+
insert into board_copies (message_id, target, data)
|
|
137
|
+
select (entry->>0)::bigint, entry->>1, entry->>2 from jsonb_array_elements(apply_sync->'copies') as entry
|
|
138
|
+
on conflict (message_id, target) do update set data = excluded.data;
|
|
139
|
+
insert into board_external_messages (key, message_id)
|
|
140
|
+
select entry->>0, (entry->>1)::bigint from jsonb_array_elements(apply_sync->'external_messages') as entry
|
|
141
|
+
on conflict (key) do update set message_id = excluded.message_id;
|
|
142
|
+
end if;
|
|
143
|
+
return true;
|
|
144
|
+
end
|
|
145
|
+
$$;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
-- Notification triggers for experimental-a2/store-postgres, needed only with
|
|
2
|
+
-- `listenConnectionString`. Apply after schema.sql. They wake live streams
|
|
3
|
+
-- for every write to A2's event and presence tables, including writes from
|
|
4
|
+
-- stores without the option. Safe to re-run.
|
|
5
|
+
|
|
6
|
+
create or replace function a2_notify_events() returns trigger language plpgsql as $$
|
|
7
|
+
begin
|
|
8
|
+
perform pg_notify('a2_events_' || md5(new.session_id), '');
|
|
9
|
+
return null;
|
|
10
|
+
end $$;
|
|
11
|
+
create or replace function a2_notify_presence() returns trigger language plpgsql as $$
|
|
12
|
+
begin
|
|
13
|
+
perform pg_notify('a2_presence_' || md5(case when TG_OP = 'DELETE' then old.ns else new.ns end),
|
|
14
|
+
coalesce(current_setting('a2.presence_source', true), ''));
|
|
15
|
+
return null;
|
|
16
|
+
end $$;
|
|
17
|
+
do $$ begin
|
|
18
|
+
if not exists (select 1 from pg_trigger where tgname = 'a2_notify_events' and tgrelid = 'a2_events'::regclass) then
|
|
19
|
+
create trigger a2_notify_events after insert on a2_events for each row execute function a2_notify_events();
|
|
20
|
+
end if;
|
|
21
|
+
if not exists (select 1 from pg_trigger where tgname = 'a2_notify_presence' and tgrelid = 'a2_presence'::regclass) then
|
|
22
|
+
create trigger a2_notify_presence after insert or update or delete on a2_presence for each row execute function a2_notify_presence();
|
|
23
|
+
end if;
|
|
24
|
+
end $$;
|