@powersync/service-module-mssql 0.0.0-dev-20260602073133 → 0.0.0-dev-20260909133214

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 (64) hide show
  1. package/CHANGELOG.md +209 -4
  2. package/dist/api/MSSQLRouteAPIAdapter.d.ts +4 -5
  3. package/dist/api/MSSQLRouteAPIAdapter.js +33 -39
  4. package/dist/api/MSSQLRouteAPIAdapter.js.map +1 -1
  5. package/dist/common/MSSQLSourceTable.d.ts +12 -2
  6. package/dist/common/MSSQLSourceTable.js +30 -4
  7. package/dist/common/MSSQLSourceTable.js.map +1 -1
  8. package/dist/module/MSSQLModule.js +2 -1
  9. package/dist/module/MSSQLModule.js.map +1 -1
  10. package/dist/replication/CDCPoller.d.ts +13 -36
  11. package/dist/replication/CDCPoller.js +173 -129
  12. package/dist/replication/CDCPoller.js.map +1 -1
  13. package/dist/replication/CDCReplicationJob.js +1 -1
  14. package/dist/replication/CDCReplicationJob.js.map +1 -1
  15. package/dist/replication/CDCReplicator.js +1 -1
  16. package/dist/replication/CDCReplicator.js.map +1 -1
  17. package/dist/replication/CDCStream.d.ts +11 -14
  18. package/dist/replication/CDCStream.js +124 -115
  19. package/dist/replication/CDCStream.js.map +1 -1
  20. package/dist/replication/CaptureReconciler.d.ts +47 -0
  21. package/dist/replication/CaptureReconciler.js +155 -0
  22. package/dist/replication/CaptureReconciler.js.map +1 -0
  23. package/dist/replication/MSSQLConnectionManager.d.ts +1 -0
  24. package/dist/replication/MSSQLConnectionManager.js +19 -14
  25. package/dist/replication/MSSQLConnectionManager.js.map +1 -1
  26. package/dist/replication/MSSQLTableReconciliationContext.d.ts +21 -0
  27. package/dist/replication/MSSQLTableReconciliationContext.js +7 -0
  28. package/dist/replication/MSSQLTableReconciliationContext.js.map +1 -0
  29. package/dist/replication/SchemaChange.d.ts +67 -0
  30. package/dist/replication/SchemaChange.js +31 -0
  31. package/dist/replication/SchemaChange.js.map +1 -0
  32. package/dist/types/types.d.ts +13 -0
  33. package/dist/types/types.js +28 -2
  34. package/dist/types/types.js.map +1 -1
  35. package/dist/utils/mssql.js +1 -1
  36. package/dist/utils/schema.d.ts +14 -1
  37. package/dist/utils/schema.js +43 -45
  38. package/dist/utils/schema.js.map +1 -1
  39. package/package.json +11 -21
  40. package/src/api/MSSQLRouteAPIAdapter.ts +38 -49
  41. package/src/common/MSSQLSourceTable.ts +32 -4
  42. package/src/module/MSSQLModule.ts +2 -1
  43. package/src/replication/CDCPoller.ts +206 -162
  44. package/src/replication/CDCReplicationJob.ts +1 -1
  45. package/src/replication/CDCReplicator.ts +1 -1
  46. package/src/replication/CDCStream.ts +157 -163
  47. package/src/replication/CaptureReconciler.ts +186 -0
  48. package/src/replication/MSSQLConnectionManager.ts +23 -14
  49. package/src/replication/MSSQLTableReconciliationContext.ts +29 -0
  50. package/src/replication/SchemaChange.ts +79 -0
  51. package/src/types/types.ts +47 -2
  52. package/src/utils/mssql.ts +1 -1
  53. package/src/utils/schema.ts +60 -54
  54. package/test/src/CDCPoller.test.ts +382 -0
  55. package/test/src/CDCStream.test.ts +6 -2
  56. package/test/src/CDCStreamTestContext.ts +30 -23
  57. package/test/src/CaptureReconciler.test.ts +171 -0
  58. package/test/src/MSSQLSourceTable.test.ts +30 -0
  59. package/test/src/config.test.ts +71 -0
  60. package/test/src/schema-changes.test.ts +513 -249
  61. package/test/src/schema.test.ts +17 -0
  62. package/test/src/util.ts +73 -9
  63. package/tsconfig.json +0 -3
  64. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,17 @@
