@powersync/service-module-mssql 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.
- package/CHANGELOG.md +85 -4
- package/dist/api/MSSQLRouteAPIAdapter.d.ts +4 -5
- package/dist/api/MSSQLRouteAPIAdapter.js +7 -5
- package/dist/api/MSSQLRouteAPIAdapter.js.map +1 -1
- package/dist/replication/CDCReplicationJob.js +1 -1
- package/dist/replication/CDCReplicationJob.js.map +1 -1
- package/dist/replication/CDCReplicator.js +1 -1
- package/dist/replication/CDCReplicator.js.map +1 -1
- package/dist/replication/CDCStream.js +9 -9
- package/dist/replication/CDCStream.js.map +1 -1
- package/dist/utils/schema.js +4 -1
- package/dist/utils/schema.js.map +1 -1
- package/package.json +11 -21
- package/src/api/MSSQLRouteAPIAdapter.ts +11 -16
- package/src/replication/CDCReplicationJob.ts +1 -1
- package/src/replication/CDCReplicator.ts +1 -1
- package/src/replication/CDCStream.ts +9 -9
- package/src/utils/schema.ts +8 -1
- package/test/src/CDCStreamTestContext.ts +23 -23
- package/test/src/util.ts +4 -4
- package/tsconfig.json +0 -3
- package/tsconfig.tsbuildinfo +1 -1
package/src/utils/schema.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { logger } from '@powersync/lib-services-framework';
|
|
1
|
+
import { ErrorCode, logger, ServiceError } from '@powersync/lib-services-framework';
|
|
2
2
|
import { TablePattern } from '@powersync/service-sync-rules';
|
|
3
3
|
import sql from 'mssql';
|
|
4
4
|
import { MSSQLConnectionManager } from '../replication/MSSQLConnectionManager.js';
|
|
@@ -150,6 +150,13 @@ export async function getTablesFromPattern(
|
|
|
150
150
|
connectionManager: MSSQLConnectionManager,
|
|
151
151
|
tablePattern: TablePattern
|
|
152
152
|
): Promise<ResolvedTable[]> {
|
|
153
|
+
if (tablePattern.isSchemaWildcard) {
|
|
154
|
+
throw new ServiceError(
|
|
155
|
+
ErrorCode.PSYNC_R2201,
|
|
156
|
+
'Schema wildcards ("%") in table patterns are not supported for SQL Server connections.'
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
153
160
|
if (tablePattern.isWildcard) {
|
|
154
161
|
const { recordset: tableResults } = await connectionManager.query(
|
|
155
162
|
`
|
|
@@ -26,7 +26,7 @@ export class CDCStreamTestContext implements AsyncDisposable {
|
|
|
26
26
|
private _cdcStream?: CDCStream;
|
|
27
27
|
private abortController = new AbortController();
|
|
28
28
|
private streamPromise?: Promise<void>;
|
|
29
|
-
private syncRulesContent?: storage.
|
|
29
|
+
private syncRulesContent?: storage.PersistedSyncConfigContent;
|
|
30
30
|
public storage?: SyncRulesBucketStorage;
|
|
31
31
|
private snapshotPromise?: Promise<void>;
|
|
32
32
|
private replicationDone = false;
|
|
@@ -75,37 +75,37 @@ export class CDCStreamTestContext implements AsyncDisposable {
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
async updateSyncRules(content: string) {
|
|
78
|
-
const
|
|
78
|
+
const replicationStream = await this.factory.updateSyncRules(
|
|
79
79
|
updateSyncRulesFromYaml(content, { validate: true, storageVersion: LEGACY_STORAGE_VERSION })
|
|
80
80
|
);
|
|
81
|
-
this.syncRulesContent =
|
|
82
|
-
this.storage = this.factory.getInstance(
|
|
81
|
+
this.syncRulesContent = replicationStream.syncConfigContent[0];
|
|
82
|
+
this.storage = this.factory.getInstance(replicationStream);
|
|
83
83
|
return this.storage!;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
async loadNextSyncRules() {
|
|
87
|
-
const
|
|
88
|
-
if (
|
|
87
|
+
const syncConfig = await this.factory.getDeployingSyncConfig();
|
|
88
|
+
if (syncConfig == null) {
|
|
89
89
|
throw new Error(`Next replication stream not available`);
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
this.syncRulesContent =
|
|
93
|
-
this.storage =
|
|
92
|
+
this.syncRulesContent = syncConfig.content;
|
|
93
|
+
this.storage = syncConfig.storage;
|
|
94
94
|
return this.storage!;
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
async loadActiveSyncRules() {
|
|
98
|
-
const
|
|
99
|
-
if (
|
|
98
|
+
const syncConfig = await this.factory.getActiveSyncConfig();
|
|
99
|
+
if (syncConfig == null) {
|
|
100
100
|
throw new Error(`Active replication stream not available`);
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
this.syncRulesContent =
|
|
104
|
-
this.storage =
|
|
103
|
+
this.syncRulesContent = syncConfig.content;
|
|
104
|
+
this.storage = syncConfig.storage;
|
|
105
105
|
return this.storage!;
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
private
|
|
108
|
+
private getSyncConfigContent(): storage.PersistedSyncConfigContent {
|
|
109
109
|
if (this.syncRulesContent == null) {
|
|
110
110
|
throw new Error('Sync config not configured - call updateSyncRules() first');
|
|
111
111
|
}
|
|
@@ -183,8 +183,8 @@ export class CDCStreamTestContext implements AsyncDisposable {
|
|
|
183
183
|
|
|
184
184
|
async getBucketsDataBatch(buckets: Record<string, InternalOpId>, options?: { timeout?: number }) {
|
|
185
185
|
let checkpoint = await this.getCheckpoint(options);
|
|
186
|
-
const
|
|
187
|
-
const map = Object.entries(buckets).map(([bucket, start]) => bucketRequest(
|
|
186
|
+
const syncConfigContent = this.getSyncConfigContent();
|
|
187
|
+
const map = Object.entries(buckets).map(([bucket, start]) => bucketRequest(syncConfigContent, bucket, start));
|
|
188
188
|
return test_utils.fromAsync(this.storage!.getBucketDataBatch(checkpoint, map));
|
|
189
189
|
}
|
|
190
190
|
|
|
@@ -196,19 +196,19 @@ export class CDCStreamTestContext implements AsyncDisposable {
|
|
|
196
196
|
if (typeof start == 'string') {
|
|
197
197
|
start = BigInt(start);
|
|
198
198
|
}
|
|
199
|
-
const
|
|
199
|
+
const syncConfigContent = this.getSyncConfigContent();
|
|
200
200
|
const checkpoint = await this.getCheckpoint(options);
|
|
201
|
-
let map = [bucketRequest(
|
|
201
|
+
let map = [bucketRequest(syncConfigContent, bucket, start)];
|
|
202
202
|
let data: OplogEntry[] = [];
|
|
203
203
|
while (true) {
|
|
204
204
|
const batch = this.storage!.getBucketDataBatch(checkpoint, map);
|
|
205
205
|
|
|
206
|
-
const batches = await test_utils.
|
|
206
|
+
const batches = await test_utils.getBatchArray(batch);
|
|
207
207
|
data = data.concat(batches[0]?.chunkData.data ?? []);
|
|
208
208
|
if (batches.length == 0 || !batches[0]!.chunkData.has_more) {
|
|
209
209
|
break;
|
|
210
210
|
}
|
|
211
|
-
map = [bucketRequest(
|
|
211
|
+
map = [bucketRequest(syncConfigContent, bucket, BigInt(batches[0]!.chunkData.next_after))];
|
|
212
212
|
}
|
|
213
213
|
return data;
|
|
214
214
|
}
|
|
@@ -226,11 +226,11 @@ export class CDCStreamTestContext implements AsyncDisposable {
|
|
|
226
226
|
if (typeof start == 'string') {
|
|
227
227
|
start = BigInt(start);
|
|
228
228
|
}
|
|
229
|
-
const
|
|
230
|
-
const
|
|
231
|
-
const map = [bucketRequest(
|
|
229
|
+
const checkpoint = await this.storage!.getCheckpoint();
|
|
230
|
+
const syncConfigContent = this.getSyncConfigContent();
|
|
231
|
+
const map = [bucketRequest(syncConfigContent, bucket, start)];
|
|
232
232
|
const batch = this.storage!.getBucketDataBatch(checkpoint, map);
|
|
233
|
-
const batches = await test_utils.
|
|
233
|
+
const batches = await test_utils.getBatchArray(batch);
|
|
234
234
|
return batches[0]?.chunkData.data ?? [];
|
|
235
235
|
}
|
|
236
236
|
}
|
package/test/src/util.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as types from '@module/types/types.js';
|
|
2
2
|
import { logger } from '@powersync/lib-services-framework';
|
|
3
|
-
import { BucketStorageFactory,
|
|
3
|
+
import { BucketStorageFactory, ReplicationCheckpoint, TestStorageConfig } from '@powersync/service-core';
|
|
4
4
|
|
|
5
5
|
import * as mongo_storage from '@powersync/service-module-mongodb-storage';
|
|
6
6
|
import * as postgres_storage from '@powersync/service-module-postgres-storage';
|
|
@@ -194,7 +194,7 @@ export async function getClientCheckpoint(
|
|
|
194
194
|
connectionManager: MSSQLConnectionManager,
|
|
195
195
|
storageFactory: BucketStorageFactory,
|
|
196
196
|
options?: { timeout?: number }
|
|
197
|
-
): Promise<
|
|
197
|
+
): Promise<ReplicationCheckpoint> {
|
|
198
198
|
const start = Date.now();
|
|
199
199
|
|
|
200
200
|
const lsn = await getLatestLSN(connectionManager);
|
|
@@ -208,13 +208,13 @@ export async function getClientCheckpoint(
|
|
|
208
208
|
|
|
209
209
|
logger.info(`Test Assertion: Waiting for LSN checkpoint: ${lsn}`);
|
|
210
210
|
while (Date.now() - start < timeout) {
|
|
211
|
-
const storage = await storageFactory.
|
|
211
|
+
const storage = (await storageFactory.getActiveSyncConfig())?.storage;
|
|
212
212
|
const cp = await storage?.getCheckpoint();
|
|
213
213
|
if (cp != null) {
|
|
214
214
|
lastCp = cp;
|
|
215
215
|
if (cp.lsn != null && cp.lsn >= lsn.toString()) {
|
|
216
216
|
logger.info(`Test Assertion: Got write checkpoint: ${lsn} : ${cp.checkpoint}`);
|
|
217
|
-
return cp
|
|
217
|
+
return cp;
|
|
218
218
|
}
|
|
219
219
|
}
|
|
220
220
|
|