@powersync/service-core-tests 0.15.5 → 0.16.0
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/CHANGELOG.md +28 -0
- package/dist/test-utils/AbstractStreamTestContext.d.ts +51 -0
- package/dist/test-utils/AbstractStreamTestContext.js +143 -0
- package/dist/test-utils/AbstractStreamTestContext.js.map +1 -0
- package/dist/test-utils/general-utils.d.ts +2 -7
- package/dist/test-utils/general-utils.js +27 -25
- package/dist/test-utils/general-utils.js.map +1 -1
- package/dist/test-utils/test-utils-index.d.ts +1 -0
- package/dist/test-utils/test-utils-index.js +1 -0
- package/dist/test-utils/test-utils-index.js.map +1 -1
- package/dist/tests/register-data-storage-data-tests.js +3 -3
- package/dist/tests/register-data-storage-data-tests.js.map +1 -1
- package/dist/tests/register-data-storage-parameter-tests.js +18 -19
- package/dist/tests/register-data-storage-parameter-tests.js.map +1 -1
- package/dist/tests/util.d.ts +1 -2
- package/dist/tests/util.js +8 -5
- package/dist/tests/util.js.map +1 -1
- package/package.json +4 -3
- package/src/test-utils/AbstractStreamTestContext.ts +179 -0
- package/src/test-utils/general-utils.ts +30 -30
- package/src/test-utils/test-utils-index.ts +1 -0
- package/src/tests/register-data-storage-data-tests.ts +3 -3
- package/src/tests/register-data-storage-parameter-tests.ts +18 -19
- package/src/tests/util.ts +12 -9
- package/tsconfig.json +3 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { ReplicationAbortedError } from '@powersync/lib-services-framework';
|
|
2
|
+
import {
|
|
3
|
+
BucketStorageFactory,
|
|
4
|
+
InternalOpId,
|
|
5
|
+
settledPromise,
|
|
6
|
+
storage,
|
|
7
|
+
SyncRulesBucketStorage,
|
|
8
|
+
unsettledPromise,
|
|
9
|
+
updateSyncRulesFromYaml
|
|
10
|
+
} from '@powersync/service-core';
|
|
11
|
+
import { StorageDataHelpers } from './StorageDataHelpers.js';
|
|
12
|
+
import { bucketRequest } from './general-utils.js';
|
|
13
|
+
import { fromAsync } from './stream_utils.js';
|
|
14
|
+
|
|
15
|
+
export abstract class AbstractStreamTestContext implements AsyncDisposable {
|
|
16
|
+
protected abortController = new AbortController();
|
|
17
|
+
protected syncRulesContent?: storage.PersistedSyncRulesContent;
|
|
18
|
+
public storage?: SyncRulesBucketStorage;
|
|
19
|
+
protected settledReplicationPromise?: Promise<PromiseSettledResult<void>>;
|
|
20
|
+
|
|
21
|
+
abstract get factory(): BucketStorageFactory;
|
|
22
|
+
protected abstract get storageVersion(): number;
|
|
23
|
+
|
|
24
|
+
async [Symbol.asyncDispose]() {
|
|
25
|
+
await this.dispose();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
protected abstract _dispose(): Promise<void>;
|
|
29
|
+
|
|
30
|
+
async dispose() {
|
|
31
|
+
this.abortController.abort();
|
|
32
|
+
try {
|
|
33
|
+
await this.settledReplicationPromise;
|
|
34
|
+
await this._dispose();
|
|
35
|
+
await this.factory?.[Symbol.asyncDispose]();
|
|
36
|
+
} catch (e) {
|
|
37
|
+
// Throwing here may result in SuppressedError. The underlying errors often don't show up
|
|
38
|
+
// in the test output, so we log it here.
|
|
39
|
+
// If we could get vitest to log SuppressedError.error and SuppressedError.suppressed, we
|
|
40
|
+
// could remove this.
|
|
41
|
+
console.error('Error during ConvexStreamTestContext dispose', e);
|
|
42
|
+
throw e;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async updateSyncRules(content: string) {
|
|
47
|
+
const syncRules = await this.factory.updateSyncRules(
|
|
48
|
+
updateSyncRulesFromYaml(content, { validate: true, storageVersion: this.storageVersion })
|
|
49
|
+
);
|
|
50
|
+
this.syncRulesContent = syncRules;
|
|
51
|
+
this.storage = this.factory.getInstance(syncRules);
|
|
52
|
+
return this.storage!;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async loadNextSyncRules() {
|
|
56
|
+
const syncRules = await this.factory.getNextSyncRulesContent();
|
|
57
|
+
if (syncRules == null) {
|
|
58
|
+
throw new Error(`Next sync rules not available`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
this.syncRulesContent = syncRules;
|
|
62
|
+
this.storage = this.factory.getInstance(syncRules);
|
|
63
|
+
return this.storage!;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async loadActiveSyncRules() {
|
|
67
|
+
const syncRules = await this.factory.getActiveSyncRulesContent();
|
|
68
|
+
if (syncRules == null) {
|
|
69
|
+
throw new Error(`Active sync rules not available`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
this.syncRulesContent = syncRules;
|
|
73
|
+
this.storage = this.factory.getInstance(syncRules);
|
|
74
|
+
return this.storage!;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private getSyncRulesContent(): storage.PersistedSyncRulesContent {
|
|
78
|
+
if (this.syncRulesContent == null) {
|
|
79
|
+
throw new Error('Sync rules not configured - call updateSyncRules() first');
|
|
80
|
+
}
|
|
81
|
+
return this.syncRulesContent;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Replicate a snapshot, start streaming, and wait for a consistent checkpoint.
|
|
86
|
+
*/
|
|
87
|
+
async initializeReplication() {
|
|
88
|
+
await this.replicateSnapshot();
|
|
89
|
+
// Make sure we're up to date
|
|
90
|
+
await this.getCheckpoint();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
protected abstract triggerReplication(): Promise<void>;
|
|
94
|
+
protected abstract waitForInitialSnapshot(): Promise<void>;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Replicate the initial snapshot, and start streaming.
|
|
98
|
+
*/
|
|
99
|
+
async replicateSnapshot() {
|
|
100
|
+
// Use a settledPromise to avoid unhandled rejections
|
|
101
|
+
this.settledReplicationPromise = settledPromise(this.triggerReplication());
|
|
102
|
+
try {
|
|
103
|
+
await Promise.race([unsettledPromise(this.settledReplicationPromise), this.waitForInitialSnapshot()]);
|
|
104
|
+
} catch (e) {
|
|
105
|
+
if (e instanceof ReplicationAbortedError && e.cause != null) {
|
|
106
|
+
// Edge case for tests: replicate() can throw an error, but we'd receive the ReplicationAbortedError from
|
|
107
|
+
// waitForInitialSnapshot() first. In that case, prioritize the cause, e.g. MissingReplicationSlotError.
|
|
108
|
+
// This is not a concern for production use, since we only use waitForInitialSnapshot() in tests.
|
|
109
|
+
throw e.cause;
|
|
110
|
+
}
|
|
111
|
+
throw e;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
abstract getClientCheckpoint(options?: { timeout?: number }): Promise<bigint>;
|
|
116
|
+
|
|
117
|
+
async getCheckpoint(options?: { timeout?: number }) {
|
|
118
|
+
let checkpoint = await Promise.race([
|
|
119
|
+
this.getClientCheckpoint(options),
|
|
120
|
+
unsettledPromise(this.settledReplicationPromise!)
|
|
121
|
+
]);
|
|
122
|
+
if (checkpoint == null) {
|
|
123
|
+
// This indicates an issue with the test setup - replicationPromise completed instead
|
|
124
|
+
// of getClientCheckpoint()
|
|
125
|
+
throw new Error('Test failure - replicationPromise completed');
|
|
126
|
+
}
|
|
127
|
+
return checkpoint;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async getBucketsDataBatch(buckets: Record<string, InternalOpId>, options?: { timeout?: number }) {
|
|
131
|
+
const helpers = new StorageDataHelpers(this.storage!, this.getSyncRulesContent());
|
|
132
|
+
const checkpoint = await this.getCheckpoint(options);
|
|
133
|
+
return helpers.getBucketsDataBatch(buckets, checkpoint);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* This waits for a client checkpoint.
|
|
138
|
+
*/
|
|
139
|
+
async getBucketData(bucket: string, start?: InternalOpId | string | undefined, options?: { timeout?: number }) {
|
|
140
|
+
const helpers = new StorageDataHelpers(this.storage!, this.getSyncRulesContent());
|
|
141
|
+
const checkpoint = await this.getCheckpoint(options);
|
|
142
|
+
return helpers.getBucketData(bucket, checkpoint, start);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
async getChecksums(buckets: string[], options?: { timeout?: number }) {
|
|
146
|
+
const checkpoint = await this.getCheckpoint(options);
|
|
147
|
+
const syncRules = this.getSyncRulesContent();
|
|
148
|
+
const versionedBuckets = buckets.map((bucket) => bucketRequest(syncRules, bucket, 0n));
|
|
149
|
+
const checksums = await this.storage!.getChecksums(checkpoint, versionedBuckets);
|
|
150
|
+
|
|
151
|
+
const unversioned = new Map();
|
|
152
|
+
for (let i = 0; i < buckets.length; i++) {
|
|
153
|
+
unversioned.set(buckets[i], checksums.get(versionedBuckets[i].bucket)!);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return unversioned;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
async getChecksum(bucket: string, options?: { timeout?: number }) {
|
|
160
|
+
const checksums = await this.getChecksums([bucket], options);
|
|
161
|
+
return checksums.get(bucket);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* This does not wait for a client checkpoint.
|
|
166
|
+
*/
|
|
167
|
+
async getCurrentBucketData(bucket: string, start?: InternalOpId | string | undefined) {
|
|
168
|
+
start ??= 0n;
|
|
169
|
+
if (typeof start == 'string') {
|
|
170
|
+
start = BigInt(start);
|
|
171
|
+
}
|
|
172
|
+
const syncRules = this.getSyncRulesContent();
|
|
173
|
+
const { checkpoint } = await this.storage!.getCheckpoint();
|
|
174
|
+
const map = [bucketRequest(syncRules, bucket, start)];
|
|
175
|
+
const batch = this.storage!.getBucketDataBatch(checkpoint, map);
|
|
176
|
+
const batches = await fromAsync(batch);
|
|
177
|
+
return batches[0]?.chunkData.data ?? [];
|
|
178
|
+
}
|
|
179
|
+
}
|
|
@@ -14,50 +14,50 @@ export const BATCH_OPTIONS: storage.CreateWriterOptions = {
|
|
|
14
14
|
storeCurrentData: true
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
-
export function makeTestTable(
|
|
18
|
-
name: string,
|
|
19
|
-
replicaIdColumns?: string[] | undefined,
|
|
20
|
-
options?: { tableIdStrings: boolean }
|
|
21
|
-
) {
|
|
22
|
-
const relId = utils.hashData('table', name, (replicaIdColumns ?? ['id']).join(','));
|
|
23
|
-
const id =
|
|
24
|
-
options?.tableIdStrings == false ? new bson.ObjectId('6544e3899293153fa7b38331') : '6544e3899293153fa7b38331';
|
|
25
|
-
return new storage.SourceTable({
|
|
26
|
-
id: id,
|
|
27
|
-
connectionTag: storage.SourceTable.DEFAULT_TAG,
|
|
28
|
-
objectId: relId,
|
|
29
|
-
schema: 'public',
|
|
30
|
-
name: name,
|
|
31
|
-
replicaIdColumns: (replicaIdColumns ?? ['id']).map((column) => ({ name: column, type: 'VARCHAR', typeId: 25 })),
|
|
32
|
-
snapshotComplete: true
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
17
|
/**
|
|
36
|
-
* With
|
|
37
|
-
*
|
|
38
|
-
* This prepares for it.
|
|
18
|
+
* With newer storage versions, we need actual test tables, resolved via the writer.
|
|
39
19
|
*/
|
|
40
20
|
export async function resolveTestTable(
|
|
41
|
-
|
|
21
|
+
writer: storage.BucketStorageBatch,
|
|
42
22
|
name: string,
|
|
43
23
|
replicaIdColumns: string[] | undefined,
|
|
44
24
|
options: { tableIdStrings: boolean },
|
|
45
25
|
idIndex: number = 1
|
|
46
26
|
) {
|
|
27
|
+
void idIndex;
|
|
28
|
+
void options;
|
|
29
|
+
|
|
47
30
|
const relId = utils.hashData('table', name, (replicaIdColumns ?? ['id']).join(','));
|
|
48
|
-
//
|
|
49
|
-
//
|
|
31
|
+
// Semi-hardcoded id for tests, to get consistent output.
|
|
32
|
+
// If the same test uses multiple tables, pass idIndex to get different ids.
|
|
50
33
|
const idString = '6544e3899293153fa7b383' + (30 + idIndex).toString().padStart(2, '0');
|
|
51
34
|
const id = options.tableIdStrings == false ? new bson.ObjectId(idString) : idString;
|
|
52
|
-
|
|
53
|
-
|
|
35
|
+
let didGenerateId = false;
|
|
36
|
+
|
|
37
|
+
const source: storage.SourceEntityDescriptor = {
|
|
54
38
|
connectionTag: storage.SourceTable.DEFAULT_TAG,
|
|
55
39
|
objectId: relId,
|
|
56
40
|
schema: 'public',
|
|
57
41
|
name: name,
|
|
58
|
-
replicaIdColumns: (replicaIdColumns ?? ['id']).map((column) => ({ name: column, type: 'VARCHAR', typeId: 25 }))
|
|
59
|
-
|
|
42
|
+
replicaIdColumns: (replicaIdColumns ?? ['id']).map((column) => ({ name: column, type: 'VARCHAR', typeId: 25 }))
|
|
43
|
+
};
|
|
44
|
+
const resolved = await writer.resolveTables({
|
|
45
|
+
connection_id: 1,
|
|
46
|
+
source,
|
|
47
|
+
idGenerator: () => {
|
|
48
|
+
if (didGenerateId) {
|
|
49
|
+
throw new Error('idGenerator called multiple times - not supported in tests');
|
|
50
|
+
}
|
|
51
|
+
didGenerateId = true;
|
|
52
|
+
return id;
|
|
53
|
+
}
|
|
60
54
|
});
|
|
55
|
+
|
|
56
|
+
const table = resolved.tables[0];
|
|
57
|
+
if (table == null) {
|
|
58
|
+
throw new Error(`Failed to resolve test table ${source.schema}.${source.name}`);
|
|
59
|
+
}
|
|
60
|
+
return table;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
export function getBatchData(
|
|
@@ -80,7 +80,7 @@ export function getBatchData(
|
|
|
80
80
|
function isParsedSyncRules(
|
|
81
81
|
syncRules: storage.PersistedSyncRulesContent | storage.PersistedSyncRules
|
|
82
82
|
): syncRules is storage.PersistedSyncRules {
|
|
83
|
-
return (syncRules as storage.PersistedSyncRules).
|
|
83
|
+
return (syncRules as storage.PersistedSyncRules).syncConfigWithErrors !== undefined;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
/**
|
|
@@ -97,7 +97,7 @@ export function bucketRequest(
|
|
|
97
97
|
const parameterStart = bucket.indexOf('[');
|
|
98
98
|
const definitionName = bucket.substring(0, parameterStart);
|
|
99
99
|
const parameters = bucket.substring(parameterStart);
|
|
100
|
-
const source = parsed.
|
|
100
|
+
const source = parsed.syncConfigWithErrors.config.bucketDataSources.find((b) => b.uniqueName === definitionName);
|
|
101
101
|
|
|
102
102
|
if (source == null) {
|
|
103
103
|
throw new Error(`Failed to find global bucket ${bucket}`);
|
|
@@ -826,7 +826,7 @@ bucket_definitions:
|
|
|
826
826
|
const bucketStorage = factory.getInstance(syncRules);
|
|
827
827
|
|
|
828
828
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
829
|
-
const sourceTable = test_utils.
|
|
829
|
+
const sourceTable = await test_utils.resolveTestTable(writer, 'test', ['id', 'description'], config);
|
|
830
830
|
|
|
831
831
|
// Pre-setup
|
|
832
832
|
await writer.markAllSnapshotDone('1/1');
|
|
@@ -939,7 +939,7 @@ bucket_definitions:
|
|
|
939
939
|
const bucketStorage = factory.getInstance(syncRules);
|
|
940
940
|
|
|
941
941
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
942
|
-
const sourceTable = test_utils.
|
|
942
|
+
const sourceTable = await test_utils.resolveTestTable(writer, 'test', ['id', 'description'], config);
|
|
943
943
|
|
|
944
944
|
// Pre-setup
|
|
945
945
|
await writer.markAllSnapshotDone('1/1');
|
|
@@ -1756,7 +1756,7 @@ streams:
|
|
|
1756
1756
|
`)
|
|
1757
1757
|
);
|
|
1758
1758
|
|
|
1759
|
-
const { errors } = deployed.parsed({ defaultSchema: 'ignored' }).
|
|
1759
|
+
const { errors } = deployed.parsed({ defaultSchema: 'ignored' }).syncConfigWithErrors;
|
|
1760
1760
|
expect(errors).toHaveLength(1);
|
|
1761
1761
|
expect(errors[0].message).toStrictEqual('Expected a SELECT statement');
|
|
1762
1762
|
expect(errors[0].location).toStrictEqual({
|
|
@@ -41,7 +41,7 @@ bucket_definitions:
|
|
|
41
41
|
)
|
|
42
42
|
);
|
|
43
43
|
const bucketStorage = factory.getInstance(syncRules);
|
|
44
|
-
const sync_rules = syncRules.parsed(test_utils.PARSE_OPTIONS).
|
|
44
|
+
const sync_rules = syncRules.parsed(test_utils.PARSE_OPTIONS).hydratedSyncConfig();
|
|
45
45
|
|
|
46
46
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
47
47
|
const testTable = await test_utils.resolveTestTable(writer, 'test', ['id'], config);
|
|
@@ -107,7 +107,7 @@ bucket_definitions:
|
|
|
107
107
|
)
|
|
108
108
|
);
|
|
109
109
|
const bucketStorage = factory.getInstance(syncRules);
|
|
110
|
-
const sync_rules = syncRules.parsed(test_utils.PARSE_OPTIONS).
|
|
110
|
+
const sync_rules = syncRules.parsed(test_utils.PARSE_OPTIONS).hydratedSyncConfig();
|
|
111
111
|
|
|
112
112
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
113
113
|
const testTable = await test_utils.resolveTestTable(writer, 'test', ['id'], config);
|
|
@@ -178,7 +178,7 @@ bucket_definitions:
|
|
|
178
178
|
)
|
|
179
179
|
);
|
|
180
180
|
const bucketStorage = factory.getInstance(syncRules);
|
|
181
|
-
const sync_rules = syncRules.parsed(test_utils.PARSE_OPTIONS).
|
|
181
|
+
const sync_rules = syncRules.parsed(test_utils.PARSE_OPTIONS).hydratedSyncConfig();
|
|
182
182
|
|
|
183
183
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
184
184
|
const table = await test_utils.resolveTestTable(writer, 'todos', ['id', 'list_id'], config);
|
|
@@ -265,7 +265,7 @@ bucket_definitions:
|
|
|
265
265
|
)
|
|
266
266
|
);
|
|
267
267
|
const bucketStorage = factory.getInstance(syncRules);
|
|
268
|
-
const sync_rules = syncRules.parsed(test_utils.PARSE_OPTIONS).
|
|
268
|
+
const sync_rules = syncRules.parsed(test_utils.PARSE_OPTIONS).hydratedSyncConfig();
|
|
269
269
|
|
|
270
270
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
271
271
|
const testTable = await test_utils.resolveTestTable(writer, 'test', ['id'], config);
|
|
@@ -333,7 +333,7 @@ bucket_definitions:
|
|
|
333
333
|
)
|
|
334
334
|
);
|
|
335
335
|
const bucketStorage = factory.getInstance(syncRules);
|
|
336
|
-
const sync_rules = syncRules.parsed(test_utils.PARSE_OPTIONS).
|
|
336
|
+
const sync_rules = syncRules.parsed(test_utils.PARSE_OPTIONS).hydratedSyncConfig();
|
|
337
337
|
|
|
338
338
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
339
339
|
const testTable = await test_utils.resolveTestTable(writer, 'test', ['id'], config);
|
|
@@ -400,7 +400,7 @@ bucket_definitions:
|
|
|
400
400
|
}
|
|
401
401
|
)
|
|
402
402
|
);
|
|
403
|
-
const sync_rules = syncRules.parsed(test_utils.PARSE_OPTIONS).
|
|
403
|
+
const sync_rules = syncRules.parsed(test_utils.PARSE_OPTIONS).hydratedSyncConfig();
|
|
404
404
|
const bucketStorage = factory.getInstance(syncRules);
|
|
405
405
|
|
|
406
406
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
@@ -458,7 +458,7 @@ bucket_definitions:
|
|
|
458
458
|
}
|
|
459
459
|
)
|
|
460
460
|
);
|
|
461
|
-
const sync_rules = syncRules.parsed(test_utils.PARSE_OPTIONS).
|
|
461
|
+
const sync_rules = syncRules.parsed(test_utils.PARSE_OPTIONS).hydratedSyncConfig();
|
|
462
462
|
const bucketStorage = factory.getInstance(syncRules);
|
|
463
463
|
|
|
464
464
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
@@ -552,7 +552,7 @@ bucket_definitions:
|
|
|
552
552
|
}
|
|
553
553
|
)
|
|
554
554
|
);
|
|
555
|
-
const sync_rules = syncRules.parsed(test_utils.PARSE_OPTIONS).
|
|
555
|
+
const sync_rules = syncRules.parsed(test_utils.PARSE_OPTIONS).hydratedSyncConfig();
|
|
556
556
|
const bucketStorage = factory.getInstance(syncRules);
|
|
557
557
|
|
|
558
558
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
@@ -654,7 +654,7 @@ bucket_definitions:
|
|
|
654
654
|
)
|
|
655
655
|
);
|
|
656
656
|
const bucketStorage = factory.getInstance(syncRules);
|
|
657
|
-
const sync_rules = syncRules.parsed(test_utils.PARSE_OPTIONS).
|
|
657
|
+
const sync_rules = syncRules.parsed(test_utils.PARSE_OPTIONS).hydratedSyncConfig();
|
|
658
658
|
|
|
659
659
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
660
660
|
const testTable = await test_utils.resolveTestTable(writer, 'test', ['id'], config);
|
|
@@ -745,7 +745,7 @@ streams:
|
|
|
745
745
|
`)
|
|
746
746
|
);
|
|
747
747
|
const bucketStorage = factory.getInstance(syncRules);
|
|
748
|
-
const sync_rules = syncRules.parsed(test_utils.PARSE_OPTIONS).
|
|
748
|
+
const sync_rules = syncRules.parsed(test_utils.PARSE_OPTIONS).hydratedSyncConfig();
|
|
749
749
|
|
|
750
750
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
751
751
|
const testTable = await test_utils.resolveTestTable(writer, 'test', ['id'], config);
|
|
@@ -786,7 +786,6 @@ streams:
|
|
|
786
786
|
return parameter_sets;
|
|
787
787
|
}
|
|
788
788
|
});
|
|
789
|
-
console.log('whatabuckets', buckets);
|
|
790
789
|
expect(buckets).toHaveLength(1);
|
|
791
790
|
expect(buckets).toMatchObject([
|
|
792
791
|
{
|
|
@@ -817,7 +816,7 @@ streams:
|
|
|
817
816
|
)
|
|
818
817
|
);
|
|
819
818
|
const bucketStorage = factory.getInstance(syncRules);
|
|
820
|
-
const sync_rules = syncRules.parsed(test_utils.PARSE_OPTIONS).
|
|
819
|
+
const sync_rules = syncRules.parsed(test_utils.PARSE_OPTIONS).hydratedSyncConfig();
|
|
821
820
|
|
|
822
821
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
823
822
|
const testTable = await test_utils.resolveTestTable(writer, 'b', ['id'], config);
|
|
@@ -866,7 +865,7 @@ streams:
|
|
|
866
865
|
`)
|
|
867
866
|
);
|
|
868
867
|
const bucketStorage = factory.getInstance(syncRules);
|
|
869
|
-
const sync_rules = syncRules.parsed(test_utils.PARSE_OPTIONS).
|
|
868
|
+
const sync_rules = syncRules.parsed(test_utils.PARSE_OPTIONS).hydratedSyncConfig();
|
|
870
869
|
|
|
871
870
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
872
871
|
const tableB = await test_utils.resolveTestTable(writer, 'b', ['id'], config);
|
|
@@ -996,11 +995,11 @@ streams:
|
|
|
996
995
|
const bucketStorage = factory.getInstance(syncRules);
|
|
997
996
|
const parsedSyncRules = syncRules.parsed(test_utils.PARSE_OPTIONS);
|
|
998
997
|
const hydrationState = parsedSyncRules.hydrationState;
|
|
999
|
-
const syncConfig = parsedSyncRules.
|
|
998
|
+
const syncConfig = parsedSyncRules.syncConfigWithErrors.config;
|
|
1000
999
|
|
|
1001
1000
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
1002
|
-
const paramATable = await test_utils.resolveTestTable(writer, 'param_a', ['id'], config);
|
|
1003
|
-
const paramBTable = await test_utils.resolveTestTable(writer, 'param_b', ['id'], config);
|
|
1001
|
+
const paramATable = await test_utils.resolveTestTable(writer, 'param_a', ['id'], config, 1);
|
|
1002
|
+
const paramBTable = await test_utils.resolveTestTable(writer, 'param_b', ['id'], config, 2);
|
|
1004
1003
|
const replicaId = test_utils.rid('id');
|
|
1005
1004
|
|
|
1006
1005
|
// Insert the same row into param_a and param_b
|
|
@@ -1092,11 +1091,11 @@ streams:
|
|
|
1092
1091
|
)
|
|
1093
1092
|
);
|
|
1094
1093
|
const bucketStorage = factory.getInstance(syncRules);
|
|
1095
|
-
const sync_rules = syncRules.parsed(test_utils.PARSE_OPTIONS).
|
|
1094
|
+
const sync_rules = syncRules.parsed(test_utils.PARSE_OPTIONS).hydratedSyncConfig();
|
|
1096
1095
|
|
|
1097
1096
|
await using writer = await bucketStorage.createWriter(test_utils.BATCH_OPTIONS);
|
|
1098
|
-
const tableB = await test_utils.resolveTestTable(writer, 'b', ['id'], config);
|
|
1099
|
-
const tableC = await test_utils.resolveTestTable(writer, 'c', ['id'], config);
|
|
1097
|
+
const tableB = await test_utils.resolveTestTable(writer, 'b', ['id'], config, 1);
|
|
1098
|
+
const tableC = await test_utils.resolveTestTable(writer, 'c', ['id'], config, 2);
|
|
1100
1099
|
|
|
1101
1100
|
await writer.markAllSnapshotDone('1/1');
|
|
1102
1101
|
await writer.save({
|
package/src/tests/util.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { storage } from '@powersync/service-core';
|
|
2
2
|
import {
|
|
3
3
|
ParameterIndexLookupCreator,
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
ParameterLookupDefinitionId,
|
|
5
|
+
ParameterLookupScope,
|
|
6
|
+
SourceTableRef,
|
|
6
7
|
TablePattern
|
|
7
8
|
} from '@powersync/service-sync-rules';
|
|
8
|
-
import { ParameterLookupScope } from '@powersync/service-sync-rules/src/HydrationState.js';
|
|
9
9
|
import { bucketRequest } from '../test-utils/general-utils.js';
|
|
10
10
|
|
|
11
11
|
export function bucketRequestMap(
|
|
@@ -26,20 +26,23 @@ export function bucketRequests(
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
const EMPTY_LOOKUP_SOURCE: ParameterIndexLookupCreator = {
|
|
29
|
-
get
|
|
29
|
+
get sourceId(): ParameterLookupDefinitionId {
|
|
30
30
|
return {
|
|
31
31
|
lookupName: 'lookup',
|
|
32
|
-
queryId: '0'
|
|
33
|
-
source: EMPTY_LOOKUP_SOURCE
|
|
32
|
+
queryId: '0'
|
|
34
33
|
};
|
|
35
34
|
},
|
|
36
35
|
getSourceTables(): Set<TablePattern> {
|
|
37
36
|
return new Set();
|
|
38
37
|
},
|
|
39
|
-
|
|
40
|
-
return
|
|
38
|
+
createEvaluator(input) {
|
|
39
|
+
return {
|
|
40
|
+
evaluateParameterRow(sourceTable, row) {
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
};
|
|
41
44
|
},
|
|
42
|
-
tableSyncsParameters(_table:
|
|
45
|
+
tableSyncsParameters(_table: SourceTableRef): boolean {
|
|
43
46
|
return false;
|
|
44
47
|
}
|
|
45
48
|
};
|