1
+ import { unsupportedTablePatternMessage } from '@module/utils/schema.js';
2
+ import { TablePattern } from '@powersync/service-sync-rules';
3
+ import { describe, expect, it } from 'vitest';
4
+
5
+ describe('unsupportedTablePatternMessage', () => {
6
+ it('accepts an exact table pattern', () => {
7
+ expect(unsupportedTablePatternMessage(new TablePattern('dbo', 'users'))).toBeNull();
8
+ });
9
+
10
+ it('rejects a table wildcard', () => {
11
+ expect(unsupportedTablePatternMessage(new TablePattern('dbo', 'test_data%'))).toMatch(/Table wildcards/);
12
+ });
13
+
14
+ it('rejects a schema wildcard', () => {
15
+ expect(unsupportedTablePatternMessage(new TablePattern('dbo%', 'users'))).toMatch(/Schema wildcards/);
16
+ });
17
+ });
package/test/src/util.ts CHANGED
@@ -1,11 +1,12 @@
1
1
  import * as types from '@module/types/types.js';
2
2
  import { logger } from '@powersync/lib-services-framework';
3
- import { BucketStorageFactory, InternalOpId, ReplicationCheckpoint, TestStorageConfig } from '@powersync/service-core';
4
-
3
+ import { BucketStorageFactory, ReplicationCheckpoint, storage, TestStorageConfig } from '@powersync/service-core';
5
4
  import * as mongo_storage from '@powersync/service-module-mongodb-storage';
6
5
  import * as postgres_storage from '@powersync/service-module-postgres-storage';
7
6
 
7
+ import { CaptureInstance } from '@module/common/CaptureInstance.js';
8
8
  import { LSN } from '@module/common/LSN.js';
9
+ import { MSSQLSourceMetadata } from '@module/replication/CaptureReconciler.js';
9
10
  import { MSSQLConnectionManager } from '@module/replication/MSSQLConnectionManager.js';
10
11
  import { createCheckpoint, escapeIdentifier, getLatestLSN, toQualifiedTableName } from '@module/utils/mssql.js';
11
12
  import sql from 'mssql';
