@remit/data-ports 0.0.17 → 0.0.19

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.17",
3
+ "version": "0.0.19",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -81,6 +81,30 @@ 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
+ const first = await repo.create({ accountConfigId, name: "First" });
89
+ const second = await repo.create({ accountConfigId, name: "Second" });
90
+ await repo.create({ accountConfigId: other, name: "Foreign" });
91
+
92
+ const page1 = await repo.listPageByAccountConfig(accountConfigId, {
93
+ limit: 1,
94
+ });
95
+ assert.equal(page1.items.length, 1);
96
+ assert.equal(page1.items[0]?.labelId, first.labelId);
97
+ assert.ok(page1.continuationToken);
98
+
99
+ const page2 = await repo.listPageByAccountConfig(accountConfigId, {
100
+ limit: 1,
101
+ continuationToken: page1.continuationToken,
102
+ });
103
+ assert.equal(page2.items.length, 1);
104
+ assert.equal(page2.items[0]?.labelId, second.labelId);
105
+ assert.equal(page2.continuationToken, undefined);
106
+ });
107
+
84
108
  test("delete removes the row", async () => {
85
109
  const accountConfigId = harness.makeId();
86
110
  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
  }
package/src/types.ts CHANGED
@@ -500,10 +500,14 @@ export type CreateFilterInput = Omit<
500
500
  };
501
501
 
502
502
  // ruleChangedAt is never client-supplied: FilterService derives it, bumping
503
- // only when a predicate/action field is present in the update (RFC 034
504
- // Decision 3.2) — a cosmetic `name` rename must not move it.
503
+ // only when the predicate, the action, scope, or expiresAt is present in the
504
+ // update (RFC 034 Decision 3.2, reader #266) — a cosmetic `name` rename must
505
+ // not move it. `scope` is updatable here (reader #266): the handler resolves
506
+ // the merged scope/expiresAt/ttl/state before calling through to the repo, so
507
+ // this type must carry `scope` as a valid key, unlike the API-facing
508
+ // `UpdateFilterInput` for that same reason.
505
509
  export type UpdateFilterInput = Partial<
506
- Omit<CreateFilterInput, "accountConfigId" | "scope">
510
+ Omit<CreateFilterInput, "accountConfigId">
507
511
  >;
508
512
 
509
513
  export type CreateFilterAnchorInput = Omit<