@powersync/service-module-postgres-storage 0.0.0-dev-20260602073133 → 0.0.0-dev-20260803144812

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 (105) hide show
  1. package/CHANGELOG.md +101 -6
  2. package/dist/migrations/scripts/1782950400000-checkpoint-requested-at.d.ts +3 -0
  3. package/dist/migrations/scripts/1782950400000-checkpoint-requested-at.js +42 -0
  4. package/dist/migrations/scripts/1782950400000-checkpoint-requested-at.js.map +1 -0
  5. package/dist/{@types/storage → storage}/PostgresBucketStorageFactory.d.ts +13 -12
  6. package/dist/storage/PostgresBucketStorageFactory.js +59 -55
  7. package/dist/storage/PostgresBucketStorageFactory.js.map +1 -1
  8. package/dist/{@types/storage → storage}/PostgresCompactor.d.ts +3 -1
  9. package/dist/storage/PostgresCompactor.js +21 -1
  10. package/dist/storage/PostgresCompactor.js.map +1 -1
  11. package/dist/storage/PostgresReportStorage.js.map +1 -1
  12. package/dist/storage/PostgresStorageProvider.js +2 -1
  13. package/dist/storage/PostgresStorageProvider.js.map +1 -1
  14. package/dist/{@types/storage → storage}/PostgresSyncRulesStorage.d.ts +36 -11
  15. package/dist/storage/PostgresSyncRulesStorage.js +250 -177
  16. package/dist/storage/PostgresSyncRulesStorage.js.map +1 -1
  17. package/dist/{@types/storage → storage}/batch/PostgresBucketBatch.d.ts +8 -24
  18. package/dist/storage/batch/PostgresBucketBatch.js +229 -194
  19. package/dist/storage/batch/PostgresBucketBatch.js.map +1 -1
  20. package/dist/{@types/storage → storage}/checkpoints/PostgresWriteCheckpointAPI.d.ts +1 -1
  21. package/dist/storage/checkpoints/PostgresWriteCheckpointAPI.js +161 -24
  22. package/dist/storage/checkpoints/PostgresWriteCheckpointAPI.js.map +1 -1
  23. package/dist/{@types/storage → storage}/current-data-store.d.ts +8 -2
  24. package/dist/storage/current-data-store.js +66 -11
  25. package/dist/storage/current-data-store.js.map +1 -1
  26. package/dist/{@types/storage → storage}/storage-index.d.ts +1 -0
  27. package/dist/storage/storage-index.js +1 -0
  28. package/dist/storage/storage-index.js.map +1 -1
  29. package/dist/storage/sync-rules/PostgresPersistedSyncConfigContent.d.ts +17 -0
  30. package/dist/storage/sync-rules/PostgresPersistedSyncConfigContent.js +90 -0
  31. package/dist/storage/sync-rules/PostgresPersistedSyncConfigContent.js.map +1 -0
  32. package/dist/{@types/types → types}/models/WriteCheckpoint.d.ts +2 -0
  33. package/dist/types/models/WriteCheckpoint.js +5 -2
  34. package/dist/types/models/WriteCheckpoint.js.map +1 -1
  35. package/dist/utils/checkpoints.d.ts +9 -0
  36. package/dist/utils/checkpoints.js +26 -0
  37. package/dist/utils/checkpoints.js.map +1 -0
  38. package/dist/utils/test-utils.js +2 -2
  39. package/dist/utils/test-utils.js.map +1 -1
  40. package/package.json +10 -22
  41. package/src/migrations/scripts/1782950400000-checkpoint-requested-at.ts +51 -0
  42. package/src/storage/PostgresBucketStorageFactory.ts +67 -58
  43. package/src/storage/PostgresCompactor.ts +25 -1
  44. package/src/storage/PostgresReportStorage.ts +1 -2
  45. package/src/storage/PostgresStorageProvider.ts +2 -1
  46. package/src/storage/PostgresSyncRulesStorage.ts +275 -191
  47. package/src/storage/batch/PostgresBucketBatch.ts +256 -214
  48. package/src/storage/checkpoints/PostgresWriteCheckpointAPI.ts +174 -24
  49. package/src/storage/current-data-store.ts +66 -11
  50. package/src/storage/storage-index.ts +1 -0
  51. package/src/storage/sync-rules/PostgresPersistedSyncConfigContent.ts +98 -0
  52. package/src/types/models/WriteCheckpoint.ts +5 -2
  53. package/src/utils/checkpoints.ts +31 -0
  54. package/src/utils/test-utils.ts +2 -2
  55. package/test/src/__snapshots__/storage_sync.test.ts.snap +0 -582
  56. package/test/src/checkpoint_notifications.test.ts +522 -0
  57. package/test/src/migrations.test.ts +1 -1
  58. package/test/src/storage.test.ts +226 -10
  59. package/test/src/storage_compacting.test.ts +15 -7
  60. package/test/src/storage_sync.test.ts +11 -8
  61. package/test/tsconfig.json +1 -3
  62. package/tsconfig.json +1 -4
  63. package/tsconfig.tsbuildinfo +1 -0
  64. package/dist/.tsbuildinfo +0 -1
  65. package/dist/@types/storage/sync-rules/PostgresPersistedSyncRulesContent.d.ts +0 -9
  66. package/dist/storage/sync-rules/PostgresPersistedSyncRulesContent.js +0 -49
  67. package/dist/storage/sync-rules/PostgresPersistedSyncRulesContent.js.map +0 -1
  68. package/src/storage/sync-rules/PostgresPersistedSyncRulesContent.ts +0 -54
  69. /package/dist/{@types/index.d.ts → index.d.ts} +0 -0
  70. /package/dist/{@types/migrations → migrations}/PostgresMigrationAgent.d.ts +0 -0
  71. /package/dist/{@types/migrations → migrations}/PostgresMigrationStore.d.ts +0 -0
  72. /package/dist/{@types/migrations → migrations}/migration-utils.d.ts +0 -0
  73. /package/dist/{@types/migrations → migrations}/scripts/1684951997326-init.d.ts +0 -0
  74. /package/dist/{@types/migrations → migrations}/scripts/1749024804042-snapshot-progress.d.ts +0 -0
  75. /package/dist/{@types/migrations → migrations}/scripts/1756282360128-connection-reporting.d.ts +0 -0
  76. /package/dist/{@types/migrations → migrations}/scripts/1771232439485-storage-version.d.ts +0 -0
  77. /package/dist/{@types/migrations → migrations}/scripts/1771424826685-current-data-pending-deletes.d.ts +0 -0
  78. /package/dist/{@types/migrations → migrations}/scripts/1771491856000-sync-plan.d.ts +0 -0
  79. /package/dist/{@types/module → module}/PostgresStorageModule.d.ts +0 -0
  80. /package/dist/{@types/storage → storage}/PostgresReportStorage.d.ts +0 -0
  81. /package/dist/{@types/storage → storage}/PostgresStorageProvider.d.ts +0 -0
  82. /package/dist/{@types/storage → storage}/batch/OperationBatch.d.ts +0 -0
  83. /package/dist/{@types/storage → storage}/batch/PostgresPersistedBatch.d.ts +0 -0
  84. /package/dist/{@types/storage → storage}/table-id.d.ts +0 -0
  85. /package/dist/{@types/types → types}/codecs.d.ts +0 -0
  86. /package/dist/{@types/types → types}/models/ActiveCheckpoint.d.ts +0 -0
  87. /package/dist/{@types/types → types}/models/ActiveCheckpointNotification.d.ts +0 -0
  88. /package/dist/{@types/types → types}/models/BucketData.d.ts +0 -0
  89. /package/dist/{@types/types → types}/models/BucketParameters.d.ts +0 -0
  90. /package/dist/{@types/types → types}/models/CurrentData.d.ts +0 -0
  91. /package/dist/{@types/types → types}/models/Instance.d.ts +0 -0
  92. /package/dist/{@types/types → types}/models/Migration.d.ts +0 -0
  93. /package/dist/{@types/types → types}/models/SdkReporting.d.ts +0 -0
  94. /package/dist/{@types/types → types}/models/SourceTable.d.ts +0 -0
  95. /package/dist/{@types/types → types}/models/SyncRules.d.ts +0 -0
  96. /package/dist/{@types/types → types}/models/json.d.ts +0 -0
  97. /package/dist/{@types/types → types}/models/models-index.d.ts +0 -0
  98. /package/dist/{@types/types → types}/types.d.ts +0 -0
  99. /package/dist/{@types/utils → utils}/application-name.d.ts +0 -0
  100. /package/dist/{@types/utils → utils}/bson.d.ts +0 -0
  101. /package/dist/{@types/utils → utils}/bucket-data.d.ts +0 -0
  102. /package/dist/{@types/utils → utils}/db.d.ts +0 -0
  103. /package/dist/{@types/utils → utils}/test-utils.d.ts +0 -0
  104. /package/dist/{@types/utils → utils}/ts-codec.d.ts +0 -0
  105. /package/dist/{@types/utils → utils}/utils-index.d.ts +0 -0
