@remit/drizzle-service 0.0.71 → 0.0.72

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/drizzle-service",
3
- "version": "0.0.71",
3
+ "version": "0.0.72",
4
4
  "description": "Drizzle ORM service over SQLite",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -18,6 +18,7 @@ import {
18
18
  desc,
19
19
  eq,
20
20
  getTableColumns,
21
+ gt,
21
22
  inArray,
22
23
  type SQL,
23
24
  sql,
@@ -748,6 +749,40 @@ export class AddressRepo implements IAddressRepository {
748
749
  );
749
750
  }
750
751
 
752
+ async listAllByAccountConfigPage(input: {
753
+ accountConfigId: string;
754
+ cursor?: string;
755
+ limit?: number;
756
+ }): Promise<ResultList<AddressItem>> {
757
+ const { accountConfigId, cursor, limit = 100 } = input;
758
+ const afterAddressId = cursor
759
+ ? (decodeToken(cursor).addressId as string)
760
+ : undefined;
761
+
762
+ const rows = await this.db
763
+ .select()
764
+ .from(addressTable)
765
+ .where(
766
+ and(
767
+ eq(addressTable.accountConfigId, accountConfigId),
768
+ afterAddressId
769
+ ? gt(addressTable.addressId, afterAddressId)
770
+ : undefined,
771
+ ),
772
+ )
773
+ .orderBy(asc(addressTable.addressId))
774
+ .limit(limit + 1);
775
+
776
+ const hasMore = rows.length > limit;
777
+ const items = rows.slice(0, limit).map(rowToAddress);
778
+ const lastItem = items[items.length - 1];
779
+ return resultList(
780
+ items,
781
+ limit,
782
+ hasMore && lastItem ? { addressId: lastItem.addressId } : undefined,
783
+ );
784
+ }
785
+
751
786
  async createEnvelopeAddress(
752
787
  input: CreateEnvelopeAddressInput,
753
788
  ): Promise<EnvelopeAddressItem> {
@@ -224,6 +224,59 @@ describe("OutboxMessageRepo", () => {
224
224
  await repo.deleteMany(accountConfigId, created);
225
225
  });
226
226
 
227
+ test("listByAccounts pages one ordering over every account (#1013)", async () => {
228
+ const accountConfigId = randomId();
229
+ const first = randomId();
230
+ const second = randomId();
231
+ const created: string[] = [];
232
+ const byAccount = new Map<string, string[]>([
233
+ [first, []],
234
+ [second, []],
235
+ ]);
236
+ for (let i = 0; i < 6; i++) {
237
+ const accountId = i % 2 === 0 ? first : second;
238
+ const msg = await repo.create(
239
+ makeOutboxInput(accountId, accountConfigId),
240
+ );
241
+ created.push(msg.outboxMessageId);
242
+ byAccount.get(accountId)?.push(msg.outboxMessageId);
243
+ }
244
+
245
+ const wholeList = await repo.listByAccounts([first, second]);
246
+ const wholeIds = wholeList.items.map((m) => m.outboxMessageId);
247
+ for (const ids of byAccount.values()) {
248
+ for (const id of ids) {
249
+ assert.ok(wholeIds.includes(id), "every account's rows come back");
250
+ }
251
+ }
252
+
253
+ const seen: string[] = [];
254
+ let continuationToken: string | undefined;
255
+ let pages = 0;
256
+ do {
257
+ const page = await repo.listByAccounts([first, second], {
258
+ limit: 2,
259
+ continuationToken,
260
+ });
261
+ seen.push(...page.items.map((m) => m.outboxMessageId));
262
+ continuationToken = page.continuationToken;
263
+ pages++;
264
+ assert.ok(pages < 10, "pagination must terminate");
265
+ } while (continuationToken);
266
+
267
+ assert.equal(seen.length, 6, "every row returned exactly once");
268
+ assert.equal(new Set(seen).size, 6, "no duplicates across pages");
269
+ assert.deepEqual([...seen].sort(), [...created].sort(), "no gaps");
270
+
271
+ await repo.deleteMany(accountConfigId, created);
272
+ });
273
+
274
+ test("listByAccounts answers no accounts with no rows", async () => {
275
+ const list = await repo.listByAccounts([]);
276
+ assert.deepEqual(list.items, []);
277
+ assert.equal(list.continuationToken, undefined);
278
+ });
279
+
227
280
  test("listQueued returns only queued messages", async () => {
228
281
  const accountId = randomId();
229
282
  const accountConfigId = randomId();
@@ -272,8 +272,17 @@ export class OutboxMessageRepo implements IOutboxMessageRepository {
272
272
  async listByAccount(
273
273
  accountId: string,
274
274
  options?: { limit?: number; continuationToken?: string },
275
+ ): Promise<ResultList<OutboxMessageItem>> {
276
+ return this.listByAccounts([accountId], options);
277
+ }
278
+
279
+ async listByAccounts(
280
+ accountIds: string[],
281
+ options?: { limit?: number; continuationToken?: string },
275
282
  ): Promise<ResultList<OutboxMessageItem>> {
276
283
  const limit = options?.limit ?? 100;
284
+ if (accountIds.length === 0) return resultList([], limit);
285
+
277
286
  const cursor = options?.continuationToken
278
287
  ? decodeToken(options.continuationToken)
279
288
  : undefined;
@@ -289,7 +298,7 @@ export class OutboxMessageRepo implements IOutboxMessageRepository {
289
298
  .from(outboxMessageTable)
290
299
  .where(
291
300
  and(
292
- eq(outboxMessageTable.accountId, accountId),
301
+ inArray(outboxMessageTable.accountId, accountIds),
293
302
  after
294
303
  ? or(
295
304
  lt(outboxMessageTable.createdAt, after.createdAt),