@remit/drizzle-service 0.0.102 → 0.0.103

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 (60) hide show
  1. package/package.json +1 -1
  2. package/src/batch.sqlite.test.ts +4 -4
  3. package/src/batch.ts +47 -21
  4. package/src/databases.ts +24 -6
  5. package/src/db.ts +20 -5
  6. package/src/index.ts +12 -0
  7. package/src/repair/junk-only-address.sqlite.test.ts +7 -2
  8. package/src/repos/account.conformance.sqlite.test.ts +6 -2
  9. package/src/repos/calendar-collection.ts +2 -2
  10. package/src/repos/calendar-default.sqlite.test.ts +6 -2
  11. package/src/repos/calendar-event-index.ts +2 -2
  12. package/src/repos/calendar-feed-token.ts +2 -2
  13. package/src/repos/calendar-object.ts +2 -2
  14. package/src/repos/calendar-put.sqlite.test.ts +6 -2
  15. package/src/repos/calendar-store.ts +36 -40
  16. package/src/repos/calendar-suggestion.ts +2 -2
  17. package/src/repos/cascade-delete.test.ts +3 -2
  18. package/src/repos/cascade-delete.ts +11 -7
  19. package/src/repos/envelope.sqlite.test.ts +3 -2
  20. package/src/repos/envelope.test.ts +3 -2
  21. package/src/repos/envelope.ts +14 -9
  22. package/src/repos/filter.ts +2 -2
  23. package/src/repos/i4-account-config.test.ts +10 -6
  24. package/src/repos/i4-account-config.ts +8 -10
  25. package/src/repos/i4-account-export-request.ts +2 -2
  26. package/src/repos/i4-account-setting.ts +2 -2
  27. package/src/repos/i4-account.test.ts +12 -8
  28. package/src/repos/i4-account.ts +6 -10
  29. package/src/repos/i4-address-junk-move.sqlite.test.ts +7 -2
  30. package/src/repos/i4-address.ts +12 -2
  31. package/src/repos/i4-config-import.ts +2 -2
  32. package/src/repos/i4-mailbox-lock.ts +2 -2
  33. package/src/repos/i4-mailbox-special-use.sqlite.test.ts +12 -10
  34. package/src/repos/i4-mailbox-special-use.ts +29 -40
  35. package/src/repos/i4-mailbox.sqlite.test.ts +12 -10
  36. package/src/repos/i4-mailbox.test.ts +15 -14
  37. package/src/repos/i4-mailbox.ts +13 -7
  38. package/src/repos/i4-message-flag-push.ts +2 -2
  39. package/src/repos/i4-message-placement-move.ts +2 -2
  40. package/src/repos/i4-organize-job-request.ts +2 -2
  41. package/src/repos/i4-outbox-attachment.test.ts +7 -2
  42. package/src/repos/i4-outbox-attachment.ts +11 -5
  43. package/src/repos/i4-outbox-message.ts +2 -2
  44. package/src/repos/i4-sender-signer-standing.ts +2 -2
  45. package/src/repos/label.ts +2 -2
  46. package/src/repos/message-flag.ts +3 -6
  47. package/src/repos/message-label.ts +2 -2
  48. package/src/repos/message.sqlite.test.ts +3 -3
  49. package/src/repos/message.test.ts +6 -5
  50. package/src/repos/message.ts +15 -10
  51. package/src/repos/quarantine.ts +2 -2
  52. package/src/repos/sync-warning.ts +2 -2
  53. package/src/repos/thread-message-body-muted.sqlite.test.ts +7 -3
  54. package/src/repos/thread-message-field-terms.sqlite.test.ts +7 -6
  55. package/src/repos/thread-message.sqlite.test.ts +7 -3
  56. package/src/repos/thread-message.test.ts +22 -18
  57. package/src/repos/thread-message.ts +13 -5
  58. package/src/search/thread-message-search.sqlite.test.ts +8 -3
  59. package/src/search/thread-message-search.ts +13 -8
  60. package/src/sqlite-repositories.ts +48 -32
@@ -2,7 +2,7 @@ import assert from "node:assert";
2
2
  import { after, before, describe, test } from "node:test";
3
3
  import { MailboxSyncStatus } from "@remit/domain-enums";
4
4
  import { eq } from "drizzle-orm";
