@voltro/plugin-comments 0.86.0 → 0.88.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/CHANGELOG.md +5484 -0
- package/THIRD-PARTY-NOTICES.md +6 -230
- package/dist/errors.js +1 -2
- package/dist/index.js +157 -158
- package/dist/quote.js +1 -2
- package/dist/rpc.js +1 -2
- package/dist/web.js +1 -2
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -1,96 +1,96 @@
|
|
|
1
1
|
import { CommentAccessRefused as e, CommentNotFound as t, CommentNotYours as n, CommentStatusRefused as r } from "./errors.js";
|
|
2
2
|
import { QUOTE_MAX_LENGTH as i, findQuote as a, textQuote as o } from "./quote.js";
|
|
3
|
-
import { BASE_NAME as s, COMMENT_THREAD_KINDS as c, commentsFeed as l, commentsRpcClientImports as u, createDescriptor as d, deleteDescriptor as f, editDescriptor as p, listDescriptor as m, markReadDescriptor as h, mentionSearchDescriptor as g, reactDescriptor as _, resolveDescriptor as
|
|
4
|
-
import { Effect as
|
|
5
|
-
import { and as
|
|
6
|
-
import { definePlugin as N, pluginInstanceName as P, publishReactivity as F } from "@voltro/protocol";
|
|
3
|
+
import { BASE_NAME as s, COMMENT_THREAD_KINDS as c, commentsFeed as l, commentsRpcClientImports as u, createDescriptor as d, deleteDescriptor as f, editDescriptor as p, listDescriptor as m, markReadDescriptor as h, mentionSearchDescriptor as g, reactDescriptor as _, resolveDescriptor as ee } from "./rpc.js";
|
|
4
|
+
import { Effect as v, Option as y } from "effect";
|
|
5
|
+
import { and as b, contains as x, eq as S, generateId as C, id as w, inSet as T, json as E, neq as D, or as O, table as k, text as A, timestamp as j } from "@voltro/database";
|
|
6
|
+
import { definePlugin as M, effectiveScopes as N, pluginInstanceName as P, publishReactivity as F } from "@voltro/protocol";
|
|
7
7
|
import { NotificationService as I } from "@voltro/plugin-notifications";
|
|
8
|
-
|
|
9
|
-
var L =
|
|
10
|
-
id:
|
|
11
|
-
anchor:
|
|
12
|
-
quote:
|
|
13
|
-
kind:
|
|
14
|
-
status:
|
|
15
|
-
createdBy:
|
|
16
|
-
createdAt:
|
|
17
|
-
tenantId:
|
|
18
|
-
}).index("byThreadAnchor", ["anchor", "tenantId"]), R =
|
|
19
|
-
id:
|
|
20
|
-
threadId:
|
|
21
|
-
body:
|
|
22
|
-
authorSubjectId:
|
|
23
|
-
mentions:
|
|
24
|
-
editedAt:
|
|
25
|
-
createdAt:
|
|
26
|
-
tenantId:
|
|
27
|
-
}).index("byCommentThread", ["threadId"]), z =
|
|
28
|
-
id:
|
|
29
|
-
threadId:
|
|
30
|
-
fromStatus:
|
|
31
|
-
toStatus:
|
|
32
|
-
actor:
|
|
33
|
-
reason:
|
|
34
|
-
at:
|
|
35
|
-
tenantId:
|
|
36
|
-
}).index("byThreadEvents", ["threadId"]), B =
|
|
37
|
-
id:
|
|
38
|
-
commentId:
|
|
39
|
-
subjectId:
|
|
40
|
-
emoji:
|
|
8
|
+
// src/index.ts
|
|
9
|
+
var L = k("_voltro_comment_threads", {
|
|
10
|
+
id: w({ prefix: "cmtthr" }),
|
|
11
|
+
anchor: A(),
|
|
12
|
+
quote: E().nullable(),
|
|
13
|
+
kind: A().default("discussion"),
|
|
14
|
+
status: A().default("open"),
|
|
15
|
+
createdBy: A(),
|
|
16
|
+
createdAt: j().default("now"),
|
|
17
|
+
tenantId: A().nullable()
|
|
18
|
+
}).index("byThreadAnchor", ["anchor", "tenantId"]), R = k("_voltro_comments", {
|
|
19
|
+
id: w({ prefix: "cmt" }),
|
|
20
|
+
threadId: A(),
|
|
21
|
+
body: A(),
|
|
22
|
+
authorSubjectId: A(),
|
|
23
|
+
mentions: E(),
|
|
24
|
+
editedAt: j().nullable(),
|
|
25
|
+
createdAt: j().default("now"),
|
|
26
|
+
tenantId: A().nullable()
|
|
27
|
+
}).index("byCommentThread", ["threadId"]), z = k("_voltro_comment_thread_events", {
|
|
28
|
+
id: w({ prefix: "cmtevt" }),
|
|
29
|
+
threadId: A(),
|
|
30
|
+
fromStatus: A().nullable(),
|
|
31
|
+
toStatus: A(),
|
|
32
|
+
actor: A(),
|
|
33
|
+
reason: A().nullable(),
|
|
34
|
+
at: j().default("now"),
|
|
35
|
+
tenantId: A().nullable()
|
|
36
|
+
}).index("byThreadEvents", ["threadId"]), B = k("_voltro_comment_reactions", {
|
|
37
|
+
id: w({ prefix: "cmtrx" }),
|
|
38
|
+
commentId: A(),
|
|
39
|
+
subjectId: A(),
|
|
40
|
+
emoji: A()
|
|
41
41
|
}).unique("byReactionIdentity", [
|
|
42
42
|
"commentId",
|
|
43
43
|
"subjectId",
|
|
44
44
|
"emoji"
|
|
45
|
-
]).index("byReactionComment", ["commentId"]), V =
|
|
46
|
-
id:
|
|
47
|
-
threadId:
|
|
48
|
-
subjectId:
|
|
49
|
-
lastReadAt:
|
|
45
|
+
]).index("byReactionComment", ["commentId"]), V = k("_voltro_comment_reads", {
|
|
46
|
+
id: w({ prefix: "cmtread" }),
|
|
47
|
+
threadId: A(),
|
|
48
|
+
subjectId: A(),
|
|
49
|
+
lastReadAt: j()
|
|
50
50
|
}).unique("byReadThreadSubject", ["threadId", "subjectId"]), H = s, U = (e) => {
|
|
51
51
|
let t = e.request.subject ?? {};
|
|
52
52
|
return {
|
|
53
53
|
id: t.id ?? null,
|
|
54
54
|
tenantId: t.tenantId ?? null,
|
|
55
|
-
scopes: t
|
|
55
|
+
scopes: N(t)
|
|
56
56
|
};
|
|
57
57
|
}, W = (i = {}) => {
|
|
58
58
|
let a = P({
|
|
59
59
|
base: H,
|
|
60
60
|
alias: i.alias,
|
|
61
61
|
instance: i.name
|
|
62
|
-
}), o, s,
|
|
62
|
+
}), o, s, w = async (e, t, n) => o === void 0 ? [] : o.query({
|
|
63
63
|
table: e,
|
|
64
64
|
predicate: t,
|
|
65
65
|
order: [],
|
|
66
66
|
take: n,
|
|
67
67
|
skip: void 0,
|
|
68
68
|
projection: void 0
|
|
69
|
-
}),
|
|
69
|
+
}), E = async (e, t, n, r) => {
|
|
70
70
|
let i = [], a = [...new Set(n)];
|
|
71
71
|
for (let n = 0; n < a.length; n += 500) {
|
|
72
|
-
let o =
|
|
73
|
-
i.push(...await
|
|
72
|
+
let o = T(t, a.slice(n, n + 500));
|
|
73
|
+
i.push(...await w(e, r === void 0 ? o : b(o, r)));
|
|
74
74
|
}
|
|
75
75
|
return i;
|
|
76
|
-
},
|
|
76
|
+
}, k = (e, t) => {
|
|
77
77
|
let n = /* @__PURE__ */ new Map();
|
|
78
78
|
for (let r of e) {
|
|
79
79
|
let e = String(r[t]), i = n.get(e);
|
|
80
80
|
i === void 0 ? n.set(e, [r]) : i.push(r);
|
|
81
81
|
}
|
|
82
82
|
return n;
|
|
83
|
-
},
|
|
83
|
+
}, A = () => {
|
|
84
84
|
F(s, l);
|
|
85
|
-
},
|
|
85
|
+
}, j = (t, n) => v.gen(function* () {
|
|
86
86
|
let r = U(n);
|
|
87
|
-
return i.access?.viaEntity === void 0 ? i.access?.scope === void 0 ? yield*
|
|
87
|
+
return i.access?.viaEntity === void 0 ? i.access?.scope === void 0 ? yield* v.fail(new e({
|
|
88
88
|
anchor: t,
|
|
89
89
|
reason: "no access rule declared — set commentsPlugin({ access: { viaEntity } }) or { access: { scope } }"
|
|
90
|
-
})) : r.scopes.includes(i.access.scope) ? void 0 : yield*
|
|
90
|
+
})) : r.scopes.includes(i.access.scope) ? void 0 : yield* v.fail(new e({
|
|
91
91
|
anchor: t,
|
|
92
92
|
reason: `missing scope '${i.access.scope}'`
|
|
93
|
-
})) : (yield*
|
|
93
|
+
})) : (yield* v.promise(async () => {
|
|
94
94
|
try {
|
|
95
95
|
return await i.access.viaEntity({
|
|
96
96
|
anchor: t,
|
|
@@ -100,25 +100,25 @@ var L = A("_voltro_comment_threads", {
|
|
|
100
100
|
} catch {
|
|
101
101
|
return !1;
|
|
102
102
|
}
|
|
103
|
-
})) ? void 0 : yield*
|
|
103
|
+
})) ? void 0 : yield* v.fail(new e({
|
|
104
104
|
anchor: t,
|
|
105
105
|
reason: "the anchored entity is not readable by this caller (or no longer available)"
|
|
106
106
|
}));
|
|
107
|
-
}),
|
|
107
|
+
}), N = async (e) => (await w("_voltro_comment_threads", S("id", e), 1))[0], W = (e) => ({
|
|
108
108
|
id: String(e.id),
|
|
109
109
|
anchor: String(e.anchor),
|
|
110
110
|
kind: c.includes(String(e.kind)) ? e.kind : "discussion",
|
|
111
111
|
status: e.status === "resolved" ? "resolved" : "open",
|
|
112
112
|
createdBy: String(e.createdBy)
|
|
113
|
-
}),
|
|
114
|
-
thread:
|
|
113
|
+
}), G = (e, t) => i.visibleTo === void 0 || i.visibleTo({
|
|
114
|
+
thread: W(e),
|
|
115
115
|
subject: U(t)
|
|
116
|
-
}),
|
|
117
|
-
let n = await
|
|
118
|
-
return n !== void 0 &&
|
|
119
|
-
},
|
|
116
|
+
}), K = async (e, t) => {
|
|
117
|
+
let n = await N(e);
|
|
118
|
+
return n !== void 0 && G(n, t) ? n : void 0;
|
|
119
|
+
}, q = async (e, t) => {
|
|
120
120
|
await e.insert("_voltro_comment_thread_events", {
|
|
121
|
-
id:
|
|
121
|
+
id: C({
|
|
122
122
|
kind: "typeid",
|
|
123
123
|
prefix: "cmtevt"
|
|
124
124
|
}, "_voltro_comment_thread_events"),
|
|
@@ -130,11 +130,11 @@ var L = A("_voltro_comment_threads", {
|
|
|
130
130
|
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
131
131
|
tenantId: t.tenantId
|
|
132
132
|
});
|
|
133
|
-
},
|
|
133
|
+
}, J = (e) => e instanceof Date ? e.toISOString() : typeof e == "string" ? e : "", Y = (e) => v.gen(function* () {
|
|
134
134
|
if (e.mentions.length === 0) return;
|
|
135
|
-
let t = yield*
|
|
136
|
-
if (
|
|
137
|
-
else for (let n of e.mentions) n !== e.author && (yield*
|
|
135
|
+
let t = yield* v.serviceOption(I);
|
|
136
|
+
if (y.isNone(t)) yield* v.logInfo("comments: mention recorded without notification — @voltro/plugin-notifications is not configured");
|
|
137
|
+
else for (let n of e.mentions) n !== e.author && (yield* v.promise(() => t.value.send({
|
|
138
138
|
to: n,
|
|
139
139
|
category: i.mentionCategory ?? "mention",
|
|
140
140
|
title: "You were mentioned",
|
|
@@ -145,7 +145,7 @@ var L = A("_voltro_comment_threads", {
|
|
|
145
145
|
},
|
|
146
146
|
tenantId: e.tenantId
|
|
147
147
|
}).then(() => void 0).catch(() => void 0)));
|
|
148
|
-
}),
|
|
148
|
+
}), X = async (e, t) => {
|
|
149
149
|
if (e.length === 0 || i.resolveMentions === void 0) return [];
|
|
150
150
|
let n = [];
|
|
151
151
|
for (let r of [...new Set(e)].slice(0, 20)) {
|
|
@@ -156,18 +156,18 @@ var L = A("_voltro_comment_threads", {
|
|
|
156
156
|
e !== void 0 && (i.crossTenant === !0 || e.tenantId === void 0 || e.tenantId === null || e.tenantId === t.tenantId) && n.push(r);
|
|
157
157
|
}
|
|
158
158
|
return n;
|
|
159
|
-
},
|
|
160
|
-
let { tenantId: n, id: r } = U(t), i = (await
|
|
159
|
+
}, Z = async (e, t) => {
|
|
160
|
+
let { tenantId: n, id: r } = U(t), i = (await w("_voltro_comment_threads", b(S("anchor", e), S("tenantId", n)))).filter((e) => G(e, t));
|
|
161
161
|
if (i.length === 0) return [];
|
|
162
162
|
let a = i.map((e) => String(e.id)), [o, s, c] = await Promise.all([
|
|
163
|
-
|
|
164
|
-
r === null ? Promise.resolve([]) :
|
|
165
|
-
|
|
166
|
-
]), l =
|
|
163
|
+
E("_voltro_comments", "threadId", a),
|
|
164
|
+
r === null ? Promise.resolve([]) : E("_voltro_comment_reads", "threadId", a, S("subjectId", r)),
|
|
165
|
+
E("_voltro_comment_thread_events", "threadId", a)
|
|
166
|
+
]), l = k(o, "threadId"), u = k(s, "threadId"), d = k(c, "threadId"), f = k(await E("_voltro_comment_reactions", "commentId", o.map((e) => String(e.id))), "commentId"), p = [];
|
|
167
167
|
for (let e of i) {
|
|
168
168
|
let t = l.get(String(e.id)) ?? [];
|
|
169
|
-
t.sort((e, t) =>
|
|
170
|
-
let n = u.get(String(e.id)) ?? [], i = n[0] ?
|
|
169
|
+
t.sort((e, t) => J(e.createdAt) < J(t.createdAt) ? -1 : 1);
|
|
170
|
+
let n = u.get(String(e.id)) ?? [], i = n[0] ? J(n[0].lastReadAt) : "", a = [];
|
|
171
171
|
for (let e of t) {
|
|
172
172
|
let t = f.get(String(e.id)) ?? [], n = /* @__PURE__ */ new Map();
|
|
173
173
|
for (let e of t) {
|
|
@@ -183,8 +183,8 @@ var L = A("_voltro_comment_threads", {
|
|
|
183
183
|
body: String(e.body),
|
|
184
184
|
authorSubjectId: String(e.authorSubjectId),
|
|
185
185
|
mentions: e.mentions ?? [],
|
|
186
|
-
editedAt: e.editedAt == null ? null :
|
|
187
|
-
createdAt:
|
|
186
|
+
editedAt: e.editedAt == null ? null : J(e.editedAt),
|
|
187
|
+
createdAt: J(e.createdAt),
|
|
188
188
|
reactions: [...n.entries()].map(([e, t]) => ({
|
|
189
189
|
emoji: e,
|
|
190
190
|
count: t.count,
|
|
@@ -193,8 +193,8 @@ var L = A("_voltro_comment_threads", {
|
|
|
193
193
|
});
|
|
194
194
|
}
|
|
195
195
|
let o = d.get(String(e.id)) ?? [];
|
|
196
|
-
o.sort((e, t) =>
|
|
197
|
-
let s =
|
|
196
|
+
o.sort((e, t) => J(e.at) < J(t.at) ? -1 : J(e.at) > J(t.at) ? 1 : String(e.id) < String(t.id) ? -1 : 1);
|
|
197
|
+
let s = W(e);
|
|
198
198
|
p.push({
|
|
199
199
|
id: s.id,
|
|
200
200
|
anchor: s.anchor,
|
|
@@ -202,58 +202,58 @@ var L = A("_voltro_comment_threads", {
|
|
|
202
202
|
quote: e.quote ?? null,
|
|
203
203
|
status: s.status,
|
|
204
204
|
createdBy: String(e.createdBy),
|
|
205
|
-
createdAt:
|
|
205
|
+
createdAt: J(e.createdAt),
|
|
206
206
|
comments: a,
|
|
207
207
|
unreadCount: a.filter((e) => String(e.authorSubjectId) !== r && String(e.createdAt) > i).length,
|
|
208
208
|
history: o.map((e) => ({
|
|
209
209
|
from: e.fromStatus === "open" || e.fromStatus === "resolved" ? e.fromStatus : null,
|
|
210
210
|
to: e.toStatus === "resolved" ? "resolved" : "open",
|
|
211
211
|
by: String(e.actor),
|
|
212
|
-
at:
|
|
212
|
+
at: J(e.at),
|
|
213
213
|
reason: e.reason == null ? null : String(e.reason)
|
|
214
214
|
}))
|
|
215
215
|
});
|
|
216
216
|
}
|
|
217
217
|
return p.sort((e, t) => String(e.createdAt) < String(t.createdAt) ? -1 : 1), p;
|
|
218
|
-
},
|
|
218
|
+
}, Q = [
|
|
219
219
|
{
|
|
220
220
|
...m,
|
|
221
221
|
description: "Threads + comments + reactions + unread for one anchor, live.",
|
|
222
|
-
execute: (e, t) =>
|
|
222
|
+
execute: (e, t) => v.gen(function* () {
|
|
223
223
|
let { anchor: n } = e;
|
|
224
|
-
return yield*
|
|
224
|
+
return yield* j(n, t), yield* v.promise(() => Z(n, t));
|
|
225
225
|
})
|
|
226
226
|
},
|
|
227
227
|
{
|
|
228
228
|
...d,
|
|
229
229
|
description: "Comment on an anchor — a reply into a thread, or a new thread.",
|
|
230
|
-
execute: (n, r) =>
|
|
230
|
+
execute: (n, r) => v.gen(function* () {
|
|
231
231
|
let i = n;
|
|
232
|
-
yield*
|
|
232
|
+
yield* j(i.anchor, r);
|
|
233
233
|
let a = U(r), s = a.id ?? "anonymous", c = o;
|
|
234
|
-
if (c === void 0) return yield*
|
|
234
|
+
if (c === void 0) return yield* v.fail(new t({ id: i.anchor }));
|
|
235
235
|
let l = i.threadId;
|
|
236
236
|
if (l !== void 0) {
|
|
237
|
-
let e = yield*
|
|
238
|
-
if (e === void 0 || String(e.anchor) !== i.anchor) return yield*
|
|
237
|
+
let e = yield* v.promise(() => K(l, r));
|
|
238
|
+
if (e === void 0 || String(e.anchor) !== i.anchor) return yield* v.fail(new t({ id: l }));
|
|
239
239
|
} else {
|
|
240
|
-
let t =
|
|
240
|
+
let t = C({
|
|
241
241
|
kind: "typeid",
|
|
242
242
|
prefix: "cmtthr"
|
|
243
243
|
}, "_voltro_comment_threads");
|
|
244
244
|
l = t;
|
|
245
245
|
let n = i.kind ?? "discussion";
|
|
246
|
-
if (!
|
|
246
|
+
if (!G({
|
|
247
247
|
id: t,
|
|
248
248
|
anchor: i.anchor,
|
|
249
249
|
kind: n,
|
|
250
250
|
status: "open",
|
|
251
251
|
createdBy: s
|
|
252
|
-
}, r)) return yield*
|
|
252
|
+
}, r)) return yield* v.fail(new e({
|
|
253
253
|
anchor: i.anchor,
|
|
254
254
|
reason: `a ${n} thread here would not be visible to its author`
|
|
255
255
|
}));
|
|
256
|
-
yield*
|
|
256
|
+
yield* v.promise(async () => {
|
|
257
257
|
await c.insert("_voltro_comment_threads", {
|
|
258
258
|
id: t,
|
|
259
259
|
anchor: i.anchor,
|
|
@@ -263,7 +263,7 @@ var L = A("_voltro_comment_threads", {
|
|
|
263
263
|
createdBy: s,
|
|
264
264
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
265
265
|
tenantId: a.tenantId
|
|
266
|
-
}), await
|
|
266
|
+
}), await q(c, {
|
|
267
267
|
threadId: t,
|
|
268
268
|
from: null,
|
|
269
269
|
to: "open",
|
|
@@ -273,11 +273,11 @@ var L = A("_voltro_comment_threads", {
|
|
|
273
273
|
});
|
|
274
274
|
});
|
|
275
275
|
}
|
|
276
|
-
let u = yield*
|
|
276
|
+
let u = yield* v.promise(() => X(i.mentions ?? [], a)), d = C({
|
|
277
277
|
kind: "typeid",
|
|
278
278
|
prefix: "cmt"
|
|
279
279
|
}, "_voltro_comments");
|
|
280
|
-
return yield*
|
|
280
|
+
return yield* v.promise(() => c.insert("_voltro_comments", {
|
|
281
281
|
id: d,
|
|
282
282
|
threadId: l,
|
|
283
283
|
body: i.body,
|
|
@@ -286,7 +286,7 @@ var L = A("_voltro_comment_threads", {
|
|
|
286
286
|
editedAt: null,
|
|
287
287
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
288
288
|
tenantId: a.tenantId
|
|
289
|
-
})),
|
|
289
|
+
})), A(), yield* Y({
|
|
290
290
|
mentions: u,
|
|
291
291
|
author: s,
|
|
292
292
|
anchor: i.anchor,
|
|
@@ -302,27 +302,27 @@ var L = A("_voltro_comment_threads", {
|
|
|
302
302
|
{
|
|
303
303
|
...p,
|
|
304
304
|
description: "Edit your own comment.",
|
|
305
|
-
execute: (e, r) =>
|
|
306
|
-
let i = e, a = (yield*
|
|
307
|
-
if (a === void 0) return yield*
|
|
308
|
-
let s = yield*
|
|
309
|
-
return s === void 0 ? yield*
|
|
305
|
+
execute: (e, r) => v.gen(function* () {
|
|
306
|
+
let i = e, a = (yield* v.promise(() => w("_voltro_comments", S("id", i.commentId), 1)))[0];
|
|
307
|
+
if (a === void 0) return yield* v.fail(new t({ id: i.commentId }));
|
|
308
|
+
let s = yield* v.promise(() => K(String(a.threadId), r));
|
|
309
|
+
return s === void 0 ? yield* v.fail(new t({ id: i.commentId })) : (yield* j(String(s.anchor), r), String(a.authorSubjectId) === (U(r).id ?? "anonymous") ? (yield* v.promise(() => o.update("_voltro_comments", i.commentId, {
|
|
310
310
|
body: i.body,
|
|
311
311
|
editedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
312
|
-
})),
|
|
312
|
+
})), A(), { ok: !0 }) : yield* v.fail(new n({ id: i.commentId })));
|
|
313
313
|
})
|
|
314
314
|
},
|
|
315
315
|
{
|
|
316
|
-
...
|
|
316
|
+
...ee,
|
|
317
317
|
description: "Resolve or reopen a thread.",
|
|
318
|
-
execute: (e, n) =>
|
|
319
|
-
let a = e, s = yield*
|
|
320
|
-
if (s === void 0) return yield*
|
|
321
|
-
yield*
|
|
322
|
-
let c =
|
|
318
|
+
execute: (e, n) => v.gen(function* () {
|
|
319
|
+
let a = e, s = yield* v.promise(() => K(a.threadId, n));
|
|
320
|
+
if (s === void 0) return yield* v.fail(new t({ id: a.threadId }));
|
|
321
|
+
yield* j(String(s.anchor), n);
|
|
322
|
+
let c = W(s), l = a.resolved ? "resolved" : "open";
|
|
323
323
|
if (c.status === l) return { ok: !0 };
|
|
324
324
|
let u = U(n);
|
|
325
|
-
if (i.statusPolicy !== void 0 && !(yield*
|
|
325
|
+
if (i.statusPolicy !== void 0 && !(yield* v.promise(async () => {
|
|
326
326
|
try {
|
|
327
327
|
return await i.statusPolicy({
|
|
328
328
|
thread: c,
|
|
@@ -333,13 +333,13 @@ var L = A("_voltro_comment_threads", {
|
|
|
333
333
|
} catch {
|
|
334
334
|
return !1;
|
|
335
335
|
}
|
|
336
|
-
}))) return yield*
|
|
336
|
+
}))) return yield* v.fail(new r({
|
|
337
337
|
threadId: a.threadId,
|
|
338
338
|
reason: `the status policy does not let this caller ${a.resolved ? "resolve" : "reopen"} this ${c.kind} thread`
|
|
339
339
|
}));
|
|
340
340
|
let d = a.reason?.trim() ? a.reason.trim() : null;
|
|
341
|
-
return yield*
|
|
342
|
-
await o.update("_voltro_comment_threads", a.threadId, { status: l }), await
|
|
341
|
+
return yield* v.promise(async () => {
|
|
342
|
+
await o.update("_voltro_comment_threads", a.threadId, { status: l }), await q(o, {
|
|
343
343
|
threadId: a.threadId,
|
|
344
344
|
from: c.status,
|
|
345
345
|
to: l,
|
|
@@ -347,59 +347,59 @@ var L = A("_voltro_comment_threads", {
|
|
|
347
347
|
reason: d,
|
|
348
348
|
tenantId: u.tenantId
|
|
349
349
|
});
|
|
350
|
-
}),
|
|
350
|
+
}), A(), { ok: !0 };
|
|
351
351
|
})
|
|
352
352
|
},
|
|
353
353
|
{
|
|
354
354
|
...f,
|
|
355
355
|
description: "Delete your own comment (comments:moderate deletes any).",
|
|
356
|
-
execute: (e, r) =>
|
|
357
|
-
let i = e, a = (yield*
|
|
358
|
-
if (a === void 0) return yield*
|
|
359
|
-
let s = yield*
|
|
360
|
-
if (s === void 0) return yield*
|
|
361
|
-
yield*
|
|
356
|
+
execute: (e, r) => v.gen(function* () {
|
|
357
|
+
let i = e, a = (yield* v.promise(() => w("_voltro_comments", S("id", i.commentId), 1)))[0];
|
|
358
|
+
if (a === void 0) return yield* v.fail(new t({ id: i.commentId }));
|
|
359
|
+
let s = yield* v.promise(() => K(String(a.threadId), r));
|
|
360
|
+
if (s === void 0) return yield* v.fail(new t({ id: i.commentId }));
|
|
361
|
+
yield* j(String(s.anchor), r);
|
|
362
362
|
let c = U(r);
|
|
363
|
-
return String(a.authorSubjectId) !== (c.id ?? "anonymous") && !c.scopes.includes("comments:moderate") ? yield*
|
|
364
|
-
for (let e of await
|
|
363
|
+
return String(a.authorSubjectId) !== (c.id ?? "anonymous") && !c.scopes.includes("comments:moderate") ? yield* v.fail(new n({ id: i.commentId })) : (yield* v.promise(async () => {
|
|
364
|
+
for (let e of await w("_voltro_comment_reactions", S("commentId", i.commentId))) await o.delete("_voltro_comment_reactions", String(e.id));
|
|
365
365
|
await o.delete("_voltro_comments", i.commentId);
|
|
366
|
-
}),
|
|
366
|
+
}), A(), { ok: !0 });
|
|
367
367
|
})
|
|
368
368
|
},
|
|
369
369
|
{
|
|
370
370
|
..._,
|
|
371
371
|
description: "Toggle an emoji reaction on a comment.",
|
|
372
|
-
execute: (e, n) =>
|
|
373
|
-
let r = e, i = (yield*
|
|
374
|
-
if (i === void 0) return yield*
|
|
375
|
-
let a = yield*
|
|
376
|
-
if (a === void 0) return yield*
|
|
377
|
-
yield*
|
|
378
|
-
let s = U(n).id ?? "anonymous", c = (yield*
|
|
379
|
-
if (c !== void 0) return yield*
|
|
380
|
-
let l =
|
|
372
|
+
execute: (e, n) => v.gen(function* () {
|
|
373
|
+
let r = e, i = (yield* v.promise(() => w("_voltro_comments", S("id", r.commentId), 1)))[0];
|
|
374
|
+
if (i === void 0) return yield* v.fail(new t({ id: r.commentId }));
|
|
375
|
+
let a = yield* v.promise(() => K(String(i.threadId), n));
|
|
376
|
+
if (a === void 0) return yield* v.fail(new t({ id: r.commentId }));
|
|
377
|
+
yield* j(String(a.anchor), n);
|
|
378
|
+
let s = U(n).id ?? "anonymous", c = (yield* v.promise(() => w("_voltro_comment_reactions", b(S("commentId", r.commentId), b(S("subjectId", s), S("emoji", r.emoji))), 1)))[0];
|
|
379
|
+
if (c !== void 0) return yield* v.promise(() => o.delete("_voltro_comment_reactions", String(c.id))), A(), { reacted: !1 };
|
|
380
|
+
let l = C({
|
|
381
381
|
kind: "typeid",
|
|
382
382
|
prefix: "cmtrx"
|
|
383
383
|
}, "_voltro_comment_reactions");
|
|
384
|
-
return yield*
|
|
384
|
+
return yield* v.promise(() => o.insert("_voltro_comment_reactions", {
|
|
385
385
|
id: l,
|
|
386
386
|
commentId: r.commentId,
|
|
387
387
|
subjectId: s,
|
|
388
388
|
emoji: r.emoji
|
|
389
|
-
})),
|
|
389
|
+
})), A(), { reacted: !0 };
|
|
390
390
|
})
|
|
391
391
|
},
|
|
392
392
|
{
|
|
393
393
|
...h,
|
|
394
394
|
description: "Stamp the caller's read marker for a thread.",
|
|
395
|
-
execute: (e, n) =>
|
|
395
|
+
execute: (e, n) => v.gen(function* () {
|
|
396
396
|
let r = e;
|
|
397
|
-
if ((yield*
|
|
398
|
-
let i = U(n).id ?? "anonymous", a =
|
|
397
|
+
if ((yield* v.promise(() => N(r.threadId))) === void 0) return yield* v.fail(new t({ id: r.threadId }));
|
|
398
|
+
let i = U(n).id ?? "anonymous", a = C({
|
|
399
399
|
kind: "typeid",
|
|
400
400
|
prefix: "cmtread"
|
|
401
401
|
}, "_voltro_comment_reads");
|
|
402
|
-
return yield*
|
|
402
|
+
return yield* v.promise(() => o.upsert("_voltro_comment_reads", {
|
|
403
403
|
id: a,
|
|
404
404
|
threadId: r.threadId,
|
|
405
405
|
subjectId: i,
|
|
@@ -413,7 +413,7 @@ var L = A("_voltro_comment_threads", {
|
|
|
413
413
|
{
|
|
414
414
|
...g,
|
|
415
415
|
description: "@-mention autocomplete over the app-declared directory, tenant-filtered.",
|
|
416
|
-
execute: (e, t) =>
|
|
416
|
+
execute: (e, t) => v.promise(async () => {
|
|
417
417
|
let { query: n } = e;
|
|
418
418
|
if (i.resolveMentions === void 0) return [];
|
|
419
419
|
let r = U(t);
|
|
@@ -433,7 +433,7 @@ var L = A("_voltro_comment_threads", {
|
|
|
433
433
|
kind: "json",
|
|
434
434
|
data: e
|
|
435
435
|
});
|
|
436
|
-
return
|
|
436
|
+
return M({
|
|
437
437
|
name: a,
|
|
438
438
|
baseName: H,
|
|
439
439
|
description: "Comment threads on any app entity — replies, resolve/reopen, @-mentions with notifications, reactions, unread — live over the reactive engine.",
|
|
@@ -445,17 +445,17 @@ var L = A("_voltro_comment_threads", {
|
|
|
445
445
|
B,
|
|
446
446
|
V
|
|
447
447
|
] },
|
|
448
|
-
routes:
|
|
448
|
+
routes: Q,
|
|
449
449
|
rpcClientDescriptors: u,
|
|
450
450
|
inspectEndpoints: [{
|
|
451
451
|
method: "GET",
|
|
452
452
|
path: "/threads",
|
|
453
453
|
scope: "process",
|
|
454
454
|
description: "Thread volume and searchable, paginated threads (operator surface).",
|
|
455
|
-
handler: (e) =>
|
|
455
|
+
handler: (e) => v.promise(async () => {
|
|
456
456
|
let t = new URL(e.url, "http://inspect.local").searchParams, n = t.get("threadId"), r = Number(t.get("offset") ?? 0), i = Number.isSafeInteger(r) && r >= 0 ? r : 0, a = (t.get("search") ?? "").trim().slice(0, 200);
|
|
457
457
|
if (n) {
|
|
458
|
-
let e = (await
|
|
458
|
+
let e = (await w("_voltro_comment_threads", S("id", n), 1))[0], t = S("threadId", n), [r, a] = e && o ? await Promise.all([o.query({
|
|
459
459
|
table: "_voltro_comments",
|
|
460
460
|
predicate: t,
|
|
461
461
|
order: [{
|
|
@@ -496,8 +496,8 @@ var L = A("_voltro_comment_threads", {
|
|
|
496
496
|
id: String(e.id),
|
|
497
497
|
body: String(e.body),
|
|
498
498
|
author: String(e.authorSubjectId),
|
|
499
|
-
createdAt:
|
|
500
|
-
editedAt: e.editedAt == null ? null :
|
|
499
|
+
createdAt: J(e.createdAt),
|
|
500
|
+
editedAt: e.editedAt == null ? null : J(e.editedAt)
|
|
501
501
|
}))
|
|
502
502
|
}
|
|
503
503
|
});
|
|
@@ -517,7 +517,7 @@ var L = A("_voltro_comment_threads", {
|
|
|
517
517
|
}]
|
|
518
518
|
});
|
|
519
519
|
return Number(n[0]?.count ?? 0);
|
|
520
|
-
}, c = a ?
|
|
520
|
+
}, c = a ? O(x("anchor", a), x("id", a), x("createdBy", a)) : void 0, [l, u, d, f, p] = await Promise.all([
|
|
521
521
|
o.query({
|
|
522
522
|
table: "_voltro_comment_threads",
|
|
523
523
|
predicate: c,
|
|
@@ -533,12 +533,12 @@ var L = A("_voltro_comment_threads", {
|
|
|
533
533
|
projection: void 0
|
|
534
534
|
}),
|
|
535
535
|
s("_voltro_comment_threads"),
|
|
536
|
-
s("_voltro_comment_threads",
|
|
536
|
+
s("_voltro_comment_threads", D("status", "resolved")),
|
|
537
537
|
s("_voltro_comments"),
|
|
538
538
|
s("_voltro_comment_threads", c)
|
|
539
539
|
]), m = l.length === 0 ? [] : await o.query({
|
|
540
540
|
table: "_voltro_comments",
|
|
541
|
-
predicate:
|
|
541
|
+
predicate: T("threadId", l.map((e) => String(e.id))),
|
|
542
542
|
order: [],
|
|
543
543
|
take: void 0,
|
|
544
544
|
skip: void 0,
|
|
@@ -570,7 +570,7 @@ var L = A("_voltro_comment_threads", {
|
|
|
570
570
|
anchor: String(e.anchor),
|
|
571
571
|
status: String(e.status),
|
|
572
572
|
createdBy: String(e.createdBy),
|
|
573
|
-
createdAt:
|
|
573
|
+
createdAt: J(e.createdAt),
|
|
574
574
|
comments: h.get(String(e.id)) ?? 0
|
|
575
575
|
}))
|
|
576
576
|
});
|
|
@@ -579,10 +579,10 @@ var L = A("_voltro_comment_threads", {
|
|
|
579
579
|
bindDataStore: (e) => {
|
|
580
580
|
o = e, s = e;
|
|
581
581
|
},
|
|
582
|
-
onActivate: (e) =>
|
|
582
|
+
onActivate: (e) => v.sync(() => {
|
|
583
583
|
i.access?.viaEntity === void 0 && i.access?.scope === void 0 && e.logger.warn("comments: no access rule declared — EVERY read and write will be refused (fail-closed). Set commentsPlugin({ access: { viaEntity } }) or { access: { scope } }."), e.logger.info("comments active", { mentions: i.resolveMentions !== void 0 });
|
|
584
584
|
}),
|
|
585
|
-
onDeactivate: () =>
|
|
585
|
+
onDeactivate: () => v.sync(() => {
|
|
586
586
|
o = void 0, s = void 0;
|
|
587
587
|
})
|
|
588
588
|
});
|
|
@@ -598,20 +598,20 @@ var L = A("_voltro_comment_threads", {
|
|
|
598
598
|
for (let [o, s] of Object.entries(t)) {
|
|
599
599
|
if (s === void 0 || !(s >= 0)) continue;
|
|
600
600
|
let t = n.getTime() - s * 864e5;
|
|
601
|
-
for (let c of await r("_voltro_comment_threads",
|
|
602
|
-
let o = [...await r("_voltro_comment_thread_events",
|
|
601
|
+
for (let c of await r("_voltro_comment_threads", b(S("status", "resolved"), S("kind", o)))) {
|
|
602
|
+
let o = [...await r("_voltro_comment_thread_events", S("threadId", String(c.id)))], l = (e) => new Date(e.at instanceof Date ? e.at : String(e.at)).getTime();
|
|
603
603
|
o.sort((e, t) => l(e) - l(t));
|
|
604
604
|
let u = [...o].reverse().find((e) => e.toStatus === "resolved" && e.fromStatus === "open");
|
|
605
605
|
if (u === void 0 || l(u) > t) continue;
|
|
606
|
-
let d = await r("_voltro_comments",
|
|
606
|
+
let d = await r("_voltro_comments", S("threadId", String(c.id)));
|
|
607
607
|
if (d.length !== 0) {
|
|
608
608
|
for (let t of d) {
|
|
609
|
-
for (let n of await r("_voltro_comment_reactions",
|
|
609
|
+
for (let n of await r("_voltro_comment_reactions", S("commentId", String(t.id)))) await e.delete("_voltro_comment_reactions", String(n.id));
|
|
610
610
|
await e.delete("_voltro_comments", String(t.id));
|
|
611
611
|
}
|
|
612
|
-
for (let t of await r("_voltro_comment_reads",
|
|
612
|
+
for (let t of await r("_voltro_comment_reads", S("threadId", String(c.id)))) await e.delete("_voltro_comment_reads", String(t.id));
|
|
613
613
|
await e.insert("_voltro_comment_thread_events", {
|
|
614
|
-
id:
|
|
614
|
+
id: C({
|
|
615
615
|
kind: "typeid",
|
|
616
616
|
prefix: "cmtevt"
|
|
617
617
|
}, "_voltro_comment_thread_events"),
|
|
@@ -631,5 +631,4 @@ var L = A("_voltro_comment_threads", {
|
|
|
631
631
|
comments: a
|
|
632
632
|
};
|
|
633
633
|
}, K = () => "plugin-comments";
|
|
634
|
-
//#endregion
|
|
635
634
|
export { c as COMMENT_THREAD_KINDS, e as CommentAccessRefused, t as CommentNotFound, n as CommentNotYours, r as CommentStatusRefused, i as QUOTE_MAX_LENGTH, G as applyCommentRetention, B as commentReactionsTable, V as commentReadsTable, z as commentThreadEventsTable, L as commentThreadsTable, l as commentsFeed, W as commentsPlugin, R as commentsTable, a as findQuote, K as pluginComments, o as textQuote };
|
package/dist/quote.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// src/quote.ts
|
|
2
2
|
var e = 1e3, t = (t, n, r) => {
|
|
3
3
|
let i = Math.max(0, Math.min(n, r)), a = Math.min(t.length, Math.max(n, r), i + e), o = t.slice(Math.max(0, i - 32), i), s = t.slice(a, a + 32);
|
|
4
4
|
return {
|
|
@@ -21,5 +21,4 @@ var e = 1e3, t = (t, n, r) => {
|
|
|
21
21
|
end: n.start + t.exact.length
|
|
22
22
|
};
|
|
23
23
|
};
|
|
24
|
-
//#endregion
|
|
25
24
|
export { e as QUOTE_MAX_LENGTH, n as findQuote, t as textQuote };
|