@voltro/plugin-chat 0.0.0-stage → 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.
Files changed (50) hide show
  1. package/CHANGELOG.md +24329 -0
  2. package/LICENSE +61 -0
  3. package/README.md +516 -2
  4. package/SECURITY.md +56 -0
  5. package/THIRD-PARTY-NOTICES.md +14931 -0
  6. package/dist/admissions.entity.js +11 -0
  7. package/dist/channels.entity.js +20 -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 +432 -0
  14. package/dist/contract.js +92 -0
  15. package/dist/errors.d.ts +13 -0
  16. package/dist/errors.js +21 -0
  17. package/dist/eventProducer.d.ts +18 -0
  18. package/dist/eventProducer.js +46 -0
  19. package/dist/events.d.ts +38 -0
  20. package/dist/events.js +36 -0
  21. package/dist/evidence.entity.js +25 -0
  22. package/dist/index.d.ts +623 -0
  23. package/dist/index.js +181 -0
  24. package/dist/inspect.js +38 -0
  25. package/dist/media.entity.js +15 -0
  26. package/dist/members.entity.js +22 -0
  27. package/dist/mentionDraft.js +21 -0
  28. package/dist/mentionNotifications.js +110 -0
  29. package/dist/messages.entity.js +28 -0
  30. package/dist/reportEvidence.js +16 -0
  31. package/dist/retention.entity.js +11 -0
  32. package/dist/rpc.d.ts +295 -0
  33. package/dist/rpc.js +267 -0
  34. package/dist/rpcRoutes.js +97 -0
  35. package/dist/server.d.ts +200 -0
  36. package/dist/server.js +7 -0
  37. package/dist/service.js +1412 -0
  38. package/dist/strategies.d.ts +148 -0
  39. package/dist/strategies.js +90 -0
  40. package/dist/testing.d.ts +139 -0
  41. package/dist/testing.js +111 -0
  42. package/dist/typing.js +88 -0
  43. package/dist/typingInvalidation.js +86 -0
  44. package/dist/typingLease.js +59 -0
  45. package/dist/typingPublisher.js +59 -0
  46. package/dist/useChatTypingPublisher.js +33 -0
  47. package/dist/useTyping.js +24 -0
  48. package/dist/web.d.ts +354 -0
  49. package/dist/web.js +19 -0
  50. package/package.json +98 -4
