@leemour/cli-messaging 0.66.0 → 0.67.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 (35) hide show
  1. package/README.md +1 -1
  2. package/dist/cli/messenger/processes.d.ts +6 -0
  3. package/dist/cli/messenger/processes.d.ts.map +1 -1
  4. package/dist/cli/messenger/processes.js +42 -1
  5. package/dist/cli/messenger/processes.js.map +1 -1
  6. package/dist/cli/messenger/store-maintenance-command.d.ts.map +1 -1
  7. package/dist/cli/messenger/store-maintenance-command.js +140 -4
  8. package/dist/cli/messenger/store-maintenance-command.js.map +1 -1
  9. package/dist/store/sqlite/accounts.d.ts +6 -0
  10. package/dist/store/sqlite/accounts.d.ts.map +1 -0
  11. package/dist/store/sqlite/accounts.js +18 -0
  12. package/dist/store/sqlite/accounts.js.map +1 -0
  13. package/dist/store/sqlite/chats.d.ts +17 -0
  14. package/dist/store/sqlite/chats.d.ts.map +1 -0
  15. package/dist/store/sqlite/chats.js +105 -0
  16. package/dist/store/sqlite/chats.js.map +1 -0
  17. package/dist/store/sqlite/drizzle/bun.js +1 -1
  18. package/dist/store/sqlite/drizzle/core.d.ts +1 -1
  19. package/dist/store/sqlite/drizzle/core.d.ts.map +1 -1
  20. package/dist/store/sqlite/drizzle/core.js +11 -1
  21. package/dist/store/sqlite/drizzle/node.js +1 -1
  22. package/dist/store/sqlite/drizzle/{shared-ZF3LACGD.js → shared-I773JEFB.js} +6 -1
  23. package/dist/store/sqlite/identities.d.ts +23 -0
  24. package/dist/store/sqlite/identities.d.ts.map +1 -0
  25. package/dist/store/sqlite/identities.js +169 -0
  26. package/dist/store/sqlite/identities.js.map +1 -0
  27. package/dist/store/sqlite/values.d.ts +8 -0
  28. package/dist/store/sqlite/values.d.ts.map +1 -0
  29. package/dist/store/sqlite/values.js +11 -0
  30. package/dist/store/sqlite/values.js.map +1 -0
  31. package/dist/store/store.d.ts.map +1 -1
  32. package/dist/store/store.js +29 -200
  33. package/dist/store/store.js.map +1 -1
  34. package/package.json +1 -1
  35. /package/dist/store/sqlite/drizzle/{shared-ZF3LACGD.js.map → shared-I773JEFB.js.map} +0 -0
