@powersync/service-core 1.21.0 → 1.22.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.
Files changed (71) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/dist/api/diagnostics.js +1 -1
  3. package/dist/api/diagnostics.js.map +1 -1
  4. package/dist/auth/RemoteJWKSCollector.js +3 -2
  5. package/dist/auth/RemoteJWKSCollector.js.map +1 -1
  6. package/dist/replication/RelationCache.d.ts +9 -2
  7. package/dist/replication/RelationCache.js +21 -2
  8. package/dist/replication/RelationCache.js.map +1 -1
  9. package/dist/routes/configure-fastify.js +3 -1
  10. package/dist/routes/configure-fastify.js.map +1 -1
  11. package/dist/routes/endpoints/admin.js +9 -5
  12. package/dist/routes/endpoints/admin.js.map +1 -1
  13. package/dist/routes/endpoints/sync-rules.js +1 -1
  14. package/dist/routes/endpoints/sync-rules.js.map +1 -1
  15. package/dist/routes/route-register.d.ts +2 -0
  16. package/dist/routes/route-register.js +65 -3
  17. package/dist/routes/route-register.js.map +1 -1
  18. package/dist/storage/BucketStorageBatch.d.ts +29 -0
  19. package/dist/storage/BucketStorageBatch.js.map +1 -1
  20. package/dist/storage/BucketStorageFactory.d.ts +4 -0
  21. package/dist/storage/BucketStorageFactory.js +1 -1
  22. package/dist/storage/BucketStorageFactory.js.map +1 -1
  23. package/dist/storage/PersistedSyncRulesContent.d.ts +3 -3
  24. package/dist/storage/PersistedSyncRulesContent.js +6 -6
  25. package/dist/storage/PersistedSyncRulesContent.js.map +1 -1
  26. package/dist/storage/SourceEntity.d.ts +8 -1
  27. package/dist/storage/SourceTable.d.ts +29 -8
  28. package/dist/storage/SourceTable.js +38 -12
  29. package/dist/storage/SourceTable.js.map +1 -1
  30. package/dist/storage/SyncRulesBucketStorage.d.ts +26 -13
  31. package/dist/storage/SyncRulesBucketStorage.js.map +1 -1
  32. package/dist/sync/BucketChecksumState.d.ts +4 -4
  33. package/dist/sync/BucketChecksumState.js +1 -1
  34. package/dist/sync/BucketChecksumState.js.map +1 -1
  35. package/dist/sync/sync.d.ts +2 -2
  36. package/dist/sync/sync.js.map +1 -1
  37. package/dist/tracing/PerformanceTracer.d.ts +17 -1
  38. package/dist/tracing/PerformanceTracer.js +3 -0
  39. package/dist/tracing/PerformanceTracer.js.map +1 -1
  40. package/dist/util/util-index.d.ts +1 -0
  41. package/dist/util/util-index.js +1 -0
  42. package/dist/util/util-index.js.map +1 -1
  43. package/dist/util/utils.d.ts +5 -0
  44. package/dist/util/utils.js +7 -0
  45. package/dist/util/utils.js.map +1 -1
  46. package/package.json +4 -4
  47. package/src/api/diagnostics.ts +3 -3
  48. package/src/auth/RemoteJWKSCollector.ts +3 -1
  49. package/src/replication/RelationCache.ts +23 -4
  50. package/src/routes/configure-fastify.ts +8 -1
  51. package/src/routes/endpoints/admin.ts +10 -5
  52. package/src/routes/endpoints/sync-rules.ts +1 -1
  53. package/src/routes/route-register.ts +73 -4
  54. package/src/storage/BucketStorageBatch.ts +32 -0
  55. package/src/storage/BucketStorageFactory.ts +6 -1
  56. package/src/storage/PersistedSyncRulesContent.ts +9 -9
  57. package/src/storage/SourceEntity.ts +9 -1
  58. package/src/storage/SourceTable.ts +53 -19
  59. package/src/storage/SyncRulesBucketStorage.ts +28 -15
  60. package/src/sync/BucketChecksumState.ts +5 -5
  61. package/src/sync/sync.ts +3 -3
  62. package/src/tracing/PerformanceTracer.ts +24 -1
  63. package/src/util/util-index.ts +1 -0
  64. package/src/util/utils.ts +8 -0
  65. package/test/src/auth.test.ts +11 -0
  66. package/test/src/diagnostics.test.ts +10 -6
  67. package/test/src/routes/error-handler.integration.test.ts +275 -0
  68. package/test/src/routes/stream.test.ts +15 -4
  69. package/test/src/storage/SourceTable.test.ts +89 -0
  70. package/test/src/sync/BucketChecksumState.test.ts +25 -17
  71. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,89 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import * as storage from '../../../src/storage/storage-index.js';
