@voltro/plugin-chat 0.0.0-stage → 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.
Files changed (50) hide show
  1. package/CHANGELOG.md +24492 -0
  2. package/LICENSE +61 -0
  3. package/README.md +516 -2
  4. package/SECURITY.md +56 -0
  5. package/THIRD-PARTY-NOTICES.md +16105 -0
  6. package/dist/admissions.entity.js +10 -0
  7. package/dist/channels.entity.js +19 -0
  8. package/dist/chat-app/events/chat.mentioned.event.ts +1 -0
  9. package/dist/chat-app/events/chat.messageChanged.event.ts +1 -0
  10. package/dist/chat-app/events/chat.typing.event.ts +1 -0
  11. package/dist/chat-app/schedules/chat.retention.cron.tsx +16 -0
  12. package/dist/chat-app/subscribers/chat.messages.subscribe.ts +4 -0
  13. package/dist/components.js +431 -0
  14. package/dist/contract.js +91 -0
  15. package/dist/errors.d.ts +13 -0
  16. package/dist/errors.js +20 -0
  17. package/dist/eventProducer.d.ts +18 -0
  18. package/dist/eventProducer.js +45 -0
  19. package/dist/events.d.ts +38 -0
  20. package/dist/events.js +35 -0
  21. package/dist/evidence.entity.js +24 -0
  22. package/dist/index.d.ts +623 -0
  23. package/dist/index.js +180 -0
  24. package/dist/inspect.js +37 -0
  25. package/dist/media.entity.js +14 -0
  26. package/dist/members.entity.js +21 -0
  27. package/dist/mentionDraft.js +20 -0
  28. package/dist/mentionNotifications.js +109 -0
  29. package/dist/messages.entity.js +27 -0
  30. package/dist/reportEvidence.js +15 -0
  31. package/dist/retention.entity.js +10 -0
  32. package/dist/rpc.d.ts +295 -0
  33. package/dist/rpc.js +266 -0
  34. package/dist/rpcRoutes.js +96 -0
  35. package/dist/server.d.ts +200 -0
  36. package/dist/server.js +6 -0
  37. package/dist/service.js +1411 -0
  38. package/dist/strategies.d.ts +148 -0
  39. package/dist/strategies.js +89 -0
  40. package/dist/testing.d.ts +139 -0
  41. package/dist/testing.js +110 -0
  42. package/dist/typing.js +87 -0
  43. package/dist/typingInvalidation.js +85 -0
  44. package/dist/typingLease.js +58 -0
  45. package/dist/typingPublisher.js +58 -0
  46. package/dist/useChatTypingPublisher.js +32 -0
  47. package/dist/useTyping.js +23 -0
  48. package/dist/web.d.ts +354 -0
  49. package/dist/web.js +18 -0
  50. package/package.json +98 -4
