@ttt-productions/chat-core 0.11.1 → 0.11.2
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/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +27 -21
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -4
- package/dist/constants.d.ts +0 -7
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js +0 -8
- package/dist/constants.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
export { MAX_CHAT_MESSAGE_LENGTH } from "./constants.js";
|
|
2
1
|
export { GROUP_GAP_SEC } from "./types.js";
|
|
3
2
|
export { isContinuation } from "./grouping.js";
|
|
4
|
-
export type { ChatId, ChatThreadV1, ChatMessageV1,
|
|
3
|
+
export type { ChatId, ChatThreadV1, ChatMessageV1, ModerationHandlers, ChatNameResolver, ChatNameResolution, ChatPrewarmSenders, } from "./types.js";
|
|
5
4
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,YAAY,EACR,MAAM,EACN,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,GACrB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
// The chat React UI, hooks, Firestore-client adapter config, and render types
|
|
6
6
|
// live in @ttt-productions/chat-react. The realtime wire contract and the pure
|
|
7
7
|
// chat Zod schemas live in @ttt-productions/chat-schemas.
|
|
8
|
-
export { MAX_CHAT_MESSAGE_LENGTH } from "./constants.js";
|
|
9
8
|
export { GROUP_GAP_SEC } from "./types.js";
|
|
10
9
|
export { isContinuation } from "./grouping.js";
|
|
11
10
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,8EAA8E;AAC9E,4EAA4E;AAC5E,EAAE;AACF,8EAA8E;AAC9E,+EAA+E;AAC/E,0DAA0D;AAE1D,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,8EAA8E;AAC9E,4EAA4E;AAC5E,EAAE;AACF,8EAA8E;AAC9E,+EAA+E;AAC/E,0DAA0D;AAE1D,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC","sourcesContent":["// Pure chat-core barrel. No React, no Firebase (client or admin) reachable from\n// here — safe for Cloud Functions, scripts, and future native/TV clients that\n// only need the contracts and grouping logic. Zero @ttt-productions/* deps.\n//\n// The chat React UI, hooks, Firestore-client adapter config, and render types\n// live in @ttt-productions/chat-react. The realtime wire contract and the pure\n// chat Zod schemas live in @ttt-productions/chat-schemas.\n\nexport { GROUP_GAP_SEC } from \"./types.js\";\nexport { isContinuation } from \"./grouping.js\";\nexport type {\n ChatId,\n ChatThreadV1,\n ChatMessageV1,\n ModerationHandlers,\n ChatNameResolver,\n ChatNameResolution,\n ChatPrewarmSenders,\n} from \"./types.js\";\n"]}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export type ChatId = string;
|
|
2
2
|
export type ChatThreadV1 = {
|
|
3
|
-
allowedUserIds: string[];
|
|
4
3
|
participantUserIds?: string[];
|
|
5
4
|
createdAt: number;
|
|
6
5
|
lastMessageAt: number;
|
|
@@ -15,27 +14,16 @@ export type ChatMessageV1 = {
|
|
|
15
14
|
text?: string;
|
|
16
15
|
type?: string;
|
|
17
16
|
isSystemMessage?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Account ids a server-written message's text refers to, stored beside the text (never inside
|
|
19
|
+
* it). The UI prewarms and resolves them like senders; an account's anonymization rewrites them.
|
|
20
|
+
*/
|
|
21
|
+
referencedUids?: string[];
|
|
18
22
|
/** Moderation tombstone flag on the stored message (backend-written); consumers
|
|
19
23
|
* render a tombstone instead of the content when true. */
|
|
20
24
|
hidden?: boolean;
|
|
21
25
|
meta?: Record<string, unknown>;
|
|
22
26
|
};
|
|
23
|
-
/**
|
|
24
|
-
* Access mode controls how chat decides whether the current user can
|
|
25
|
-
* read/write a thread.
|
|
26
|
-
*
|
|
27
|
-
* - "firestore-rules" — trust Firestore rules. canAccessThread returns true
|
|
28
|
-
* for any signed-in user; if rules deny, onSnapshot will surface
|
|
29
|
-
* permission-denied. Use this when access depends on data the client doesn't
|
|
30
|
-
* reliably know up-front (entity membership, invite participation, etc.).
|
|
31
|
-
*
|
|
32
|
-
* - "explicit-allowlist" — access is enforced client-side via
|
|
33
|
-
* threadAllowedUserIds. The list is required in this mode. Use this when the
|
|
34
|
-
* consumer already knows the participants (admin/support threads).
|
|
35
|
-
*
|
|
36
|
-
* Admins (`isAdmin: true`) bypass both modes.
|
|
37
|
-
*/
|
|
38
|
-
export type ChatAccessMode = "firestore-rules" | "explicit-allowlist";
|
|
39
27
|
export type ModerationHandlers = {
|
|
40
28
|
onReportMessage?: (messageId: string, reason?: string) => void | Promise<void>;
|
|
41
29
|
onReportThread?: (threadId: string, reason?: string) => void | Promise<void>;
|
|
@@ -45,11 +33,29 @@ export type ModerationHandlers = {
|
|
|
45
33
|
/** Max seconds between messages to be grouped as continuation */
|
|
46
34
|
export declare const GROUP_GAP_SEC = 120;
|
|
47
35
|
/**
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* the
|
|
36
|
+
* What the app knows about a sender's display name right now. `pending` — the read has
|
|
37
|
+
* not answered; `unavailable` — the read answered and there is no person to name;
|
|
38
|
+
* `failed` — the read failed, and `retry` asks again. Only `resolved` carries a name:
|
|
39
|
+
* the chat UI never invents one for the other three, it hands them to the app's
|
|
40
|
+
* renderer (chat-react's `renderUnresolvedName`).
|
|
41
|
+
*/
|
|
42
|
+
export type ChatNameResolution = {
|
|
43
|
+
status: 'resolved';
|
|
44
|
+
name: string;
|
|
45
|
+
} | {
|
|
46
|
+
status: 'pending';
|
|
47
|
+
} | {
|
|
48
|
+
status: 'unavailable';
|
|
49
|
+
} | {
|
|
50
|
+
status: 'failed';
|
|
51
|
+
retry: () => void;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Resolves a senderId synchronously from the app's own cache. Called during render,
|
|
55
|
+
* so it reads what the app already holds and never starts a fetch itself — the app
|
|
56
|
+
* fetches through {@link ChatPrewarmSenders}.
|
|
51
57
|
*/
|
|
52
|
-
export type ChatNameResolver = (senderId: string) =>
|
|
58
|
+
export type ChatNameResolver = (senderId: string) => ChatNameResolution;
|
|
53
59
|
/**
|
|
54
60
|
* Optional pre-warm callback. The chat UI calls this with the deduped list of
|
|
55
61
|
* senderIds visible in the current message page so the consuming app can
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC;AAE5B,MAAM,MAAM,YAAY,GAAG;IACzB,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC;AAE5B,MAAM,MAAM,YAAY,GAAG;IACzB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B;8DAC0D;IAC1D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC,CAAC;AAMF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/E,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7D,CAAC;AAMF,iEAAiE;AACjE,eAAO,MAAM,aAAa,MAAM,CAAC;AAMjC;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,GAC1B;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,GACrB;IAAE,MAAM,EAAE,aAAa,CAAA;CAAE,GACzB;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,IAAI,CAAA;CAAE,CAAC;AAE5C;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,kBAAkB,CAAC;AAExE;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC"}
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,mBAAmB;AACnB,+CAA+C;AAC/C,EAAE;AACF,yEAAyE;AACzE,gFAAgF;AAChF,8EAA8E;AAC9E,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,yDAAyD;
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,mBAAmB;AACnB,+CAA+C;AAC/C,EAAE;AACF,yEAAyE;AACzE,gFAAgF;AAChF,8EAA8E;AAC9E,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,yDAAyD;AA0CzD,+CAA+C;AAC/C,kDAAkD;AAClD,+CAA+C;AAE/C,iEAAiE;AACjE,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,CAAC","sourcesContent":["// ============================================\n// THREAD & MESSAGE\n// ============================================\n//\n// Chat is TEXT-ONLY. A message never carries a file: files belong to the\n// CONVERSATION (the Conversation Files list owned by the consuming app), not to\n// a message in its timeline. There is no attachment contract in this package.\n//\n// A message also carries NO reply pointer: no chat surface has an authoring\n// affordance for replying to a specific message, so a `replyTo` contract here\n// would be unreachable machinery (DJ ruling 2026-07-29).\n\nexport type ChatId = string;\n\nexport type ChatThreadV1 = {\n participantUserIds?: string[];\n createdAt: number; // millis\n lastMessageAt: number; // millis\n status?: string; // opaque to chat-core\n meta?: Record<string, unknown>; // opaque\n};\n\nexport type ChatMessageV1 = {\n messageId: string;\n threadId: string;\n createdAt: number; // millis\n senderId: string;\n text?: string;\n type?: string; // optional for renderer registry\n isSystemMessage?: boolean;\n /**\n * Account ids a server-written message's text refers to, stored beside the text (never inside\n * it). The UI prewarms and resolves them like senders; an account's anonymization rewrites them.\n */\n referencedUids?: string[];\n /** Moderation tombstone flag on the stored message (backend-written); consumers\n * render a tombstone instead of the content when true. */\n hidden?: boolean;\n meta?: Record<string, unknown>;\n};\n\n// ============================================\n// MODERATION\n// ============================================\n\nexport type ModerationHandlers = {\n onReportMessage?: (messageId: string, reason?: string) => void | Promise<void>;\n onReportThread?: (threadId: string, reason?: string) => void | Promise<void>;\n onDeleteMessage?: (messageId: string) => void | Promise<void>; // admin only (gated)\n onDeleteThread?: (threadId: string) => void | Promise<void>; // admin only (gated)\n};\n\n// ============================================\n// MESSAGE GROUPING (internal, exported for tests)\n// ============================================\n\n/** Max seconds between messages to be grouped as continuation */\nexport const GROUP_GAP_SEC = 120;\n\n// ============================================\n// NAME RESOLUTION\n// ============================================\n\n/**\n * What the app knows about a sender's display name right now. `pending` — the read has\n * not answered; `unavailable` — the read answered and there is no person to name;\n * `failed` — the read failed, and `retry` asks again. Only `resolved` carries a name:\n * the chat UI never invents one for the other three, it hands them to the app's\n * renderer (chat-react's `renderUnresolvedName`).\n */\nexport type ChatNameResolution =\n | { status: 'resolved'; name: string }\n | { status: 'pending' }\n | { status: 'unavailable' }\n | { status: 'failed'; retry: () => void };\n\n/**\n * Resolves a senderId synchronously from the app's own cache. Called during render,\n * so it reads what the app already holds and never starts a fetch itself — the app\n * fetches through {@link ChatPrewarmSenders}.\n */\nexport type ChatNameResolver = (senderId: string) => ChatNameResolution;\n\n/**\n * Optional pre-warm callback. The chat UI calls this with the deduped list of\n * senderIds visible in the current message page so the consuming app can\n * batch-fetch names into its cache. Implementations should be idempotent —\n * the same id list will be passed across re-renders.\n */\nexport type ChatPrewarmSenders = (senderIds: string[]) => void;\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ttt-productions/chat-core",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.2",
|
|
4
4
|
"description": "Pure chat contracts and grouping helpers for TTT Productions apps (no React, no Firebase)",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -27,9 +27,6 @@
|
|
|
27
27
|
"typecheck": "tsc --noEmit",
|
|
28
28
|
"prepublishOnly": "npm run clean && npm run build"
|
|
29
29
|
},
|
|
30
|
-
"devDependencies": {
|
|
31
|
-
"typescript": "^5.8.3"
|
|
32
|
-
},
|
|
33
30
|
"author": "DJ (TTT Productions)",
|
|
34
31
|
"license": "MIT"
|
|
35
32
|
}
|
package/dist/constants.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Maximum chat message text length (characters). Consumer apps may override
|
|
3
|
-
* by passing a custom value through `ChatCoreConfig`; this constant is the
|
|
4
|
-
* package default and is also what chat-core's own internal schemas use.
|
|
5
|
-
*/
|
|
6
|
-
export declare const MAX_CHAT_MESSAGE_LENGTH = 4000;
|
|
7
|
-
//# sourceMappingURL=constants.d.ts.map
|
package/dist/constants.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,OAAO,CAAC"}
|
package/dist/constants.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
// Chat-domain limits and operational constants.
|
|
2
|
-
/**
|
|
3
|
-
* Maximum chat message text length (characters). Consumer apps may override
|
|
4
|
-
* by passing a custom value through `ChatCoreConfig`; this constant is the
|
|
5
|
-
* package default and is also what chat-core's own internal schemas use.
|
|
6
|
-
*/
|
|
7
|
-
export const MAX_CHAT_MESSAGE_LENGTH = 4000;
|
|
8
|
-
//# sourceMappingURL=constants.js.map
|
package/dist/constants.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAEhD;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,IAAI,CAAC","sourcesContent":["// Chat-domain limits and operational constants.\n\n/**\n * Maximum chat message text length (characters). Consumer apps may override\n * by passing a custom value through `ChatCoreConfig`; this constant is the\n * package default and is also what chat-core's own internal schemas use.\n */\nexport const MAX_CHAT_MESSAGE_LENGTH = 4000;\n"]}
|