@@ -0,0 +1,46 @@
1
+ import "./contract.js";
2
+ import { mentioned as e, messageChanged as t } from "./events.js";
3
+ //#region src/eventProducer.ts
4
+ var n = (e) => {
5
+ if (e.table !== "_voltro_chat_messages") throw Error("Chat events require the owned message table");
6
+ let t = (e.op === "delete" ? e.old : e.new)?.tenantId;
7
+ if (typeof t != "string" || !t.trim() || t.length > 256 || t.includes("\0") || t === "~" || e.op === "update" && e.old?.tenantId !== t) throw Error("Chat events require stable committed tenant evidence");
8
+ return t;
9
+ }, r = async (r, a) => {
10
+ n(r);
11
+ let o = r.op === "delete" ? r.old : r.new;
12
+ if (!o || typeof o.id != "string" || !o.id || o.id.length > 64 || typeof o.channelId != "string" || !o.channelId || !Number.isSafeInteger(o.version) || Number(o.version) < 0) throw Error("Chat events require committed identity/version evidence");
13
+ if (r.op === "update" && o.version === r.old?.version) return;
14
+ if (r.op === "update" && (!Number.isSafeInteger(r.old?.version) || Number(o.version) <= Number(r.old?.version))) throw Error("Chat event version must advance");
15
+ let s = i(r);
16
+ if (!a.publish) throw Error("Chat event publisher is unavailable");
17
+ await a.publish(t, { channelId: o.channelId }, {
18
+ messageId: o.id,
19
+ version: Number(o.version),
20
+ change: r.op === "delete" || o.deletedAt !== null ? "deleted" : r.op === "insert" ? "created" : "edited"
21
+ });
22
+ for (let t of s) await a.publish(e, {
23
+ channelId: t.channelId,
24
+ subjectId: t.recipientId
25
+ }, { messageId: t.messageId });
26
+ }, i = (e) => {
27
+ let t = n(e), r = e.new;
28
+ if (e.op !== "insert" || !r) return [];
29
+ if (typeof r.id != "string" || !r.id || r.id.length > 64 || typeof r.channelId != "string" || !r.channelId || r.channelId.length > 256) throw Error("Chat mentions require committed message/channel evidence");
30
+ let i = [];
31
+ if (e.op === "insert" && r.deletedAt === null && r.authorId !== null) {
32
+ let e = r.payload, t = e && typeof e == "object" && !Array.isArray(e) ? e.mentions : void 0;
33
+ if (t !== void 0) {
34
+ if (typeof r.authorId != "string" || !r.authorId.trim() || !Array.isArray(t) || t.length > 100 || t.some((e) => typeof e != "string" || !e.trim() || e.length > 256 || e.includes("\0") || e === "~")) throw Error("Chat mention events require bounded committed recipient evidence");
35
+ for (let e of new Set(t)) e !== r.authorId && i.push(e);
36
+ }
37
+ }
38
+ return i.map((e) => ({
39
+ tenantId: t,
40
+ channelId: r.channelId,
41
+ messageId: r.id,
42
+ recipientId: e
43
+ }));
44
+ };
45
+ //#endregion
46
+ export { n as chatEventTenant, i as committedChatMentions, r as publishChatChange };
@@ -0,0 +1,38 @@
1
+ import { DeclaredAccess } from '@voltro/protocol';
2
+ import { EventDescriptor } from '@voltro/protocol';
3
+ import { Schema } from 'effect';
4
+
5
+ /** Operator/server integration metadata. Never expose this as a player subscription grant. */
6
+ export declare const mentioned: EventDescriptor<"chat.mentioned", Schema.Struct<{
7
+ readonly channelId: Schema.NonEmptyString;
8
+ readonly subjectId: Schema.NonEmptyString;
9
+ }>, Schema.Struct<{
10
+ readonly messageId: Schema.NonEmptyString;
11
+ }>, DeclaredAccess<{
12
+ readonly channelId: string;
13
+ readonly subjectId: string;
14
+ }>>;
15
+
16
+ /** Operator metadata only; player-facing messages use the membership-filtered live query. */
17
+ export declare const messageChanged: EventDescriptor<"chat.messageChanged", Schema.Struct<{
18
+ readonly channelId: Schema.String;
19
+ }>, Schema.Struct<{
20
+ readonly messageId: Schema.String;
21
+ readonly version: Schema.Number;
22
+ readonly change: Schema.Literals<readonly ["created", "edited", "deleted"]>;
23
+ }>, DeclaredAccess<{
24
+ readonly channelId: string;
25
+ }>>;
26
+
27
+ /** Private ephemeral signal; no transcript, row write, webhook or operator-event fallback. */
28
+ export declare const typing: EventDescriptor<"chat.typing", Schema.Struct<{
29
+ readonly channelId: Schema.NonEmptyString;
30
+ }>, Schema.Struct<{
31
+ readonly subjectId: Schema.NonEmptyString;
32
+ readonly active: Schema.Boolean;
33
+ readonly expiresAt: Schema.Number;
34
+ }>, DeclaredAccess<{
35
+ readonly channelId: string;
36
+ }>>;
37
+
38
+ export { }
package/dist/events.js ADDED
@@ -0,0 +1,36 @@
1
+ import { ChatTypingSchema as e } from "./contract.js";
2
+ import { Schema as t } from "effect";
3
+ import { defineEvent as n } from "@voltro/protocol";
4
+ //#region src/events.ts
5
+ var r = n({
6
+ name: "chat.messageChanged",
7
+ key: t.Struct({ channelId: t.String }),
8
+ payload: t.Struct({
9
+ messageId: t.String,
10
+ version: t.Number.pipe(t.check(t.isInt()), t.check(t.isGreaterThanOrEqualTo(0))),
11
+ change: t.Literals([
12
+ "created",
13
+ "edited",
14
+ "deleted"
15
+ ])
16
+ }),
17
+ guards: [{ scope: "chat:events:read" }]
18
+ }), i = n({
19
+ name: "chat.typing",
20
+ key: t.Struct({ channelId: t.NonEmptyString.pipe(t.check(t.isMaxLength(256))) }),
21
+ payload: e,
22
+ guards: [{ authenticated: !0 }],
23
+ clientPolicy: "chat.typing.membership",
24
+ delivery: "latest",
25
+ rewind: !1
26
+ }), a = n({
27
+ name: "chat.mentioned",
28
+ key: t.Struct({
29
+ channelId: t.NonEmptyString.pipe(t.check(t.isMaxLength(256))),
30
+ subjectId: t.NonEmptyString.pipe(t.check(t.isMaxLength(256)))
31
+ }),
32
+ payload: t.Struct({ messageId: t.NonEmptyString.pipe(t.check(t.isMaxLength(64))) }),
33
+ guards: [{ scope: "chat:events:read" }]
34
+ });
35
+ //#endregion
36
+ export { a as mentioned, r as messageChanged, i as typing };
@@ -0,0 +1,25 @@
1
+ import { id as e, integer as t, table as n, text as r, timestamp as i } from "@voltro/database";
2
+ //#region src/evidence.entity.ts
3
+ var a = n("_voltro_chat_evidence", {
4
+ id: e({ prefix: "cevi" }),
5
+ tenantId: r().maxLength(256).externalId().serverOnly(),
6
+ channelId: r().maxLength(64).serverOnly(),
7
+ messageId: r().maxLength(64).serverOnly(),
8
+ messageVersion: t().serverOnly(),
9
+ kind: r().serverOnly(),
10
+ authorId: r().maxLength(256).nullable().externalId().sensitive("pii").serverOnly(),
11
+ body: r().sensitive("pii").serverOnly(),
12
+ originalBody: r().sensitive("pii").serverOnly(),
13
+ messageCreatedAt: i().serverOnly(),
14
+ messageEditedAt: i().nullable().serverOnly(),
15
+ messageDeletedAt: i().nullable().serverOnly(),
16
+ capturedAt: i().serverOnly(),
17
+ expiresAt: i().serverOnly(),
18
+ erasedAt: i().nullable().serverOnly()
19
+ }).index(["tenantId", "authorId"]).index(["channelId", "expiresAt"]).index([
20
+ "channelId",
21
+ "messageId",
22
+ "messageVersion"
23
+ ]);
24
+ //#endregion
25
+ export { a as chatEvidenceTable };