@@ -0,0 +1,58 @@
1
+ import { CHAT_TYPING_TTL_MS as e, ChatTypingSchema as t } from "./contract.js";
2
+ import { Schema as n } from "effect";
3
+ var r = Object.freeze([]), i = class {
4
+ #e;
5
+ #t = /* @__PURE__ */ new Map();
6
+ #n = /* @__PURE__ */ new Set();
7
+ #r = r;
8
+ #i;
9
+ constructor(e) {
10
+ this.#e = e ?? {
11
+ wall: Date.now,
12
+ monotonic: () => performance.now(),
13
+ schedule: (e, t) => setTimeout(e, t),
14
+ cancel: (e) => clearTimeout(e)
15
+ };
16
+ }
17
+ getSnapshot = () => this.#r;
18
+ getServerSnapshot = () => r;
19
+ subscribe = (e) => (this.#n.add(e), () => {
20
+ this.#n.delete(e);
21
+ });
22
+ receive(r) {
23
+ if (!n.is(t)(r) || r.subjectId.includes("\0") || r.subjectId.startsWith("~")) return;
24
+ let i = this.#r;
25
+ if (this.#a(), !r.active) this.#t.delete(r.subjectId);
26
+ else {
27
+ let t = Math.min(e, r.expiresAt - this.#e.wall());
28
+ Number.isFinite(t) && t > 0 && (this.#t.has(r.subjectId) || this.#t.size < 128) && this.#t.set(r.subjectId, this.#e.monotonic() + t);
29
+ }
30
+ this.#o(i), this.#s();
31
+ }
32
+ clear = () => {
33
+ this.#i !== void 0 && this.#e.cancel(this.#i), this.#i = void 0, this.#t.clear(), this.#o();
34
+ };
35
+ #a() {
36
+ let e = this.#e.monotonic(), t = !1;
37
+ for (let [n, r] of this.#t) r <= e && (this.#t.delete(n), t = !0);
38
+ t && (this.#r = this.#t.size === 0 ? r : Object.freeze([...this.#t.keys()].sort()));
39
+ }
40
+ #o(e = this.#r) {
41
+ let t = [...this.#t.keys()].sort();
42
+ if (!(t.length === e.length && t.every((t, n) => t === e[n]))) {
43
+ this.#r = t.length === 0 ? r : Object.freeze(t);
44
+ for (let e of this.#n) e();
45
+ }
46
+ }
47
+ #s() {
48
+ if (this.#i !== void 0 && this.#e.cancel(this.#i), this.#i = void 0, this.#t.size === 0) return;
49
+ let e = Math.max(0, Math.min(...this.#t.values()) - this.#e.monotonic());
50
+ this.#i = this.#e.schedule(() => {
51
+ this.#i = void 0;
52
+ let e = this.#r;
53
+ if (this.#a(), e !== this.#r) for (let e of this.#n) e();
54
+ this.#s();
55
+ }, e);
56
+ }
57
+ };
58
+ export { i as TypingLeaseStore };
@@ -0,0 +1,58 @@
1
+ // src/typingPublisher.ts
2
+ var e = Object.freeze({
3
+ pending: !1,
4
+ error: void 0
5
+ }), t = class {
6
+ #e;
7
+ #t;
8
+ #n;
9
+ #r = /* @__PURE__ */ new Set();
10
+ #i;
11
+ #a = e;
12
+ #o = -Infinity;
13
+ #s = !1;
14
+ #c = !1;
15
+ constructor(e, t, n = () => performance.now()) {
16
+ this.#e = e, this.#t = t, this.#n = n;
17
+ }
18
+ getSnapshot = () => this.#a;
19
+ getServerSnapshot = () => e;
20
+ subscribe = (e) => (this.#r.add(e), () => {
21
+ this.#r.delete(e);
22
+ });
23
+ activate() {
24
+ this.#i === void 0 && (this.#i = new AbortController());
25
+ }
26
+ close = () => {
27
+ let e = this.#i;
28
+ this.#i = void 0, this.#c = !1, this.#s = !1, e?.abort();
29
+ };
30
+ activity = (e) => {
31
+ if (this.#i === void 0 || this.#i.signal.aborted) return !1;
32
+ if (!e) {
33
+ if (!this.#s) return !1;
34
+ if (this.#a.pending) return this.#c = !0, !1;
35
+ } else if (this.#n() < this.#o) return !1;
36
+ return this.#t.owner === void 0 && (this.#u(e, this.#i), !0);
37
+ };
38
+ #l(e) {
39
+ this.#a = e;
40
+ for (let e of this.#r) e();
41
+ }
42
+ #u(e, t) {
43
+ let n = {};
44
+ this.#t.owner = n, this.#c = !1, e ? (this.#o = this.#n() + 2e3, this.#s = !0) : this.#s = !1, this.#l({
45
+ pending: !0,
46
+ error: void 0
47
+ }), Promise.resolve().then(() => {
48
+ if (!t.signal.aborted) return this.#e(e, t.signal);
49
+ }).then(() => this.#d(t, n, void 0), (e) => this.#d(t, n, e));
50
+ }
51
+ #d(t, n, r) {
52
+ this.#t.owner === n && (this.#t.owner = void 0), this.#i === t ? (this.#l({
53
+ pending: !1,
54
+ error: r
55
+ }), this.#c && !t.signal.aborted && this.activity(!1)) : this.#l(e);
56
+ }
57
+ };
58
+ export { t as TypingPublisher };
@@ -0,0 +1,32 @@
1
+ import { BASE_NAME as e } from "./rpc.js";
2
+ import { TypingPublisher as t } from "./typingPublisher.js";
3
+ import { Effect as n } from "effect";
4
+ import { pluginTag as r } from "@voltro/protocol";
5
+ import { isUnresolvedApi as i, resolveByTag as a, useFrameworkApi as o } from "@voltro/client";
6
+ import { useLayoutEffect as s, useMemo as c, useRef as l, useSyncExternalStore as u } from "react";
7
+ import { runRpcPromise as d } from "@voltro/client/runtime";
8
+ // src/useChatTypingPublisher.ts
9
+ var f = (f, p = "app") => {
10
+ let m = o(p), h = l({ owner: void 0 }), g = c(() => new t(async (t, o) => {
11
+ if (f === null || i(m) || m.subjectSignal?.aborted) return;
12
+ let s = a(m.client, r(e, "setTyping"));
13
+ await d(m.runtime, n.suspend(() => s({
14
+ channelId: f,
15
+ active: t
16
+ })).pipe(n.timeout("1 second")), { signal: o });
17
+ }, h.current), [
18
+ f,
19
+ p,
20
+ m.cache
21
+ ]), _ = u(g.subscribe, g.getSnapshot, g.getServerSnapshot);
22
+ return s(() => {
23
+ let e = m.subjectSignal ?? m.recovery?.subjectSignal;
24
+ if (!(f === null || i(m) || e?.aborted)) return g.activate(), e?.addEventListener("abort", g.close, { once: !0 }), () => {
25
+ e?.removeEventListener("abort", g.close), g.close();
26
+ };
27
+ }, [g]), {
28
+ ..._,
29
+ activity: g.activity
30
+ };
31
+ };
32
+ export { f as useChatTypingPublisher };
@@ -0,0 +1,23 @@
1
+ import { typing as e } from "./events.js";
2
+ import { TypingLeaseStore as t } from "./typingLease.js";
3
+ import { useEvent as n, useFrameworkApi as r } from "@voltro/client";
4
+ import { useEffect as i, useLayoutEffect as a, useMemo as o, useSyncExternalStore as s } from "react";
5
+ // src/useTyping.ts
6
+ var c = Object.freeze([]), l = (l, u = "app") => {
7
+ let d = r(u), f = o(() => new t(), [
8
+ l,
9
+ u,
10
+ d.cache
11
+ ]), p = n(e, l === null ? null : { channelId: l }, (e) => f.receive(e), {
12
+ apiName: u,
13
+ onMissed: f.clear
14
+ }), m = s(f.subscribe, f.getSnapshot, f.getServerSnapshot);
15
+ return a(() => {
16
+ p.status !== "live" && f.clear();
17
+ }, [f, p.status]), i(() => () => f.clear(), [f]), {
18
+ channelId: l,
19
+ subjects: p.status === "live" ? m : c,
20
+ status: p.status
21
+ };
22
+ };
23
+ export { l as useTyping };
package/dist/web.d.ts ADDED
@@ -0,0 +1,354 @@
1
+ import { ActionState } from '@voltro/client';
2
+ import { EventStatus } from '@voltro/client';
3
+ import { ReactNode } from 'react';
4
+ import { Schema } from 'effect';
5
+ import { SubscriptionState } from '@voltro/client';
6
+
7
+ /** Native buttons are channel navigation; no incomplete ARIA tab keyboard model. */
8
+ export declare const ChannelTabs: ({ channels, selectedId, onSelect, unread, labels, disabled }: ChannelTabsProps) => ReactNode;
9
+
10
+ export declare interface ChannelTabsProps {
11
+ readonly channels: ReadonlyArray<ChatChannel>;
12
+ readonly selectedId: string | null;
13
+ readonly onSelect: (channelId: string) => void;
14
+ readonly unread?: ReadonlyArray<ChatUnread> | undefined;
15
+ readonly labels?: ChatLabels | undefined;
16
+ readonly disabled?: boolean | undefined;
17
+ }
18
+
19
+ /** Trusted identity comes from a server Players projection joined by subject ID. */
20
+ export declare interface ChatAuthor {
21
+ readonly subjectId: string;
22
+ readonly displayName: string;
23
+ }
24
+
25
+ export declare type ChatAuthorProjection = typeof ChatAuthorProjectionSchema.Type;
26
+
27
+ /** Roster-only identity; displayName already includes the Players tag. */
28
+ declare const ChatAuthorProjectionSchema: Schema.Struct<{
29
+ readonly subjectId: Schema.String;
30
+ readonly displayName: Schema.String;
31
+ readonly avatar: Schema.NullOr<Schema.String>;
32
+ }>;
33
+
34
+ declare type ChatChannel = typeof ChatChannelSchema.Type;
35
+
36
+ declare const ChatChannelSchema: Schema.Struct<{
37
+ readonly id: Schema.String;
38
+ readonly kind: Schema.Literals<readonly ["global", "lobby", "party", "guild", "match", "dm", "custom"]>;
39
+ readonly refId: Schema.String;
40
+ readonly name: Schema.String;
41
+ readonly slowModeMs: Schema.Number;
42
+ readonly retentionMs: Schema.NullOr<Schema.Number>;
43
+ readonly maxMembers: Schema.Number;
44
+ readonly frozen: Schema.Boolean;
45
+ readonly createdAt: Schema.Number;
46
+ readonly metadata: Schema.$Record<Schema.String, Schema.Unknown>;
47
+ }>;
48
+
49
+ export declare interface ChatLabels {
50
+ readonly title: string;
51
+ readonly empty: string;
52
+ readonly loading: string;
53
+ readonly failed: string;
54
+ readonly deleted: string;
55
+ readonly unknown: string;
56
+ readonly edited: string;
57
+ readonly flagged: string;
58
+ readonly draft: string;
59
+ readonly send: string;
60
+ readonly sending: string;
61
+ readonly older: string;
62
+ readonly report: string;
63
+ readonly unread: string;
64
+ readonly more: string;
65
+ readonly choose: string;
66
+ /** Optional so existing custom label sets keep compiling; English is the fallback. */
67
+ readonly media?: string;
68
+ readonly openMedia?: string;
69
+ }
70
+
71
+ export declare const chatLabels: Readonly<Record<'en' | 'de', ChatLabels>>;
72
+
73
+ export declare interface ChatMentionLabels {
74
+ readonly title: string;
75
+ readonly empty: string;
76
+ readonly loading: string;
77
+ readonly more: string;
78
+ readonly help: string;
79
+ }
80
+
81
+ export declare const chatMentionLabels: Readonly<Record<'en' | 'de', ChatMentionLabels>>;
82
+
83
+ declare type ChatMessage = typeof ChatMessageSchema.Type;
84
+
85
+ declare const ChatMessageSchema: Schema.Struct<{
86
+ readonly id: Schema.String;
87
+ readonly channelId: Schema.String;
88
+ readonly authorId: Schema.NullOr<Schema.String>;
89
+ readonly kind: Schema.Literals<readonly ["text", "emote", "system", "media"]>;
90
+ readonly body: Schema.String;
91
+ readonly payload: Schema.$Record<Schema.String, Schema.Unknown>;
92
+ readonly replyToId: Schema.NullOr<Schema.String>;
93
+ readonly editedAt: Schema.NullOr<Schema.Number>;
94
+ readonly deletedAt: Schema.NullOr<Schema.Number>;
95
+ readonly flagged: Schema.Boolean;
96
+ readonly createdAt: Schema.Number;
97
+ readonly version: Schema.Number;
98
+ readonly metadata: Schema.$Record<Schema.String, Schema.Unknown>;
99
+ }>;
100
+
101
+ export declare const ChatPanel: ({ scopeKey, dataScopeKey, channelId, messages, authors, labels, locale, loading, onReport, onOpenMedia, canLoadOlder, onLoadOlder, typing, typingLabels, ...composer }: ChatPanelProps) => ReactNode;
102
+
103
+ export declare interface ChatPanelProps extends MessageListProps, ComposerProps {
104
+ readonly scopeKey: string;
105
+ readonly dataScopeKey: string;
106
+ readonly channelId: string;
107
+ readonly typing?: ChatTypingState | undefined;
108
+ readonly typingLabels?: ChatTypingLabels | undefined;
109
+ readonly canLoadOlder?: boolean | undefined;
110
+ readonly onLoadOlder?: (() => void) | undefined;
111
+ }
112
+
113
+ export declare interface ChatTypingLabels {
114
+ readonly typing: string;
115
+ readonly peopleTyping: string;
116
+ readonly someoneTyping: string;
117
+ }
118
+
119
+ export declare const chatTypingLabels: Readonly<Record<'en' | 'de', ChatTypingLabels>>;
120
+
121
+ export declare interface ChatTypingPublisherState extends TypingPublisherSnapshot {
122
+ /** Call from actual input activity; false on blur/send. No active hint is queued. */
123
+ readonly activity: (active: boolean) => boolean;
124
+ }
125
+
126
+ export declare interface ChatTypingState {
127
+ readonly channelId: string | null;
128
+ readonly subjects: ReadonlyArray<string>;
129
+ readonly status: EventStatus;
130
+ }
131
+
132
+ declare type ChatUnread = typeof ChatUnreadSchema.Type;
133
+
134
+ declare const ChatUnreadSchema: Schema.Struct<{
135
+ readonly channelId: Schema.String;
136
+ readonly count: Schema.Number;
137
+ readonly truncated: Schema.Boolean;
138
+ }>;
139
+
140
+ /** Parent retains draft, request ID and uncertain send state; this component never retries or clears them. */
141
+ export declare const Composer: ({ value, onChange, onSend, onTyping, mentionCandidates, mentionLabels, mentionsLoading, onLoadMoreMentions, pending, disabled, error, labels, maxBodyLength }: ComposerProps) => ReactNode;
142
+
143
+ export declare interface ComposerProps {
144
+ readonly value: string;
145
+ readonly onChange: (body: string) => void;
146
+ readonly onSend: (body: string) => void;
147
+ readonly onTyping?: ((active: boolean) => void) | undefined;
148
+ readonly mentionCandidates?: ReadonlyArray<ChatAuthor> | undefined;
149
+ readonly mentionLabels?: ChatMentionLabels | undefined;
150
+ readonly mentionsLoading?: boolean | undefined;
151
+ readonly onLoadMoreMentions?: (() => void) | undefined;
152
+ readonly pending?: boolean | undefined;
153
+ readonly disabled?: boolean | undefined;
154
+ readonly error?: unknown | undefined;
155
+ readonly labels?: ChatLabels | undefined;
156
+ readonly maxBodyLength?: number | undefined;
157
+ }
158
+
159
+ declare interface DeleteChatInput {
160
+ readonly messageId: string;
161
+ readonly baseVersion: number;
162
+ }
163
+
164
+ declare interface EditChatInput {
165
+ readonly messageId: string;
166
+ readonly baseVersion: number;
167
+ readonly body: string;
168
+ }
169
+
170
+ /** Variable-height windowing preserves a focused row and does not move the reader on live updates. */
171
+ export declare const MessageList: ({ messages, authors, labels, locale, loading, onReport, onOpenMedia }: MessageListProps) => ReactNode;
172
+
173
+ export declare interface MessageListProps {
174
+ readonly messages: ReadonlyArray<ChatMessage>;
175
+ readonly authors: ReadonlyArray<ChatAuthor>;
176
+ readonly labels?: ChatLabels | undefined;
177
+ readonly locale?: string | undefined;
178
+ readonly loading?: boolean | undefined;
179
+ readonly onReport?: ((messageId: string) => void) | undefined;
180
+ /** Called for a visible media message; resolve its URL with `chat.mediaUrl` and show it. */
181
+ readonly onOpenMedia?: ((messageId: string) => void) | undefined;
182
+ }
183
+
184
+ /** `mediaId` names a `_voltro_storage_refs` row the sender uploaded; the body is then an optional caption. */
185
+ declare interface SendChatInput {
186
+ readonly channelId: string;
187
+ readonly requestId: string;
188
+ readonly body: string;
189
+ readonly replyToId?: string | undefined;
190
+ readonly mediaId?: string | undefined;
191
+ }
192
+
193
+ declare interface SetChatTypingInput {
194
+ readonly channelId: string;
195
+ readonly active: boolean;
196
+ }
197
+
198
+ /** Never display raw subject IDs or names supplied by a typing event. */
199
+ export declare const TypingIndicator: ({ subjects, authors, labels, locale }: TypingIndicatorProps) => ReactNode;
200
+
201
+ export declare interface TypingIndicatorProps {
202
+ readonly subjects: ReadonlyArray<string>;
203
+ readonly authors: ReadonlyArray<ChatAuthor>;
204
+ readonly labels?: ChatTypingLabels | undefined;
205
+ readonly locale?: string | undefined;
206
+ }
207
+
208
+ declare interface TypingPublisherSnapshot {
209
+ readonly pending: boolean;
210
+ readonly error: unknown | undefined;
211
+ }
212
+
213
+ export declare const useChannel: (channelId: string, apiName?: string) => SubscriptionState<{
214
+ readonly id: string;
215
+ readonly kind: "custom" | "match" | "global" | "lobby" | "party" | "guild" | "dm";
216
+ readonly refId: string;
217
+ readonly name: string;
218
+ readonly slowModeMs: number;
219
+ readonly retentionMs: number | null;
220
+ readonly maxMembers: number;
221
+ readonly frozen: boolean;
222
+ readonly createdAt: number;
223
+ readonly metadata: {
224
+ readonly [x: string]: unknown;
225
+ };
226
+ }>;
227
+
228
+ export declare const useChannelList: (apiName?: string) => SubscriptionState<readonly {
229
+ readonly id: string;
230
+ readonly kind: "custom" | "match" | "global" | "lobby" | "party" | "guild" | "dm";
231
+ readonly refId: string;
232
+ readonly name: string;
233
+ readonly slowModeMs: number;
234
+ readonly retentionMs: number | null;
235
+ readonly maxMembers: number;
236
+ readonly frozen: boolean;
237
+ readonly createdAt: number;
238
+ readonly metadata: {
239
+ readonly [x: string]: unknown;
240
+ };
241
+ }[]>;
242
+
243
+ export declare const useChatAuthors: (channelId: string, subjectIds: ReadonlyArray<string>, apiName?: string) => SubscriptionState<readonly {
244
+ readonly subjectId: string;
245
+ readonly displayName: string;
246
+ readonly avatar: string | null;
247
+ }[]>;
248
+
249
+ export declare const useChatEdit: (apiName?: string) => ActionState<EditChatInput, unknown>;
250
+
251
+ export declare const useChatJoin: (apiName?: string) => ActionState<{
252
+ channelId: string;
253
+ }, {
254
+ readonly id: string;
255
+ readonly channelId: string;
256
+ readonly subjectId: string;
257
+ readonly role: "member" | "owner" | "mod";
258
+ readonly mutedUntil: number | null;
259
+ readonly lastReadAt: number;
260
+ readonly lastReadId: string | null;
261
+ readonly notify: boolean;
262
+ readonly metadata: {
263
+ readonly [x: string]: unknown;
264
+ };
265
+ }>;
266
+
267
+ export declare const useChatLeave: (apiName?: string) => ActionState<{
268
+ channelId: string;
269
+ }, unknown>;
270
+
271
+ export declare const useChatMarkRead: (apiName?: string) => ActionState<{
272
+ channelId: string;
273
+ messageId: string;
274
+ }, unknown>;
275
+
276
+ export declare const useChatMembership: (channelId: string, apiName?: string) => SubscriptionState<{
277
+ readonly id: string;
278
+ readonly channelId: string;
279
+ readonly subjectId: string;
280
+ readonly role: "member" | "owner" | "mod";
281
+ readonly mutedUntil: number | null;
282
+ readonly lastReadAt: number;
283
+ readonly lastReadId: string | null;
284
+ readonly notify: boolean;
285
+ readonly metadata: {
286
+ readonly [x: string]: unknown;
287
+ };
288
+ }>;
289
+
290
+ export declare const useChatMentionCandidates: (channelId: string, after?: string, apiName?: string) => SubscriptionState<{
291
+ readonly authors: readonly {
292
+ readonly subjectId: string;
293
+ readonly displayName: string;
294
+ readonly avatar: string | null;
295
+ }[];
296
+ readonly after: string | null;
297
+ }>;
298
+
299
+ export declare const useChatMessages: (channelId: string, before?: {
300
+ at: number;
301
+ id: string;
302
+ }, apiName?: string) => SubscriptionState<{
303
+ readonly messages: readonly {
304
+ readonly id: string;
305
+ readonly channelId: string;
306
+ readonly authorId: string | null;
307
+ readonly kind: "text" | "system" | "emote" | "media";
308
+ readonly body: string;
309
+ readonly payload: {
310
+ readonly [x: string]: unknown;
311
+ };
312
+ readonly replyToId: string | null;
313
+ readonly editedAt: number | null;
314
+ readonly deletedAt: number | null;
315
+ readonly flagged: boolean;
316
+ readonly createdAt: number;
317
+ readonly version: number;
318
+ readonly metadata: {
319
+ readonly [x: string]: unknown;
320
+ };
321
+ }[];
322
+ readonly before: {
323
+ readonly at: number;
324
+ readonly id: string;
325
+ } | null;
326
+ }>;
327
+
328
+ export declare const useChatOriginal: (apiName?: string) => ActionState<{
329
+ messageId: string;
330
+ }, unknown>;
331
+
332
+ export declare const useChatRemove: (apiName?: string) => ActionState<DeleteChatInput, unknown>;
333
+
334
+ export declare const useChatSend: (apiName?: string) => ActionState<SendChatInput, unknown>;
335
+
336
+ export declare const useChatSetTyping: (apiName?: string) => ActionState<SetChatTypingInput, unknown>;
337
+
338
+ export declare const useChatTransferOwnership: (apiName?: string) => ActionState<{
339
+ channelId: string;
340
+ targetId: string;
341
+ }, unknown>;
342
+
343
+ export declare const useChatTypingPublisher: (channelId: string | null, apiName?: string) => ChatTypingPublisherState;
344
+
345
+ /** Private hints expire within five local monotonic seconds; never persisted. */
346
+ export declare const useTyping: (channelId: string | null, apiName?: string) => ChatTypingState;
347
+
348
+ export declare const useUnread: (apiName?: string) => SubscriptionState<readonly {
349
+ readonly channelId: string;
350
+ readonly count: number;
351
+ readonly truncated: boolean;
352
+ }[]>;
353
+
354
+ export { }
package/dist/web.js ADDED
@@ -0,0 +1,18 @@
1
+ import { BASE_NAME as e } from "./rpc.js";
2
+ import { ChannelTabs as t, ChatPanel as n, Composer as r, MessageList as i, TypingIndicator as a, chatLabels as o, chatMentionLabels as s, chatTypingLabels as c } from "./components.js";
3
+ import { useTyping as l } from "./useTyping.js";
4
+ import { useChatTypingPublisher as u } from "./useChatTypingPublisher.js";
5
+ import { pluginTag as d } from "@voltro/protocol";
6
+ import { useAction as f, useSubscription as p } from "@voltro/client";
7
+ // src/web.ts
8
+ var m = (t, n, r = "app") => p(r, d(e, "mentionCandidates"), {
9
+ channelId: t,
10
+ ...n === void 0 ? {} : { after: n }
11
+ }), h = (t, n, r = "app") => p(r, d(e, "authors"), {
12
+ channelId: t,
13
+ subjectIds: n
14
+ }), g = (t, n = "app") => p(n, d(e, "channel"), { channelId: t }), _ = (t, n = "app") => p(n, d(e, "membership"), { channelId: t }), v = (t = "app") => p(t, d(e, "channels"), {}), y = (t, n, r = "app") => p(r, d(e, "messages"), {
15
+ channelId: t,
16
+ ...n === void 0 ? {} : { before: n }
17
+ }), b = (t = "app") => f(t, d(e, "send")), x = (t = "app") => f(t, d(e, "edit")), S = (t = "app") => f(t, d(e, "remove")), C = (t = "app") => p(t, d(e, "unread"), {}), w = (t = "app") => f(t, d(e, "markRead")), T = (t = "app") => f(t, d(e, "original")), E = (t = "app") => f(t, d(e, "join")), D = (t = "app") => f(t, d(e, "leave")), O = (t = "app") => f(t, d(e, "transferOwnership")), k = (t = "app") => f(t, d(e, "setTyping"));
18
+ export { t as ChannelTabs, n as ChatPanel, r as Composer, i as MessageList, a as TypingIndicator, o as chatLabels, s as chatMentionLabels, c as chatTypingLabels, g as useChannel, v as useChannelList, h as useChatAuthors, x as useChatEdit, E as useChatJoin, D as useChatLeave, w as useChatMarkRead, _ as useChatMembership, m as useChatMentionCandidates, y as useChatMessages, T as useChatOriginal, S as useChatRemove, b as useChatSend, k as useChatSetTyping, O as useChatTransferOwnership, u as useChatTypingPublisher, l as useTyping, C as useUnread };
package/package.json CHANGED
@@ -1,6 +1,100 @@
1
1
  {
2
2
  "name": "@voltro/plugin-chat",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.88.0",
4
+ "description": "Membership-filtered durable chat with configurable moderation, rate and retention strategies",
5
+ "keywords": [
6
+ "voltro",
7
+ "typescript",
8
+ "framework"
9
+ ],
10
+ "license": "SEE LICENSE IN LICENSE",
11
+ "homepage": "https://voltro.dev",
12
+ "bugs": {
13
+ "email": "support@voltro.dev"
14
+ },
15
+ "author": {
16
+ "name": "Voltro UG",
17
+ "url": "https://voltro.dev"
18
+ },
19
+ "type": "module",
20
+ "exports": {
21
+ ".": {
22
+ "types": "./dist/index.d.ts",
23
+ "import": "./dist/index.js",
24
+ "default": "./dist/index.js"
25
+ },
26
+ "./package.json": "./package.json",
27
+ "./errors": {
28
+ "types": "./dist/errors.d.ts",
29
+ "import": "./dist/errors.js",
30
+ "default": "./dist/errors.js"
31
+ },
32
+ "./rpc": {
33
+ "types": "./dist/rpc.d.ts",
34
+ "import": "./dist/rpc.js",
35
+ "default": "./dist/rpc.js"
36
+ },
37
+ "./strategies": {
38
+ "types": "./dist/strategies.d.ts",
39
+ "import": "./dist/strategies.js",
40
+ "default": "./dist/strategies.js"
41
+ },
42
+ "./testing": {
43
+ "types": "./dist/testing.d.ts",
44
+ "import": "./dist/testing.js",
45
+ "default": "./dist/testing.js"
46
+ },
47
+ "./web": {
48
+ "types": "./dist/web.d.ts",
49
+ "import": "./dist/web.js",
50
+ "default": "./dist/web.js"
51
+ },
52
+ "./events": {
53
+ "types": "./dist/events.d.ts",
54
+ "import": "./dist/events.js",
55
+ "default": "./dist/events.js"
56
+ },
57
+ "./events/server": {
58
+ "types": "./dist/eventProducer.d.ts",
59
+ "import": "./dist/eventProducer.js",
60
+ "default": "./dist/eventProducer.js"
61
+ },
62
+ "./server": {
63
+ "types": "./dist/server.d.ts",
64
+ "import": "./dist/server.js",
65
+ "default": "./dist/server.js"
66
+ }
67
+ },
68
+ "main": "./dist/index.js",
69
+ "module": "./dist/index.js",
70
+ "types": "./dist/index.d.ts",
71
+ "sideEffects": false,
72
+ "engines": {
73
+ "node": ">=24.0.0"
74
+ },
75
+ "dependencies": {
76
+ "@voltro/protocol": "0.88.0",
77
+ "@voltro/database": "0.88.0",
78
+ "@voltro/client": "0.88.0",
79
+ "@voltro/runtime": "0.88.0",
80
+ "@voltro/plugin-ratelimit": "0.88.0",
81
+ "@voltro/plugin-moderation": "0.88.0",
82
+ "@voltro/plugin-social": "0.88.0",
83
+ "@voltro/plugin-players": "0.88.0",
84
+ "@voltro/plugin-notifications": "0.88.0",
85
+ "@voltro/kv": "0.88.0",
86
+ "@voltro/ui-shadcn": "0.88.0",
87
+ "@voltro/plugin-sanctions": "0.88.0",
88
+ "@voltro/plugin-licensing": "0.88.0",
89
+ "@voltro/plugin-storage": "0.88.0",
90
+ "@voltro/plugin-guilds": "0.88.0",
91
+ "@voltro/plugin-matchmaking": "0.88.0"
92
+ },
93
+ "peerDependencies": {
94
+ "effect": "4.1.0",
95
+ "react": "^19.0.0"
96
+ },
97
+ "publishConfig": {
98
+ "access": "public"
99
+ }
100
+ }