3
+
4
+ /**
5
+ * Build a SourceTable with the current `ref`-based options shape.
6
+ * Data/parameter sources are not relevant to the storeCurrentData behaviour, so they default to empty.
7
+ */
8
+ function makeTable(options: Partial<storage.SourceTableOptions> = {}): storage.SourceTable {
9
+ return new storage.SourceTable({
10
+ id: 'test-id',
11
+ ref: { connectionTag: 'test', schema: 'public', name: 'test_table' },
12
+ objectId: 123,
13
+ replicaIdColumns: [{ name: 'id' }],
14
+ snapshotComplete: true,
15
+ bucketDataSources: [],
16
+ parameterLookupSources: [],
17
+ ...options
18
+ });
19
+ }
20
+
21
+ describe('SourceTable', () => {
22
+ describe('storeCurrentData property', () => {
23
+ test('defaults to true', () => {
24
+ const table = makeTable();
25
+ expect(table.storeCurrentData).toBe(true);
26
+ });
27
+
28
+ test('can be set to false', () => {
29
+ const table = makeTable();
30
+ table.storeCurrentData = false;
31
+ expect(table.storeCurrentData).toBe(false);
32
+ });
33
+
34
+ test('is preserved when cloning', () => {
35
+ const table = makeTable();
36
+ table.storeCurrentData = false;
37
+ const cloned = table.clone();
38
+
39
+ expect(cloned.storeCurrentData).toBe(false);
40
+ expect(cloned).not.toBe(table);
41
+ });
42
+
43
+ test('clone preserves all properties including storeCurrentData', () => {
44
+ const table = makeTable({
45
+ replicaIdColumns: [{ name: 'id', type: 'int4' }],
46
+ snapshotComplete: false
47
+ });
48
+
49
+ table.syncData = false;
50
+ table.syncParameters = false;
51
+ table.syncEvent = false;
52
+ table.storeCurrentData = false;
53
+ table.snapshotStatus = {
54
+ totalEstimatedCount: 100,
55
+ replicatedCount: 50,
56
+ lastKey: Buffer.from('test')
57
+ };
58
+
59
+ const cloned = table.clone();
60
+
61
+ expect(cloned.syncData).toBe(false);
62
+ expect(cloned.syncParameters).toBe(false);
63
+ expect(cloned.syncEvent).toBe(false);
64
+ expect(cloned.storeCurrentData).toBe(false);
65
+ expect(cloned.snapshotStatus).toEqual(table.snapshotStatus);
66
+ });
67
+ });
68
+
69
+ describe('integration with other properties', () => {
70
+ test('storeCurrentData does not affect syncAny', () => {
71
+ const table = makeTable();
72
+
73
+ table.storeCurrentData = false;
74
+ table.syncData = true;
75
+ table.syncParameters = false;
76
+ table.syncEvent = false;
77
+
78
+ expect(table.syncAny).toBe(true); // Should still be true
79
+ });
80
+
81
+ test('storeCurrentData is independent of snapshot status', () => {
82
+ const table = makeTable({ snapshotComplete: false });
83
+
84
+ table.storeCurrentData = false;
85
+ expect(table.snapshotComplete).toBe(false);
86
+ expect(table.storeCurrentData).toBe(false);
87
+ });
88
+ });
89
+ });
@@ -15,34 +15,39 @@ import {
15
15
  } from '@/index.js';
16
16
  import { JSONBig } from '@powersync/service-jsonbig';
17
17
  import {
18
+ nodeSqlite,
18
19
  ParameterIndexLookupCreator,
20
+ ParameterLookupDefinitionId,
19
21
  ParameterLookupRows,
22
+ ParameterLookupScope,
20
23
  ScopedParameterLookup,
21
- SourceTableInterface,
22
- SqliteRow,
24
+ SourceTableRef,
23
25
  SqlSyncRules,
24
26
  TablePattern,
25
27
  versionedHydrationState
26
28
  } from '@powersync/service-sync-rules';
27
- import { ParameterLookupScope } from '@powersync/service-sync-rules/src/HydrationState.js';
29
+ import * as sqlite from 'node:sqlite';
28
30
  import { beforeEach, describe, expect, test } from 'vitest';
29
31
 
