@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.
- package/CHANGELOG.md +31 -0
- package/dist/api/diagnostics.js +1 -1
- package/dist/api/diagnostics.js.map +1 -1
- package/dist/auth/RemoteJWKSCollector.js +3 -2
- package/dist/auth/RemoteJWKSCollector.js.map +1 -1
- package/dist/replication/RelationCache.d.ts +9 -2
- package/dist/replication/RelationCache.js +21 -2
- package/dist/replication/RelationCache.js.map +1 -1
- package/dist/routes/configure-fastify.js +3 -1
- package/dist/routes/configure-fastify.js.map +1 -1
- package/dist/routes/endpoints/admin.js +9 -5
- package/dist/routes/endpoints/admin.js.map +1 -1
- package/dist/routes/endpoints/sync-rules.js +1 -1
- package/dist/routes/endpoints/sync-rules.js.map +1 -1
- package/dist/routes/route-register.d.ts +2 -0
- package/dist/routes/route-register.js +65 -3
- package/dist/routes/route-register.js.map +1 -1
- package/dist/storage/BucketStorageBatch.d.ts +29 -0
- package/dist/storage/BucketStorageBatch.js.map +1 -1
- package/dist/storage/BucketStorageFactory.d.ts +4 -0
- package/dist/storage/BucketStorageFactory.js +1 -1
- package/dist/storage/BucketStorageFactory.js.map +1 -1
- package/dist/storage/PersistedSyncRulesContent.d.ts +3 -3
- package/dist/storage/PersistedSyncRulesContent.js +6 -6
- package/dist/storage/PersistedSyncRulesContent.js.map +1 -1
- package/dist/storage/SourceEntity.d.ts +8 -1
- package/dist/storage/SourceTable.d.ts +29 -8
- package/dist/storage/SourceTable.js +38 -12
- package/dist/storage/SourceTable.js.map +1 -1
- package/dist/storage/SyncRulesBucketStorage.d.ts +26 -13
- package/dist/storage/SyncRulesBucketStorage.js.map +1 -1
- package/dist/sync/BucketChecksumState.d.ts +4 -4
- package/dist/sync/BucketChecksumState.js +1 -1
- package/dist/sync/BucketChecksumState.js.map +1 -1
- package/dist/sync/sync.d.ts +2 -2
- package/dist/sync/sync.js.map +1 -1
- package/dist/tracing/PerformanceTracer.d.ts +17 -1
- package/dist/tracing/PerformanceTracer.js +3 -0
- package/dist/tracing/PerformanceTracer.js.map +1 -1
- package/dist/util/util-index.d.ts +1 -0
- package/dist/util/util-index.js +1 -0
- package/dist/util/util-index.js.map +1 -1
- package/dist/util/utils.d.ts +5 -0
- package/dist/util/utils.js +7 -0
- package/dist/util/utils.js.map +1 -1
- package/package.json +4 -4
- package/src/api/diagnostics.ts +3 -3
- package/src/auth/RemoteJWKSCollector.ts +3 -1
- package/src/replication/RelationCache.ts +23 -4
- package/src/routes/configure-fastify.ts +8 -1
- package/src/routes/endpoints/admin.ts +10 -5
- package/src/routes/endpoints/sync-rules.ts +1 -1
- package/src/routes/route-register.ts +73 -4
- package/src/storage/BucketStorageBatch.ts +32 -0
- package/src/storage/BucketStorageFactory.ts +6 -1
- package/src/storage/PersistedSyncRulesContent.ts +9 -9
- package/src/storage/SourceEntity.ts +9 -1
- package/src/storage/SourceTable.ts +53 -19
- package/src/storage/SyncRulesBucketStorage.ts +28 -15
- package/src/sync/BucketChecksumState.ts +5 -5
- package/src/sync/sync.ts +3 -3
- package/src/tracing/PerformanceTracer.ts +24 -1
- package/src/util/util-index.ts +1 -0
- package/src/util/utils.ts +8 -0
- package/test/src/auth.test.ts +11 -0
- package/test/src/diagnostics.test.ts +10 -6
- package/test/src/routes/error-handler.integration.test.ts +275 -0
- package/test/src/routes/stream.test.ts +15 -4
- package/test/src/storage/SourceTable.test.ts +89 -0
- package/test/src/sync/BucketChecksumState.test.ts +25 -17
- package/tsconfig.tsbuildinfo +1 -1
package/dist/util/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/util/utils.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/util/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAK7B,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AA2B1E,MAAM,CAAC,MAAM,YAAY,GAAG,sCAAsC,CAAC;AAEnE,MAAM,UAAU,gBAAgB,CAAC,UAAkB;IACjD,OAAO,IAAI,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC;AACrE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,GAA8B;IAC1D,OAAO,GAAG,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,EAAU,EAAE,IAAY;IAC7D,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IACzC,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;IAC7B,OAAO,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,SAAiB;IAC1C,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IACzC,IAAI,CAAC,MAAM,CAAC,UAAU,SAAS,EAAE,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;IAC7B,OAAO,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AAChC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,EAAgB;IACrD,6EAA6E;IAC7E,6CAA6C;IAC7C,IAAI,OAAO,EAAE,IAAI,QAAQ,EAAE,CAAC;QAC1B,MAAM,IAAI,qBAAqB,CAAC,yBAAyB,EAAE,KAAK,OAAO,EAAE,GAAG,CAAC,CAAC;IAChF,CAAC;IACD,OAAO,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,QAAqB,EAAE,OAAoB;IACvE,mBAAmB;IACnB,MAAM,cAAc,GAAG,IAAI,GAAG,EAA0B,CAAC;IAEzD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAS,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IAElD,KAAK,IAAI,QAAQ,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QACtC,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;YACd,QAAQ;YACR,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAChD,CAAC;aAAM,CAAC;YACN,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YACjC,IAAI,QAAQ,CAAC,QAAQ,IAAI,CAAC,CAAC,QAAQ,IAAI,QAAQ,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;gBACjE,UAAU;gBACV,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YAChD,CAAC;iBAAM,CAAC;gBACN,YAAY;YACd,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,cAAc,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC;QAC5C,cAAc,EAAE,CAAC,GAAG,QAAQ,CAAC;KAC9B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,CAAS,EAAE,CAAS;IAC/C,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,CAAmC;IACnE,OAAO,iBAAiB,IAAI,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,CAAiB,EAAE,CAA0C;IAC9F,MAAM,QAAQ,GAAG,mBAAmB,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACrD,IAAI,iBAAiB,CAAC,QAAQ,CAAC,EAAE,CAAC;QAChC,oCAAoC;QACpC,MAAM,IAAI,qBAAqB,CAAC,wBAAwB,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,MAAc,EACd,CAA0C,EAC1C,CAA0C;IAE1C,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;QAC3B,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1B,aAAa;YACb,OAAO,CAAC,CAAC;QACX,CAAC;QACD,QAAQ;QACR,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1B,OAAO;gBACL,MAAM;gBACN,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,eAAe,CAAC;gBACrD,KAAK,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,YAAY;aAChC,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,OAAO;gBACL,MAAM;gBACN,eAAe,EAAE,YAAY,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC,eAAe,CAAC;gBACnE,YAAY,EAAE,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC,YAAY;aAC9C,CAAC;QACJ,CAAC;IACH,CAAC;SAAM,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,OAAO,CAAC,CAAC;IACX,CAAC;SAAM,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,OAAO,CAAC,CAAC;IACX,CAAC;SAAM,CAAC;QACN,+DAA+D;QAC/D,OAAO;YACL,MAAM;YACN,eAAe,EAAE,CAAC;YAClB,YAAY,EAAE,CAAC;SAChB,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,qBAAqB,CAC5B,KAAoC,EACpC,OAAmC;IAEnC,IAAI,MAAM,GAAwB,EAAE,CAAC;IACrC,KAAK,IAAI,MAAM,IAAI,OAAO,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACzB,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,0BAA0B,CACxC,KAAoC,EACpC,OAAmC;IAEnC,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QACxB,gDAAgD;QAChD,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;IAClC,CAAC;IACD,MAAM,WAAW,GAAG,qBAAqB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAE1D,OAAO,cAAc,CAAC,WAAW,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAyB;IACtD,+EAA+E;IAC/E,4EAA4E;IAC5E,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAChC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAI,GAAqC;IACvE,KAAK,IAAI,GAAG,IAAI,GAAG,EAAE,CAAC;QACpB,IAAI,OAAO,GAAG,CAAC,GAAG,CAAC,IAAI,WAAW,EAAE,CAAC;YACnC,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC3B,SAAkB,EAClB,GAAqC;IAErC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,gDAAgD;QAChD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;AAChC,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY,CAAC,UAAwB;IACnD,IAAI,QAAQ,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC7C,IAAI,aAAa,GAAG,CAAC,CAAC;IAEtB,KAAK,IAAI,EAAE,IAAI,UAAU,EAAE,CAAC;QAC1B,MAAM,GAAG,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;QACvB,IAAI,EAAE,CAAC,EAAE,IAAI,KAAK,EAAE,CAAC;YACnB,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACnC,IAAI,QAAQ,EAAE,CAAC;gBACb,aAAa,GAAG,YAAY,CAAC,aAAa,EAAE,QAAQ,CAAC,QAAkB,CAAC,CAAC;YAC3E,CAAC;YACD,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACxB,CAAC;aAAM,IAAI,EAAE,CAAC,EAAE,IAAI,QAAQ,EAAE,CAAC;YAC7B,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACnC,IAAI,QAAQ,EAAE,CAAC;gBACb,aAAa,GAAG,YAAY,CAAC,aAAa,EAAE,QAAQ,CAAC,QAAkB,CAAC,CAAC;YAC3E,CAAC;YACD,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACrB,aAAa,GAAG,YAAY,CAAC,aAAa,EAAE,EAAE,CAAC,QAAkB,CAAC,CAAC;QACrE,CAAC;aAAM,IAAI,EAAE,CAAC,EAAE,IAAI,OAAO,EAAE,CAAC;YAC5B,QAAQ,CAAC,KAAK,EAAE,CAAC;YACjB,aAAa,GAAG,EAAE,CAAC,QAAkB,CAAC;QACxC,CAAC;aAAM,IAAI,EAAE,CAAC,EAAE,IAAI,MAAM,EAAE,CAAC;YAC3B,aAAa,GAAG,YAAY,CAAC,aAAa,EAAE,EAAE,CAAC,QAAkB,CAAC,CAAC;QACrE,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CAAC,qBAAqB,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAChD,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,IAAI,UAAU,GAAiB;QAC7B,wDAAwD;QACxD,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE;QACpD,GAAG,IAAI;KACR,CAAC;IAEF,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAC,CAAS;IAC/B,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACf,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAS,MAAM,CAAC,KAAiB;IAC/B,OAAO,GAAG,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;AACnE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,MAAiD;IAC/E,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;QACnB,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAChD,IAAI,IAAI,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC;QACxB,+CAA+C;QAC/C,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;YAClB,IAAI,IAAI,CAAC,CAAC;QACZ,CAAC;aAAM,IAAI,OAAO,KAAK,IAAI,QAAQ,EAAE,CAAC;YACpC,IAAI,IAAI,CAAC,CAAC;QACZ,CAAC;aAAM,IAAI,OAAO,KAAK,IAAI,QAAQ,EAAE,CAAC;YACpC,IAAI,IAAI,CAAC,CAAC;QACZ,CAAC;aAAM,IAAI,OAAO,KAAK,IAAI,QAAQ,EAAE,CAAC;YACpC,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC;QACvB,CAAC;aAAM,IAAI,KAAK,YAAY,UAAU,EAAE,CAAC;YACvC,IAAI,IAAI,KAAK,CAAC,UAAU,CAAC;QAC3B,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
8
|
-
"version": "1.
|
|
8
|
+
"version": "1.22.0",
|
|
9
9
|
"main": "dist/index.js",
|
|
10
10
|
"license": "FSL-1.1-ALv2",
|
|
11
11
|
"type": "module",
|
|
@@ -33,10 +33,10 @@
|
|
|
33
33
|
"uuid": "^14.0.0",
|
|
34
34
|
"winston": "^3.13.0",
|
|
35
35
|
"yaml": "^2.8.3",
|
|
36
|
-
"@powersync/lib-services-framework": "0.9.
|
|
36
|
+
"@powersync/lib-services-framework": "0.9.5",
|
|
37
37
|
"@powersync/service-jsonbig": "0.17.13",
|
|
38
|
-
"@powersync/service-rsocket-router": "0.2.
|
|
39
|
-
"@powersync/service-sync-rules": "0.
|
|
38
|
+
"@powersync/service-rsocket-router": "0.2.21",
|
|
39
|
+
"@powersync/service-sync-rules": "0.37.0",
|
|
40
40
|
"@powersync/service-types": "0.15.2"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
package/src/api/diagnostics.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { logger } from '@powersync/lib-services-framework';
|
|
2
|
-
import { DEFAULT_TAG,
|
|
2
|
+
import { DEFAULT_TAG, SourceTableRef, SyncConfigWithErrors } from '@powersync/service-sync-rules';
|
|
3
3
|
import { ReplicationError, SyncRulesStatus, TableInfo } from '@powersync/service-types';
|
|
4
4
|
|
|
5
5
|
import * as storage from '../storage/storage-index.js';
|
|
@@ -46,7 +46,7 @@ export async function getSyncRulesStatus(
|
|
|
46
46
|
let persisted: storage.PersistedSyncRules;
|
|
47
47
|
try {
|
|
48
48
|
persisted = sync_rules.parsed(apiHandler.getParseSyncRulesOptions());
|
|
49
|
-
parsed = persisted.
|
|
49
|
+
parsed = persisted.syncConfigWithErrors;
|
|
50
50
|
} catch (e) {
|
|
51
51
|
return {
|
|
52
52
|
content: include_content ? sync_rules.sync_rules_content : undefined,
|
|
@@ -116,7 +116,7 @@ export async function getSyncRulesStatus(
|
|
|
116
116
|
errors: [{ level: 'fatal', message: 'connection failed', ts: now }]
|
|
117
117
|
};
|
|
118
118
|
} else {
|
|
119
|
-
const source:
|
|
119
|
+
const source: SourceTableRef = {
|
|
120
120
|
connectionTag: tag,
|
|
121
121
|
schema: pattern.schema,
|
|
122
122
|
name: pattern.tablePattern
|
|
@@ -5,6 +5,7 @@ import fetch from 'node-fetch';
|
|
|
5
5
|
import {
|
|
6
6
|
AuthorizationError,
|
|
7
7
|
ErrorCode,
|
|
8
|
+
hostnameFromSocketAddress,
|
|
8
9
|
LookupOptions,
|
|
9
10
|
makeHostnameLookupFunction,
|
|
10
11
|
ServiceAssertionError,
|
|
@@ -140,7 +141,8 @@ export class RemoteJWKSCollector implements KeyCollector {
|
|
|
140
141
|
*/
|
|
141
142
|
resolveAgent(): http.Agent | https.Agent {
|
|
142
143
|
const lookupOptions = this.options?.lookupOptions ?? { reject_ip_ranges: [] };
|
|
143
|
-
const
|
|
144
|
+
const hostname = hostnameFromSocketAddress(this.url.hostname);
|
|
145
|
+
const lookup = makeHostnameLookupFunction(hostname, lookupOptions);
|
|
144
146
|
|
|
145
147
|
const options: http.AgentOptions = {
|
|
146
148
|
lookup
|
|
@@ -1,24 +1,43 @@
|
|
|
1
1
|
import { SourceTable } from '../storage/SourceTable.js';
|
|
2
2
|
|
|
3
3
|
export class RelationCache<T> {
|
|
4
|
-
private cache = new Map<string | number, SourceTable>();
|
|
4
|
+
private cache = new Map<string | number, SourceTable[]>();
|
|
5
5
|
private idFunction: (item: T | SourceTable) => string | number;
|
|
6
6
|
|
|
7
7
|
constructor(idFunction: (item: T | SourceTable) => string | number) {
|
|
8
8
|
this.idFunction = idFunction;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Update a single table in-place - use when the snapshot status of the table has changed.
|
|
13
|
+
*/
|
|
11
14
|
update(table: SourceTable) {
|
|
12
15
|
const id = this.idFunction(table);
|
|
13
|
-
this.cache.
|
|
16
|
+
const existing = this.cache.get(id) ?? [];
|
|
17
|
+
const replacementIndex = existing.findIndex((candidate) => candidate.id == table.id);
|
|
18
|
+
if (replacementIndex == -1) {
|
|
19
|
+
this.cache.set(id, [...existing, table]);
|
|
20
|
+
} else {
|
|
21
|
+
const next = [...existing];
|
|
22
|
+
next[replacementIndex] = table;
|
|
23
|
+
this.cache.set(id, next);
|
|
24
|
+
}
|
|
14
25
|
}
|
|
15
26
|
|
|
16
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Set the full set of tables for a specific reference.
|
|
29
|
+
*/
|
|
30
|
+
updateAll(ref: T, tables: SourceTable[]) {
|
|
31
|
+
const id = this.idFunction(ref);
|
|
32
|
+
this.cache.set(id, tables);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
getAll(source: T | SourceTable): SourceTable[] | undefined {
|
|
17
36
|
const id = this.idFunction(source);
|
|
18
37
|
return this.cache.get(id);
|
|
19
38
|
}
|
|
20
39
|
|
|
21
|
-
delete(source: T
|
|
40
|
+
delete(source: T): boolean {
|
|
22
41
|
const id = this.idFunction(source);
|
|
23
42
|
return this.cache.delete(id);
|
|
24
43
|
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type fastify from 'fastify';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
registerFastifyErrorHandler,
|
|
5
|
+
registerFastifyNotFoundHandler,
|
|
6
|
+
registerFastifyRoutes
|
|
7
|
+
} from './route-register.js';
|
|
4
8
|
|
|
5
9
|
import * as system from '../system/system-index.js';
|
|
6
10
|
|
|
@@ -66,6 +70,9 @@ export function configureFastifyServer(server: fastify.FastifyInstance, options:
|
|
|
66
70
|
};
|
|
67
71
|
};
|
|
68
72
|
|
|
73
|
+
// Set on the outer server so both child scopes inherit.
|
|
74
|
+
registerFastifyErrorHandler(server);
|
|
75
|
+
|
|
69
76
|
/**
|
|
70
77
|
* Fastify creates an encapsulated context for each `.register` call.
|
|
71
78
|
* Creating a separate context here to separate the concurrency limits for Admin APIs
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import * as sqlite from 'node:sqlite';
|
|
2
|
+
|
|
1
3
|
import { ErrorCode, errors, router, schema } from '@powersync/lib-services-framework';
|
|
2
|
-
import { SourceSchema, SqlSyncRules, StaticSchema } from '@powersync/service-sync-rules';
|
|
4
|
+
import { nodeSqlite, SourceSchema, SqlSyncRules, StaticSchema } from '@powersync/service-sync-rules';
|
|
3
5
|
import { internal_routes } from '@powersync/service-types';
|
|
4
6
|
|
|
5
7
|
import { DEFAULT_HYDRATION_STATE } from '@powersync/service-sync-rules';
|
|
@@ -136,7 +138,7 @@ export const reprocess = routeDefinition({
|
|
|
136
138
|
// 2. If the source does not set the storage version, this will update it do the current version.
|
|
137
139
|
// We can consider tweaking this behavior in the future.
|
|
138
140
|
const new_rules = await activeBucketStorage.updateSyncRules(
|
|
139
|
-
storage.updateSyncRulesFromYaml(active.
|
|
141
|
+
storage.updateSyncRulesFromYaml(active.syncConfigWithErrors.config.content, {
|
|
140
142
|
// This sync config already passed validation. But if the config is not valid anymore due
|
|
141
143
|
// to a service change, we do want to report the error here.
|
|
142
144
|
validate: true
|
|
@@ -176,13 +178,16 @@ class FakeSyncRulesContentForValidation extends storage.PersistedSyncRulesConten
|
|
|
176
178
|
parsed(options: storage.ParseSyncRulesOptions): storage.PersistedSyncRules {
|
|
177
179
|
return {
|
|
178
180
|
...this,
|
|
179
|
-
|
|
181
|
+
syncConfigWithErrors: SqlSyncRules.fromYaml(this.sync_rules_content, {
|
|
180
182
|
...this.apiHandler.getParseSyncRulesOptions(),
|
|
181
183
|
schema: this.schema
|
|
182
184
|
}),
|
|
183
185
|
hydrationState: DEFAULT_HYDRATION_STATE,
|
|
184
|
-
|
|
185
|
-
return this.
|
|
186
|
+
hydratedSyncConfig() {
|
|
187
|
+
return this.syncConfigWithErrors.config.hydrate({
|
|
188
|
+
hydrationState: DEFAULT_HYDRATION_STATE,
|
|
189
|
+
sqlite: nodeSqlite(sqlite)
|
|
190
|
+
});
|
|
186
191
|
}
|
|
187
192
|
};
|
|
188
193
|
}
|
|
@@ -167,7 +167,7 @@ export const reprocessSyncRules = routeDefinition({
|
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
const new_rules = await activeBucketStorage.updateSyncRules(
|
|
170
|
-
updateSyncRulesFromYaml(sync_rules.
|
|
170
|
+
updateSyncRulesFromYaml(sync_rules.syncConfigWithErrors.config.content, {
|
|
171
171
|
// This sync config already passed validation. But if the rules are not valid anymore due
|
|
172
172
|
// to a service change, we do want to report the error here.
|
|
173
173
|
validate: true
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type fastify from 'fastify';
|
|
2
|
+
import * as zlib from 'node:zlib';
|
|
2
3
|
import * as uuid from 'uuid';
|
|
3
4
|
|
|
4
|
-
import { errors, HTTPMethod, logger, RouteNotFound, router
|
|
5
|
+
import { errors, HTTPMethod, logger, RouteNotFound, router } from '@powersync/lib-services-framework';
|
|
5
6
|
import { FastifyReply } from 'fastify';
|
|
6
7
|
import { Context, ContextProvider, RequestEndpoint, RequestEndpointHandlerPayload } from './router.js';
|
|
7
8
|
|
|
@@ -105,18 +106,86 @@ export function registerFastifyNotFoundHandler(app: fastify.FastifyInstance) {
|
|
|
105
106
|
});
|
|
106
107
|
}
|
|
107
108
|
|
|
108
|
-
|
|
109
|
+
/** Registers a custom error handler that emits service-error JSON honouring any negotiated `Content-Encoding`. */
|
|
110
|
+
export function registerFastifyErrorHandler(app: fastify.FastifyInstance) {
|
|
111
|
+
app.setErrorHandler<Error>(async (error, _request, reply) => {
|
|
112
|
+
if (reply.raw.headersSent) {
|
|
113
|
+
// Headers already flushed - reply.code/header would throw ERR_HTTP_HEADERS_SENT.
|
|
114
|
+
reply.raw.destroy(error);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const { status, data } = fastifyErrorToResponse(error);
|
|
119
|
+
if (status >= 500) {
|
|
120
|
+
logger.error('Request failed', error);
|
|
121
|
+
} else {
|
|
122
|
+
logger.warn(`Request failed: ${error.message}`, {
|
|
123
|
+
status,
|
|
124
|
+
code: data.error.code
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const json = JSON.stringify(data);
|
|
129
|
+
|
|
130
|
+
// Fastify's default handler leaves `content-encoding` intact when it rewrites the body.
|
|
131
|
+
const encoding = reply.getHeader('content-encoding');
|
|
132
|
+
let body: string | Buffer = json;
|
|
133
|
+
if (encoding === 'gzip') {
|
|
134
|
+
body = zlib.gzipSync(json);
|
|
135
|
+
} else if (encoding === 'zstd') {
|
|
136
|
+
body = zlib.zstdCompressSync(json);
|
|
137
|
+
} else {
|
|
138
|
+
reply.removeHeader('content-encoding');
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
reply
|
|
142
|
+
.code(status)
|
|
143
|
+
.header('content-type', 'application/json; charset=utf-8')
|
|
144
|
+
.header('content-length', Buffer.byteLength(body))
|
|
145
|
+
.send(body);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
type ErrorResponseData = { error: errors.ErrorData };
|
|
150
|
+
|
|
151
|
+
function serviceErrorToResponse(serviceError: errors.ServiceError): router.RouterResponse<ErrorResponseData> {
|
|
109
152
|
return new router.RouterResponse({
|
|
110
|
-
status:
|
|
153
|
+
status: serviceError.errorData.status || 500,
|
|
111
154
|
headers: {
|
|
112
155
|
'Content-Type': 'application/json'
|
|
113
156
|
},
|
|
114
157
|
data: {
|
|
115
|
-
error:
|
|
158
|
+
error: serviceError.errorData
|
|
116
159
|
}
|
|
117
160
|
});
|
|
118
161
|
}
|
|
119
162
|
|
|
163
|
+
function fastifyErrorToResponse(error: any): router.RouterResponse<ErrorResponseData> {
|
|
164
|
+
// Preserve 4xx status from Fastify built-ins (validation, invalid JSON body, etc.) instead of collapsing to 500.
|
|
165
|
+
if (
|
|
166
|
+
typeof error?.statusCode === 'number' &&
|
|
167
|
+
error.statusCode >= 400 &&
|
|
168
|
+
error.statusCode < 500 &&
|
|
169
|
+
typeof error.code === 'string'
|
|
170
|
+
) {
|
|
171
|
+
return new router.RouterResponse({
|
|
172
|
+
status: error.statusCode,
|
|
173
|
+
headers: {
|
|
174
|
+
'Content-Type': 'application/json'
|
|
175
|
+
},
|
|
176
|
+
data: {
|
|
177
|
+
error: {
|
|
178
|
+
name: error.name,
|
|
179
|
+
code: error.code,
|
|
180
|
+
status: error.statusCode,
|
|
181
|
+
description: error.message
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
return serviceErrorToResponse(errors.asServiceError(error));
|
|
187
|
+
}
|
|
188
|
+
|
|
120
189
|
async function respond(reply: FastifyReply, response: router.RouterResponse) {
|
|
121
190
|
Object.keys(response.headers).forEach((key) => {
|
|
122
191
|
reply.header(key, response.headers[key]);
|
|
@@ -5,6 +5,7 @@ import { InternalOpId } from '../util/utils.js';
|
|
|
5
5
|
import { ReplicationEventPayload } from './ReplicationEventPayload.js';
|
|
6
6
|
import { SourceTable, TableSnapshotStatus } from './SourceTable.js';
|
|
7
7
|
import { BatchedCustomWriteCheckpointOptions } from './storage-index.js';
|
|
8
|
+
import { ResolveTablesOptions, ResolveTablesResult } from './SyncRulesBucketStorage.js';
|
|
8
9
|
|
|
9
10
|
export const DEFAULT_BUCKET_BATCH_COMMIT_OPTIONS: ResolvedBucketBatchCommitOptions = {
|
|
10
11
|
createEmptyCheckpoints: true,
|
|
@@ -22,6 +23,11 @@ export interface BucketStorageBatch extends ObserverClient<BucketBatchStorageLis
|
|
|
22
23
|
*/
|
|
23
24
|
last_flushed_op: InternalOpId | null;
|
|
24
25
|
|
|
26
|
+
/**
|
|
27
|
+
* True for snapshot batches that should skip rows already present in current_data.
|
|
28
|
+
*/
|
|
29
|
+
readonly skipExistingRows: boolean;
|
|
30
|
+
|
|
25
31
|
/**
|
|
26
32
|
* Save an op, and potentially flush.
|
|
27
33
|
*
|
|
@@ -91,10 +97,36 @@ export interface BucketStorageBatch extends ObserverClient<BucketBatchStorageLis
|
|
|
91
97
|
|
|
92
98
|
markTableSnapshotDone(tables: SourceTable[], no_checkpoint_before_lsn?: string): Promise<SourceTable[]>;
|
|
93
99
|
markTableSnapshotRequired(table: SourceTable): Promise<void>;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Mark the full replication snapshot as done without validating individual source table snapshot state.
|
|
103
|
+
*
|
|
104
|
+
* This is primarily intended for storage tests and setup helpers that manually construct storage state.
|
|
105
|
+
* Replicators should use `markSnapshotDone()` instead, because that validates that all known source tables
|
|
106
|
+
* have completed snapshotting before allowing checkpoints to be unblocked.
|
|
107
|
+
*/
|
|
94
108
|
markAllSnapshotDone(no_checkpoint_before_lsn: string): Promise<void>;
|
|
95
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Mark the full replication snapshot as done after validating that all known source tables have completed snapshotting.
|
|
112
|
+
*
|
|
113
|
+
* Replicators should use this method when completing an initial snapshot. The validation prevents races where
|
|
114
|
+
* new source tables are marked as requiring a snapshot while global snapshot finalization is running.
|
|
115
|
+
*
|
|
116
|
+
* If `throwOnConflict` is false, this will instead return early without throwing if there are source tables that still require snapshotting.
|
|
117
|
+
* Use that only in cases where concurrency is expected, and can automatically retry/continue.
|
|
118
|
+
*/
|
|
119
|
+
markSnapshotDone(no_checkpoint_before_lsn: string, options?: { throwOnConflict?: boolean }): Promise<void>;
|
|
120
|
+
|
|
96
121
|
updateTableProgress(table: SourceTable, progress: Partial<TableSnapshotStatus>): Promise<SourceTable>;
|
|
97
122
|
|
|
123
|
+
/**
|
|
124
|
+
* Get the current status for an existing source table without creating or resolving a replacement table.
|
|
125
|
+
*/
|
|
126
|
+
getSourceTableStatus(table: SourceTable): Promise<SourceTable | null>;
|
|
127
|
+
|
|
128
|
+
resolveTables(options: ResolveTablesOptions): Promise<ResolveTablesResult>;
|
|
129
|
+
|
|
98
130
|
/**
|
|
99
131
|
* Queues the creation of a custom Write Checkpoint. This will be persisted after operations are flushed.
|
|
100
132
|
*/
|
|
@@ -170,6 +170,11 @@ export interface UpdateSyncRulesOptions {
|
|
|
170
170
|
};
|
|
171
171
|
lock?: boolean;
|
|
172
172
|
storageVersion?: number;
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Only relevant if the result is used. This does not affect the persisted config.
|
|
176
|
+
*/
|
|
177
|
+
defaultSchema?: string;
|
|
173
178
|
}
|
|
174
179
|
|
|
175
180
|
export interface SerializedSyncPlan {
|
|
@@ -196,7 +201,7 @@ export function updateSyncRulesFromYaml(
|
|
|
196
201
|
const config = SqlSyncRules.fromYaml(content, {
|
|
197
202
|
// No schema-based validation at this point
|
|
198
203
|
schema: undefined,
|
|
199
|
-
defaultSchema: 'not_applicable', // Not needed for validation
|
|
204
|
+
defaultSchema: options?.defaultSchema ?? 'not_applicable', // Not needed for validation
|
|
200
205
|
throwOnError: options?.validate ?? false
|
|
201
206
|
});
|
|
202
207
|
|
|
@@ -5,9 +5,9 @@ import {
|
|
|
5
5
|
DEFAULT_HYDRATION_STATE,
|
|
6
6
|
deserializeSyncPlan,
|
|
7
7
|
ErrorLocation,
|
|
8
|
-
|
|
8
|
+
HydratedSyncConfig,
|
|
9
9
|
HydrationState,
|
|
10
|
-
|
|
10
|
+
nodeSqlite,
|
|
11
11
|
PrecompiledSyncConfig,
|
|
12
12
|
SqlEventDescriptor,
|
|
13
13
|
SqlSyncRules,
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
versionedHydrationState,
|
|
16
16
|
YamlError
|
|
17
17
|
} from '@powersync/service-sync-rules';
|
|
18
|
+
import * as sqlite from 'node:sqlite';
|
|
18
19
|
import { SerializedSyncPlan, UpdateSyncRulesOptions } from './BucketStorageFactory.js';
|
|
19
20
|
import { ReplicationLock } from './ReplicationLock.js';
|
|
20
21
|
import { STORAGE_VERSION_CONFIG, StorageVersionConfig } from './StorageVersionConfig.js';
|
|
@@ -101,7 +102,6 @@ export abstract class PersistedSyncRulesContent implements PersistedSyncRulesCon
|
|
|
101
102
|
|
|
102
103
|
const precompiled = new PrecompiledSyncConfig(plan, compatibility, eventDefinitions, {
|
|
103
104
|
defaultSchema: options.defaultSchema,
|
|
104
|
-
engine: javaScriptExpressionEngine(compatibility),
|
|
105
105
|
sourceText: this.sync_rules_content
|
|
106
106
|
});
|
|
107
107
|
|
|
@@ -141,10 +141,10 @@ export abstract class PersistedSyncRulesContent implements PersistedSyncRulesCon
|
|
|
141
141
|
return {
|
|
142
142
|
id: this.id,
|
|
143
143
|
slot_name: this.slot_name,
|
|
144
|
-
|
|
144
|
+
syncConfigWithErrors: config,
|
|
145
145
|
hydrationState,
|
|
146
|
-
|
|
147
|
-
return config.config.hydrate({ hydrationState });
|
|
146
|
+
hydratedSyncConfig: () => {
|
|
147
|
+
return config.config.hydrate({ hydrationState, sqlite: nodeSqlite(sqlite) });
|
|
148
148
|
}
|
|
149
149
|
};
|
|
150
150
|
}
|
|
@@ -153,7 +153,7 @@ export abstract class PersistedSyncRulesContent implements PersistedSyncRulesCon
|
|
|
153
153
|
// defaultSchema is not relevant for the parsed version here
|
|
154
154
|
const parsed = this.parsed({ defaultSchema: 'not_applicable' });
|
|
155
155
|
return {
|
|
156
|
-
config: { yaml: this.sync_rules_content, plan: this.compiled_plan, parsed: parsed.
|
|
156
|
+
config: { yaml: this.sync_rules_content, plan: this.compiled_plan, parsed: parsed.syncConfigWithErrors },
|
|
157
157
|
...options
|
|
158
158
|
};
|
|
159
159
|
}
|
|
@@ -163,12 +163,12 @@ export abstract class PersistedSyncRulesContent implements PersistedSyncRulesCon
|
|
|
163
163
|
|
|
164
164
|
export interface PersistedSyncRules {
|
|
165
165
|
readonly id: number;
|
|
166
|
-
readonly
|
|
166
|
+
readonly syncConfigWithErrors: SyncConfigWithErrors;
|
|
167
167
|
readonly slot_name: string;
|
|
168
168
|
/**
|
|
169
169
|
* For testing only.
|
|
170
170
|
*/
|
|
171
171
|
readonly hydrationState: HydrationState;
|
|
172
172
|
|
|
173
|
-
|
|
173
|
+
hydratedSyncConfig(): HydratedSyncConfig;
|
|
174
174
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { SourceTableRef } from '@powersync/service-sync-rules';
|
|
2
|
+
|
|
1
3
|
export interface ColumnDescriptor {
|
|
2
4
|
name: string;
|
|
3
5
|
/**
|
|
@@ -10,7 +12,7 @@ export interface ColumnDescriptor {
|
|
|
10
12
|
typeId?: number;
|
|
11
13
|
}
|
|
12
14
|
|
|
13
|
-
export interface SourceEntityDescriptor {
|
|
15
|
+
export interface SourceEntityDescriptor extends SourceTableRef {
|
|
14
16
|
/**
|
|
15
17
|
* The internal id of the source entity structure in the database.
|
|
16
18
|
* If undefined, the schema and name are used as the identifier.
|
|
@@ -23,4 +25,10 @@ export interface SourceEntityDescriptor {
|
|
|
23
25
|
* The columns that are used to uniquely identify a record in the source entity.
|
|
24
26
|
*/
|
|
25
27
|
replicaIdColumns: ColumnDescriptor[];
|
|
28
|
+
/**
|
|
29
|
+
* Whether the source always sends complete row data with each operation (e.g. Postgres REPLICA
|
|
30
|
+
* IDENTITY FULL). When true, no current_data copy is needed. Undefined means the source does not
|
|
31
|
+
* report this, in which case we default to keeping a copy.
|
|
32
|
+
*/
|
|
33
|
+
sendsCompleteRows?: boolean;
|
|
26
34
|
}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
BucketDataSource,
|
|
3
|
+
DEFAULT_TAG,
|
|
4
|
+
ParameterIndexLookupCreator,
|
|
5
|
+
SourceTableRef
|
|
6
|
+
} from '@powersync/service-sync-rules';
|
|
2
7
|
import { bson } from '../index.js';
|
|
3
8
|
import * as util from '../util/util-index.js';
|
|
4
|
-
import { ColumnDescriptor
|
|
9
|
+
import { ColumnDescriptor } from './SourceEntity.js';
|
|
5
10
|
|
|
6
11
|
/**
|
|
7
12
|
* Format of the id depends on the bucket storage module. It should be consistent within the module.
|
|
@@ -10,12 +15,12 @@ export type SourceTableId = string | bson.ObjectId;
|
|
|
10
15
|
|
|
11
16
|
export interface SourceTableOptions {
|
|
12
17
|
id: SourceTableId;
|
|
13
|
-
|
|
18
|
+
ref: SourceTableRef;
|
|
14
19
|
objectId: number | string | undefined;
|
|
15
|
-
schema: string;
|
|
16
|
-
name: string;
|
|
17
20
|
replicaIdColumns: ColumnDescriptor[];
|
|
18
21
|
snapshotComplete: boolean;
|
|
22
|
+
bucketDataSources: BucketDataSource[];
|
|
23
|
+
parameterLookupSources: ParameterIndexLookupCreator[];
|
|
19
24
|
}
|
|
20
25
|
|
|
21
26
|
export interface TableSnapshotStatus {
|
|
@@ -24,7 +29,13 @@ export interface TableSnapshotStatus {
|
|
|
24
29
|
lastKey: Uint8Array | null;
|
|
25
30
|
}
|
|
26
31
|
|
|
27
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Represents a resolved source table.
|
|
34
|
+
*
|
|
35
|
+
* There could be multiple of these for the same SourceTableRef.
|
|
36
|
+
* For that reason, we do not implement the SourceTableRef interface, to ensure that the two are not used interchangably.
|
|
37
|
+
*/
|
|
38
|
+
export class SourceTable {
|
|
28
39
|
static readonly DEFAULT_TAG = DEFAULT_TAG;
|
|
29
40
|
|
|
30
41
|
/**
|
|
@@ -54,6 +65,19 @@ export class SourceTable implements SourceEntityDescriptor {
|
|
|
54
65
|
*/
|
|
55
66
|
public syncEvent = true;
|
|
56
67
|
|
|
68
|
+
/**
|
|
69
|
+
* True if raw data should be stored in current_data collection.
|
|
70
|
+
*
|
|
71
|
+
* This is needed when the source sends partial row data (e.g. TOAST values).
|
|
72
|
+
* When REPLICA IDENTITY FULL is configured, complete rows are always sent,
|
|
73
|
+
* so we don't need to store raw data.
|
|
74
|
+
*
|
|
75
|
+
* This value is resolved externally based on table configuration.
|
|
76
|
+
*
|
|
77
|
+
* Defaults to true for tests (conservative approach).
|
|
78
|
+
*/
|
|
79
|
+
public storeCurrentData = true;
|
|
80
|
+
|
|
57
81
|
/**
|
|
58
82
|
* Always undefined if snapshotComplete = true.
|
|
59
83
|
*
|
|
@@ -71,31 +95,39 @@ export class SourceTable implements SourceEntityDescriptor {
|
|
|
71
95
|
return this.options.id;
|
|
72
96
|
}
|
|
73
97
|
|
|
74
|
-
get connectionTag() {
|
|
75
|
-
return this.options.connectionTag;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
98
|
get objectId() {
|
|
79
99
|
return this.options.objectId;
|
|
80
100
|
}
|
|
81
101
|
|
|
82
102
|
get schema() {
|
|
83
|
-
return this.options.schema;
|
|
103
|
+
return this.options.ref.schema;
|
|
84
104
|
}
|
|
85
105
|
get name() {
|
|
86
|
-
return this.options.name;
|
|
106
|
+
return this.options.ref.name;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
get ref() {
|
|
110
|
+
return this.options.ref;
|
|
87
111
|
}
|
|
88
112
|
|
|
89
113
|
get replicaIdColumns() {
|
|
90
114
|
return this.options.replicaIdColumns;
|
|
91
115
|
}
|
|
92
116
|
|
|
117
|
+
get bucketDataSources() {
|
|
118
|
+
return this.options.bucketDataSources;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
get parameterLookupSources() {
|
|
122
|
+
return this.options.parameterLookupSources;
|
|
123
|
+
}
|
|
124
|
+
|
|
93
125
|
/**
|
|
94
|
-
*
|
|
95
|
-
*
|
|
126
|
+
* Sanitized name of the entity in the format of "{schema}.{entity name}".
|
|
127
|
+
* Suitable for safe use in Postgres queries.
|
|
96
128
|
*/
|
|
97
129
|
get qualifiedName() {
|
|
98
|
-
return
|
|
130
|
+
return util.qualifiedName(this.ref);
|
|
99
131
|
}
|
|
100
132
|
|
|
101
133
|
get syncAny() {
|
|
@@ -108,15 +140,17 @@ export class SourceTable implements SourceEntityDescriptor {
|
|
|
108
140
|
clone() {
|
|
109
141
|
const copy = new SourceTable({
|
|
110
142
|
id: this.id,
|
|
111
|
-
|
|
143
|
+
ref: this.options.ref,
|
|
112
144
|
objectId: this.objectId,
|
|
113
|
-
schema: this.schema,
|
|
114
|
-
name: this.name,
|
|
115
145
|
replicaIdColumns: this.replicaIdColumns,
|
|
116
|
-
snapshotComplete: this.snapshotComplete
|
|
146
|
+
snapshotComplete: this.snapshotComplete,
|
|
147
|
+
bucketDataSources: this.bucketDataSources,
|
|
148
|
+
parameterLookupSources: this.parameterLookupSources
|
|
117
149
|
});
|
|
118
150
|
copy.syncData = this.syncData;
|
|
119
151
|
copy.syncParameters = this.syncParameters;
|
|
152
|
+
copy.syncEvent = this.syncEvent;
|
|
153
|
+
copy.storeCurrentData = this.storeCurrentData;
|
|
120
154
|
copy.snapshotStatus = this.snapshotStatus;
|
|
121
155
|
return copy;
|
|
122
156
|
}
|