@ttt-productions/chat-core 0.11.4 → 0.11.5
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/grouping.d.ts +0 -18
- package/dist/grouping.d.ts.map +1 -1
- package/dist/grouping.js +0 -18
- package/dist/grouping.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -7
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +0 -29
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +0 -15
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
package/dist/grouping.d.ts
CHANGED
|
@@ -1,21 +1,3 @@
|
|
|
1
1
|
import type { ChatMessageGroupKey, ChatMessageV1 } from './types.js';
|
|
2
|
-
/**
|
|
3
|
-
* Determine if `msg` is a "continuation" of `prev` for the purpose of
|
|
4
|
-
* visually grouping consecutive messages from the same sender in the
|
|
5
|
-
* message list.
|
|
6
|
-
*
|
|
7
|
-
* A message is a continuation when ALL of the following hold:
|
|
8
|
-
* - `prev` exists.
|
|
9
|
-
* - Neither `prev` nor `msg` is a system message.
|
|
10
|
-
* - `prev` and `msg` have the same `senderId`.
|
|
11
|
-
* - `msg.createdAt - prev.createdAt` is in the inclusive range
|
|
12
|
-
* `[0, GROUP_GAP_SEC * 1000]` milliseconds. Negative gaps
|
|
13
|
-
* (out-of-order messages) are treated as not-a-continuation.
|
|
14
|
-
* - When the app supplies `groupKey`, both messages have the same key — a
|
|
15
|
-
* continuation hides the sender line, so a per-message fact the app shows
|
|
16
|
-
* there must break the group when it changes.
|
|
17
|
-
*
|
|
18
|
-
* Pure function. No side effects. Safe to call from server and client.
|
|
19
|
-
*/
|
|
20
2
|
export declare function isContinuation(prev: ChatMessageV1 | undefined, msg: ChatMessageV1, groupKey?: ChatMessageGroupKey): boolean;
|
|
21
3
|
//# sourceMappingURL=grouping.d.ts.map
|
package/dist/grouping.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grouping.d.ts","sourceRoot":"","sources":["../src/grouping.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGrE
|
|
1
|
+
{"version":3,"file":"grouping.d.ts","sourceRoot":"","sources":["../src/grouping.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGrE,wBAAgB,cAAc,CAC5B,IAAI,EAAE,aAAa,GAAG,SAAS,EAC/B,GAAG,EAAE,aAAa,EAClB,QAAQ,CAAC,EAAE,mBAAmB,GAC7B,OAAO,CAOT"}
|
package/dist/grouping.js
CHANGED
|
@@ -1,22 +1,4 @@
|
|
|
1
1
|
import { GROUP_GAP_SEC } from './types.js';
|
|
2
|
-
/**
|
|
3
|
-
* Determine if `msg` is a "continuation" of `prev` for the purpose of
|
|
4
|
-
* visually grouping consecutive messages from the same sender in the
|
|
5
|
-
* message list.
|
|
6
|
-
*
|
|
7
|
-
* A message is a continuation when ALL of the following hold:
|
|
8
|
-
* - `prev` exists.
|
|
9
|
-
* - Neither `prev` nor `msg` is a system message.
|
|
10
|
-
* - `prev` and `msg` have the same `senderId`.
|
|
11
|
-
* - `msg.createdAt - prev.createdAt` is in the inclusive range
|
|
12
|
-
* `[0, GROUP_GAP_SEC * 1000]` milliseconds. Negative gaps
|
|
13
|
-
* (out-of-order messages) are treated as not-a-continuation.
|
|
14
|
-
* - When the app supplies `groupKey`, both messages have the same key — a
|
|
15
|
-
* continuation hides the sender line, so a per-message fact the app shows
|
|
16
|
-
* there must break the group when it changes.
|
|
17
|
-
*
|
|
18
|
-
* Pure function. No side effects. Safe to call from server and client.
|
|
19
|
-
*/
|
|
20
2
|
export function isContinuation(prev, msg, groupKey) {
|
|
21
3
|
if (!prev)
|
|
22
4
|
return false;
|
package/dist/grouping.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grouping.js","sourceRoot":"","sources":["../src/grouping.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C
|
|
1
|
+
{"version":3,"file":"grouping.js","sourceRoot":"","sources":["../src/grouping.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,MAAM,UAAU,cAAc,CAC5B,IAA+B,EAC/B,GAAkB,EAClB,QAA8B;IAE9B,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC;IACxB,IAAI,GAAG,CAAC,eAAe,IAAI,IAAI,CAAC,eAAe;QAAE,OAAO,KAAK,CAAC;IAC9D,IAAI,GAAG,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC;IACjD,IAAI,QAAQ,IAAI,QAAQ,CAAC,GAAG,CAAC,KAAK,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/D,MAAM,KAAK,GAAG,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;IAC7C,OAAO,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,aAAa,GAAG,IAAI,CAAC;AACrD,CAAC","sourcesContent":["import type { ChatMessageGroupKey, ChatMessageV1 } from './types.js';\nimport { GROUP_GAP_SEC } from './types.js';\n\nexport function isContinuation(\n prev: ChatMessageV1 | undefined,\n msg: ChatMessageV1,\n groupKey?: ChatMessageGroupKey,\n): boolean {\n if (!prev) return false;\n if (msg.isSystemMessage || prev.isSystemMessage) return false;\n if (msg.senderId !== prev.senderId) return false;\n if (groupKey && groupKey(msg) !== groupKey(prev)) return false;\n const gapMs = msg.createdAt - prev.createdAt;\n return gapMs >= 0 && gapMs <= GROUP_GAP_SEC * 1000;\n}\n"]}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,YAAY,EACV,MAAM,EACN,YAAY,EACZ,aAAa,EACb,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
// Pure chat-core barrel. No React, no Firebase (client or admin) reachable from
|
|
2
|
-
// here — safe for Cloud Functions, scripts, and future native/TV clients that
|
|
3
|
-
// only need the contracts and grouping logic. Zero @ttt-productions/* deps.
|
|
4
|
-
//
|
|
5
|
-
// The chat React UI, hooks, Firestore-client adapter config, and render types
|
|
6
|
-
// live in @ttt-productions/chat-react. The realtime wire contract and the pure
|
|
7
|
-
// chat Zod schemas live in @ttt-productions/chat-schemas.
|
|
8
1
|
export { GROUP_GAP_SEC } from './types.js';
|
|
9
2
|
export { isContinuation } from './grouping.js';
|
|
10
3
|
//# 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,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC","sourcesContent":["export { GROUP_GAP_SEC } from './types.js';\nexport { isContinuation } from './grouping.js';\nexport type {\n ChatId,\n ChatThreadV1,\n ChatMessageV1,\n ChatMessageGroupKey,\n ModerationHandlers,\n ChatNameResolver,\n ChatNameResolution,\n ChatPrewarmSenders,\n} from './types.js';\n"]}
|
package/dist/types.d.ts
CHANGED
|
@@ -14,13 +14,7 @@ export type ChatMessageV1 = {
|
|
|
14
14
|
text?: string;
|
|
15
15
|
type?: string;
|
|
16
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
17
|
referencedUids?: string[];
|
|
22
|
-
/** Moderation tombstone flag on the stored message (backend-written); consumers
|
|
23
|
-
* render a tombstone instead of the content when true. */
|
|
24
18
|
hidden?: boolean;
|
|
25
19
|
meta?: Record<string, unknown>;
|
|
26
20
|
};
|
|
@@ -30,20 +24,8 @@ export type ModerationHandlers = {
|
|
|
30
24
|
onDeleteMessage?: (messageId: string) => void | Promise<void>;
|
|
31
25
|
onDeleteThread?: (threadId: string) => void | Promise<void>;
|
|
32
26
|
};
|
|
33
|
-
/** Max seconds between messages to be grouped as continuation */
|
|
34
27
|
export declare const GROUP_GAP_SEC = 120;
|
|
35
|
-
/**
|
|
36
|
-
* The app's own per-message grouping fact: two consecutive messages from one sender group only
|
|
37
|
-
* when their keys are equal. `undefined` is an ordinary key value like any other.
|
|
38
|
-
*/
|
|
39
28
|
export type ChatMessageGroupKey = (m: ChatMessageV1) => string | undefined;
|
|
40
|
-
/**
|
|
41
|
-
* What the app knows about a sender's display name right now. `pending` — the read has
|
|
42
|
-
* not answered; `unavailable` — the read answered and there is no person to name;
|
|
43
|
-
* `failed` — the read failed, and `retry` asks again. Only `resolved` carries a name:
|
|
44
|
-
* the chat UI never invents one for the other three, it hands them to the app's
|
|
45
|
-
* renderer (chat-react's `renderUnresolvedName`).
|
|
46
|
-
*/
|
|
47
29
|
export type ChatNameResolution = {
|
|
48
30
|
status: 'resolved';
|
|
49
31
|
name: string;
|
|
@@ -55,17 +37,6 @@ export type ChatNameResolution = {
|
|
|
55
37
|
status: 'failed';
|
|
56
38
|
retry: () => void;
|
|
57
39
|
};
|
|
58
|
-
/**
|
|
59
|
-
* Resolves a senderId synchronously from the app's own cache. Called during render,
|
|
60
|
-
* so it reads what the app already holds and never starts a fetch itself — the app
|
|
61
|
-
* fetches through {@link ChatPrewarmSenders}.
|
|
62
|
-
*/
|
|
63
40
|
export type ChatNameResolver = (senderId: string) => ChatNameResolution;
|
|
64
|
-
/**
|
|
65
|
-
* Optional pre-warm callback. The chat UI calls this with the deduped list of
|
|
66
|
-
* senderIds visible in the current message page so the consuming app can
|
|
67
|
-
* batch-fetch names into its cache. Implementations should be idempotent —
|
|
68
|
-
* the same id list will be passed across re-renders.
|
|
69
|
-
*/
|
|
70
41
|
export type ChatPrewarmSenders = (senderIds: string[]) => void;
|
|
71
42
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,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,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC,CAAC;AAEF,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;AAEF,eAAO,MAAM,aAAa,MAAM,CAAC;AAEjC,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,EAAE,aAAa,KAAK,MAAM,GAAG,SAAS,CAAC;AAE3E,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,MAAM,MAAM,gBAAgB,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,kBAAkB,CAAC;AAExE,MAAM,MAAM,kBAAkB,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC"}
|
package/dist/types.js
CHANGED
|
@@ -1,17 +1,2 @@
|
|
|
1
|
-
// ============================================
|
|
2
|
-
// THREAD & MESSAGE
|
|
3
|
-
// ============================================
|
|
4
|
-
//
|
|
5
|
-
// Chat is TEXT-ONLY. A message never carries a file: files belong to the
|
|
6
|
-
// CONVERSATION (the Conversation Files list owned by the consuming app), not to
|
|
7
|
-
// a message in its timeline. There is no attachment contract in this package.
|
|
8
|
-
//
|
|
9
|
-
// A message also carries NO reply pointer: no chat surface has an authoring
|
|
10
|
-
// affordance for replying to a specific message, so a `replyTo` contract here
|
|
11
|
-
// would be unreachable machinery.
|
|
12
|
-
// ============================================
|
|
13
|
-
// MESSAGE GROUPING (internal, exported for tests)
|
|
14
|
-
// ============================================
|
|
15
|
-
/** Max seconds between messages to be grouped as continuation */
|
|
16
1
|
export const GROUP_GAP_SEC = 120;
|
|
17
2
|
//# sourceMappingURL=types.js.map
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AA8BA,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,CAAC","sourcesContent":["export type ChatId = string;\n\nexport type ChatThreadV1 = {\n participantUserIds?: string[];\n createdAt: number;\n lastMessageAt: number;\n status?: string;\n meta?: Record<string, unknown>;\n};\n\nexport type ChatMessageV1 = {\n messageId: string;\n threadId: string;\n createdAt: number;\n senderId: string;\n text?: string;\n type?: string;\n isSystemMessage?: boolean;\n referencedUids?: string[];\n hidden?: boolean;\n meta?: Record<string, unknown>;\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>;\n onDeleteThread?: (threadId: string) => void | Promise<void>;\n};\n\nexport const GROUP_GAP_SEC = 120;\n\nexport type ChatMessageGroupKey = (m: ChatMessageV1) => string | undefined;\n\nexport type ChatNameResolution =\n | { status: 'resolved'; name: string }\n | { status: 'pending' }\n | { status: 'unavailable' }\n | { status: 'failed'; retry: () => void };\n\nexport type ChatNameResolver = (senderId: string) => ChatNameResolution;\n\nexport type ChatPrewarmSenders = (senderIds: string[]) => void;\n"]}
|