5
- import { runBatch } from "../batch.js";
5
+ import { syncBatch } from "../batch.js";
6
6
  import {
7
7
  envelopeId as deriveEnvelopeId,
8
8
  rootBodyPartId as deriveRootBodyPartId,
@@ -10,14 +10,13 @@ import {
10
10
  import {
11
11
  filterTable,
12
12
  mailboxSpecialUseTable,
13
- mailboxTable,
14
13
  messageTable,
15
14
  threadMessageTable,
16
15
  } from "../schema.js";
17
- import { SearchIndex } from "../search/thread-message-search.js";
16
+ import { createSqliteRepositories } from "../sqlite-repositories.js";
18
17
  import { createTestDb, randomId, type TestDb } from "../test-db.js";
19
- import { MailboxRepo } from "./i4-mailbox.js";
20
- import { DrizzleMessageRepository, deleteMessageSubtree } from "./message.js";
18
+ import type { MailboxRepo } from "./i4-mailbox.js";
19
+ import { deleteMessageSubtree } from "./message.js";
21
20
  import { mailboxCreated } from "./test-helpers.js";
22
21
 
23
22
  /** Every state a row can carry, for a transition that decides against none. */
@@ -55,10 +54,11 @@ describe("MailboxRepo", () => {
55
54
 
56
55
  before(async () => {
57
56
  ({ db, close } = await createTestDb());
58
- repo = new MailboxRepo(
59
- db as never,
60
- new SearchIndex(db as never, db as never),
61
- );
57
+ repo = createSqliteRepositories({
58
+ app: db,
59
+ mail: db,
60
+ search: db,
61
+ }).mailbox;
62
62
  });
63
63
 
64
64
  after(async () => {
@@ -543,10 +543,11 @@ describe("MailboxRepo", () => {
543
543
  describe("deleteMailboxWithMail — the folder's mail goes with it (D8)", () => {
544
544
  const seedMessage = async (mailboxId: string, uid: number) => {
545
545
  const messageId = randomId();
546
- await new DrizzleMessageRepository(
547
- db as never,
548
- new SearchIndex(db as never, db as never),
549
- ).create({
546
+ await createSqliteRepositories({
547
+ app: db,
548
+ mail: db,
549
+ search: db,
550
+ }).message.create({
550
551
  messageId,
551
552
  mailboxId,
552
553
  uid,
@@ -674,7 +675,7 @@ describe("MailboxRepo", () => {
674
675
 
675
676
  // The shape an interruption leaves: one message's rows already gone,
676
677
  // the mailbox row still there and still `deleting`.
677
- await runBatch(db, deleteMessageSubtree(db, [first]));
678
+ await syncBatch(db)(deleteMessageSubtree(db, [first]));
678
679
  await repo.transition(accountId, mailbox.mailboxId, {
679
680
  from: EVERY_STATE,
680
681
  to: MailboxSyncStatus.deleting,
@@ -27,8 +27,8 @@ import {
27
27
  sql,
28
28
  } from "drizzle-orm";
29
29
  import shortUuid from "short-uuid";
30
- import { runBatch } from "../batch.js";
31
- import type { Db } from "../db.js";
30
+ import type { WriteBatch } from "../batch.js";
31
+ import type { RepositoryDb, SqliteStore } from "../db.js";
32
32
  import { NotFoundError } from "../error.js";
33
33
  import { decodeToken, resultList } from "../pagination.js";
34
34
  import {
@@ -52,7 +52,7 @@ const base36Translator = shortUuid.createTranslator(
52
52
  );
53
53
  const generateMailboxId = () => base36Translator.fromUUID(randomUUID());
54
54
 
55
- type DB = Db<Record<string, unknown>>;
55
+ type DB = RepositoryDb<Record<string, unknown>>;
56
56
 
57
57
  /**
58
58
  * Message subtrees removed per batch by {@link MailboxRepo.deleteMailboxWithMail},
@@ -149,10 +149,16 @@ export function rowToMailbox(
149
149
  }
150
150
 
151
151
  export class MailboxRepo implements IMailboxRepository {
152
+ private readonly db: DB;
153
+ private readonly batch: WriteBatch;
154
+
152
155
  constructor(
153
- private db: DB,
156
+ store: SqliteStore<Record<string, unknown>>,
154
157
  private search: SearchIndex,
155
- ) {}
158
+ ) {
159
+ this.db = store.db;
160
+ this.batch = store.batch;
161
+ }
156
162
 
157
163
  async create(input: CreateMailboxInput): Promise<CreateMailboxResult> {
158
164
  const now = Date.now();
@@ -379,7 +385,7 @@ export class MailboxRepo implements IMailboxRepository {
379
385
 
380
386
  async deleteMany(accountId: string, mailboxIds: string[]): Promise<void> {
381
387
  if (mailboxIds.length === 0) return;
382
- await runBatch(this.db, [
388
+ await this.batch([
383
389
  this.db
384
390
  .delete(syncWarningTable)
385
391
  .where(
@@ -556,7 +562,7 @@ export class MailboxRepo implements IMailboxRepository {
556
562
 
557
563
  // The primitive the rest of the codebase deletes mail with: nine
558
564
  // per-message child tables. A bespoke table list would orphan them.
559
- await runBatch(this.db, [
565
+ await this.batch([
560
566
  ...deleteMessageSubtree(this.db, messageIds),
561
567
  this.db
562
568
  .delete(threadMessageTable)
@@ -3,10 +3,10 @@ import type {
3
3
  PutMessageFlagPushInput,
4
4
  } from "@remit/data-ports";
5
5
  import { and, eq } from "drizzle-orm";
6
- import type { Db } from "../db.js";
6
+ import type { RepositoryDb } from "../db.js";
7
7
  import { messageFlagPushTable } from "../schema/i4-message-flag-push.js";
8
8
 
9
- type DB = Db<Record<string, unknown>>;
9
+ type DB = RepositoryDb<Record<string, unknown>>;
10
10
 
11
11
  export type { MessageFlagPushItem, PutMessageFlagPushInput };
12
12
  export type FlagPushOperation = MessageFlagPushItem["operation"];
@@ -3,10 +3,10 @@ import type {
3
3
  PutMessagePlacementMoveInput,
4
4
  } from "@remit/data-ports";
5
5
  import { eq } from "drizzle-orm";
6
- import type { Db } from "../db.js";
6
+ import type { RepositoryDb } from "../db.js";
7
7
  import { messagePlacementMoveTable } from "../schema/i4-message-placement-move.js";
8
8
 
9
- type DB = Db<Record<string, unknown>>;
9
+ type DB = RepositoryDb<Record<string, unknown>>;
10
10
 
11
11
  export type { MessagePlacementMoveItem, PutMessagePlacementMoveInput };
12
12
  export type MessagePlacementMoveState = MessagePlacementMoveItem["state"];
@@ -6,13 +6,13 @@ import type {
6
6
  UpdateOrganizeJobRequestInput,
7
7
  } from "@remit/data-ports";
8
8
  import { eq } from "drizzle-orm";
9
- import type { Db } from "../db.js";
9
+ import type { RepositoryDb } from "../db.js";
10
10
  import { NotFoundError } from "../error.js";
11
11
  import { randomId } from "../id.js";
12
12
  import { decodeToken, resultList } from "../pagination.js";
13
13
  import { organizeJobRequestTable } from "../schema/i4-organize-job-request.js";
14
14
 
15
- type DB = Db<Record<string, unknown>>;
15
+ type DB = RepositoryDb<Record<string, unknown>>;
16
16
 
17
17
  function rowToItem(
18
18
  row: typeof organizeJobRequestTable.$inferSelect,
@@ -1,7 +1,8 @@
1
1
  import assert from "node:assert";
2
2
  import { after, before, describe, test } from "node:test";
3
+ import { createSqliteRepositories } from "../sqlite-repositories.js";
3
4
  import { createTestDb, randomId } from "../test-db.js";
4
- import { OutboxAttachmentRepo } from "./i4-outbox-attachment.js";
5
+ import type { OutboxAttachmentRepo } from "./i4-outbox-attachment.js";
5
6
 
6
7
  const CAP = { maxTotalBytes: 1000, maxCount: 3, nowSeconds: 1_000_000 };
7
8
 
@@ -27,7 +28,11 @@ const input = (
27
28
 
28
29
  before(async () => {
29
30
  harness = await createTestDb();
30
- repo = new OutboxAttachmentRepo(harness.db);
31
+ repo = createSqliteRepositories({
32
+ app: harness.db,
33
+ mail: harness.db,
34
+ search: harness.db,
35
+ }).outboxAttachment;
31
36
  });
32
37
 
33
38
  after(async () => {
@@ -7,13 +7,13 @@ import type {
7
7
  } from "@remit/data-ports";
8
8
  import { holdsRoom } from "@remit/data-ports";
9
9
  import { and, eq, gt, gte, lt, or, sum } from "drizzle-orm";
10
- import { runBatch } from "../batch.js";
11
- import type { Db } from "../db.js";
10
+ import type { WriteBatch } from "../batch.js";
11
+ import type { RepositoryDb, SqliteStore } from "../db.js";
12
12
  import { NotFoundError } from "../error.js";
13
13
  import { outboxAttachmentTable } from "../schema/i4-outbox-attachment.js";
14
14
  import { inList } from "./in-list.js";
15
15
 
16
- type DB = Db<Record<string, unknown>>;
16
+ type DB = RepositoryDb<Record<string, unknown>>;
17
17
 
18
18
  function rowToOutboxAttachment(
19
19
  row: typeof outboxAttachmentTable.$inferSelect,
@@ -35,7 +35,13 @@ function rowToOutboxAttachment(
35
35
  }
36
36
 
37
37
  export class OutboxAttachmentRepo implements IOutboxAttachmentRepository {
38
- constructor(private db: DB) {}
38
+ private readonly db: DB;
39
+ private readonly batch: WriteBatch;
40
+
41
+ constructor(store: SqliteStore<Record<string, unknown>>) {
42
+ this.db = store.db;
43
+ this.batch = store.batch;
44
+ }
39
45
 
40
46
  /**
41
47
  * The per-message cap. The insert, the read of the draft's live rows and a
@@ -60,7 +66,7 @@ export class OutboxAttachmentRepo implements IOutboxAttachmentRepository {
60
66
  gte(outboxAttachmentTable.reservationExpiresAt, cap.nowSeconds),
61
67
  ),
62
68
  );
63
- const [inserted, rows, removed] = await runBatch(this.db, [
69
+ const [inserted, rows, removed] = await this.batch([
64
70
  this.db
65
71
  .insert(outboxAttachmentTable)
66
72
  .values({
@@ -6,13 +6,13 @@ import type {
6
6
  UpdateOutboxMessageInput,
7
7
  } from "@remit/data-ports";
8
8
  import { and, desc, eq, lt, or } from "drizzle-orm";
9
- import type { Db } from "../db.js";
9
+ import type { RepositoryDb } from "../db.js";
10
10
  import { ForbiddenError, NotFoundError } from "../error.js";
11
11
  import { decodeToken, resultList } from "../pagination.js";
12
12
  import { outboxMessageTable } from "../schema/i4-outbox-message.js";
13
13
  import { inList } from "./in-list.js";
14
14
 
15
- type DB = Db<Record<string, unknown>>;
15
+ type DB = RepositoryDb<Record<string, unknown>>;
16
16
 
17
17
  function rowToOutboxMessage(
18
18
  row: typeof outboxMessageTable.$inferSelect,
@@ -4,11 +4,11 @@ import type {
4
4
  SenderSignerStandingItem,
5
5
  } from "@remit/data-ports";
6
6
  import { and, eq, sql } from "drizzle-orm";
7
- import type { Db } from "../db.js";
7
+ import type { RepositoryDb } from "../db.js";
8
8
  import { NotFoundError } from "../error.js";
9
9
  import { senderSignerStandingTable } from "../schema.js";
10
10
 
11
- type DB = Db<Record<string, unknown>>;
11
+ type DB = RepositoryDb<Record<string, unknown>>;
12
12
 
13
13
  function rowToStanding(
14
14
  row: typeof senderSignerStandingTable.$inferSelect,
@@ -6,13 +6,13 @@ import type {
6
6
  UpdateLabelInput,
7
7
  } from "@remit/data-ports";
8
8
  import { and, asc, eq, gt, or } from "drizzle-orm";
9
- import type { Db } from "../db.js";
9
+ import type { RepositoryDb } from "../db.js";
10
10
  import { NotFoundError } from "../error.js";
11
11
  import { randomId } from "../id.js";
12
12
  import { decodeToken, resultList } from "../pagination.js";
13
13
  import { labelTable } from "../schema.js";
14
14
 
15
- type DB = Db<Record<string, unknown>>;
15
+ type DB = RepositoryDb<Record<string, unknown>>;
16
16
 
17
17
  const normalize = (name: string): string => name.trim().toLowerCase();
18
18
 
@@ -5,15 +5,12 @@ import type {
5
5
  MessageFlagItem,
6
6
  } from "@remit/data-ports";
7
7
  import { and, eq } from "drizzle-orm";
8
- import type { Db } from "../db.js";
8
+ import type { RepositoryDb } from "../db.js";
9
9
  import { NotFoundError } from "../error.js";
10
- import {
11
- type MessageDataSchema,
12
- messageFlagTable,
13
- } from "../schema/message-data.js";
10
+ import { messageFlagTable } from "../schema/message-data.js";
14
11
  import { inList } from "./in-list.js";
15
12
 
16
- type DB = Db<MessageDataSchema>;
13
+ type DB = RepositoryDb<Record<string, unknown>>;
17
14
 
18
15
  function rowToMessageFlag(
19
16
  row: typeof messageFlagTable.$inferSelect,
@@ -4,12 +4,12 @@ import type {
4
4
  MessageLabelItem,
5
5
  } from "@remit/data-ports";
6
6
  import { and, desc, eq } from "drizzle-orm";
7
- import type { Db } from "../db.js";
7
+ import type { RepositoryDb } from "../db.js";
8
8
  import { deterministicBase36Id } from "../id.js";
9
9
  import { messageLabelTable } from "../schema.js";
10
10
  import { inList } from "./in-list.js";
11
11
 
12
- type DB = Db<Record<string, unknown>>;
12
+ type DB = RepositoryDb<Record<string, unknown>>;
13
13
 
14
14
  function rowToMessageLabel(
15
15
  row: typeof messageLabelTable.$inferSelect,
@@ -6,9 +6,9 @@ import {
6
6
  } from "../id.js";
7
7
  import { messageDataSchema } from "../schema/message-data.js";
8
8
  import { threadMessageTable } from "../schema/thread-message.js";
9
- import { SearchIndex } from "../search/thread-message-search.js";
9
+ import { createSqliteRepositories } from "../sqlite-repositories.js";
10
10
  import { createSqliteTestDb, type SqliteTestDb } from "../test-db-sqlite.js";
11
- import { DrizzleMessageRepository } from "./message.js";
11
+ import type { DrizzleMessageRepository } from "./message.js";
12
12
 
13
13
  const SCHEMA = { ...messageDataSchema, threadMessages: threadMessageTable };
14
14
 
@@ -43,7 +43,7 @@ describe("DrizzleMessageRepository (sqlite)", () => {
43
43
 
44
44
  before(async () => {
45
45
  ({ db, close } = await createSqliteTestDb(SCHEMA));
46
- repo = new DrizzleMessageRepository(db, new SearchIndex(db, db));
46
+ repo = createSqliteRepositories({ app: db, mail: db, search: db }).message;
47
47
  });
48
48
 
49
49
  after(async () => {
@@ -4,9 +4,9 @@ import {
4
4
  envelopeId as deriveEnvelopeId,
5
5
  rootBodyPartId as deriveRootBodyPartId,
6
6
  } from "../id.js";
7
- import { SearchIndex } from "../search/thread-message-search.js";
8
- import { DrizzleEnvelopeRepository } from "./envelope.js";
9
- import { DrizzleMessageRepository } from "./message.js";
7
+ import { createSqliteRepositories } from "../sqlite-repositories.js";
8
+ import type { DrizzleEnvelopeRepository } from "./envelope.js";
9
+ import type { DrizzleMessageRepository } from "./message.js";
10
10
  import { createTestDb, type TestDb } from "./test-helpers.js";
11
11
 
12
12
  describe("DrizzleMessageRepository", () => {
@@ -37,8 +37,9 @@ describe("DrizzleMessageRepository", () => {
37
37
 
38
38
  before(async () => {
39
39
  ({ db, stop } = await createTestDb());
40
- messageRepo = new DrizzleMessageRepository(db, new SearchIndex(db, db));
41
- envelopeRepo = new DrizzleEnvelopeRepository(db);
40
+ const repos = createSqliteRepositories({ app: db, mail: db, search: db });
41
+ messageRepo = repos.message;
42
+ envelopeRepo = repos.envelope;
42
43
  });
43
44
 
44
45
  after(async () => {
@@ -18,8 +18,8 @@ import {
18
18
  or,
19
19
  type SQL,
20
20
  } from "drizzle-orm";
21
- import { runBatch, type SqliteBatchItem } from "../batch.js";
22
- import type { Db } from "../db.js";
21
+ import type { SqliteBatchItem, WriteBatch } from "../batch.js";
22
+ import type { RepositoryDb, SqliteStore } from "../db.js";
23
23
  import {
24
24
  CreateFailedConflictError,
25
25
  isUniqueViolation,
@@ -37,7 +37,6 @@ import {
37
37
  bodyStructureRefetchTable,
38
38
  envelopeAddressTable,
39
39
  envelopeTable,
40
- type MessageDataSchema,
41
40
  messageFlagTable,
42
41
  messageReferenceTable,
43
42
  messageTable,
@@ -56,7 +55,7 @@ import {
56
55
  toRawMessageStorageItem,
57
56
  } from "./mappers.js";
58
57
 
59
- type DB = Db<MessageDataSchema>;
58
+ type DB = RepositoryDb<Record<string, unknown>>;
60
59
 
61
60
  function toMessageItem(row: typeof messageTable.$inferSelect): MessageItem {
62
61
  return {
@@ -112,7 +111,7 @@ function toMessageItem(row: typeof messageTable.$inferSelect): MessageItem {
112
111
  };
113
112
  }
114
113
 
115
- export type SubtreeDb = Pick<Db<Record<string, unknown>>, "delete">;
114
+ export type SubtreeDb = Pick<RepositoryDb<Record<string, unknown>>, "delete">;
116
115
 
117
116
  /**
118
117
  * The statements that delete a message and its whole per-message subtree by
@@ -193,10 +192,16 @@ const placementTerms = (expected: PlacementPredicate): SQL[] => {
193
192
  };
194
193
 
195
194
  export class DrizzleMessageRepository implements IMessageRepository {
195
+ private readonly db: DB;
196
+ private readonly batch: WriteBatch;
197
+
196
198
  constructor(
197
- private db: DB,
199
+ store: SqliteStore<Record<string, unknown>>,
198
200
  private search: SearchIndex,
199
- ) {}
201
+ ) {
202
+ this.db = store.db;
203
+ this.batch = store.batch;
204
+ }
200
205
 
201
206
  private rowOf(input: CreateMessageInput) {
202
207
  const now = Date.now();
@@ -462,7 +467,7 @@ export class DrizzleMessageRepository implements IMessageRepository {
462
467
  .select({ threadMessageId: threadMessageTable.threadMessageId })
463
468
  .from(threadMessageTable)
464
469
  .where(eq(threadMessageTable.messageId, messageId));
465
- const results = await runBatch(this.db, [
470
+ const results = await this.batch([
466
471
  this.db
467
472
  .delete(threadMessageTable)
468
473
  .where(and(eq(threadMessageTable.messageId, messageId), placed)),
@@ -475,7 +480,7 @@ export class DrizzleMessageRepository implements IMessageRepository {
475
480
 
476
481
  async deleteMany(messageIds: string[]): Promise<void> {
477
482
  if (messageIds.length === 0) return;
478
- await runBatch(this.db, deleteMessageSubtree(this.db, messageIds));
483
+ await this.batch(deleteMessageSubtree(this.db, messageIds));
479
484
  }
480
485
 
481
486
  async listByMailbox(
@@ -623,7 +628,7 @@ export class DrizzleMessageRepository implements IMessageRepository {
623
628
  .select({ threadMessageId: threadMessageTable.threadMessageId })
624
629
  .from(threadMessageTable)
625
630
  .where(eq(threadMessageTable.messageId, messageId));
626
- const [moved] = await runBatch(this.db, [
631
+ const [moved] = await this.batch([
627
632
  this.db
628
633
  .update(messageTable)
629
634
  .set({
@@ -6,10 +6,10 @@ import type {
6
6
  } from "@remit/data-ports";
7
7
  import { deriveQuarantineId } from "@remit/data-ports/id";
8
8
  import { desc, eq } from "drizzle-orm";
9
- import type { Db } from "../db.js";
9
+ import type { RepositoryDb } from "../db.js";
10
10
  import { quarantineTable } from "../schema/quarantine.js";
11
11
 
12
- type DB = Db<Record<string, unknown>>;
12
+ type DB = RepositoryDb<Record<string, unknown>>;
13
13
 
14
14
  function rowToItem(row: typeof quarantineTable.$inferSelect): QuarantineItem {
15
15
  return {
@@ -6,11 +6,11 @@ import type {
6
6
  } from "@remit/data-ports";
7
7
  import { deriveSyncWarningId } from "@remit/data-ports/id";
8
8
  import { and, count, desc, eq, gte, sql } from "drizzle-orm";
9
- import type { Db } from "../db.js";
9
+ import type { RepositoryDb } from "../db.js";
10
10
  import { syncWarningTable } from "../schema/sync-warning.js";
11
11
  import { inList } from "./in-list.js";
12
12
 
13
- type DB = Db<Record<string, unknown>>;
13
+ type DB = RepositoryDb<Record<string, unknown>>;
14
14
 
15
15
  export class SyncWarningRepo implements ISyncWarningRepository {
16
16
  constructor(private db: DB) {}
@@ -12,10 +12,10 @@ import { after, before, describe, test } from "node:test";
12
12
  import type { CreateThreadMessageInput } from "@remit/data-ports";
13
13
  import { addressTable } from "../schema/i4-address.js";
14
14
  import { threadMessageTable } from "../schema/thread-message.js";
15
- import { SearchIndex } from "../search/thread-message-search.js";
15
+ import { createSqliteRepositories } from "../sqlite-repositories.js";
16
16
  import { createSqliteTestDb } from "../test-db-sqlite.js";
17
17
  import { shippedIndexDdl } from "../test-shipped-sqlite-schema.js";
18
- import { DrizzleThreadMessageRepository } from "./thread-message.js";
18
+ import type { DrizzleThreadMessageRepository } from "./thread-message.js";
19
19
 
20
20
  // The index the mail baseline creates for this predicate, read from the one
21
21
  // committed source so the plan assertion below is about the real object.
@@ -61,7 +61,11 @@ describe("thread-message body and muted-sender predicates (sqlite)", () => {
61
61
  { searchIndex: true },
62
62
  ));
63
63
  sqlite.exec(mutedIndexDdl);
64
- repo = new DrizzleThreadMessageRepository(db, new SearchIndex(db, db));
64
+ repo = createSqliteRepositories({
65
+ app: db,
66
+ mail: db,
67
+ search: db,
68
+ }).threadMessage;
65
69
  });
66
70
 
67
71
  after(async () => {
@@ -2,10 +2,10 @@ import assert from "node:assert/strict";
2
2
  import { after, before, describe, test } from "node:test";
3
3
  import type { CreateThreadMessageInput } from "@remit/data-ports";
4
4
  import { threadMessageTable } from "../schema/thread-message.js";
5
- import { SearchIndex } from "../search/thread-message-search.js";
5
+ import { createSqliteRepositories } from "../sqlite-repositories.js";
6
6
  import { createSqliteTestDb } from "../test-db-sqlite.js";
7
7
  import {
8
- DrizzleThreadMessageRepository,
8
+ type DrizzleThreadMessageRepository,
9
9
  THREAD_SEARCH_MAX_LIMIT,
10
10
  } from "./thread-message.js";
11
11
 
@@ -55,10 +55,11 @@ describe("DrizzleThreadMessageRepository.listByFieldTerms (sqlite, #459)", () =>
55
55
  { searchIndex: true },
56
56
  );
57
57
  close = created.close;
58
- repo = new DrizzleThreadMessageRepository(
59
- created.db,
60
- new SearchIndex(created.db, created.db),
61
- );
58
+ repo = createSqliteRepositories({
59
+ app: created.db,
60
+ mail: created.db,
61
+ search: created.db,
62
+ }).threadMessage;
62
63
 
63
64
  await repo.create(
64
65
  makeInput({
@@ -2,7 +2,7 @@ import assert from "node:assert/strict";
2
2
  import { after, before, describe, test } from "node:test";
3
3
  import type { CreateThreadMessageInput } from "@remit/data-ports";
4
4
  import { threadMessageTable } from "../schema/thread-message.js";
5
- import { SearchIndex } from "../search/thread-message-search.js";
5
+ import { createSqliteRepositories } from "../sqlite-repositories.js";
6
6
  import { createSqliteTestDb } from "../test-db-sqlite.js";
7
7
  import {
8
8
  BASE_DATE,
@@ -12,7 +12,7 @@ import {
12
12
  totalRows,
13
13
  } from "./category-fixture.js";
14
14
  import {
15
- DrizzleThreadMessageRepository,
15
+ type DrizzleThreadMessageRepository,
16
16
  THREAD_SEARCH_MAX_LIMIT,
17
17
  } from "./thread-message.js";
18
18
 
@@ -58,7 +58,11 @@ describe("DrizzleThreadMessageRepository (sqlite)", () => {
58
58
  },
59
59
  { searchIndex: true },
60
60
  ));
61
- repo = new DrizzleThreadMessageRepository(db, new SearchIndex(db, db));
61
+ repo = createSqliteRepositories({
62
+ app: db,
63
+ mail: db,
64
+ search: db,
65
+ }).threadMessage;
62
66
  });
63
67
 
64
68
  after(async () => {
@@ -3,11 +3,11 @@ import { after, before, describe, test } from "node:test";
3
3
  import type { CreateThreadMessageInput } from "@remit/data-ports";
4
4
  import shortUuid from "short-uuid";
5
5
  import { threadMessageTable } from "../schema/thread-message.js";
6
- import { SearchIndex } from "../search/thread-message-search.js";
6
+ import { createSqliteRepositories } from "../sqlite-repositories.js";
7
7
  import { createSqliteTestDb } from "../test-db-sqlite.js";
8
8
  import {
9
9
  clampThreadSearchLimit,
10
- DrizzleThreadMessageRepository,
10
+ type DrizzleThreadMessageRepository,
11
11
  deriveThreadMessageId,
12
12
  THREAD_SEARCH_MAX_LIMIT,
13
13
  } from "./thread-message.js";
@@ -87,10 +87,11 @@ describe("DrizzleThreadMessageRepository.searchByMailboxWindow / countByMailbox"
87
87
  before(async () => {
88
88
  const harness = await setupDb();
89
89
  close = harness.close;
90
- repo = new DrizzleThreadMessageRepository(
91
- harness.db,
92
- new SearchIndex(harness.db, harness.db),
93
- );
90
+ repo = createSqliteRepositories({
91
+ app: harness.db,
92
+ mail: harness.db,
93
+ search: harness.db,
94
+ }).threadMessage;
94
95
  });
95
96
 
96
97
  after(async () => {
@@ -391,10 +392,11 @@ describe("DrizzleThreadMessageRepository.searchByDate", () => {
391
392
  before(async () => {
392
393
  const harness = await setupDb();
393
394
  close = harness.close;
394
- repo = new DrizzleThreadMessageRepository(
395
- harness.db,
396
- new SearchIndex(harness.db, harness.db),
397
- );
395
+ repo = createSqliteRepositories({
396
+ app: harness.db,
397
+ mail: harness.db,
398
+ search: harness.db,
399
+ }).threadMessage;
398
400
  });
399
401
 
400
402
  after(async () => {
@@ -921,10 +923,11 @@ describe("DrizzleThreadMessageRepository — native text search", () => {
921
923
  before(async () => {
922
924
  const harness = await setupDb();
923
925
  close = harness.close;
924
- repo = new DrizzleThreadMessageRepository(
925
- harness.db,
926
- new SearchIndex(harness.db, harness.db),
927
- );
926
+ repo = createSqliteRepositories({
927
+ app: harness.db,
928
+ mail: harness.db,
929
+ search: harness.db,
930
+ }).threadMessage;
928
931
  });
929
932
 
930
933
  after(async () => {
@@ -1096,10 +1099,11 @@ describe("DrizzleThreadMessageRepository — core CRUD", () => {
1096
1099
  before(async () => {
1097
1100
  const harness = await setupDb();
1098
1101
  close = harness.close;
1099
- repo = new DrizzleThreadMessageRepository(
1100
- harness.db,
1101
- new SearchIndex(harness.db, harness.db),
1102
- );
1102
+ repo = createSqliteRepositories({
1103
+ app: harness.db,
1104
+ mail: harness.db,
1105
+ search: harness.db,
1106
+ }).threadMessage;
1103
1107
  });
1104
1108
 
1105
1109
  after(async () => {