30
32
  describe('BucketChecksumState', () => {
31
33
  const LOOKUP_SOURCE: ParameterIndexLookupCreator = {
32
- get defaultLookupScope(): ParameterLookupScope {
34
+ get sourceId(): ParameterLookupDefinitionId {
33
35
  return {
34
36
  lookupName: 'lookup',
35
- queryId: '0',
36
- source: LOOKUP_SOURCE
37
+ queryId: '0'
37
38
  };
38
39
  },
39
40
  getSourceTables(): Set<TablePattern> {
40
41
  return new Set();
41
42
  },
42
- evaluateParameterRow(_sourceTable: SourceTableInterface, _row: SqliteRow) {
43
- return [];
43
+ createEvaluator() {
44
+ return {
45
+ evaluateParameterRow() {
46
+ return [];
47
+ }
48
+ };
44
49
  },
45
- tableSyncsParameters(_table: SourceTableInterface): boolean {
50
+ tableSyncsParameters(_table: SourceTableRef): boolean {
46
51
  return false;
47
52
  }
48
53
  };
@@ -60,7 +65,7 @@ bucket_definitions:
60
65
  data: []
61
66
  `,
62
67
  { defaultSchema: 'public' }
63
- ).config.hydrate({ hydrationState: versionedHydrationState(1) });
68
+ ).config.hydrate({ hydrationState: versionedHydrationState(1), sqlite: nodeSqlite(sqlite) });
64
69
 
65
70
  // global[1] and global[2]
66
71
  const SYNC_RULES_GLOBAL_TWO = SqlSyncRules.fromYaml(
@@ -73,7 +78,7 @@ bucket_definitions:
73
78
  data: []
74
79
  `,
75
80
  { defaultSchema: 'public' }
76
- ).config.hydrate({ hydrationState: versionedHydrationState(2) });
81
+ ).config.hydrate({ hydrationState: versionedHydrationState(2), sqlite: nodeSqlite(sqlite) });
77
82
 
78
83
  // by_project[n]
79
84
  const SYNC_RULES_DYNAMIC = SqlSyncRules.fromYaml(
@@ -84,7 +89,7 @@ bucket_definitions:
84
89
  data: []
85
90
  `,
86
91
  { defaultSchema: 'public' }
87
- ).config.hydrate({ hydrationState: versionedHydrationState(3) });
92
+ ).config.hydrate({ hydrationState: versionedHydrationState(3), sqlite: nodeSqlite(sqlite) });
88
93
 
89
94
  const syncContext = new SyncContext({
90
95
  maxBuckets: 100,
@@ -655,7 +660,7 @@ config:
655
660
 
656
661
  const rules = SqlSyncRules.fromYaml(source, {
657
662
  defaultSchema: 'public'
658
- }).config.hydrate({ hydrationState: versionedHydrationState(1) });
663
+ }).config.hydrate({ hydrationState: versionedHydrationState(1), sqlite: nodeSqlite(sqlite) });
659
664
 
660
665
  return new BucketChecksumState({
661
666
  syncContext,
@@ -921,7 +926,8 @@ streams:
921
926
  `,
922
927
  { defaultSchema: 'public' }
923
928
  ).config.hydrate({
924
- hydrationState: versionedHydrationState(1)
929
+ hydrationState: versionedHydrationState(1),
930
+ sqlite: nodeSqlite(sqlite)
925
931
  });
926
932
 
927
933
  const storage = new MockBucketChecksumStateStorage();
@@ -1018,7 +1024,8 @@ streams:
1018
1024
  `,
1019
1025
  { defaultSchema: 'public' }
1020
1026
  ).config.hydrate({
1021
- hydrationState: versionedHydrationState(1)
1027
+ hydrationState: versionedHydrationState(1),
1028
+ sqlite: nodeSqlite(sqlite)
1022
1029
  });
1023
1030
 
1024
1031
  const storage = new MockBucketChecksumStateStorage();
@@ -1090,7 +1097,7 @@ streams:
1090
1097
  query: SELECT id FROM comments WHERE p IN auth.parameter('c')
1091
1098
  `,
1092
1099
  { defaultSchema: 'public' }
1093
- ).config.hydrate({ hydrationState: versionedHydrationState(4) });
1100
+ ).config.hydrate({ hydrationState: versionedHydrationState(4), sqlite: nodeSqlite(sqlite) });
1094
1101
 
1095
1102
  const storage = new MockBucketChecksumStateStorage();
1096
1103
 
@@ -1165,7 +1172,8 @@ streams:
1165
1172
  }
1166
1173
 
1167
1174
  const SYNC_RULES_MANY = SqlSyncRules.fromYaml(yamlDefinitions, { defaultSchema: 'public' }).config.hydrate({
1168
- hydrationState: versionedHydrationState(5)
1175
+ hydrationState: versionedHydrationState(5),
1176
+ sqlite: nodeSqlite(sqlite)
1169
1177
  });
1170
1178
 
1171
1179
  const storage = new MockBucketChecksumStateStorage();