@@ -1,8 +1,14 @@
1
- import { storage, updateSyncRulesFromYaml } from '@powersync/service-core';
1
+ import { framework, storage, updateSyncRulesFromYaml } from '@powersync/service-core';
2
2
  import { bucketRequest, register, test_utils } from '@powersync/service-core-tests';
3
+ import * as t from 'ts-codec';
3
4
  import { describe, expect, test } from 'vitest';
5
+ import { CLEAR_BATCH_LIMIT } from '../../src/storage/PostgresSyncRulesStorage.js';
4
6
  import { POSTGRES_STORAGE_FACTORY, TEST_STORAGE_VERSIONS } from './util.js';
5
7
 
8
+ const CheckpointRequestedAtRow = t.object({
9
+ checkpoint_requested_at: t.Null.or(framework.codecs.date)
10
+ });
11
+
6
12
  describe('Sync Bucket Validation', register.registerBucketValidationTests);
7
13
 
8
14
  for (let storageVersion of TEST_STORAGE_VERSIONS) {
@@ -10,12 +16,219 @@ for (let storageVersion of TEST_STORAGE_VERSIONS) {
10
16
  register.registerDataStorageParameterTests({ ...POSTGRES_STORAGE_FACTORY, storageVersion }));
11
17
 
12
18
  describe(`Postgres Sync Bucket Storage - Data - v${storageVersion}`, () =>
13
- register.registerDataStorageDataTests({ ...POSTGRES_STORAGE_FACTORY, storageVersion }));
19
+ register.registerDataStorageDataTests({
20
+ ...POSTGRES_STORAGE_FACTORY,
21
+ storageVersion,
22
+ compressedBucketStorage: false
23
+ }));
14
24
 
