@voltro/plugin-comments 0.85.0 → 0.87.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/quote.js ADDED
@@ -0,0 +1,25 @@
1
+ //#region src/quote.ts
2
+ var e = 1e3, t = (t, n, r) => {
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
+ return {
5
+ exact: t.slice(i, a),
6
+ ...o === "" ? {} : { prefix: o },
7
+ ...s === "" ? {} : { suffix: s }
8
+ };
9
+ }, n = (e, t) => {
10
+ if (t.exact === "") return null;
11
+ let n = null;
12
+ for (let r = e.indexOf(t.exact); r !== -1; r = e.indexOf(t.exact, r + 1)) {
13
+ let i = e.slice(0, r), a = e.slice(r + t.exact.length), o = (t.prefix !== void 0 && i.endsWith(t.prefix) ? 1 : 0) + (t.suffix !== void 0 && a.startsWith(t.suffix) ? 1 : 0);
14
+ (n === null || o > n.score) && (n = {
15
+ start: r,
16
+ score: o
17
+ });
18
+ }
19
+ return n === null ? null : {
20
+ start: n.start,
21
+ end: n.start + t.exact.length
22
+ };
23
+ };
24
+ //#endregion
25
+ export { e as QUOTE_MAX_LENGTH, n as findQuote, t as textQuote };
package/dist/rpc.js CHANGED
@@ -1,2 +1,194 @@
1
- import { a as e, c as t, d as n, f as r, i, l as a, n as o, o as s, r as c, s as l, t as u, u as d } from "./rpc-BTQBcdhT.js";
2
- export { u as BASE_NAME, o as COMMENT_THREAD_KINDS, c as commentsFeed, i as commentsRpcClientImports, e as createDescriptor, s as deleteDescriptor, l as editDescriptor, t as listDescriptor, a as markReadDescriptor, d as mentionSearchDescriptor, n as reactDescriptor, r as resolveDescriptor };
1
+ import { CommentAccessRefused as e, CommentNotFound as t, CommentNotYours as n, CommentStatusRefused as r } from "./errors.js";
2
+ import { QUOTE_MAX_LENGTH as i } from "./quote.js";
3
+ import { Schema as a } from "effect";
4
+ import { defineMutation as o, defineQuery as s, reactivityChannel as c } from "@voltro/protocol";
5
+ //#region src/rpc.ts
6
+ var l = "@voltro/plugin-comments", u = c("comments"), d = a.Struct({
7
+ id: a.String,
8
+ threadId: a.String,
9
+ body: a.String,
10
+ authorSubjectId: a.String,
11
+ mentions: a.Array(a.String),
12
+ editedAt: a.NullOr(a.String),
13
+ createdAt: a.String,
14
+ reactions: a.Array(a.Struct({
15
+ emoji: a.String,
16
+ count: a.Number,
17
+ mine: a.Boolean
18
+ }))
19
+ }), f = a.Struct({
20
+ exact: a.String.pipe(a.check(a.isMinLength(1)), a.check(a.isMaxLength(i))),
21
+ prefix: a.optional(a.String.pipe(a.check(a.isMaxLength(32)))),
22
+ suffix: a.optional(a.String.pipe(a.check(a.isMaxLength(32))))
23
+ }), p = [
24
+ "discussion",
25
+ "note",
26
+ "review"
27
+ ], m = a.Literals(p), h = a.Struct({
28
+ from: a.NullOr(a.Literals(["open", "resolved"])),
29
+ to: a.Literals(["open", "resolved"]),
30
+ by: a.String,
31
+ at: a.String,
32
+ reason: a.NullOr(a.String)
33
+ }), g = a.Struct({
34
+ id: a.String,
35
+ anchor: a.String,
36
+ kind: m,
37
+ quote: a.NullOr(f),
38
+ status: a.Literals(["open", "resolved"]),
39
+ createdBy: a.String,
40
+ createdAt: a.String,
41
+ comments: a.Array(d),
42
+ unreadCount: a.Number,
43
+ history: a.Array(h)
44
+ }), _ = s({
45
+ name: "comments.list",
46
+ source: u,
47
+ input: a.Struct({ anchor: a.String }),
48
+ output: a.Array(g),
49
+ error: e,
50
+ openAccess: "delegated: the executor runs the app-declared anchor access rule (viaEntity guard or scope) and is fail-closed — an undeclared rule refuses every read"
51
+ }), v = o({
52
+ name: "comments.create",
53
+ input: a.Struct({
54
+ anchor: a.String,
55
+ body: a.String,
56
+ threadId: a.optional(a.String),
57
+ mentions: a.optional(a.Array(a.String)),
58
+ quote: a.optional(f),
59
+ kind: a.optional(m)
60
+ }),
61
+ output: a.Struct({
62
+ threadId: a.String,
63
+ commentId: a.String
64
+ }),
65
+ error: a.Union([e, t]),
66
+ openAccess: "delegated: the executor runs the app-declared anchor access rule before any write; the author is always the calling subject"
67
+ }), y = o({
68
+ name: "comments.edit",
69
+ input: a.Struct({
70
+ commentId: a.String,
71
+ body: a.String
72
+ }),
73
+ output: a.Struct({ ok: a.Boolean }),
74
+ error: a.Union([
75
+ e,
76
+ t,
77
+ n
78
+ ]),
79
+ openAccess: "author-scoped: only the comment's own author may edit, checked in the executor on top of the anchor access rule"
80
+ }), b = o({
81
+ name: "comments.resolve",
82
+ input: a.Struct({
83
+ threadId: a.String,
84
+ resolved: a.Boolean,
85
+ reason: a.optional(a.String.pipe(a.check(a.isMaxLength(500))))
86
+ }),
87
+ output: a.Struct({ ok: a.Boolean }),
88
+ error: a.Union([
89
+ e,
90
+ t,
91
+ r
92
+ ]),
93
+ openAccess: "delegated: anchor access rule in the executor, then the app's optional status policy — without one, anyone who may read the anchor may resolve/reopen (the Liveblocks semantic); every change is recorded"
94
+ }), x = o({
95
+ name: "comments.delete",
96
+ input: a.Struct({ commentId: a.String }),
97
+ output: a.Struct({ ok: a.Boolean }),
98
+ error: a.Union([
99
+ e,
100
+ t,
101
+ n
102
+ ]),
103
+ openAccess: "author-scoped, with a comments:moderate scope override — both checked in the executor on top of the anchor access rule"
104
+ }), S = o({
105
+ name: "comments.react",
106
+ input: a.Struct({
107
+ commentId: a.String,
108
+ emoji: a.String
109
+ }),
110
+ output: a.Struct({ reacted: a.Boolean }),
111
+ error: a.Union([e, t]),
112
+ openAccess: "delegated: anchor access rule in the executor; the toggle writes only the calling subject's own reaction row"
113
+ }), C = o({
114
+ name: "comments.markRead",
115
+ input: a.Struct({ threadId: a.String }),
116
+ output: a.Struct({ ok: a.Boolean }),
117
+ error: t,
118
+ openAccess: "self-scoped write: stamps only the calling subject's own read marker for the thread"
119
+ }), w = s({
120
+ name: "comments.mentionSearch",
121
+ input: a.Struct({ query: a.String }),
122
+ output: a.Array(a.Struct({
123
+ subjectId: a.String,
124
+ label: a.String
125
+ })),
126
+ openAccess: "delegated: the app-declared mention resolver receives the CALLING subject and its default filters to the caller's tenant — cross-tenant subjects are structurally unreachable"
127
+ }), T = [
128
+ {
129
+ tag: "comments.list",
130
+ kind: "query",
131
+ import: {
132
+ module: "@voltro/plugin-comments/rpc",
133
+ name: "listDescriptor"
134
+ }
135
+ },
136
+ {
137
+ tag: "comments.create",
138
+ kind: "mutation",
139
+ import: {
140
+ module: "@voltro/plugin-comments/rpc",
141
+ name: "createDescriptor"
142
+ }
143
+ },
144
+ {
145
+ tag: "comments.edit",
146
+ kind: "mutation",
147
+ import: {
148
+ module: "@voltro/plugin-comments/rpc",
149
+ name: "editDescriptor"
150
+ }
151
+ },
152
+ {
153
+ tag: "comments.resolve",
154
+ kind: "mutation",
155
+ import: {
156
+ module: "@voltro/plugin-comments/rpc",
157
+ name: "resolveDescriptor"
158
+ }
159
+ },
160
+ {
161
+ tag: "comments.delete",
162
+ kind: "mutation",
163
+ import: {
164
+ module: "@voltro/plugin-comments/rpc",
165
+ name: "deleteDescriptor"
166
+ }
167
+ },
168
+ {
169
+ tag: "comments.react",
170
+ kind: "mutation",
171
+ import: {
172
+ module: "@voltro/plugin-comments/rpc",
173
+ name: "reactDescriptor"
174
+ }
175
+ },
176
+ {
177
+ tag: "comments.markRead",
178
+ kind: "mutation",
179
+ import: {
180
+ module: "@voltro/plugin-comments/rpc",
181
+ name: "markReadDescriptor"
182
+ }
183
+ },
184
+ {
185
+ tag: "comments.mentionSearch",
186
+ kind: "query",
187
+ import: {
188
+ module: "@voltro/plugin-comments/rpc",
189
+ name: "mentionSearchDescriptor"
190
+ }
191
+ }
192
+ ];
193
+ //#endregion
194
+ export { l as BASE_NAME, p as COMMENT_THREAD_KINDS, u as commentsFeed, T as commentsRpcClientImports, v as createDescriptor, x as deleteDescriptor, y as editDescriptor, _ as listDescriptor, C as markReadDescriptor, w as mentionSearchDescriptor, S as reactDescriptor, b as resolveDescriptor };
package/dist/web.js CHANGED
@@ -1,8 +1,9 @@
1
- import { h as e, m as t, n, p as r, t as i } from "./rpc-BTQBcdhT.js";
1
+ import { QUOTE_MAX_LENGTH as e, findQuote as t, textQuote as n } from "./quote.js";
2
+ import { BASE_NAME as r, COMMENT_THREAD_KINDS as i } from "./rpc.js";
2
3
  import { pluginTag as a } from "@voltro/protocol";