@@ -194,7 +195,7 @@ export async function getClientCheckpoint(
194
195
  connectionManager: MSSQLConnectionManager,
195
196
  storageFactory: BucketStorageFactory,
196
197
  options?: { timeout?: number }
197
- ): Promise<InternalOpId> {
198
+ ): Promise<ReplicationCheckpoint> {
198
199
  const start = Date.now();
199
200
 
200
201
  const lsn = await getLatestLSN(connectionManager);
@@ -208,13 +209,13 @@ export async function getClientCheckpoint(
208
209
 
209
210
  logger.info(`Test Assertion: Waiting for LSN checkpoint: ${lsn}`);
210
211
  while (Date.now() - start < timeout) {
211
- const storage = await storageFactory.getActiveStorage();
212
+ const storage = (await storageFactory.getActiveSyncConfig())?.storage;
212
213
  const cp = await storage?.getCheckpoint();
213
214
  if (cp != null) {
214
215
  lastCp = cp;
215
216
  if (cp.lsn != null && cp.lsn >= lsn.toString()) {
216
217
  logger.info(`Test Assertion: Got write checkpoint: ${lsn} : ${cp.checkpoint}`);
217
- return cp.checkpoint;
218
+ return cp;
218
219
  }
219
220
  }
220
221
 
@@ -242,24 +243,87 @@ export interface EnableCDCForTableOptions {
242
243
  connectionManager: MSSQLConnectionManager;
243
244
  table: string;
244
245
  captureInstance?: string;
246
+ /**
247
+ * Columns to capture. SQL Server captures all columns by default.
248
+ */
249
+ capturedColumns?: string[];
245
250
  }
246
251
 
247
252
  export async function enableCDCForTable(options: EnableCDCForTableOptions): Promise<void> {
248
- const { connectionManager, table, captureInstance } = options;
253
+ const { connectionManager, table, captureInstance, capturedColumns } = options;
249
254
 
250
255
  await connectionManager.execute('sys.sp_cdc_enable_table', [
251
256
  { name: 'source_schema', value: connectionManager.schema },
252
257
  { name: 'source_name', value: table },
253
258
  { name: 'role_name', value: 'cdc_reader' },
254
259
  { name: 'supports_net_changes', value: 0 },
255
- ...(captureInstance !== undefined ? [{ name: 'capture_instance', value: captureInstance }] : [])
260
+ ...(captureInstance !== undefined ? [{ name: 'capture_instance', value: captureInstance }] : []),
261
+ ...(capturedColumns !== undefined ? [{ name: 'captured_column_list', value: capturedColumns.join(',') }] : [])
256
262
  ]);
257
263
  }
258
264
 
259
- export async function disableCDCForTable(connectionManager: MSSQLConnectionManager, tableName: string) {
265
+ /**
266
+ * Disable one capture instance, or all instances by default.
267
+ */
268
+ export async function disableCDCForTable(
269
+ connectionManager: MSSQLConnectionManager,
270
+ tableName: string,
271
+ captureInstance: string = 'all'
272
+ ) {
260
273
  await connectionManager.execute('sys.sp_cdc_disable_table', [
261
274
  { name: 'source_schema', value: connectionManager.schema },
262
275
  { name: 'source_name', value: tableName },
263
- { name: 'capture_instance', value: 'all' }
276
+ { name: 'capture_instance', value: captureInstance }
264
277
  ]);
265
278
  }
279
+
280
+ /**
281
+ * Create a capture instance with the given capture-table object id.
282
+ */
283
+ export function createCaptureInstance(objectId: number): CaptureInstance {
284
+ return {
285
+ name: `dbo_users_${objectId}`,
286
+ objectId,
287
+ minLSN: LSN.fromString(LSN.ZERO),
288
+ createDate: new Date(),
289
+ pendingSchemaChanges: []
290
+ };
291
+ }
292
+ /**
293
+ * Build a persisted source-table candidate with optional capture metadata.
294
+ */
295
+ export function createSourceTableCandidate(
296
+ id: string,
297
+ metadata?: MSSQLSourceMetadata,
298
+ overrides: Partial<ConstructorParameters<typeof storage.SourceTable>[0]> = {}
299
+ ): storage.SourceTable {
300
+ const descriptor = createSourceDescriptor();
301
+
302
+ return new storage.SourceTable({
303
+ id,
304
+ ref: descriptor,
305
+ objectId: descriptor.objectId,
306
+ replicaIdColumns: descriptor.replicaIdColumns,
307
+ snapshotComplete: true,
308
+ bucketDataSources: [],
309
+ parameterLookupSources: [],
310
+ sourceMetadata: metadata,
311
+ ...overrides
312
+ });
313
+ }
314
+
315
+ /**
316
+ * Create a source descriptor with optional identity overrides.
317
+ */
318
+ export function createSourceDescriptor(
319
+ overrides: Partial<storage.SourceEntityDescriptor> = {}
320
+ ): storage.SourceEntityDescriptor {
321
+ return {
322
+ connectionTag: 'default',
323
+ schema: 'dbo',
324
+ name: 'users',
325
+ objectId: 100,
326
+ replicaIdColumns: [{ name: 'id', type: 'int', typeId: 56 }],
327
+ ...overrides
328
+ };
329
+ }
package/tsconfig.json CHANGED
@@ -3,9 +3,6 @@
3
3
  "compilerOptions": {
4
4
  "rootDir": "src",
5
5
  "outDir": "dist",
6
- "esModuleInterop": true,
7
- "skipLibCheck": true,
8
- "sourceMap": true,
9
6
  "typeRoots": ["./node_modules/@types"]
10
7
  },
11
8
  "include": ["src"],