@@ -0,0 +1,23 @@
1
+ import type { Contact, Id, Page, Provider } from "../../domain/models.js";
2
+ import type { PeopleLookup } from "../../resolve.js";
3
+ import type { AccountKey, PersonFacts } from "../store.js";
4
+ import type { StoreContext } from "./open.js";
5
+ type Facts = Omit<PersonFacts, "id" | "name">;
6
+ /** Every new identity gets its own person; linking two is a later, recorded act. */
7
+ export declare const identityOf: ({ orm, now }: StoreContext, provider: Provider, nativeId: Id, name: string | null, facts?: Facts) => number;
8
+ /** An identity as `accountKey` saw it — recorded as seen by that account, so reads stay per account. */
9
+ export declare const identityPk: (context: StoreContext, accountKey: number, provider: Provider, nativeId: Id, name: string | null, facts?: Facts) => number;
10
+ export declare const people: ({ orm }: StoreContext, provider: Provider, { account, accounts: native }: {
11
+ account?: Id;
12
+ accounts?: Id[];
13
+ }) => PeopleLookup;
14
+ export declare const contacts: ({ orm }: StoreContext, accountKey: number, key: AccountKey, { order, query, limit, offset }: {
15
+ order: "recent" | "name";
16
+ query?: string;
17
+ limit: number;
18
+ offset?: number;
19
+ }) => Page<Contact>;
20
+ export declare const countContacts: ({ orm }: StoreContext, accountKey: number, key: AccountKey, query: string | undefined) => number;
21
+ export declare const refreshRecency: ({ orm }: StoreContext, accountKey: number) => void;
22
+ export {};
23
+ //# sourceMappingURL=identities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identities.d.ts","sourceRoot":"","sources":["../../../src/store/sqlite/identities.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACzE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAG1D,OAAO,KAAK,EAAO,YAAY,EAAE,MAAM,WAAW,CAAA;AAalD,KAAK,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,IAAI,GAAG,MAAM,CAAC,CAAA;AAqC7C,oFAAoF;AACpF,eAAO,MAAM,UAAU,iBACP,YAAY,YAChB,QAAQ,YACR,EAAE,QACN,MAAM,GAAG,IAAI,UACZ,KAAK,KACX,MAgEF,CAAA;AAED,wGAAwG;AACxG,eAAO,MAAM,UAAU,YACZ,YAAY,cACT,MAAM,YACR,QAAQ,YACR,EAAE,QACN,MAAM,GAAG,IAAI,UACZ,KAAK,KACX,MAIF,CAAA;AAED,eAAO,MAAM,MAAM,YACR,YAAY,YACX,QAAQ,iCACa;IAAE,OAAO,CAAC,EAAE,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAA;CAAE,KAC/D,YAiBF,CAAA;AAmBD,eAAO,MAAM,QAAQ,YACV,YAAY,cACT,MAAM,OACb,UAAU,mCACsB;IAAE,KAAK,EAAE,QAAQ,GAAG,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,KAChH,IAAI,CAAC,OAAO,CAqBd,CAAA;AAED,eAAO,MAAM,aAAa,YACf,YAAY,cACT,MAAM,OACb,UAAU,SACR,MAAM,GAAG,SAAS,KACxB,MAQA,CAAA;AAEH,eAAO,MAAM,cAAc,YAAa,YAAY,cAAc,MAAM,KAAG,IAU1E,CAAA"}
@@ -0,0 +1,169 @@
1
+ import { CliError } from "@leemour/cli-core";
2
+ import { ulid } from "../ulid.js";
3
+ import { and, eq, inArray, ne, sql } from "./drizzle/core.js";
4
+ import { accountIdentities, accounts, chatMembers, chats, identities, identityLinkEvents, identityLinks, persons, } from "./schema.js";
5
+ import { toIso } from "./values.js";
6
+ const flag = (value) => (value === undefined || value === null ? null : Number(value));
7
+ const prepare = (orm) => ({
8
+ find: orm
9
+ .select({
10
+ pk: identities.pk,
11
+ name: identities.name,
12
+ username: identities.username,
13
+ isBot: identities.isBot,
14
+ description: identities.description,
15
+ })
16
+ .from(identities)
17
+ .where(and(eq(identities.provider, sql.placeholder("provider")), eq(identities.nativeId, sql.placeholder("nativeId"))))
18
+ .prepare(),
19
+ seen: orm
20
+ .insert(accountIdentities)
21
+ .values({
22
+ accountPk: sql.placeholder("accountPk"),
23
+ identityPk: sql.placeholder("identityPk"),
24
+ firstSeenAt: sql.placeholder("firstSeenAt"),
25
+ })
26
+ .onConflictDoNothing()
27
+ .prepare(),
28
+ });
29
+ // Built once per store: both run for every message saved, and building a Drizzle query costs more than running it.
30
+ const prepared = new WeakMap();
31
+ const statementsOf = (orm) => {
32
+ const statements = prepared.get(orm) ?? prepare(orm);
33
+ prepared.set(orm, statements);
34
+ return statements;
35
+ };
36
+ /** Every new identity gets its own person; linking two is a later, recorded act. */
37
+ export const identityOf = ({ orm, now }, provider, nativeId, name, facts = {}) => {
38
+ const found = statementsOf(orm).find.get({ provider, nativeId });
39
+ if (found) {
40
+ const changed = {
41
+ name: name ?? found.name,
42
+ username: facts.username ?? found.username,
43
+ isBot: flag(facts.isBot) ?? found.isBot,
44
+ description: facts.description ?? found.description,
45
+ };
46
+ // Only on a real change: the search trigger rewrites the index row on every update of `name`.
47
+ if (changed.name !== found.name ||
48
+ changed.username !== found.username ||
49
+ changed.isBot !== found.isBot ||
50
+ changed.description !== found.description) {
51
+ orm
52
+ .update(identities)
53
+ .set({ ...changed, updatedAt: now() })
54
+ .where(eq(identities.pk, found.pk))
55
+ .run();
56
+ }
57
+ return found.pk;
58
+ }
59
+ const at = now();
60
+ const identity = Number(orm
61
+ .insert(identities)
62
+ .values({
63
+ provider,
64
+ nativeId,
65
+ name,
66
+ username: facts.username ?? null,
67
+ isBot: flag(facts.isBot),
68
+ description: facts.description ?? null,
69
+ firstSeenAt: at,
70
+ updatedAt: at,
71
+ })
72
+ .returning({ pk: identities.pk })
73
+ .get()?.pk);
74
+ const person = Number(orm
75
+ .insert(persons)
76
+ .values({ uid: ulid(at), name, createdAt: at, updatedAt: at })
77
+ .returning({ pk: persons.pk })
78
+ .get()?.pk);
79
+ orm
80
+ .insert(identityLinks)
81
+ .values({
82
+ identityPk: identity,
83
+ personPk: person,
84
+ method: "initial",
85
+ confidence: 1,
86
+ linkedAt: at,
87
+ linkedBy: "ingest",
88
+ })
89
+ .run();
90
+ orm
91
+ .insert(identityLinkEvents)
92
+ .values({ identityPk: identity, fromPersonPk: null, toPersonPk: person, method: "initial", at, by: "ingest" })
93
+ .run();
94
+ return identity;
95
+ };
96
+ /** An identity as `accountKey` saw it — recorded as seen by that account, so reads stay per account. */
97
+ export const identityPk = (context, accountKey, provider, nativeId, name, facts = {}) => {
98
+ const identity = identityOf(context, provider, nativeId, name, facts);
99
+ statementsOf(context.orm).seen.run({ accountPk: accountKey, identityPk: identity, firstSeenAt: context.now() });
100
+ return identity;
101
+ };
102
+ export const people = ({ orm }, provider, { account, accounts: native }) => {
103
+ const within = native ?? (account === undefined ? undefined : [account]);
104
+ const seenBy = within &&
105
+ orm
106
+ .select({ pk: accountIdentities.identityPk })
107
+ .from(accountIdentities)
108
+ .innerJoin(accounts, eq(accounts.pk, accountIdentities.accountPk))
109
+ .where(and(eq(accounts.provider, provider), inArray(accounts.nativeId, within)));
110
+ const everyone = orm
111
+ .select({ id: identities.nativeId, name: identities.name, username: identities.username })
112
+ .from(identities)
113
+ .where(and(eq(identities.provider, provider), seenBy ? inArray(identities.pk, seenBy) : undefined))
114
+ .all()
115
+ .map((row) => ({ ...row, description: null, lastMessagedAt: null }));
116
+ const byId = new Map(everyone.map((person) => [person.id, person]));
117
+ return { get: (id) => byId.get(id), all: () => everyone };
118
+ };
119
+ /** A contact: someone other than the account itself, in one of its one-to-one chats. */
120
+ const contactsWhere = (accountKey, key, query) => {
121
+ if (query !== undefined && query.trim().length < 3) {
122
+ throw new CliError("validation_error", `a contact search takes at least 3 characters, got "${query}"`);
123
+ }
124
+ return and(eq(accountIdentities.accountPk, accountKey), ne(identities.nativeId, key.account), sql `EXISTS (SELECT 1 FROM ${chatMembers} JOIN ${chats} ON ${chats.pk} = ${chatMembers.chatPk}
125
+ WHERE ${chatMembers.identityPk} = ${identities.pk} AND ${chats.accountPk} = ${accountIdentities.accountPk}
126
+ AND ${chats.kind} = 'dialog')`, query === undefined
127
+ ? undefined
128
+ : sql `${identities.pk} IN (SELECT rowid FROM identities_fts WHERE identities_fts MATCH ${`"${query.trim().replaceAll('"', '""')}"`})`);
129
+ };
130
+ export const contacts = ({ orm }, accountKey, key, { order, query, limit, offset = 0 }) => {
131
+ const byName = [sql `${identities.name} IS NULL`, identities.name, identities.nativeId];
132
+ const rows = orm
133
+ .select({
134
+ id: identities.nativeId,
135
+ name: identities.name,
136
+ username: identities.username,
137
+ description: identities.description,
138
+ lastMessagedAt: accountIdentities.lastMessagedAt,
139
+ })
140
+ .from(accountIdentities)
141
+ .innerJoin(identities, eq(identities.pk, accountIdentities.identityPk))
142
+ .where(contactsWhere(accountKey, key, query))
143
+ .orderBy(...(order === "recent" ? [sql `${accountIdentities.lastMessagedAt} DESC NULLS LAST`] : []), ...byName)
144
+ .limit(limit + 1)
145
+ .offset(offset)
146
+ .all();
147
+ return {
148
+ items: rows.slice(0, limit).map((row) => ({ ...row, lastMessagedAt: toIso(row.lastMessagedAt) })),
149
+ hasMore: rows.length > limit,
150
+ };
151
+ };
152
+ export const countContacts = ({ orm }, accountKey, key, query) => Number(orm
153
+ .select({ n: sql `count(*)` })
154
+ .from(accountIdentities)
155
+ .innerJoin(identities, eq(identities.pk, accountIdentities.identityPk))
156
+ .where(contactsWhere(accountKey, key, query))
157
+ .get()?.n);
158
+ export const refreshRecency = ({ orm }, accountKey) => {
159
+ orm
160
+ .update(accountIdentities)
161
+ .set({
162
+ lastMessagedAt: sql `(SELECT max(${chats.lastMessageAt}) FROM ${chatMembers} JOIN ${chats} ON ${chats.pk} = ${chatMembers.chatPk}
163
+ WHERE ${chatMembers.identityPk} = ${accountIdentities.identityPk} AND ${chats.accountPk} = ${accountIdentities.accountPk}
164
+ AND ${chats.kind} = 'dialog')`,
165
+ })
166
+ .where(eq(accountIdentities.accountPk, accountKey))
167
+ .run();
168
+ };
169
+ //# sourceMappingURL=identities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identities.js","sourceRoot":"","sources":["../../../src/store/sqlite/identities.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export declare const toMs: (iso: string | null | undefined) => number | null;
2
+ export declare const toIso: (ms: unknown) => string | null;
3
+ export declare const json: (value: unknown) => string | null;
4
+ export declare const parsed: <T>(text: unknown) => T | undefined;
5
+ export declare const present: <T extends Record<string, unknown>>(entries: T) => {
6
+ [k: string]: unknown;
7
+ };
8
+ //# sourceMappingURL=values.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"values.d.ts","sourceRoot":"","sources":["../../../src/store/sqlite/values.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,IAAI,QAAS,MAAM,GAAG,IAAI,GAAG,SAAS,KAAG,MAAM,GAAG,IAI9D,CAAA;AAED,eAAO,MAAM,KAAK,OAAQ,OAAO,KAAG,MAAM,GAAG,IAAoE,CAAA;AAEjH,eAAO,MAAM,IAAI,UAAW,OAAO,KAAG,MAAM,GAAG,IAA4D,CAAA;AAE3G,eAAO,MAAM,MAAM,GAAI,CAAC,QAAQ,OAAO,KAAG,CAAC,GAAG,SACkB,CAAA;AAEhE,eAAO,MAAM,OAAO,GAAI,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,CAAC;;CACqC,CAAA"}
@@ -0,0 +1,11 @@
1
+ export const toMs = (iso) => {
2
+ if (iso === null || iso === undefined)
3
+ return null;
4
+ const ms = Date.parse(iso);
5
+ return Number.isNaN(ms) ? null : ms;
6
+ };
7
+ export const toIso = (ms) => (typeof ms === "number" ? new Date(ms).toISOString() : null);
8
+ export const json = (value) => (value === undefined ? null : JSON.stringify(value));
9
+ export const parsed = (text) => typeof text === "string" ? JSON.parse(text) : undefined;
10
+ export const present = (entries) => Object.fromEntries(Object.entries(entries).filter(([, value]) => value !== null && value !== undefined));
11
+ //# sourceMappingURL=values.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"values.js","sourceRoot":"","sources":["../../../src/store/sqlite/values.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,GAA8B,EAAiB,EAAE;IACpE,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,IAAI,CAAA;IAClD,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC1B,OAAO,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAA;AACrC,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,EAAW,EAAiB,EAAE,CAAC,CAAC,OAAO,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;AAEjH,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,KAAc,EAAiB,EAAE,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAA;AAE3G,MAAM,CAAC,MAAM,MAAM,GAAG,CAAI,IAAa,EAAiB,EAAE,CACxD,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAO,CAAC,CAAC,CAAC,SAAS,CAAA;AAEhE,MAAM,CAAC,MAAM,OAAO,GAAG,CAAoC,OAAU,EAAE,EAAE,CACvE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,CAAC,CAAC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/store/store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/store/store.ts"],"names":[],"mappings":"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"}
@@ -5,9 +5,12 @@ import { formatLocator } from "../domain/locator.js";
5
5
  import { migrate } from "./migrations.js";
6
6
  import { NORMALIZER_VERSION, normalize } from "./normalize.js";
7
7
  import { storePath } from "./path.js";
8
+ import * as accounts from "./sqlite/accounts.js";
8
9
  import { backfillNormalized, pendingNormalization } from "./sqlite/backfill.js";
10
+ import * as chatQueries from "./sqlite/chats.js";
11
+ import * as identities from "./sqlite/identities.js";
9
12
  import { openSqlite } from "./sqlite/open.js";
10
- import { ulid } from "./ulid.js";
13
+ import { json, parsed, present, toIso, toMs } from "./sqlite/values.js";
11
14
  /** About 40 ms of the first open (129k rows/s measured at 1M, 2026-09-30); Tab opens the store too. */
12
15
  export const BACKFILL_ON_OPEN = 5_000;
13
16
  export const openStore = async ({ path, env, now = Date.now } = {}) => {
@@ -31,7 +34,8 @@ export const openStore = async ({ path, env, now = Date.now } = {}) => {
31
34
  };
32
35
  /** Telegram's chat types that number their messages themselves, not per account. */
33
36
  const OWN_NUMBERING = "('channel', 'supergroup', 'gigagroup', 'monoforum')";
34
- const storeOver = ({ database, now }) => {
37
+ const storeOver = (context) => {
38
+ const { database, now } = context;
35
39
  const one = (sql, ...parameters) => database.prepare(sql).get(...parameters);
36
40
  const all = (sql, ...parameters) => database.prepare(sql).all(...parameters);
37
41
  const run = (sql, ...parameters) => database.prepare(sql).run(...parameters);
@@ -46,64 +50,11 @@ const storeOver = ({ database, now }) => {
46
50
  throw error;
47
51
  }
48
52
  };
49
- const accountPk = ({ provider, account }, name = null) => Number(one(`INSERT INTO accounts (provider, native_id, name, created_at) VALUES (?, ?, ?, ?)
50
- ON CONFLICT (provider, native_id) DO UPDATE SET name = coalesce(excluded.name, accounts.name)
51
- RETURNING pk`, provider, account, name, now())?.pk);
52
- const findAccountPk = ({ provider, account }) => {
53
- const row = one("SELECT pk FROM accounts WHERE provider = ? AND native_id = ?", provider, account);
54
- return row ? Number(row.pk) : undefined;
55
- };
56
- const findChatPk = (accountKey, chatId) => {
57
- const row = one("SELECT pk FROM chats WHERE account_pk = ? AND native_id = ?", accountKey, chatId);
58
- return row ? Number(row.pk) : undefined;
59
- };
60
- const upsertChat = (accountKey, chat) => {
61
- run(`INSERT INTO chats (account_pk, native_id, kind, title, unread_count, last_message_at, participants_count,
62
- provider_metadata, membership_state, updated_at)
63
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
64
- ON CONFLICT (account_pk, native_id) DO UPDATE SET
65
- kind = excluded.kind, title = excluded.title, unread_count = excluded.unread_count,
66
- last_message_at = excluded.last_message_at, participants_count = excluded.participants_count,
67
- provider_metadata = excluded.provider_metadata,
68
- membership_state = coalesce(excluded.membership_state, chats.membership_state),
69
- updated_at = excluded.updated_at`, accountKey, chat.id, chat.kind, chat.title, chat.unreadCount, toMs(chat.lastMessageAt), chat.participantsCount, json(chat.providerMetadata), chat.membershipState ?? null, now());
70
- };
71
- /** A chat known only from its messages, until the chat list names it. */
72
- const chatPkFor = (accountKey, chatId) => findChatPk(accountKey, chatId) ??
73
- Number(one("INSERT INTO chats (account_pk, native_id, kind, updated_at) VALUES (?, ?, 'unknown', ?) RETURNING pk", accountKey, chatId, now())?.pk);
74
- /** An identity as `accountKey` saw it — recorded as seen by that account, so reads stay per account. */
75
- const identityPk = (accountKey, provider, nativeId, name, facts = {}) => {
76
- const identity = identityOf(provider, nativeId, name, facts);
77
- run("INSERT OR IGNORE INTO account_identities (account_pk, identity_pk, first_seen_at) VALUES (?, ?, ?)", accountKey, identity, now());
78
- return identity;
79
- };
80
- /** Every new identity gets its own person; linking two is a later, recorded act. */
81
- const identityOf = (provider, nativeId, name, facts = {}) => {
82
- const found = one("SELECT pk, name, username, is_bot, description FROM identities WHERE provider = ? AND native_id = ?", provider, nativeId);
83
- if (found) {
84
- const username = facts.username ?? found.username ?? null;
85
- const isBot = facts.isBot === undefined || facts.isBot === null ? (found.is_bot ?? null) : Number(facts.isBot);
86
- const newName = name ?? found.name ?? null;
87
- const description = facts.description ?? found.description ?? null;
88
- // Only on a real change: the search trigger rewrites the index row on every update of `name`.
89
- if (newName !== found.name ||
90
- username !== found.username ||
91
- isBot !== found.is_bot ||
92
- description !== found.description) {
93
- run("UPDATE identities SET name = ?, username = ?, is_bot = ?, description = ?, updated_at = ? WHERE pk = ?", newName, username, isBot, description, now(), Number(found.pk));
94
- }
95
- return Number(found.pk);
96
- }
97
- const at = now();
98
- const identity = Number(one(`INSERT INTO identities (provider, native_id, name, username, is_bot, description, first_seen_at, updated_at)
99
- VALUES (?, ?, ?, ?, ?, ?, ?, ?) RETURNING pk`, provider, nativeId, name, facts.username ?? null, facts.isBot === undefined || facts.isBot === null ? null : Number(facts.isBot), facts.description ?? null, at, at)?.pk);
100
- const person = Number(one("INSERT INTO persons (uid, name, created_at, updated_at) VALUES (?, ?, ?, ?) RETURNING pk", ulid(at), name, at, at)?.pk);
101
- run(`INSERT INTO identity_links (identity_pk, person_pk, method, confidence, linked_at, linked_by)
102
- VALUES (?, ?, 'initial', 1, ?, 'ingest')`, identity, person, at);
103
- run(`INSERT INTO identity_link_events (identity_pk, from_person_pk, to_person_pk, method, at, by)
104
- VALUES (?, NULL, ?, 'initial', ?, 'ingest')`, identity, person, at);
105
- return identity;
106
- };
53
+ const accountPk = (key, name = null) => accounts.accountPk(context, key, name);
54
+ const findAccountPk = (key) => accounts.findAccountPk(context, key);
55
+ const findChatPk = (accountKey, chatId) => chatQueries.findChatPk(context, accountKey, chatId);
56
+ const chatPkFor = (accountKey, chatId) => chatQueries.chatPkFor(context, accountKey, chatId);
57
+ const identityPk = (accountKey, provider, nativeId, name, facts) => identities.identityPk(context, accountKey, provider, nativeId, name, facts);
107
58
  const upsertMessage = (key, accountKey, chatKey, message, via, seenAt) => {
108
59
  const sender = message.senderId === null || message.senderIsChat
109
60
  ? null
@@ -274,13 +225,7 @@ const storeOver = ({ database, now }) => {
274
225
  }
275
226
  return found;
276
227
  };
277
- const writeMembers = (key, accountKey, chatId, memberIds) => {
278
- const chatKey = chatPkFor(accountKey, chatId);
279
- run("DELETE FROM chat_members WHERE chat_pk = ?", chatKey);
280
- for (const id of new Set(memberIds)) {
281
- run("INSERT INTO chat_members (chat_pk, identity_pk) VALUES (?, ?)", chatKey, identityPk(accountKey, key.provider, id, null));
282
- }
283
- };
228
+ const writeMembers = (key, accountKey, chatId, memberIds) => chatQueries.writeMembers(context, key, accountKey, chatId, memberIds);
284
229
  const writeState = (accountKey, name, value) => {
285
230
  run(`INSERT INTO sync_state (account_pk, key, value, at) VALUES (?, ?, ?, ?)
286
231
  ON CONFLICT (account_pk, key) DO UPDATE SET value = excluded.value, at = excluded.at`, accountKey, name, value, now());
@@ -298,54 +243,16 @@ const storeOver = ({ database, now }) => {
298
243
  run("DELETE FROM transcripts WHERE chat_pk = ? AND message_native_id = ?", Number(row.chat_pk), String(row.native_id));
299
244
  return 1;
300
245
  };
301
- const chatsWhere = (accountKey, { query, kind, unread }) => {
302
- const conditions = ["account_pk = ?"];
303
- const parameters = [accountKey];
304
- if (query !== undefined) {
305
- if (query.trim().length < 3) {
306
- throw new CliError("validation_error", `a chat search takes at least 3 characters, got "${query}"`);
307
- }
308
- conditions.push("pk IN (SELECT rowid FROM chats_fts WHERE chats_fts MATCH ?)");
309
- parameters.push(`"${query.trim().replaceAll('"', '""')}"`);
310
- }
311
- if (kind !== undefined) {
312
- conditions.push("kind = ?");
313
- parameters.push(kind);
314
- }
315
- if (unread)
316
- conditions.push("unread_count > 0");
317
- return { sql: `WHERE ${conditions.join(" AND ")}`, parameters };
318
- };
319
- /** A contact: someone other than the account itself, in one of its one-to-one chats. */
320
- const contactsWhere = (accountKey, key, query) => {
321
- const parameters = [accountKey, key.account];
322
- let match = "";
323
- if (query !== undefined) {
324
- if (query.trim().length < 3) {
325
- throw new CliError("validation_error", `a contact search takes at least 3 characters, got "${query}"`);
326
- }
327
- match = "AND i.pk IN (SELECT rowid FROM identities_fts WHERE identities_fts MATCH ?)";
328
- parameters.push(`"${query.trim().replaceAll('"', '""')}"`);
329
- }
330
- return {
331
- sql: `FROM account_identities ai JOIN identities i ON i.pk = ai.identity_pk
332
- WHERE ai.account_pk = ? AND i.native_id != ?
333
- AND EXISTS (SELECT 1 FROM chat_members cm JOIN chats c ON c.pk = cm.chat_pk
334
- WHERE cm.identity_pk = i.pk AND c.account_pk = ai.account_pk AND c.kind = 'dialog')
335
- ${match}`,
336
- parameters,
337
- };
338
- };
339
246
  const MESSAGE_COLUMNS = `m.*, c.native_id AS chat_native_id, i.native_id AS sender_native_id`;
340
247
  const MESSAGE_JOINS = `JOIN chats c ON c.pk = m.chat_pk LEFT JOIN identities i ON i.pk = m.sender_identity_pk`;
341
248
  return {
342
249
  saveAccount: async (key, { name }) => {
343
250
  accountPk(key, name);
344
251
  },
345
- saveChats: async (key, chats) => inTransaction(() => {
252
+ saveChats: async (key, list) => inTransaction(() => {
346
253
  const accountKey = accountPk(key);
347
- for (const chat of chats)
348
- upsertChat(accountKey, chat);
254
+ for (const chat of list)
255
+ chatQueries.upsertChat(context, accountKey, chat);
349
256
  }),
350
257
  saveMessages: async (key, chatId, messages, { via, seenAt }) => inTransaction(() => {
351
258
  const accountKey = accountPk(key);
@@ -359,24 +266,11 @@ const storeOver = ({ database, now }) => {
359
266
  members: async (key, chatId) => {
360
267
  const accountKey = findAccountPk(key);
361
268
  const chatKey = accountKey === undefined ? undefined : findChatPk(accountKey, chatId);
362
- if (chatKey === undefined)
363
- return [];
364
- return all(`SELECT i.native_id, i.name, i.username FROM chat_members cm JOIN identities i ON i.pk = cm.identity_pk
365
- WHERE cm.chat_pk = ? ORDER BY i.name IS NULL, i.name, i.native_id`, chatKey).map((row) => ({
366
- id: String(row.native_id),
367
- name: row.name ?? null,
368
- username: row.username ?? null,
369
- }));
269
+ return chatKey === undefined ? [] : chatQueries.members(context, chatKey);
370
270
  },
371
271
  chatsWith: async (key, memberId) => {
372
272
  const accountKey = findAccountPk(key);
373
- if (accountKey === undefined)
374
- return [];
375
- return all(`SELECT c.* FROM chat_members cm
376
- JOIN chats c ON c.pk = cm.chat_pk
377
- JOIN identities i ON i.pk = cm.identity_pk
378
- WHERE c.account_pk = ? AND i.provider = ? AND i.native_id = ?
379
- ORDER BY c.last_message_at DESC NULLS LAST, c.pk`, accountKey, key.provider, memberId).map(toChat);
273
+ return accountKey === undefined ? [] : chatQueries.chatsWith(context, accountKey, key, memberId);
380
274
  },
381
275
  syncState: async (key, name) => {
382
276
  const accountKey = findAccountPk(key);
@@ -389,7 +283,7 @@ const storeOver = ({ database, now }) => {
389
283
  applyDelta: async (key, { chats = [], people = [], members = new Map(), state = {} }) => inTransaction(() => {
390
284
  const accountKey = accountPk(key);
391
285
  for (const chat of chats)
392
- upsertChat(accountKey, chat);
286
+ chatQueries.upsertChat(context, accountKey, chat);
393
287
  for (const person of people)
394
288
  identityPk(accountKey, key.provider, person.id, person.name, person);
395
289
  for (const [chatId, ids] of members)
@@ -437,21 +331,15 @@ const storeOver = ({ database, now }) => {
437
331
  text = excluded.text, source = excluded.source, heard_at = excluded.heard_at`, chatPkFor(accountPk(key), chatId), messageId, text, source, now());
438
332
  });
439
333
  },
440
- chats: async (key, { limit, offset = 0, ...filter }) => {
334
+ chats: async (key, window) => {
441
335
  const accountKey = findAccountPk(key);
442
- if (accountKey === undefined)
443
- return { items: [], hasMore: false };
444
- const where = chatsWhere(accountKey, filter);
445
- const rows = all(`SELECT * FROM chats ${where.sql} ORDER BY last_message_at DESC NULLS LAST, pk LIMIT ? OFFSET ?`, ...where.parameters, limit === undefined ? -1 : limit + 1, offset);
446
- const hasMore = limit !== undefined && rows.length > limit;
447
- return { items: rows.slice(0, limit).map(toChat), hasMore };
336
+ return accountKey === undefined
337
+ ? { items: [], hasMore: false }
338
+ : chatQueries.listChats(context, accountKey, window);
448
339
  },
449
340
  countChats: async (key, filter = {}) => {
450
341
  const accountKey = findAccountPk(key);
451
- if (accountKey === undefined)
452
- return 0;
453
- const where = chatsWhere(accountKey, filter);
454
- return Number(one(`SELECT count(*) AS n FROM chats ${where.sql}`, ...where.parameters)?.n);
342
+ return accountKey === undefined ? 0 : chatQueries.countChats(context, accountKey, filter);
455
343
  },
456
344
  countMessages: async (key, chatId, { since } = {}) => {
457
345
  const accountKey = findAccountPk(key);
@@ -577,60 +465,27 @@ const storeOver = ({ database, now }) => {
577
465
  },
578
466
  search: async (query, { limit, account }) => find({ text: query, limit, ...(account ? { account } : {}) }),
579
467
  find: async (filter) => find(filter),
580
- contacts: async (key, { order, query, limit, offset = 0 }) => {
468
+ contacts: async (key, options) => {
581
469
  const accountKey = findAccountPk(key);
582
470
  if (accountKey === undefined)
583
471
  return { items: [], hasMore: false };
584
- const where = contactsWhere(accountKey, key, query);
585
- const rows = all(`SELECT i.native_id, i.name, i.username, i.description, ai.last_messaged_at ${where.sql}
586
- ORDER BY ${order === "recent" ? "ai.last_messaged_at DESC NULLS LAST, " : ""}i.name IS NULL, i.name, i.native_id
587
- LIMIT ? OFFSET ?`, ...where.parameters, limit + 1, offset);
588
- return {
589
- items: rows.slice(0, limit).map((row) => ({
590
- id: String(row.native_id),
591
- name: row.name ?? null,
592
- username: row.username ?? null,
593
- description: row.description ?? null,
594
- lastMessagedAt: toIso(row.last_messaged_at),
595
- })),
596
- hasMore: rows.length > limit,
597
- };
472
+ return identities.contacts(context, accountKey, key, options);
598
473
  },
599
474
  countContacts: async (key, { query } = {}) => {
600
475
  const accountKey = findAccountPk(key);
601
- if (accountKey === undefined)
602
- return 0;
603
- const where = contactsWhere(accountKey, key, query);
604
- return Number(one(`SELECT count(*) AS n ${where.sql}`, ...where.parameters)?.n);
476
+ return accountKey === undefined ? 0 : identities.countContacts(context, accountKey, key, query);
605
477
  },
606
478
  refreshRecency: async (key) => {
607
479
  const accountKey = findAccountPk(key);
608
- if (accountKey === undefined)
609
- return;
610
- inTransaction(() => {
611
- run(`UPDATE account_identities SET last_messaged_at = (
612
- SELECT max(c.last_message_at) FROM chat_members cm JOIN chats c ON c.pk = cm.chat_pk
613
- WHERE cm.identity_pk = account_identities.identity_pk AND c.account_pk = account_identities.account_pk
614
- AND c.kind = 'dialog')
615
- WHERE account_pk = ?`, accountKey);
616
- });
480
+ if (accountKey !== undefined)
481
+ identities.refreshRecency(context, accountKey);
617
482
  },
618
483
  savePeople: async (key, people) => inTransaction(() => {
619
484
  const accountKey = accountPk(key);
620
485
  for (const person of people)
621
486
  identityPk(accountKey, key.provider, person.id, person.name, person);
622
487
  }),
623
- people: async (provider, { account, accounts } = {}) => {
624
- const within = accounts ?? (account === undefined ? undefined : [account]);
625
- const scope = within
626
- ? `AND pk IN (SELECT ai.identity_pk FROM account_identities ai JOIN accounts a ON a.pk = ai.account_pk
627
- WHERE a.provider = ? AND a.native_id IN (${within.map(() => "?").join(", ") || "NULL"}))`
628
- : "";
629
- const rows = all(`SELECT native_id, name, username FROM identities WHERE provider = ? ${scope}`, provider, ...(within ? [provider, ...within] : []));
630
- const everyone = rows.map(toContact);
631
- const byId = new Map(everyone.map((person) => [person.id, person]));
632
- return { get: (id) => byId.get(id), all: () => everyone };
633
- },
488
+ people: async (provider, options = {}) => identities.people(context, provider, options),
634
489
  saveReactions: async (key, chatId, messageId, reactions) => {
635
490
  const accountKey = findAccountPk(key);
636
491
  const chatKey = accountKey === undefined ? undefined : findChatPk(accountKey, chatId);
@@ -682,32 +537,6 @@ const storeOver = ({ database, now }) => {
682
537
  };
683
538
  };
684
539
  const searchable = (text) => ({ normalized_text: normalize(text), normalizer_version: NORMALIZER_VERSION });
685
- const toMs = (iso) => {
686
- if (iso === null || iso === undefined)
687
- return null;
688
- const ms = Date.parse(iso);
689
- return Number.isNaN(ms) ? null : ms;
690
- };
691
- const toIso = (ms) => (typeof ms === "number" ? new Date(ms).toISOString() : null);
692
- const json = (value) => (value === undefined ? null : JSON.stringify(value));
693
- const parsed = (text) => (typeof text === "string" ? JSON.parse(text) : undefined);
694
- const present = (entries) => Object.fromEntries(Object.entries(entries).filter(([, value]) => value !== null && value !== undefined));
695
- const toContact = (row) => ({
696
- id: String(row.native_id),
697
- name: row.name ?? null,
698
- username: row.username ?? null,
699
- description: null,
700
- lastMessagedAt: null,
701
- });
702
- const toChat = (row) => ({
703
- id: String(row.native_id),
704
- title: row.title ?? null,
705
- kind: row.kind,
706
- unreadCount: row.unread_count ?? null,
707
- lastMessageAt: toIso(row.last_message_at),
708
- participantsCount: row.participants_count ?? null,
709
- ...present({ membershipState: row.membership_state, providerMetadata: parsed(row.provider_metadata) }),
710
- });
711
540
  const toAttachment = (row) => ({
712
541
  kind: String(row.kind),
713
542
  ...present({