15
25
  describe(`Postgres Sync Bucket Storage - Checkpoints - v${storageVersion}`, () =>
16
26
  register.registerDataStorageCheckpointTests({ ...POSTGRES_STORAGE_FACTORY, storageVersion }));
17
27
 
18
28
  describe(`Postgres Sync Bucket Storage - pg-specific - v${storageVersion}`, () => {
29
+ test('uses checkpoint_requested_at as the client-requested checkpoint marker', async () => {
30
+ await using factory = await POSTGRES_STORAGE_FACTORY.factory();
31
+ const syncRules = await factory.updateSyncRules(
32
+ updateSyncRulesFromYaml(
33
+ `
34
+ bucket_definitions:
35
+ global:
36
+ data: []
37
+ `,
38
+ { storageVersion }
39
+ )
40
+ );
41
+ const bucketStorage = factory.getInstance(syncRules);
42
+ const requestedAt = async (userId = 'user1') =>
43
+ (
44
+ await factory.db.sql`
45
+ SELECT
46
+ checkpoint_requested_at
47
+ FROM
48
+ write_checkpoints
49
+ WHERE
50
+ user_id = ${{ type: 'varchar', value: userId }}
51
+ `
52
+ .decoded(CheckpointRequestedAtRow)
53
+ .first()
54
+ )?.checkpoint_requested_at;
55
+
56
+ await bucketStorage.createManagedWriteCheckpoints([
57
+ { user_id: 'user1', heads: { '1': '5/0' }, checkpoint_request_id: 42n }
58
+ ]);
59
+ const requested = await requestedAt();
60
+ expect(requested).toBeInstanceOf(Date);
61
+
62
+ await bucketStorage.createManagedWriteCheckpoints([
63
+ { user_id: 'user1', heads: { '1': '6/0' }, checkpoint_request_id: 41n }
64
+ ]);
65
+ await expect(requestedAt()).resolves.toEqual(requested);
66
+
67
+ const expiredRequestedAt = new Date('2024-01-01T00:00:00.000Z');
68
+ await factory.db.sql`
69
+ UPDATE write_checkpoints
70
+ SET
71
+ checkpoint_requested_at = ${{ type: 1184, value: expiredRequestedAt.toISOString() }}
72
+ WHERE
73
+ user_id = 'user1'
74
+ `.execute();
75
+ await bucketStorage.createManagedWriteCheckpoints([
76
+ { user_id: 'user1', heads: { '1': '6/0' }, checkpoint_request_id: 42n }
77
+ ]);
78
+ // Retrying the current id refreshes its retention timestamp. The shared
79
+ // checkpoint tests verify that the original source head is preserved.
80
+ expect((await requestedAt())!.getTime()).toBeGreaterThan(expiredRequestedAt.getTime());
81
+
82
+ await factory.db.sql`
83
+ UPDATE write_checkpoints
84
+ SET
85
+ checkpoint_requested_at = ${{ type: 1184, value: expiredRequestedAt.toISOString() }}
86
+ WHERE
87
+ user_id = 'user1'
88
+ `.execute();
89
+ await bucketStorage.createManagedWriteCheckpoints([
90
+ { user_id: 'user1', heads: { '1': '6/0' }, checkpoint_request_id: 43n }
91
+ ]);
92
+ // A greater id refreshes retention while advancing the stored checkpoint.
93
+ expect((await requestedAt())!.getTime()).toBeGreaterThan(expiredRequestedAt.getTime());
94
+
95
+ await bucketStorage.createManagedWriteCheckpoints([{ user_id: 'user1', heads: { '1': '7/0' } }]);
96
+ await expect(requestedAt()).resolves.toBeNull();
97
+
98
+ await bucketStorage.createManagedWriteCheckpoints([
99
+ { user_id: 'user2', heads: { '1': '8/0' }, checkpoint_request_id: 50n }
100
+ ]);
101
+ await factory.db.sql`
102
+ UPDATE write_checkpoints
103
+ SET
104
+ checkpoint_requested_at = ${{ type: 1184, value: '2024-01-01T00:00:00.000Z' }}
105
+ WHERE
106
+ user_id = 'user2'
107
+ `.execute();
108
+ await bucketStorage.compact({
109
+ compactBuckets: [],
110
+ deleteCheckpointRequestsBefore: new Date('2024-02-01T00:00:00.000Z')
111
+ });
112
+ // Compaction removes expired requests based on the refreshed timestamp.
113
+ await expect(requestedAt('user2')).resolves.toBeUndefined();
114
+
115
+ const customRequestedAt = async (userId = 'custom1') =>
116
+ (
117
+ await factory.db.sql`
118
+ SELECT
119
+ checkpoint_requested_at
120
+ FROM
121
+ custom_write_checkpoints
122
+ WHERE
123
+ user_id = ${{ type: 'varchar', value: userId }}
124
+ `
125
+ .decoded(CheckpointRequestedAtRow)
126
+ .first()
127
+ )?.checkpoint_requested_at;
128
+
129
+ bucketStorage.setWriteCheckpointMode(storage.WriteCheckpointMode.CUSTOM);
130
+ await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
131
+ await writer.markAllSnapshotDone('1/1');
132
+ const customCheckpointRequestedAt = new Date('2024-01-01T00:00:00.000Z');
133
+ writer.addCustomWriteCheckpoint({
134
+ user_id: 'custom1',
135
+ checkpoint: 51n,
136
+ checkpoint_requested_at: customCheckpointRequestedAt
137
+ });
138
+ await writer.flush();
139
+ await expect(customRequestedAt()).resolves.toEqual(customCheckpointRequestedAt);
140
+
141
+ writer.addCustomWriteCheckpoint({
142
+ user_id: 'custom1',
143
+ checkpoint: 52n
144
+ });
145
+ await writer.flush();
146
+ await expect(customRequestedAt()).resolves.toBeNull();
147
+ });
148
+
149
+ test('clears storage in batches', async () => {
150
+ await using factory = await POSTGRES_STORAGE_FACTORY.factory();
151
+ const syncRules = await factory.updateSyncRules(
152
+ updateSyncRulesFromYaml(
153
+ `
154
+ bucket_definitions:
155
+ global:
156
+ data: []
157
+ `,
158
+ { storageVersion }
159
+ )
160
+ );
161
+ const bucketStorage = factory.getInstance(syncRules);
162
+ const groupId = bucketStorage.replicationStreamId;
163
+ const otherGroupId = groupId + 1;
164
+ const currentDataTable = bucketStorage.storageConfig.softDeleteCurrentData ? 'v3_current_data' : 'current_data';
165
+
166
+ // Seed more than one batch of bucket data, plus rows in the other tables,
167
+ // directly - clear() only depends on group_id.
168
+ const seed = async (gid: number, bucketDataRows: number) => {
169
+ await factory.db.query({
170
+ statement: `
171
+ INSERT INTO bucket_data (group_id, bucket_name, op_id, op, checksum)
172
+ SELECT $1, 'global[]', i, 'PUT', 0 FROM generate_series(1, $2) i
173
+ `,
174
+ params: [
175
+ { type: 'int4', value: gid },
176
+ { type: 'int4', value: bucketDataRows }
177
+ ]
178
+ });
179
+ await factory.db.query({
180
+ statement: `
181
+ INSERT INTO bucket_parameters (group_id, source_table, source_key, lookup, bucket_parameters)
182
+ SELECT $1, 'test', int4send(i), ''::bytea, '[]' FROM generate_series(1, 10) i
183
+ `,
184
+ params: [{ type: 'int4', value: gid }]
185
+ });
186
+ await factory.db.query({
187
+ statement: `
188
+ INSERT INTO ${currentDataTable} (group_id, source_table, source_key, buckets, data, lookups)
189
+ SELECT $1, 'test', int4send(i), '[]', ''::bytea, '{}' FROM generate_series(1, 10) i
190
+ `,
191
+ params: [{ type: 'int4', value: gid }]
192
+ });
193
+ await factory.db.query({
194
+ statement: `
195
+ INSERT INTO source_tables (id, group_id, connection_id, schema_name, table_name)
196
+ VALUES ($2, $1, 1, 'public', 'test')
197
+ `,
198
+ params: [
199
+ { type: 'int4', value: gid },
200
+ { type: 'varchar', value: `test-${gid}` }
201
+ ]
202
+ });
203
+ };
204
+ await seed(groupId, CLEAR_BATCH_LIMIT + 100);
205
+ await seed(otherGroupId, 10);
206
+
207
+ const countRows = async (table: string, gid: number) => {
208
+ const [row] = await factory.db.queryRows<{ count: bigint }>({
209
+ statement: `SELECT COUNT(*) AS count FROM ${table} WHERE group_id = $1`,
210
+ params: [{ type: 'int4', value: gid }]
211
+ });
212
+ return Number(row.count);
213
+ };
214
+
215
+ await bucketStorage.clear();
216
+
217
+ for (const table of ['bucket_data', 'bucket_parameters', currentDataTable, 'source_tables']) {
218
+ expect(await countRows(table, groupId), table).toEqual(0);
219
+ }
220
+ // Rows of other groups are not affected.
221
+ expect(await countRows('bucket_data', otherGroupId)).toEqual(10);
222
+ expect(await countRows('bucket_parameters', otherGroupId)).toEqual(10);
223
+ expect(await countRows(currentDataTable, otherGroupId)).toEqual(10);
224
+ expect(await countRows('source_tables', otherGroupId)).toEqual(1);
225
+
226
+ // An aborted signal stops the operation.
227
+ await expect(bucketStorage.clear({ signal: AbortSignal.abort() })).rejects.toThrow(
228
+ framework.ReplicationAbortedError
229
+ );
230
+ });
231
+
19
232
  /**
20
233
  * The split of returned results can vary depending on storage drivers.
21
234
  * The large rows here are 2MB large while the default chunk limit is 1mb.
@@ -39,7 +252,8 @@ for (let storageVersion of TEST_STORAGE_VERSIONS) {
39
252
  )
40
253
  );
41
254
  const bucketStorage = factory.getInstance(syncRules);
42
- const globalBucket = bucketRequest(syncRules, 'global[]');
255
+ const syncRulesContent = syncRules.syncConfigContent[0];
256
+ const globalBucket = bucketRequest(syncRulesContent, 'global[]');
43
257
 
44
258
  const result = await (async () => {
45
259
  await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
@@ -94,7 +308,9 @@ for (let storageVersion of TEST_STORAGE_VERSIONS) {
94
308
 
95
309
  const options: storage.BucketDataBatchOptions = {};
96
310
 
97
- const batch1 = await test_utils.fromAsync(bucketStorage.getBucketDataBatch(checkpoint, [globalBucket], options));
311
+ const batch1 = await test_utils.getBatchArray(
312
+ bucketStorage.getBucketDataBatch(test_utils.testCheckpoint(checkpoint), [globalBucket], options)
313
+ );
98
314
  expect(test_utils.getBatchData(batch1)).toEqual([
99
315
  { op_id: '1', op: 'PUT', object_id: 'test1', checksum: 2871785649 }
100
316
  ]);
@@ -104,9 +320,9 @@ for (let storageVersion of TEST_STORAGE_VERSIONS) {
104
320
  next_after: '1'
105
321
  });
106
322
 
107
- const batch2 = await test_utils.fromAsync(
323
+ const batch2 = await test_utils.getBatchArray(
108
324
  bucketStorage.getBucketDataBatch(
109
- checkpoint,
325
+ test_utils.testCheckpoint(checkpoint),
110
326
  [{ ...globalBucket, start: BigInt(batch1[0].chunkData.next_after) }],
111
327
  options
112
328
  )
@@ -120,9 +336,9 @@ for (let storageVersion of TEST_STORAGE_VERSIONS) {
120
336
  next_after: '2'
121
337
  });
122
338
 
123
- const batch3 = await test_utils.fromAsync(
339
+ const batch3 = await test_utils.getBatchArray(
124
340
  bucketStorage.getBucketDataBatch(
125
- checkpoint,
341
+ test_utils.testCheckpoint(checkpoint),
126
342
  [{ ...globalBucket, start: BigInt(batch2[0].chunkData.next_after) }],
127
343
  options
128
344
  )
@@ -136,9 +352,9 @@ for (let storageVersion of TEST_STORAGE_VERSIONS) {
136
352
  next_after: '3'
137
353
  });
138
354
 
139
- const batch4 = await test_utils.fromAsync(
355
+ const batch4 = await test_utils.getBatchArray(
140
356
  bucketStorage.getBucketDataBatch(
141
- checkpoint,
357
+ test_utils.testCheckpoint(checkpoint),
142
358
  [{ ...globalBucket, start: BigInt(batch3[0].chunkData.next_after) }],
143
359
  options
144
360
  )
@@ -17,6 +17,7 @@ bucket_definitions:
17
17
  `)
18
18
  );
19
19
  const bucketStorage = factory.getInstance(syncRules);
20
+ const syncRulesContent = syncRules.syncConfigContent[0];
20
21
 
21
22
  const result = await (async () => {
22
23
  await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
@@ -44,12 +45,14 @@ bucket_definitions:
44
45
  // Compact with an explicit bucket name — exercises the this.buckets
45
46
  // iteration path, NOT the compactAllBuckets discovery path.
46
47
  await bucketStorage.compact({
47
- compactBuckets: [bucketRequest(syncRules, 'global[]').bucket],
48
+ compactBuckets: [bucketRequest(syncRulesContent, 'global[]').bucket],
48
49
  minBucketChanges: 1
49
50
  });
50
51
 
51
- const batch = await test_utils.oneFromAsync(
52
- bucketStorage.getBucketDataBatch(checkpoint, [bucketRequest(syncRules, 'global[]', 0n)])
52
+ const batch = await test_utils.getSingleBatchItem(
53
+ bucketStorage.getBucketDataBatch(test_utils.testCheckpoint(checkpoint), [
54
+ bucketRequest(syncRulesContent, 'global[]', 0n)
55
+ ])
53
56
  );
54
57
 
55
58
  expect(batch.chunkData.data).toMatchObject([
@@ -70,7 +73,8 @@ bucket_definitions:
70
73
  `)
71
74
  );
72
75
  const bucketStorage = factory.getInstance(syncRules);
73
- const request = bucketRequest(syncRules, 'global[]');
76
+ const syncRulesContent = syncRules.syncConfigContent[0];
77
+ const request = bucketRequest(syncRulesContent, 'global[]');
74
78
 
75
79
  const result = await (async () => {
76
80
  await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
@@ -106,18 +110,22 @@ bucket_definitions:
106
110
  })();
107
111
 
108
112
  const checkpoint = result!.flushed_op;
109
- const rowsBefore = await test_utils.oneFromAsync(bucketStorage.getBucketDataBatch(checkpoint, [request]));
113
+ const rowsBefore = await test_utils.getSingleBatchItem(
114
+ bucketStorage.getBucketDataBatch(test_utils.testCheckpoint(checkpoint), [request])
115
+ );
110
116
  const dataBefore = test_utils.getBatchData(rowsBefore);
111
117
  const clearToOpId = BigInt(dataBefore[2].op_id);
112
118
 
113
- const compactor = new PostgresCompactor(factory.db, bucketStorage.group_id, {});
119
+ const compactor = new PostgresCompactor(factory.db, bucketStorage.replicationStreamId, {});
114
120
  // Trigger the private method directly
115
121
  await expect(compactor.clearBucketForTests(request.bucket, clearToOpId)).rejects.toThrow(
116
122
  /Unexpected PUT operation/
117
123
  );
118
124
 
119
125
  // The method wraps in a transaction; on assertion error the bucket must remain unchanged.
120
- const rowsAfter = await test_utils.oneFromAsync(bucketStorage.getBucketDataBatch(checkpoint, [request]));
126
+ const rowsAfter = await test_utils.getSingleBatchItem(
127
+ bucketStorage.getBucketDataBatch(test_utils.testCheckpoint(checkpoint), [request])
128
+ );
121
129
  expect(test_utils.getBatchData(rowsAfter)).toEqual(dataBefore);
122
130
  });
123
131
  });
@@ -34,7 +34,8 @@ function registerStorageVersionTests(storageVersion: number) {
34
34
  )
35
35
  );
36
36
  const bucketStorage = factory.getInstance(syncRules);
37
- const globalBucket = bucketRequest(syncRules, 'global[]');
37
+ const syncRulesContent = syncRules.syncConfigContent[0];
38
+ const globalBucket = bucketRequest(syncRulesContent, 'global[]');
38
39
 
39
40
  await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
40
41
 
@@ -89,7 +90,9 @@ function registerStorageVersionTests(storageVersion: number) {
89
90
 
90
91
  const options: storage.BucketDataBatchOptions = {};
91
92
 
92
- const batch1 = await test_utils.fromAsync(bucketStorage.getBucketDataBatch(checkpoint, [globalBucket], options));
93
+ const batch1 = await test_utils.getBatchArray(
94
+ bucketStorage.getBucketDataBatch(test_utils.testCheckpoint(checkpoint), [globalBucket], options)
95
+ );
93
96
  expect(test_utils.getBatchData(batch1)).toEqual([
94
97
  { op_id: '1', op: 'PUT', object_id: 'test1', checksum: 2871785649 }
95
98
  ]);
@@ -99,9 +102,9 @@ function registerStorageVersionTests(storageVersion: number) {
99
102
  next_after: '1'
100
103
  });
101
104
 
102
- const batch2 = await test_utils.fromAsync(
105
+ const batch2 = await test_utils.getBatchArray(
103
106
  bucketStorage.getBucketDataBatch(
104
- checkpoint,
107
+ test_utils.testCheckpoint(checkpoint),
105
108
  [{ ...globalBucket, start: BigInt(batch1[0].chunkData.next_after) }],
106
109
  options
107
110
  )
@@ -115,9 +118,9 @@ function registerStorageVersionTests(storageVersion: number) {
115
118
  next_after: '2'
116
119
  });
117
120
 
118
- const batch3 = await test_utils.fromAsync(
121
+ const batch3 = await test_utils.getBatchArray(
119
122
  bucketStorage.getBucketDataBatch(
120
- checkpoint,
123
+ test_utils.testCheckpoint(checkpoint),
121
124
  [{ ...globalBucket, start: BigInt(batch2[0].chunkData.next_after) }],
122
125
  options
123
126
  )
@@ -131,9 +134,9 @@ function registerStorageVersionTests(storageVersion: number) {
131
134
  next_after: '3'
132
135
  });
133
136
 
134
- const batch4 = await test_utils.fromAsync(
137
+ const batch4 = await test_utils.getBatchArray(
135
138
  bucketStorage.getBucketDataBatch(
136
- checkpoint,
139
+ test_utils.testCheckpoint(checkpoint),
137
140
  [{ ...globalBucket, start: BigInt(batch3[0].chunkData.next_after) }],
138
141
  options
139
142
  )
@@ -1,9 +1,7 @@
1
1
  {
2
2
  "extends": "../../../tsconfig.tests.json",
3
3
  "compilerOptions": {
4
- "declarationDir": "dist/@types",
5
- "tsBuildInfoFile": "dist/.tsbuildinfo",
6
- "lib": ["ES2022", "esnext.disposable"],
4
+ "lib": ["ES2024", "esnext.disposable"],
7
5
  "rootDir": "src"
8
6
  },
9
7
  "include": ["src"],
package/tsconfig.json CHANGED
@@ -1,11 +1,8 @@
1
1
  {
2
2
  "extends": "../../tsconfig.base.json",
3
3
  "compilerOptions": {
4
- "outDir": "dist",
5
- "declarationDir": "dist/@types",
6
- "tsBuildInfoFile": "dist/.tsbuildinfo",
7
4
  "rootDir": "src",
8
- "skipLibCheck": true
5
+ "outDir": "dist"
9
6
  },
10
7
  "include": ["src"],
11
8
  "references": [