@powersync/service-core 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 (230) hide show
  1. package/CHANGELOG.md +152 -4
  2. package/dist/api/RouteAPI.d.ts +42 -14
  3. package/dist/api/diagnostics.d.ts +12 -1
  4. package/dist/api/diagnostics.js +36 -22
  5. package/dist/api/diagnostics.js.map +1 -1
  6. package/dist/entry/commands/compact-action.js +30 -22
  7. package/dist/entry/commands/compact-action.js.map +1 -1
  8. package/dist/metrics/metrics-interfaces.d.ts +5 -1
  9. package/dist/metrics/metrics-interfaces.js.map +1 -1
  10. package/dist/metrics/open-telemetry/MetricAttributeFilteringExporter.d.ts +36 -0
  11. package/dist/metrics/open-telemetry/MetricAttributeFilteringExporter.js +70 -0
  12. package/dist/metrics/open-telemetry/MetricAttributeFilteringExporter.js.map +1 -0
  13. package/dist/metrics/open-telemetry/OpenTelemetryMetricsFactory.js +6 -1
  14. package/dist/metrics/open-telemetry/OpenTelemetryMetricsFactory.js.map +1 -1
  15. package/dist/metrics/open-telemetry/util.js +7 -3
  16. package/dist/metrics/open-telemetry/util.js.map +1 -1
  17. package/dist/modules/AbstractModule.d.ts +6 -2
  18. package/dist/modules/AbstractModule.js.map +1 -1
  19. package/dist/replication/AbstractReplicator.d.ts +31 -7
  20. package/dist/replication/AbstractReplicator.js +168 -74
  21. package/dist/replication/AbstractReplicator.js.map +1 -1
  22. package/dist/replication/ReplicationModule.d.ts +3 -3
  23. package/dist/replication/ReplicationModule.js.map +1 -1
  24. package/dist/routes/RouterEngine.d.ts +1 -0
  25. package/dist/routes/RouterEngine.js +6 -1
  26. package/dist/routes/RouterEngine.js.map +1 -1
  27. package/dist/routes/configure-fastify.d.ts +104 -56
  28. package/dist/routes/configure-fastify.js +15 -2
  29. package/dist/routes/configure-fastify.js.map +1 -1
  30. package/dist/routes/endpoints/admin.d.ts +42 -24
  31. package/dist/routes/endpoints/admin.js +49 -36
  32. package/dist/routes/endpoints/admin.js.map +1 -1
  33. package/dist/routes/endpoints/checkpointing.d.ts +62 -0
  34. package/dist/routes/endpoints/checkpointing.js +65 -7
  35. package/dist/routes/endpoints/checkpointing.js.map +1 -1
  36. package/dist/routes/endpoints/socket-route.js +3 -2
  37. package/dist/routes/endpoints/socket-route.js.map +1 -1
  38. package/dist/routes/endpoints/sync-rules.js +25 -14
  39. package/dist/routes/endpoints/sync-rules.js.map +1 -1
  40. package/dist/routes/endpoints/sync-stream.js +1 -1
  41. package/dist/routes/endpoints/sync-stream.js.map +1 -1
  42. package/dist/runner/teardown.js +8 -8
  43. package/dist/runner/teardown.js.map +1 -1
  44. package/dist/storage/BucketStorageBatch.d.ts +64 -17
  45. package/dist/storage/BucketStorageBatch.js.map +1 -1
  46. package/dist/storage/BucketStorageFactory.d.ts +50 -31
  47. package/dist/storage/BucketStorageFactory.js +10 -20
  48. package/dist/storage/BucketStorageFactory.js.map +1 -1
  49. package/dist/storage/CheckpointChecksumInvalidatedError.d.ts +12 -0
  50. package/dist/storage/CheckpointChecksumInvalidatedError.js +17 -0
  51. package/dist/storage/CheckpointChecksumInvalidatedError.js.map +1 -0
  52. package/dist/storage/ChecksumCache.d.ts +11 -6
  53. package/dist/storage/ChecksumCache.js +5 -4
  54. package/dist/storage/ChecksumCache.js.map +1 -1
  55. package/dist/storage/ParsedSyncConfigSet.d.ts +23 -0
  56. package/dist/storage/ParsedSyncConfigSet.js +2 -0
  57. package/dist/storage/ParsedSyncConfigSet.js.map +1 -0
  58. package/dist/storage/PersistedReplicationStream.d.ts +32 -0
  59. package/dist/storage/PersistedReplicationStream.js +26 -0
  60. package/dist/storage/PersistedReplicationStream.js.map +1 -0
  61. package/dist/storage/PersistedSyncConfigContent.d.ts +65 -0
  62. package/dist/storage/PersistedSyncConfigContent.js +138 -0
  63. package/dist/storage/PersistedSyncConfigContent.js.map +1 -0
  64. package/dist/storage/PersistedSyncConfigStatus.d.ts +13 -0
  65. package/dist/storage/PersistedSyncConfigStatus.js +2 -0
  66. package/dist/storage/PersistedSyncConfigStatus.js.map +1 -0
  67. package/dist/storage/ReplicationEventPayload.d.ts +6 -1
  68. package/dist/storage/SourceEntity.d.ts +13 -2
  69. package/dist/storage/SourceTable.d.ts +53 -4
  70. package/dist/storage/SourceTable.js +62 -7
  71. package/dist/storage/SourceTable.js.map +1 -1
  72. package/dist/storage/SourceTableReconciler.d.ts +83 -0
  73. package/dist/storage/SourceTableReconciler.js +95 -0
  74. package/dist/storage/SourceTableReconciler.js.map +1 -0
  75. package/dist/storage/StorageVersionConfig.d.ts +4 -0
  76. package/dist/storage/StorageVersionConfig.js +10 -1
  77. package/dist/storage/StorageVersionConfig.js.map +1 -1
  78. package/dist/storage/SyncRulesBucketStorage.d.ts +162 -26
  79. package/dist/storage/SyncRulesBucketStorage.js +3 -0
  80. package/dist/storage/SyncRulesBucketStorage.js.map +1 -1
  81. package/dist/storage/WriteCheckpointAPI.d.ts +85 -6
  82. package/dist/storage/WriteCheckpointAPI.js +33 -0
  83. package/dist/storage/WriteCheckpointAPI.js.map +1 -1
  84. package/dist/storage/implementation/BucketDefinitionMapping.d.ts +133 -0
  85. package/dist/storage/implementation/BucketDefinitionMapping.js +351 -0
  86. package/dist/storage/implementation/BucketDefinitionMapping.js.map +1 -0
  87. package/dist/storage/implementation/IncrementalReprocessingCompatibility.d.ts +6 -0
  88. package/dist/storage/implementation/IncrementalReprocessingCompatibility.js +31 -0
  89. package/dist/storage/implementation/IncrementalReprocessingCompatibility.js.map +1 -0
  90. package/dist/storage/implementation/IncrementalReprocessingSyncConfigLog.d.ts +17 -0
  91. package/dist/storage/implementation/IncrementalReprocessingSyncConfigLog.js +70 -0
  92. package/dist/storage/implementation/IncrementalReprocessingSyncConfigLog.js.map +1 -0
  93. package/dist/storage/implementation/ReplicationStreamStorageIds.d.ts +15 -0
  94. package/dist/storage/implementation/ReplicationStreamStorageIds.js +20 -0
  95. package/dist/storage/implementation/ReplicationStreamStorageIds.js.map +1 -0
  96. package/dist/storage/storage-index.d.ts +10 -1
  97. package/dist/storage/storage-index.js +10 -1
  98. package/dist/storage/storage-index.js.map +1 -1
  99. package/dist/storage/storage-metrics.js +120 -4
  100. package/dist/storage/storage-metrics.js.map +1 -1
  101. package/dist/sync/BucketChecksumState.d.ts +12 -2
  102. package/dist/sync/BucketChecksumState.js +69 -21
  103. package/dist/sync/BucketChecksumState.js.map +1 -1
  104. package/dist/sync/RequestTracker.d.ts +7 -0
  105. package/dist/sync/RequestTracker.js +12 -0
  106. package/dist/sync/RequestTracker.js.map +1 -1
  107. package/dist/sync/sync.js +184 -43
  108. package/dist/sync/sync.js.map +1 -1
  109. package/dist/sync/util.d.ts +5 -0
  110. package/dist/sync/util.js +19 -1
  111. package/dist/sync/util.js.map +1 -1
  112. package/dist/system/ServiceContext.d.ts +2 -0
  113. package/dist/system/ServiceContext.js +2 -0
  114. package/dist/system/ServiceContext.js.map +1 -1
  115. package/dist/tracing/PerformanceTracer.d.ts +23 -1
  116. package/dist/tracing/PerformanceTracer.js +11 -0
  117. package/dist/tracing/PerformanceTracer.js.map +1 -1
  118. package/dist/util/checkpointing.d.ts +4 -8
  119. package/dist/util/checkpointing.js +1 -16
  120. package/dist/util/checkpointing.js.map +1 -1
  121. package/dist/util/config/compound-config-collector.js +23 -2
  122. package/dist/util/config/compound-config-collector.js.map +1 -1
  123. package/dist/util/config/defaults.d.ts +2 -0
  124. package/dist/util/config/defaults.js +2 -0
  125. package/dist/util/config/defaults.js.map +1 -1
  126. package/dist/util/config/sync-rules/impl/base64-sync-rules-collector.js +1 -0
  127. package/dist/util/config/sync-rules/impl/base64-sync-rules-collector.js.map +1 -1
  128. package/dist/util/config/sync-rules/impl/filesystem-sync-rules-collector.js +1 -0
  129. package/dist/util/config/sync-rules/impl/filesystem-sync-rules-collector.js.map +1 -1
  130. package/dist/util/config/sync-rules/sync-rules-provider.d.ts +2 -0
  131. package/dist/util/config/sync-rules/sync-rules-provider.js +3 -0
  132. package/dist/util/config/sync-rules/sync-rules-provider.js.map +1 -1
  133. package/dist/util/config/types.d.ts +4 -1
  134. package/dist/util/lsn.d.ts +4 -0
  135. package/dist/util/lsn.js +10 -0
  136. package/dist/util/lsn.js.map +1 -1
  137. package/dist/util/protocol-types.d.ts +4 -4
  138. package/dist/util/protocol-types.js +3 -2
  139. package/dist/util/protocol-types.js.map +1 -1
  140. package/dist/util/util-index.d.ts +1 -0
  141. package/dist/util/util-index.js +1 -0
  142. package/dist/util/util-index.js.map +1 -1
  143. package/dist/util/utils.d.ts +3 -2
  144. package/dist/util/utils.js +17 -2
  145. package/dist/util/utils.js.map +1 -1
  146. package/dist/util/write-checkpoint-batcher.d.ts +19 -0
  147. package/dist/util/write-checkpoint-batcher.js +100 -0
  148. package/dist/util/write-checkpoint-batcher.js.map +1 -0
  149. package/package.json +7 -7
  150. package/src/api/RouteAPI.ts +43 -14
  151. package/src/api/diagnostics.ts +45 -26
  152. package/src/entry/commands/compact-action.ts +37 -23
  153. package/src/metrics/metrics-interfaces.ts +6 -1
  154. package/src/metrics/open-telemetry/MetricAttributeFilteringExporter.ts +85 -0
  155. package/src/metrics/open-telemetry/OpenTelemetryMetricsFactory.ts +7 -2
  156. package/src/metrics/open-telemetry/util.ts +7 -3
  157. package/src/modules/AbstractModule.ts +6 -2
  158. package/src/replication/AbstractReplicator.ts +212 -78
  159. package/src/replication/ReplicationModule.ts +2 -3
  160. package/src/routes/RouterEngine.ts +7 -1
  161. package/src/routes/configure-fastify.ts +25 -2
  162. package/src/routes/endpoints/admin.ts +75 -51
  163. package/src/routes/endpoints/checkpointing.ts +79 -8
  164. package/src/routes/endpoints/socket-route.ts +3 -2
  165. package/src/routes/endpoints/sync-rules.ts +26 -14
  166. package/src/routes/endpoints/sync-stream.ts +1 -1
  167. package/src/runner/teardown.ts +8 -8
  168. package/src/storage/BucketStorageBatch.ts +65 -18
  169. package/src/storage/BucketStorageFactory.ts +73 -46
  170. package/src/storage/CheckpointChecksumInvalidatedError.ts +17 -0
  171. package/src/storage/ChecksumCache.ts +27 -14
  172. package/src/storage/ParsedSyncConfigSet.ts +25 -0
  173. package/src/storage/PersistedReplicationStream.ts +55 -0
  174. package/src/storage/PersistedSyncConfigContent.ts +207 -0
  175. package/src/storage/PersistedSyncConfigStatus.ts +14 -0
  176. package/src/storage/ReplicationEventPayload.ts +6 -1
  177. package/src/storage/SourceEntity.ts +12 -2
  178. package/src/storage/SourceTable.ts +96 -8
  179. package/src/storage/SourceTableReconciler.ts +188 -0
  180. package/src/storage/StorageVersionConfig.ts +11 -1
  181. package/src/storage/SyncRulesBucketStorage.ts +189 -27
  182. package/src/storage/WriteCheckpointAPI.ts +140 -6
  183. package/src/storage/implementation/BucketDefinitionMapping.ts +539 -0
  184. package/src/storage/implementation/IncrementalReprocessingCompatibility.ts +41 -0
  185. package/src/storage/implementation/IncrementalReprocessingSyncConfigLog.ts +126 -0
  186. package/src/storage/implementation/ReplicationStreamStorageIds.ts +21 -0
  187. package/src/storage/storage-index.ts +11 -1
  188. package/src/storage/storage-metrics.ts +154 -8
  189. package/src/sync/BucketChecksumState.ts +105 -21
  190. package/src/sync/RequestTracker.ts +20 -0
  191. package/src/sync/sync.ts +214 -50
  192. package/src/sync/util.ts +33 -8
  193. package/src/system/ServiceContext.ts +7 -0
  194. package/src/tracing/PerformanceTracer.ts +41 -1
  195. package/src/util/checkpointing.ts +4 -22
  196. package/src/util/config/compound-config-collector.ts +31 -1
  197. package/src/util/config/defaults.ts +2 -0
  198. package/src/util/config/sync-rules/impl/base64-sync-rules-collector.ts +1 -0
  199. package/src/util/config/sync-rules/impl/filesystem-sync-rules-collector.ts +1 -0
  200. package/src/util/config/sync-rules/sync-rules-provider.ts +5 -0
  201. package/src/util/config/types.ts +4 -1
  202. package/src/util/lsn.ts +9 -0
  203. package/src/util/protocol-types.ts +3 -2
  204. package/src/util/util-index.ts +1 -0
  205. package/src/util/utils.ts +16 -2
  206. package/src/util/write-checkpoint-batcher.ts +142 -0
  207. package/test/src/AbstractReplicator.test.ts +177 -0
  208. package/test/src/MetricAttributeFilteringExporter.test.ts +96 -0
  209. package/test/src/PersistedSyncConfigContent.test.ts +152 -0
  210. package/test/src/checksum_cache.test.ts +22 -0
  211. package/test/src/config.test.ts +142 -0
  212. package/test/src/diagnostics.test.ts +87 -34
  213. package/test/src/module-loader.test.ts +33 -1
  214. package/test/src/routes/admin.test.ts +188 -18
  215. package/test/src/routes/checkpointing.test.ts +54 -0
  216. package/test/src/routes/mocks.ts +6 -2
  217. package/test/src/routes/stream.test.ts +123 -2
  218. package/test/src/source-table-reconciler.test.ts +244 -0
  219. package/test/src/storage/SourceTable.test.ts +92 -0
  220. package/test/src/storage-metrics.test.ts +148 -0
  221. package/test/src/sync/BucketChecksumState.test.ts +98 -12
  222. package/test/src/sync/util.test.ts +28 -1
  223. package/test/src/util/checkpointing.test.ts +249 -0
  224. package/test/src/util/utils.test.ts +23 -0
  225. package/tsconfig.json +1 -4
  226. package/tsconfig.tsbuildinfo +1 -1
  227. package/dist/storage/PersistedSyncRulesContent.d.ts +0 -59
  228. package/dist/storage/PersistedSyncRulesContent.js +0 -100
  229. package/dist/storage/PersistedSyncRulesContent.js.map +0 -1
  230. package/src/storage/PersistedSyncRulesContent.ts +0 -174
