@remit/data-ports 0.0.19 → 0.0.21
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
package/src/conformance/label.ts
CHANGED
|
@@ -85,15 +85,20 @@ export function labelRepositoryConformance(
|
|
|
85
85
|
const accountConfigId = harness.makeId();
|
|
86
86
|
const other = harness.makeId();
|
|
87
87
|
|
|
88
|
-
|
|
89
|
-
|
|
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
|
+
]);
|
|
90
96
|
await repo.create({ accountConfigId: other, name: "Foreign" });
|
|
91
97
|
|
|
92
98
|
const page1 = await repo.listPageByAccountConfig(accountConfigId, {
|
|
93
99
|
limit: 1,
|
|
94
100
|
});
|
|
95
101
|
assert.equal(page1.items.length, 1);
|
|
96
|
-
assert.equal(page1.items[0]?.labelId, first.labelId);
|
|
97
102
|
assert.ok(page1.continuationToken);
|
|
98
103
|
|
|
99
104
|
const page2 = await repo.listPageByAccountConfig(accountConfigId, {
|
|
@@ -101,8 +106,20 @@ export function labelRepositoryConformance(
|
|
|
101
106
|
continuationToken: page1.continuationToken,
|
|
102
107
|
});
|
|
103
108
|
assert.equal(page2.items.length, 1);
|
|
104
|
-
assert.equal(page2.items[0]?.labelId, second.labelId);
|
|
105
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
|
+
}
|
|
106
123
|
});
|
|
107
124
|
|
|
108
125
|
test("delete removes the row", async () => {
|
package/src/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ export type { IAddressRepository } from "./interfaces/address.js";
|
|
|
6
6
|
export type { IEnvelopeRepository } from "./interfaces/envelope.js";
|
|
7
7
|
export type { IFilterRepository } from "./interfaces/filter.js";
|
|
8
8
|
export type { IFilterAnchorRepository } from "./interfaces/filter-anchor.js";
|
|
9
|
+
export type { IFilterAnchorTransaction } from "./interfaces/filter-anchor-transaction.js";
|
|
9
10
|
export type { ILabelRepository } from "./interfaces/label.js";
|
|
10
11
|
export type { IMailboxRepository } from "./interfaces/mailbox.js";
|
|
11
12
|
export type { IMailboxLockRepository } from "./interfaces/mailbox-lock.js";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CreateFilterAnchorInput,
|
|
3
|
+
CreateFilterInput,
|
|
4
|
+
FilterItem,
|
|
5
|
+
} from "../types.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Atomically creates a `Filter` row and its optional sibling `FilterAnchor`
|
|
9
|
+
* row (#351). Without this, the two writes ran sequentially: a failure on the
|
|
10
|
+
* second left a `Filter` durably marked `hasAnchor: true` with no matching
|
|
11
|
+
* `FilterAnchor` row — a filter that looks normal but silently matches
|
|
12
|
+
* nothing, forever, with no repair path (the anchor message id is never
|
|
13
|
+
* retained once `createFilterWithAnchor` returns).
|
|
14
|
+
*
|
|
15
|
+
* `anchor` omits `filterId` — it is not known until the `Filter` row is
|
|
16
|
+
* created inside the same transaction.
|
|
17
|
+
*/
|
|
18
|
+
export interface IFilterAnchorTransaction {
|
|
19
|
+
createWithAnchor(
|
|
20
|
+
filter: CreateFilterInput,
|
|
21
|
+
anchor: Omit<CreateFilterAnchorInput, "filterId"> | null,
|
|
22
|
+
): Promise<FilterItem>;
|
|
23
|
+
}
|