3
4
  import { useMutation as o, useSubscription as s } from "@voltro/client";
4
5
  //#region src/web.ts
5
- var c = (e) => a(i, e), l = (e, t = "app") => {
6
+ var c = (e) => a(r, e), l = (e, t = "app") => {
6
7
  let { data: n, loading: r } = s(t, c("list"), { anchor: e }), i = o(t, c("create")), a = o(t, c("edit")), l = o(t, c("resolve")), u = o(t, c("delete")), d = o(t, c("react")), f = o(t, c("markRead")), p = n ?? [];
7
8
  return {
8
9
  threads: p,
@@ -37,4 +38,4 @@ var c = (e) => a(i, e), l = (e, t = "app") => {
37
38
  return n ?? [];
38
39
  };
39
40
  //#endregion
40
- export { n as COMMENT_THREAD_KINDS, r as QUOTE_MAX_LENGTH, t as findQuote, e as textQuote, l as useComments, d as useMentionSearch, u as useThread };
41
+ export { i as COMMENT_THREAD_KINDS, e as QUOTE_MAX_LENGTH, t as findQuote, n as textQuote, l as useComments, d as useMentionSearch, u as useThread };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voltro/plugin-comments",
3
- "version": "0.85.0",
3
+ "version": "0.87.0",
4
4
  "description": "Comment threads on any anchor your app can name — replies, resolve/reopen, reactions, per-subject unread — live over the existing reactivity channel, with no second push mechanism. Access delegates to your app's own guard (access.viaEntity) or a scope and fails closed when neither is declared; @-mentions are re-filtered to the caller's tenant on search and re-validated at create, then delivered through plugin-notifications when it is installed. useComments / useThread / useMentionSearch in /web, an ejectable <CommentsThread> in @voltro/ui, plus inspect endpoints and a dashboard panel.",
5
5
  "keywords": [
6
6
  "voltro",
@@ -48,10 +48,10 @@
48
48
  "node": ">=24.0.0"
49
49
  },
50
50
  "dependencies": {
51
- "@voltro/client": "0.85.0",
52
- "@voltro/database": "0.85.0",
53
- "@voltro/plugin-notifications": "0.85.0",
54
- "@voltro/protocol": "0.85.0"
51
+ "@voltro/client": "0.87.0",
52
+ "@voltro/database": "0.87.0",
53
+ "@voltro/plugin-notifications": "0.87.0",
54
+ "@voltro/protocol": "0.87.0"
55
55
  },
56
56
  "peerDependencies": {
57
57
  "effect": "4.0.1",
@@ -1,214 +0,0 @@
1
- import { CommentAccessRefused as e, CommentNotFound as t, CommentNotYours as n, CommentStatusRefused as r } from "./errors.js";
2
- import { Schema as i } from "effect";
3
- import { defineMutation as a, defineQuery as o, reactivityChannel as s } from "@voltro/protocol";
4
- //#region src/quote.ts
5
- var c = 1e3, l = 32, u = (e, t, n) => {
6
- let r = Math.max(0, Math.min(t, n)), i = Math.min(e.length, Math.max(t, n), r + c), a = e.slice(Math.max(0, r - l), r), o = e.slice(i, i + l);
7
- return {
8
- exact: e.slice(r, i),
9
- ...a === "" ? {} : { prefix: a },
10
- ...o === "" ? {} : { suffix: o }
11
- };
12
- }, d = (e, t) => {
13
- if (t.exact === "") return null;
14
- let n = null;
15
- for (let r = e.indexOf(t.exact); r !== -1; r = e.indexOf(t.exact, r + 1)) {
16
- let i = e.slice(0, r), a = e.slice(r + t.exact.length), o = (t.prefix !== void 0 && i.endsWith(t.prefix) ? 1 : 0) + (t.suffix !== void 0 && a.startsWith(t.suffix) ? 1 : 0);
17
- (n === null || o > n.score) && (n = {
18
- start: r,
19
- score: o
20
- });
21
- }
22
- return n === null ? null : {
23
- start: n.start,
24
- end: n.start + t.exact.length
25
- };
26
- }, f = "@voltro/plugin-comments", p = s("comments"), m = i.Struct({
27
- id: i.String,
28
- threadId: i.String,
29
- body: i.String,
30
- authorSubjectId: i.String,
31
- mentions: i.Array(i.String),
32
- editedAt: i.NullOr(i.String),
33
- createdAt: i.String,
34
- reactions: i.Array(i.Struct({
35
- emoji: i.String,
36
- count: i.Number,
37
- mine: i.Boolean
38
- }))
39
- }), h = i.Struct({
40
- exact: i.String.pipe(i.check(i.isMinLength(1)), i.check(i.isMaxLength(c))),
41
- prefix: i.optional(i.String.pipe(i.check(i.isMaxLength(32)))),
42
- suffix: i.optional(i.String.pipe(i.check(i.isMaxLength(32))))
43
- }), g = [
44
- "discussion",
45
- "note",
46
- "review"
47
- ], _ = i.Literals(g), v = i.Struct({
48
- from: i.NullOr(i.Literals(["open", "resolved"])),
49
- to: i.Literals(["open", "resolved"]),
50
- by: i.String,
51
- at: i.String,
52
- reason: i.NullOr(i.String)
53
- }), y = i.Struct({
54
- id: i.String,
55
- anchor: i.String,
56
- kind: _,
57
- quote: i.NullOr(h),
58
- status: i.Literals(["open", "resolved"]),
59
- createdBy: i.String,
60
- createdAt: i.String,
61
- comments: i.Array(m),
62
- unreadCount: i.Number,
63
- history: i.Array(v)
64
- }), b = o({
65
- name: "comments.list",
66
- source: p,
67
- input: i.Struct({ anchor: i.String }),
68
- output: i.Array(y),
69
- error: e,
70
- openAccess: "delegated: the executor runs the app-declared anchor access rule (viaEntity guard or scope) and is fail-closed — an undeclared rule refuses every read"
71
- }), x = a({
72
- name: "comments.create",
73
- input: i.Struct({
74
- anchor: i.String,
75
- body: i.String,
76
- threadId: i.optional(i.String),
77
- mentions: i.optional(i.Array(i.String)),
78
- quote: i.optional(h),
79
- kind: i.optional(_)
80
- }),
81
- output: i.Struct({
82
- threadId: i.String,
83
- commentId: i.String
84
- }),
85
- error: i.Union([e, t]),
86
- openAccess: "delegated: the executor runs the app-declared anchor access rule before any write; the author is always the calling subject"
87
- }), S = a({
88
- name: "comments.edit",
89
- input: i.Struct({
90
- commentId: i.String,
91
- body: i.String
92
- }),
93
- output: i.Struct({ ok: i.Boolean }),
94
- error: i.Union([
95
- e,
96
- t,
97
- n
98
- ]),
99
- openAccess: "author-scoped: only the comment's own author may edit, checked in the executor on top of the anchor access rule"
100
- }), C = a({
101
- name: "comments.resolve",
102
- input: i.Struct({
103
- threadId: i.String,
104
- resolved: i.Boolean,
105
- reason: i.optional(i.String.pipe(i.check(i.isMaxLength(500))))
106
- }),
107
- output: i.Struct({ ok: i.Boolean }),
108
- error: i.Union([
109
- e,
110
- t,
111
- r
112
- ]),
113
- openAccess: "delegated: anchor access rule in the executor, then the app's optional status policy — without one, anyone who may read the anchor may resolve/reopen (the Liveblocks semantic); every change is recorded"
114
- }), w = a({
115
- name: "comments.delete",
116
- input: i.Struct({ commentId: i.String }),
117
- output: i.Struct({ ok: i.Boolean }),
118
- error: i.Union([
119
- e,
120
- t,
121
- n
122
- ]),
123
- openAccess: "author-scoped, with a comments:moderate scope override — both checked in the executor on top of the anchor access rule"
124
- }), T = a({
125
- name: "comments.react",
126
- input: i.Struct({
127
- commentId: i.String,
128
- emoji: i.String
129
- }),
130
- output: i.Struct({ reacted: i.Boolean }),
131
- error: i.Union([e, t]),
132
- openAccess: "delegated: anchor access rule in the executor; the toggle writes only the calling subject's own reaction row"
133
- }), E = a({
134
- name: "comments.markRead",
135
- input: i.Struct({ threadId: i.String }),
136
- output: i.Struct({ ok: i.Boolean }),
137
- error: t,
138
- openAccess: "self-scoped write: stamps only the calling subject's own read marker for the thread"
139
- }), D = o({
140
- name: "comments.mentionSearch",
141
- input: i.Struct({ query: i.String }),
142
- output: i.Array(i.Struct({
143
- subjectId: i.String,
144
- label: i.String
145
- })),
146
- openAccess: "delegated: the app-declared mention resolver receives the CALLING subject and its default filters to the caller's tenant — cross-tenant subjects are structurally unreachable"
147
- }), O = [
148
- {
149
- tag: "comments.list",
150
- kind: "query",
151
- import: {
152
- module: "@voltro/plugin-comments/rpc",
153
- name: "listDescriptor"
154
- }
155
- },
156
- {
157
- tag: "comments.create",
158
- kind: "mutation",
159
- import: {
160
- module: "@voltro/plugin-comments/rpc",
161
- name: "createDescriptor"
162
- }
163
- },
164
- {
165
- tag: "comments.edit",
166
- kind: "mutation",
167
- import: {
168
- module: "@voltro/plugin-comments/rpc",
169
- name: "editDescriptor"
170
- }
171
- },
172
- {
173
- tag: "comments.resolve",
174
- kind: "mutation",
175
- import: {
176
- module: "@voltro/plugin-comments/rpc",
177
- name: "resolveDescriptor"
178
- }
179
- },
180
- {
181
- tag: "comments.delete",
182
- kind: "mutation",
183
- import: {
184
- module: "@voltro/plugin-comments/rpc",
185
- name: "deleteDescriptor"
186
- }
187
- },
188
- {
189
- tag: "comments.react",
190
- kind: "mutation",
191
- import: {
192
- module: "@voltro/plugin-comments/rpc",
193
- name: "reactDescriptor"
194
- }
195
- },
196
- {
197
- tag: "comments.markRead",
198
- kind: "mutation",
199
- import: {
200
- module: "@voltro/plugin-comments/rpc",
201
- name: "markReadDescriptor"
202
- }
203
- },
204
- {
205
- tag: "comments.mentionSearch",
206
- kind: "query",
207
- import: {
208
- module: "@voltro/plugin-comments/rpc",
209
- name: "mentionSearchDescriptor"
210
- }
211
- }
212
- ];
213
- //#endregion
214
- export { x as a, b as c, T as d, C as f, u as h, O as i, E as l, d as m, g as n, w as o, c as p, p as r, S as s, f as t, D as u };