@@ -0,0 +1,138 @@
1
+ import { logger as defaultLogger, ErrorCode, ServiceError } from '@powersync/lib-services-framework';
2
+ import { CompatibilityContext, CompatibilityOption, compileEventDefinitions, DEFAULT_HYDRATION_STATE, deserializeSyncPlan, nodeSqlite, PrecompiledSyncConfig, SqlSyncRules, versionedHydrationState, YamlError } from '@powersync/service-sync-rules';
3
+ import * as sqlite from 'node:sqlite';
4
+ import { STORAGE_VERSION_CONFIG } from './StorageVersionConfig.js';
5
+ export function parsePersistedSyncConfigContent(options) {
6
+ const { content, compiledPlan, storageVersion, parseOptions } = options;
7
+ if (compiledPlan == null) {
8
+ // Fallback: Only parse from YAML if no compiled plan is available.
9
+ return SqlSyncRules.fromYaml(content, parseOptions);
10
+ }
11
+ const plan = deserializeSyncPlan(compiledPlan.plan);
12
+ const compatibility = CompatibilityContext.deserialize(compiledPlan.compatibility);
13
+ const errors = [];
14
+ // Compiled events are additive to plan versions 1 and 2. New readers prefer them when present; when an older plan
15
+ // does not contain them, normalize the dual-written raw SQL at this loading boundary. This keeps legacy event
16
+ // evaluators out of PrecompiledSyncConfig while older binaries can continue reading the same persisted config.
17
+ if (compiledPlan.plan.events == null) {
18
+ const normalized = compileEventDefinitions(compiledPlan.eventDescriptors, {
19
+ ...parseOptions,
20
+ // The legacy evaluator ignored event payload filters. Preserve that behavior for plans deployed before compiled
21
+ // events existed; a redeploy compiles and validates those filters before the replacement config is activated.
22
+ compileEventPayloadFilters: false
23
+ });
24
+ const fatalErrors = normalized.errors.filter((error) => error.type == 'fatal');
25
+ if (fatalErrors.length != 0) {
26
+ throw new Error(`Failed to compile persisted replication events: ${fatalErrors.map((error) => error.message).join(', ')}`);
27
+ }
28
+ plan.events = normalized.events;
29
+ errors.push(...normalized.errors.map((error) => new YamlError(error)));
30
+ }
31
+ const precompiled = new PrecompiledSyncConfig(plan, compatibility, {
32
+ defaultSchema: parseOptions.defaultSchema,
33
+ sourceText: content
34
+ });
35
+ // Note: If the original content did not define a storage version, this will still set the storage version.
36
+ // This means asUpdateOptions will not change the storage version, even if the default changes.
37
+ precompiled.storageVersion = storageVersion;
38
+ if (compiledPlan.errors) {
39
+ for (const error of compiledPlan.errors) {
40
+ const location = error.location && {
41
+ start: error.location.start_offset,
42
+ end: error.location.end_offset
43
+ };
44
+ const asYamlError = new YamlError(new Error(error.message), location);
45
+ asYamlError.type = error.level;
46
+ errors.push(asYamlError);
47
+ }
48
+ }
49
+ return { config: precompiled, errors };
50
+ }
51
+ /**
52
+ * Immutable sync config content for one sync config inside a replication stream.
53
+ *
54
+ * This represents the persisted config content. Fetch per-config status with
55
+ * {@link getSyncConfigStatus}. Use {@link PersistedReplicationStream} for stream
56
+ * lifecycle concerns such as locking and termination.
57
+ */
58
+ export class PersistedSyncConfigContent {
59
+ replicationStreamId;
60
+ sync_rules_content;
61
+ compiled_plan;
62
+ replicationStreamName;
63
+ storageVersion;
64
+ logger;
65
+ syncConfigId;
66
+ syncConfigState;
67
+ version_label;
68
+ constructor(data) {
69
+ this.replicationStreamId = data.replicationStreamId;
70
+ this.sync_rules_content = data.sync_rules_content;
71
+ this.compiled_plan = data.compiled_plan;
72
+ this.replicationStreamName = data.replicationStreamName;
73
+ this.storageVersion = data.storageVersion;
74
+ this.syncConfigId = data.syncConfigId ?? null;
75
+ this.syncConfigState = data.syncConfigState;
76
+ this.version_label = data.version_label;
77
+ const versionPrefix = this.version_label == null ? '' : `[${this.version_label}]`;
78
+ this.logger = defaultLogger.child({ prefix: `[${this.replicationStreamName}]${versionPrefix} ` });
79
+ }
80
+ /**
81
+ * Load the storage config.
82
+ *
83
+ * This may throw if the persisted storage version is not supported.
84
+ */
85
+ getStorageConfig() {
86
+ const storageConfig = STORAGE_VERSION_CONFIG[this.storageVersion];
87
+ if (storageConfig == null) {
88
+ throw new ServiceError(ErrorCode.PSYNC_S1005, `Unsupported storage version ${this.storageVersion} for replication stream ${this.replicationStreamId}`);
89
+ }
90
+ return storageConfig;
91
+ }
92
+ /**
93
+ * Parse only this config's content into a single {@link SyncConfigWithErrors}.
94
+ *
95
+ * This does not depend on any other configs in the same replication stream.
96
+ */
97
+ parseSingleConfig(options) {
98
+ return parsePersistedSyncConfigContent({
99
+ content: this.sync_rules_content,
100
+ compiledPlan: this.compiled_plan,
101
+ storageVersion: this.storageVersion,
102
+ parseOptions: options
103
+ });
104
+ }
105
+ parsed(options) {
106
+ let hydrationState;
107
+ const config = this.parseSingleConfig(options);
108
+ const storageConfig = this.getStorageConfig();
109
+ if (storageConfig.versionedBuckets ||
110
+ config.config.compatibility.isEnabled(CompatibilityOption.versionedBucketIds)) {
111
+ hydrationState = versionedHydrationState(this.replicationStreamId);
112
+ }
113
+ else {
114
+ hydrationState = DEFAULT_HYDRATION_STATE;
115
+ }
116
+ let hydrated;
117
+ return {
118
+ replicationStreamId: this.replicationStreamId,
119
+ replicationStreamName: this.replicationStreamName,
120
+ syncConfigs: [config],
121
+ hydrationState,
122
+ get hydratedSyncConfig() {
123
+ hydrated ??= config.config.hydrate({ hydrationState, sqlite: nodeSqlite(sqlite) });
124
+ return hydrated;
125
+ }
126
+ };
127
+ }
128
+ asUpdateOptions(options) {
129
+ // defaultSchema is not relevant for the parsed version here
130
+ const parsed = this.parseSingleConfig({ defaultSchema: 'not_applicable' });
131
+ return {
132
+ config: { yaml: this.sync_rules_content, plan: this.compiled_plan, parsed },
133
+ version_label: this.version_label,
134
+ ...options
135
+ };
136
+ }
137
+ }
138
+ //# sourceMappingURL=PersistedSyncConfigContent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PersistedSyncConfigContent.js","sourceRoot":"","sources":["../../src/storage/PersistedSyncConfigContent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { SyncRuleState } from './BucketStorage.js';
2
+ import { PersistedSyncConfigId } from './PersistedSyncConfigContent.js';
3
+ export interface PersistedSyncConfigStatus {
4
+ readonly id: PersistedSyncConfigId;
5
+ readonly replicationStreamId: number;
6
+ readonly state: SyncRuleState;
7
+ readonly snapshot_done?: boolean;
8
+ readonly last_checkpoint_lsn: string | null;
9
+ readonly last_fatal_error?: string | null;
10
+ readonly last_fatal_error_ts?: Date | null;
11
+ readonly last_keepalive_ts?: Date | null;
12
+ readonly last_checkpoint_ts?: Date | null;
13
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=PersistedSyncConfigStatus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PersistedSyncConfigStatus.js","sourceRoot":"","sources":["../../src/storage/PersistedSyncConfigStatus.ts"],"names":[],"mappings":""}
@@ -9,6 +9,11 @@ export type EventData = {
9
9
  export type ReplicationEventPayload = {
10
10
  batch: BucketStorageBatch;
11
11
  data: EventData;
12
- event: sync_rules.SqlEventDescriptor;
12
+ event: sync_rules.HydratedEventDescriptor;
13
+ /**
14
+ * Storage-assigned id for this event definition. Present when storage uses persisted event mappings, allowing event
15
+ * handlers to route custom checkpoints without deriving an id from compiled event content.
16
+ */
17
+ event_id?: sync_rules.EventDefinitionId;
13
18
  table: SourceTable;
14
19
  };
@@ -1,4 +1,11 @@
1
1
  import { SourceTableRef } from '@powersync/service-sync-rules';
2
+ /**
3
+ * Source-specific JSON metadata. Storage does not interpret it. Source-table APIs use null to
4
+ * represent the absence of metadata.
5
+ */
6
+ export type JsonValue = string | number | boolean | null | JsonValue[] | {
7
+ [key: string]: JsonValue;
8
+ };
2
9
  export interface ColumnDescriptor {
3
10
  name: string;
4
11
  /**
@@ -17,10 +24,14 @@ export interface SourceEntityDescriptor extends SourceTableRef {
17
24
  * If specified, this is specifically used to detect renames.
18
25
  */
19
26
  objectId: number | string | undefined;
20
- schema: string;
21
- name: string;
22
27
  /**
23
28
  * The columns that are used to uniquely identify a record in the source entity.
24
29
  */
25
30
  replicaIdColumns: ColumnDescriptor[];
31
+ /**
32
+ * Whether the source always sends complete row data with each operation (e.g. Postgres REPLICA
33
+ * IDENTITY FULL). When true, no current_data copy is needed. Undefined means the source does not
34
+ * report this, in which case we default to keeping a copy.
35
+ */
36
+ sendsCompleteRows?: boolean;
26
37
  }
@@ -1,10 +1,14 @@
1
- import { BucketDataSource, ParameterIndexLookupCreator, SourceTableRef } from '@powersync/service-sync-rules';
1
+ import { BucketDataSource, BucketDefinitionId, EventDefinitionId, ParameterIndexId, ParameterIndexLookupCreator, SourceTableRef } from '@powersync/service-sync-rules';
2
2
  import { bson } from '../index.js';
3
- import { ColumnDescriptor } from './SourceEntity.js';
3
+ import { ColumnDescriptor, JsonValue } from './SourceEntity.js';
4
4
  /**
5
5
  * Format of the id depends on the bucket storage module. It should be consistent within the module.
6
6
  */
7
7
  export type SourceTableId = string | bson.ObjectId;
8
+ /**
9
+ * Compare source-table ids without coercing between storage-specific types.
10
+ */
11
+ export declare function sourceTableIdEquals(left: SourceTableId, right: SourceTableId): boolean;
8
12
  export interface SourceTableOptions {
9
13
  id: SourceTableId;
10
14
  ref: SourceTableRef;
@@ -13,6 +17,19 @@ export interface SourceTableOptions {
13
17
  snapshotComplete: boolean;
14
18
  bucketDataSources: BucketDataSource[];
15
19
  parameterLookupSources: ParameterIndexLookupCreator[];
20
+ bucketDataSourceIds?: Set<BucketDefinitionId>;
21
+ parameterLookupSourceIds?: Set<ParameterIndexId>;
22
+ /**
23
+ * Compiled event definitions assigned to this persisted source-table record.
24
+ *
25
+ * Undefined is the legacy/non-incremental representation where event selection is
26
+ * based on the table ref. V3 incremental storage always supplies this set.
27
+ */
28
+ eventDefinitionIds?: Set<EventDefinitionId>;
29
+ /**
30
+ * Source-specific metadata. Null when no metadata has been recorded.
31
+ */
32
+ sourceMetadata?: JsonValue;
16
33
  }
17
34
  export interface TableSnapshotStatus {
18
35
  totalEstimatedCount: number;
@@ -45,13 +62,27 @@ export declare class SourceTable {
45
62
  */
46
63
  syncParameters: boolean;
47
64
  /**
48
- * True if the table is used in sync config for events.
65
+ * True if this table should evaluate event definitions for row changes.
49
66
  *
50
- * This value is resolved externally, and cached here.
67
+ * This value is resolved externally, and cached here. V3 storage assigns disjoint
68
+ * event-definition ids to SourceTables for the same physical table. Multiple records
69
+ * may evaluate different events, but each event id is evaluated through at most one record.
51
70
  *
52
71
  * Defaults to true for tests.
53
72
  */
54
73
  syncEvent: boolean;
74
+ /**
75
+ * True if raw data should be stored in current_data collection.
76
+ *
77
+ * This is needed when the source sends partial row data (e.g. TOAST values).
78
+ * When REPLICA IDENTITY FULL is configured, complete rows are always sent,
79
+ * so we don't need to store raw data.
80
+ *
81
+ * This value is resolved externally based on table configuration.
82
+ *
83
+ * Defaults to true for tests (conservative approach).
84
+ */
85
+ storeCurrentData: boolean;
55
86
  /**
56
87
  * Always undefined if snapshotComplete = true.
57
88
  *
@@ -68,6 +99,12 @@ export declare class SourceTable {
68
99
  get replicaIdColumns(): ColumnDescriptor[];
69
100
  get bucketDataSources(): BucketDataSource[];
70
101
  get parameterLookupSources(): ParameterIndexLookupCreator[];
102
+ get bucketDataSourceIds(): Set<string> | undefined;
103
+ get parameterLookupSourceIds(): Set<string> | undefined;
104
+ get eventDefinitionIds(): Set<string> | undefined;
105
+ get sourceMetadata(): string | number | boolean | JsonValue[] | {
106
+ [key: string]: JsonValue;
107
+ } | null;
71
108
  /**
72
109
  * Sanitized name of the entity in the format of "{schema}.{entity name}".
73
110
  * Suitable for safe use in Postgres queries.
@@ -78,5 +115,17 @@ export declare class SourceTable {
78
115
  * In-memory clone of the table status.
79
116
  */
80
117
  clone(): SourceTable;
118
+ /**
119
+ * Copy this table with different source metadata, preserving its resolved state.
120
+ */
121
+ withSourceMetadata(sourceMetadata: JsonValue): SourceTable;
122
+ private copyWithSourceMetadata;
81
123
  formatSnapshotProgress(): string;
82
124
  }
125
+ /**
126
+ * A cloned SourceTable exposed to reconciliation with public fields typed as read-only.
127
+ * `options` is omitted so callers cannot mutate the underlying option bag without an explicit cast.
128
+ */
129
+ export type SourceTableCandidate = Omit<Readonly<SourceTable>, 'options' | 'withSourceMetadata'> & {
130
+ withSourceMetadata(sourceMetadata: JsonValue): SourceTableCandidate;
131
+ };
@@ -1,5 +1,14 @@
1
1
  import { DEFAULT_TAG } from '@powersync/service-sync-rules';
2
2
  import * as util from '../util/util-index.js';
3
+ /**
4
+ * Compare source-table ids without coercing between storage-specific types.
5
+ */
6
+ export function sourceTableIdEquals(left, right) {
7
+ if (typeof left === 'string' || typeof right === 'string') {
8
+ return typeof left === 'string' && typeof right === 'string' && left === right;
9
+ }
10
+ return left.equals(right);
11
+ }
3
12
  /**
4
13
  * Represents a resolved source table.
5
14
  *
@@ -26,13 +35,27 @@ export class SourceTable {
26
35
  */
27
36
  syncParameters = true;
28
37
  /**
29
- * True if the table is used in sync config for events.
38
+ * True if this table should evaluate event definitions for row changes.
30
39
  *
31
- * This value is resolved externally, and cached here.
40
+ * This value is resolved externally, and cached here. V3 storage assigns disjoint
41
+ * event-definition ids to SourceTables for the same physical table. Multiple records
42
+ * may evaluate different events, but each event id is evaluated through at most one record.
32
43
  *
33
44
  * Defaults to true for tests.
34
45
  */
35
46
  syncEvent = true;
47
+ /**
48
+ * True if raw data should be stored in current_data collection.
49
+ *
50
+ * This is needed when the source sends partial row data (e.g. TOAST values).
51
+ * When REPLICA IDENTITY FULL is configured, complete rows are always sent,
52
+ * so we don't need to store raw data.
53
+ *
54
+ * This value is resolved externally based on table configuration.
55
+ *
56
+ * Defaults to true for tests (conservative approach).
57
+ */
58
+ storeCurrentData = true;
36
59
  /**
37
60
  * Always undefined if snapshotComplete = true.
38
61
  *
@@ -68,6 +91,18 @@ export class SourceTable {
68
91
  get parameterLookupSources() {
69
92
  return this.options.parameterLookupSources;
70
93
  }
94
+ get bucketDataSourceIds() {
95
+ return this.options.bucketDataSourceIds;
96
+ }
97
+ get parameterLookupSourceIds() {
98
+ return this.options.parameterLookupSourceIds;
99
+ }
100
+ get eventDefinitionIds() {
101
+ return this.options.eventDefinitionIds;
102
+ }
103
+ get sourceMetadata() {
104
+ return this.options.sourceMetadata ?? null;
105
+ }
71
106
  /**
72
107
  * Sanitized name of the entity in the format of "{schema}.{entity name}".
73
108
  * Suitable for safe use in Postgres queries.
@@ -82,19 +117,39 @@ export class SourceTable {
82
117
  * In-memory clone of the table status.
83
118
  */
84
119
  clone() {
120
+ return this.copyWithSourceMetadata(this.sourceMetadata);
121
+ }
122
+ /**
123
+ * Copy this table with different source metadata, preserving its resolved state.
124
+ */
125
+ withSourceMetadata(sourceMetadata) {
126
+ return this.copyWithSourceMetadata(sourceMetadata);
127
+ }
128
+ copyWithSourceMetadata(sourceMetadata) {
85
129
  const copy = new SourceTable({
86
130
  id: this.id,
87
- ref: this.options.ref,
131
+ ref: { ...this.options.ref },
88
132
  objectId: this.objectId,
89
- replicaIdColumns: this.replicaIdColumns,
133
+ replicaIdColumns: this.replicaIdColumns.map((column) => ({ ...column })),
90
134
  snapshotComplete: this.snapshotComplete,
91
- bucketDataSources: this.bucketDataSources,
92
- parameterLookupSources: this.parameterLookupSources
135
+ bucketDataSources: [...this.bucketDataSources],
136
+ parameterLookupSources: [...this.parameterLookupSources],
137
+ bucketDataSourceIds: this.bucketDataSourceIds == null ? undefined : new Set(this.bucketDataSourceIds),
138
+ parameterLookupSourceIds: this.parameterLookupSourceIds == null ? undefined : new Set(this.parameterLookupSourceIds),
139
+ eventDefinitionIds: this.eventDefinitionIds == null ? undefined : new Set(this.eventDefinitionIds),
140
+ sourceMetadata: structuredClone(sourceMetadata)
93
141
  });
94
142
  copy.syncData = this.syncData;
95
143
  copy.syncParameters = this.syncParameters;
96
144
  copy.syncEvent = this.syncEvent;
97
- copy.snapshotStatus = this.snapshotStatus;
145
+ copy.storeCurrentData = this.storeCurrentData;
146
+ copy.snapshotStatus =
147
+ this.snapshotStatus == null
148
+ ? undefined
149
+ : {
150
+ ...this.snapshotStatus,
151
+ lastKey: this.snapshotStatus.lastKey?.slice() ?? null
152
+ };
98
153
  return copy;
99
154
  }
100
155
  formatSnapshotProgress() {
@@ -1 +1 @@
1
- {"version":3,"file":"SourceTable.js","sourceRoot":"","sources":["../../src/storage/SourceTable.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SourceTable.js","sourceRoot":"","sources":["../../src/storage/SourceTable.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,83 @@
1
+ import { JsonValue, SourceEntityDescriptor } from './SourceEntity.js';
2
+ import { SourceTable, SourceTableCandidate, SourceTableId } from './SourceTable.js';
3
+ /**
4
+ * A source connector's classification of overlapping persisted tables.
5
+ */
6
+ export interface SourceTableCandidateResolution {
7
+ /**
8
+ * Records storage can reuse. Copies may include updated source metadata.
9
+ */
10
+ compatibleTables: ReadonlyArray<SourceTableCandidate>;
11
+ /**
12
+ * Records that cannot be reused. Every candidate must appear in exactly one result list.
13
+ */
14
+ incompatibleTables: ReadonlyArray<SourceTableCandidate>;
15
+ /**
16
+ * Values for records storage creates during this resolution.
17
+ */
18
+ newTableValues: SourceTableCreateValues;
19
+ }
20
+ export interface SourceTableCreateValues {
21
+ /**
22
+ * Source metadata for new records. Null means no metadata.
23
+ */
24
+ sourceMetadata: JsonValue;
25
+ }
26
+ /**
27
+ * Input to a source-owned reconciliation callback. The callback may run inside a storage
28
+ * transaction, so it must not mutate storage or perform slow external work.
29
+ */
30
+ export interface SourceTableCandidateReconcilerInput {
31
+ /**
32
+ * Source entity being resolved.
33
+ */
34
+ source: SourceEntityDescriptor;
35
+ /**
36
+ * Persisted tables overlapping by name or object id.
37
+ */
38
+ candidates: ReadonlyArray<SourceTableCandidate>;
39
+ }
40
+ export type SourceTableCandidateReconciler = (input: SourceTableCandidateReconcilerInput) => SourceTableCandidateResolution | Promise<SourceTableCandidateResolution>;
41
+ /**
42
+ * Compare replica-id columns in order.
43
+ */
44
+ export declare function sameReplicaIdColumns(left: SourceTableCandidate['replicaIdColumns'], right: SourceEntityDescriptor): boolean;
45
+ /**
46
+ * Compare the shared source-table identity fields.
47
+ */
48
+ export declare function sourceIdentityCompatible(source: SourceEntityDescriptor, candidate: SourceTableCandidate): boolean;
49
+ /**
50
+ * Default identity-based reconciliation for connectors without source-specific metadata.
51
+ */
52
+ export declare const defaultSourceTableReconciler: SourceTableCandidateReconciler;
53
+ /**
54
+ * Check that every candidate was classified exactly once.
55
+ */
56
+ export declare function validateSourceTableCandidateResolution(candidates: ReadonlyArray<SourceTableCandidate>, resolution: SourceTableCandidateResolution): void;
57
+ /**
58
+ * A source-metadata update to persist.
59
+ */
60
+ export interface SourceTableMetadataUpdate {
61
+ id: SourceTableId;
62
+ sourceMetadata: JsonValue;
63
+ }
64
+ /**
65
+ * Rebuild a resolution from storage-owned tables, applying only reconciler-owned metadata to
66
+ * compatible tables. All other mutable table state comes from storage.
67
+ *
68
+ * Reconciler candidates are typed as read-only, but TypeScript types provide no runtime protection:
69
+ * callback code can cast a cloned candidate and mutate it. Rematerializing by id ensures those
70
+ * mutations are not trusted even when the compile-time boundary is bypassed.
71
+ */
72
+ export declare function materializeSourceTableResolution(tables: ReadonlyArray<SourceTable>, resolution: SourceTableCandidateResolution): MaterializedSourceTableResolution;
73
+ export interface MaterializedSourceTableResolution {
74
+ compatibleTables: SourceTable[];
75
+ incompatibleTables: SourceTable[];
76
+ newTableValues: SourceTableCreateValues;
77
+ }
78
+ /**
79
+ * Return source-metadata changes from compatible candidates, comparing metadata by value against
80
+ * the original storage-owned tables. The reconciler may mutate its isolated candidate clones, so
81
+ * those clones cannot be used as the persisted baseline.
82
+ */
83
+ export declare function diffSourceTableUpdates(persistedTables: ReadonlyArray<SourceTable>, resolution: SourceTableCandidateResolution): SourceTableMetadataUpdate[];
@@ -0,0 +1,95 @@
1
+ import { ServiceAssertionError } from '@powersync/lib-services-framework';
2
+ import { isDeepStrictEqual } from 'node:util';
3
+ import { sourceTableIdEquals } from './SourceTable.js';
4
+ /**
5
+ * Compare replica-id columns in order.
6
+ */
7
+ export function sameReplicaIdColumns(left, right) {
8
+ const target = right.replicaIdColumns;
9
+ return (left.length == target.length &&
10
+ left.every((column, index) => column.name == target[index].name && column.type == target[index].type && column.typeId == target[index].typeId));
11
+ }
12
+ /**
13
+ * Compare the shared source-table identity fields.
14
+ */
15
+ export function sourceIdentityCompatible(source, candidate) {
16
+ return (candidate.schema == source.schema &&
17
+ candidate.name == source.name &&
18
+ (source.objectId == null || candidate.objectId == source.objectId) &&
19
+ sameReplicaIdColumns(candidate.replicaIdColumns, source));
20
+ }
21
+ /**
22
+ * Default identity-based reconciliation for connectors without source-specific metadata.
23
+ */
24
+ export const defaultSourceTableReconciler = ({ source, candidates }) => {
25
+ const compatibleTables = [];
26
+ const incompatibleTables = [];
27
+ for (const candidate of candidates) {
28
+ if (sourceIdentityCompatible(source, candidate)) {
29
+ compatibleTables.push(candidate);
30
+ }
31
+ else {
32
+ incompatibleTables.push(candidate);
33
+ }
34
+ }
35
+ return { compatibleTables, incompatibleTables, newTableValues: { sourceMetadata: null } };
36
+ };
37
+ /**
38
+ * Check that every candidate was classified exactly once.
39
+ */
40
+ export function validateSourceTableCandidateResolution(candidates, resolution) {
41
+ const classifiedTables = [...resolution.compatibleTables, ...resolution.incompatibleTables];
42
+ for (const candidate of candidates) {
43
+ const classifications = classifiedTables.filter((table) => sourceTableIdEquals(table.id, candidate.id));
44
+ if (classifications.length !== 1) {
45
+ throw new ServiceAssertionError(`Source table candidate ${candidate.id.toString()} must be classified exactly once, got ${classifications.length}`);
46
+ }
47
+ }
48
+ for (const table of classifiedTables) {
49
+ if (!candidates.some((candidate) => sourceTableIdEquals(candidate.id, table.id))) {
50
+ throw new ServiceAssertionError(`Source table reconciliation returned unknown candidate ${table.id.toString()}`);
51
+ }
52
+ }
53
+ }
54
+ /**
55
+ * Rebuild a resolution from storage-owned tables, applying only reconciler-owned metadata to
56
+ * compatible tables. All other mutable table state comes from storage.
57
+ *
58
+ * Reconciler candidates are typed as read-only, but TypeScript types provide no runtime protection:
59
+ * callback code can cast a cloned candidate and mutate it. Rematerializing by id ensures those
60
+ * mutations are not trusted even when the compile-time boundary is bypassed.
61
+ */
62
+ export function materializeSourceTableResolution(tables, resolution) {
63
+ const findTable = (candidate) => {
64
+ const table = tables.find((table) => sourceTableIdEquals(table.id, candidate.id));
65
+ if (table == null) {
66
+ throw new ServiceAssertionError(`Source table candidate ${candidate.id.toString()} was not persisted`);
67
+ }
68
+ return table;
69
+ };
70
+ return {
71
+ compatibleTables: resolution.compatibleTables.map((candidate) => findTable(candidate).withSourceMetadata(candidate.sourceMetadata)),
72
+ incompatibleTables: resolution.incompatibleTables.map(findTable),
73
+ newTableValues: resolution.newTableValues
74
+ };
75
+ }
76
+ /**
77
+ * Return source-metadata changes from compatible candidates, comparing metadata by value against
78
+ * the original storage-owned tables. The reconciler may mutate its isolated candidate clones, so
79
+ * those clones cannot be used as the persisted baseline.
80
+ */
81
+ export function diffSourceTableUpdates(persistedTables, resolution) {
82
+ const updates = [];
83
+ for (const resolvedTable of resolution.compatibleTables) {
84
+ const persistedTable = persistedTables.find((table) => sourceTableIdEquals(table.id, resolvedTable.id));
85
+ if (persistedTable == null) {
86
+ throw new ServiceAssertionError(`Source table reconciliation returned unknown candidate ${resolvedTable.id.toString()}`);
87
+ }
88
+ if (isDeepStrictEqual(persistedTable.sourceMetadata, resolvedTable.sourceMetadata)) {
89
+ continue;
90
+ }
91
+ updates.push({ id: resolvedTable.id, sourceMetadata: resolvedTable.sourceMetadata });
92
+ }
93
+ return updates;
94
+ }
95
+ //# sourceMappingURL=SourceTableReconciler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SourceTableReconciler.js","sourceRoot":"","sources":["../../src/storage/SourceTableReconciler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE9C,OAAO,EAAoD,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAiDzG;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAClC,IAA8C,EAC9C,KAA6B;IAE7B,MAAM,MAAM,GAAG,KAAK,CAAC,gBAAgB,CAAC;IACtC,OAAO,CACL,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM;QAC5B,IAAI,CAAC,KAAK,CACR,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAChB,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,IAAI,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAClH,CACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,wBAAwB,CAAC,MAA8B,EAAE,SAA+B;IACtG,OAAO,CACL,SAAS,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM;QACjC,SAAS,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI;QAC7B,CAAC,MAAM,CAAC,QAAQ,IAAI,IAAI,IAAI,SAAS,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC;QAClE,oBAAoB,CAAC,SAAS,CAAC,gBAAgB,EAAE,MAAM,CAAC,CACzD,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAmC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE;IACrG,MAAM,gBAAgB,GAA2B,EAAE,CAAC;IACpD,MAAM,kBAAkB,GAA2B,EAAE,CAAC;IACtD,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,wBAAwB,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,CAAC;YAChD,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACnC,CAAC;aAAM,CAAC;YACN,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IACD,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,cAAc,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,EAAE,CAAC;AAC5F,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,sCAAsC,CACpD,UAA+C,EAC/C,UAA0C;IAE1C,MAAM,gBAAgB,GAAG,CAAC,GAAG,UAAU,CAAC,gBAAgB,EAAE,GAAG,UAAU,CAAC,kBAAkB,CAAC,CAAC;IAE5F,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,MAAM,eAAe,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,mBAAmB,CAAC,KAAK,CAAC,EAAE,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;QACxG,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjC,MAAM,IAAI,qBAAqB,CAC7B,0BAA0B,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,yCAAyC,eAAe,CAAC,MAAM,EAAE,CACnH,CAAC;QACJ,CAAC;IACH,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,gBAAgB,EAAE,CAAC;QACrC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,mBAAmB,CAAC,SAAS,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;YACjF,MAAM,IAAI,qBAAqB,CAAC,0DAA0D,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QACnH,CAAC;IACH,CAAC;AACH,CAAC;AAUD;;;;;;;GAOG;AACH,MAAM,UAAU,gCAAgC,CAC9C,MAAkC,EAClC,UAA0C;IAE1C,MAAM,SAAS,GAAG,CAAC,SAA+B,EAAe,EAAE;QACjE,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,mBAAmB,CAAC,KAAK,CAAC,EAAE,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;QAClF,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;YAClB,MAAM,IAAI,qBAAqB,CAAC,0BAA0B,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAC;QACzG,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IACF,OAAO;QACL,gBAAgB,EAAE,UAAU,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAC9D,SAAS,CAAC,SAAS,CAAC,CAAC,kBAAkB,CAAC,SAAS,CAAC,cAAc,CAAC,CAClE;QACD,kBAAkB,EAAE,UAAU,CAAC,kBAAkB,CAAC,GAAG,CAAC,SAAS,CAAC;QAChE,cAAc,EAAE,UAAU,CAAC,cAAc;KAC1C,CAAC;AACJ,CAAC;AAQD;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CACpC,eAA2C,EAC3C,UAA0C;IAE1C,MAAM,OAAO,GAAgC,EAAE,CAAC;IAChD,KAAK,MAAM,aAAa,IAAI,UAAU,CAAC,gBAAgB,EAAE,CAAC;QACxD,MAAM,cAAc,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,mBAAmB,CAAC,KAAK,CAAC,EAAE,EAAE,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC;QACxG,IAAI,cAAc,IAAI,IAAI,EAAE,CAAC;YAC3B,MAAM,IAAI,qBAAqB,CAC7B,0DAA0D,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,EAAE,CACxF,CAAC;QACJ,CAAC;QACD,IAAI,iBAAiB,CAAC,cAAc,CAAC,cAAc,EAAE,aAAa,CAAC,cAAc,CAAC,EAAE,CAAC;YACnF,SAAS;QACX,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,aAAa,CAAC,EAAE,EAAE,cAAc,EAAE,aAAa,CAAC,cAAc,EAAE,CAAC,CAAC;IACvF,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -33,6 +33,10 @@ export declare const STORAGE_VERSION_2 = 2;
33
33
  * This is used to build towards incremental reprocessing.
34
34
  */
35
35
  export declare const STORAGE_VERSION_3 = 3;
36
+ /**
37
+ * Same as version 3, but marked as stable.
38
+ */
39
+ export declare const STORAGE_VERSION_4 = 4;
36
40
  /**
37
41
  * Oldest supported storage version.
38
42
  */