@remit/data-ports 0.0.18 → 0.0.20

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remit/data-ports",
3
- "version": "0.0.18",
3
+ "version": "0.0.20",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -81,6 +81,47 @@ export function labelRepositoryConformance(
81
81
  assert.equal(missing, null);
82
82
  });
83
83
 
84
+ test("listPageByAccountConfig pages through an account's labels, scoped to the account", async () => {
85
+ const accountConfigId = harness.makeId();
86
+ const other = harness.makeId();
87
+
88
+ // Created concurrently so their `createdAt` millisecond can tie (as it
89
+ // reliably does against the synchronous sqlite driver): the keyset's
90
+ // `labelId` tiebreak then decides order, so this asserts pagination is
91
+ // exhaustive and duplicate-free rather than a specific creation order.
92
+ const created = await Promise.all([
93
+ repo.create({ accountConfigId, name: "First" }),
94
+ repo.create({ accountConfigId, name: "Second" }),
95
+ ]);
96
+ await repo.create({ accountConfigId: other, name: "Foreign" });
97
+
98
+ const page1 = await repo.listPageByAccountConfig(accountConfigId, {
99
+ limit: 1,
100
+ });
101
+ assert.equal(page1.items.length, 1);
102
+ assert.ok(page1.continuationToken);
103
+
104
+ const page2 = await repo.listPageByAccountConfig(accountConfigId, {
105
+ limit: 1,
106
+ continuationToken: page1.continuationToken,
107
+ });
108
+ assert.equal(page2.items.length, 1);
109
+ assert.equal(page2.continuationToken, undefined);
110
+
111
+ const seen = new Set([
112
+ ...page1.items.map((label) => label.labelId),
113
+ ...page2.items.map((label) => label.labelId),
114
+ ]);
115
+ assert.equal(
116
+ seen.size,
117
+ created.length,
118
+ "every label is paged exactly once",
119
+ );
120
+ for (const label of created) {
121
+ assert.ok(seen.has(label.labelId));
122
+ }
123
+ });
124
+
84
125
  test("delete removes the row", async () => {
85
126
  const accountConfigId = harness.makeId();
86
127
  const label = await repo.create({ accountConfigId, name: "Gone" });
@@ -1,6 +1,7 @@
1
1
  import type {
2
2
  CreateLabelInput,
3
3
  LabelItem,
4
+ ResultList,
4
5
  UpdateLabelInput,
5
6
  } from "../types.js";
6
7
 
@@ -14,6 +15,14 @@ export interface ILabelRepository {
14
15
  ): Promise<LabelItem>;
15
16
  delete(accountConfigId: string, labelId: string): Promise<void>;
16
17
  listByAccountConfig(accountConfigId: string): Promise<LabelItem[]>;
18
+ /**
19
+ * A single signed page of an account config's labels (issue #26), mirroring
20
+ * `IFilterRepository.listPageByAccountConfig` — the settings-page/API list.
21
+ */
22
+ listPageByAccountConfig(
23
+ accountConfigId: string,
24
+ options?: { limit?: number; continuationToken?: string },
25
+ ): Promise<ResultList<LabelItem>>;
17
26
  findByNormalizedName(
18
27
  accountConfigId: string,
19
28
  normalizedName: string,
@@ -4,8 +4,22 @@ export interface IMessageLabelRepository {
4
4
  apply(input: CreateMessageLabelInput): Promise<MessageLabelItem>;
5
5
  remove(messageId: string, labelId: string): Promise<void>;
6
6
  listByMessageId(messageId: string): Promise<MessageLabelItem[]>;
7
+ /**
8
+ * Batch-fetch every MessageLabel row across a page of messages in one query
9
+ * — the read-time enrichment a thread listing needs (issue #26), mirroring
10
+ * the one-BatchGet-per-page contract `enrichThreadRows` already holds for
11
+ * Message/Address.
12
+ */
13
+ listByMessageIds(messageIds: string[]): Promise<MessageLabelItem[]>;
7
14
  listByLabelId(
8
15
  accountConfigId: string,
9
16
  labelId: string,
10
17
  ): Promise<MessageLabelItem[]>;
18
+ /**
19
+ * Delete every MessageLabel row for a label in one statement — the message
20
+ * side of a label delete's cascade (issue #26). A label delete cascades in
21
+ * both directions: this clears the applied-to-messages side, and the
22
+ * caller separately deletes any filter whose actionLabelId is this label.
23
+ */
24
+ removeAllByLabelId(accountConfigId: string, labelId: string): Promise<void>;
11
25
  }