@powersync/service-module-postgres-storage 0.18.0 → 0.19.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/dist/migrations/scripts/1788000000000-sync-config-version-label.d.ts +3 -0
  3. package/dist/migrations/scripts/1788000000000-sync-config-version-label.js +12 -0
  4. package/dist/migrations/scripts/1788000000000-sync-config-version-label.js.map +1 -0
  5. package/dist/storage/PostgresBucketStorageFactory.d.ts +1 -0
  6. package/dist/storage/PostgresBucketStorageFactory.js +14 -7
  7. package/dist/storage/PostgresBucketStorageFactory.js.map +1 -1
  8. package/dist/storage/PostgresStorageProvider.js +2 -1
  9. package/dist/storage/PostgresStorageProvider.js.map +1 -1
  10. package/dist/storage/PostgresSyncRulesStorage.d.ts +4 -3
  11. package/dist/storage/PostgresSyncRulesStorage.js +17 -5
  12. package/dist/storage/PostgresSyncRulesStorage.js.map +1 -1
  13. package/dist/storage/batch/PostgresBucketBatch.d.ts +2 -2
  14. package/dist/storage/batch/PostgresBucketBatch.js +8 -5
  15. package/dist/storage/batch/PostgresBucketBatch.js.map +1 -1
  16. package/dist/storage/checkpoints/PostgresWriteCheckpointAPI.d.ts +1 -1
  17. package/dist/storage/checkpoints/PostgresWriteCheckpointAPI.js +2 -2
  18. package/dist/storage/checkpoints/PostgresWriteCheckpointAPI.js.map +1 -1
  19. package/dist/storage/sync-rules/PostgresPersistedSyncConfigContent.js +5 -1
  20. package/dist/storage/sync-rules/PostgresPersistedSyncConfigContent.js.map +1 -1
  21. package/dist/types/models/ActiveCheckpoint.d.ts +2 -2
  22. package/dist/types/models/ActiveCheckpoint.js +3 -2
  23. package/dist/types/models/ActiveCheckpoint.js.map +1 -1
  24. package/dist/types/models/ActiveCheckpointNotification.d.ts +2 -2
  25. package/dist/types/models/BucketData.d.ts +6 -6
  26. package/dist/types/models/BucketData.js +7 -6
  27. package/dist/types/models/BucketData.js.map +1 -1
  28. package/dist/types/models/CurrentData.d.ts +1 -1
  29. package/dist/types/models/CurrentData.js +2 -1
  30. package/dist/types/models/CurrentData.js.map +1 -1
  31. package/dist/types/models/SdkReporting.d.ts +3 -3
  32. package/dist/types/models/SdkReporting.js +3 -5
  33. package/dist/types/models/SdkReporting.js.map +1 -1
  34. package/dist/types/models/SourceTable.d.ts +7 -7
  35. package/dist/types/models/SourceTable.js +7 -6
  36. package/dist/types/models/SourceTable.js.map +1 -1
  37. package/dist/types/models/SyncRules.d.ts +11 -10
  38. package/dist/types/models/SyncRules.js +12 -11
  39. package/dist/types/models/SyncRules.js.map +1 -1
  40. package/dist/types/models/WriteCheckpoint.d.ts +2 -2
  41. package/dist/types/models/WriteCheckpoint.js +3 -2
  42. package/dist/types/models/WriteCheckpoint.js.map +1 -1
  43. package/dist/types/types.d.ts +2 -0
  44. package/package.json +8 -8
  45. package/src/migrations/scripts/1788000000000-sync-config-version-label.ts +18 -0
  46. package/src/storage/PostgresBucketStorageFactory.ts +15 -7
  47. package/src/storage/PostgresStorageProvider.ts +2 -1
  48. package/src/storage/PostgresSyncRulesStorage.ts +21 -6
  49. package/src/storage/batch/PostgresBucketBatch.ts +9 -6
  50. package/src/storage/checkpoints/PostgresWriteCheckpointAPI.ts +2 -2
  51. package/src/storage/sync-rules/PostgresPersistedSyncConfigContent.ts +8 -1
  52. package/src/types/models/ActiveCheckpoint.ts +3 -2
  53. package/src/types/models/BucketData.ts +7 -6
  54. package/src/types/models/CurrentData.ts +2 -1
  55. package/src/types/models/SdkReporting.ts +4 -4
  56. package/src/types/models/SourceTable.ts +7 -6
  57. package/src/types/models/SyncRules.ts +12 -11
  58. package/src/types/models/WriteCheckpoint.ts +3 -2
  59. package/test/src/__snapshots__/storage_sync.test.ts.snap +0 -995
  60. package/test/src/checkpoint_notifications.test.ts +8 -2
  61. package/test/src/storage.test.ts +12 -4
  62. package/test/src/storage_compacting.test.ts +2 -2
  63. package/test/src/util.ts +1 -1
  64. package/tsconfig.tsbuildinfo +1 -1
@@ -15,6 +15,7 @@ export type PostgresBucketStorageOptions = {
15
15
  config: NormalizedPostgresStorageConfig;
16
16
  replicationStreamNamePrefix: string;
17
17
  checksumCacheTtlMs?: number;
18
+ defaultStorageVersion?: number;
18
19
  };
19
20
 
20
21
  export class PostgresBucketStorageFactory extends storage.BucketStorageFactory {
@@ -78,7 +79,8 @@ export class PostgresBucketStorageFactory extends storage.BucketStorageFactory {
78
79
  return {
79
80
  operations_size_bytes: 0,
80
81
  parameters_size_bytes: 0,
81
- replication_size_bytes: 0
82
+ replication_size_bytes: 0,
83
+ object_storage_size_bytes: 0
82
84
  };
83
85
  }
84
86
 
@@ -104,7 +106,8 @@ export class PostgresBucketStorageFactory extends storage.BucketStorageFactory {
104
106
  return {
105
107
  operations_size_bytes: Number(sizes!.operations_size_bytes),
106
108
  parameters_size_bytes: Number(sizes!.parameter_size_bytes),
107
- replication_size_bytes: Number(sizes!.v1_current_size_bytes) + Number(sizes!.v3_current_size_bytes)
109
+ replication_size_bytes: Number(sizes!.v1_current_size_bytes) + Number(sizes!.v3_current_size_bytes),
110
+ object_storage_size_bytes: 0
108
111
  };
109
112
  }
110
113
 
@@ -156,12 +159,15 @@ export class PostgresBucketStorageFactory extends storage.BucketStorageFactory {
156
159
 
157
160
  async updateSyncRules(options: storage.UpdateSyncRulesOptions): Promise<PostgresPersistedReplicationStream> {
158
161
  const storageVersion =
159
- options.storageVersion ?? options.config.parsed.config.storageVersion ?? storage.CURRENT_STORAGE_VERSION;
162
+ options.storageVersion ??
163
+ options.config.parsed.config.storageVersion ??
164
+ this.options.defaultStorageVersion ??
165
+ storage.CURRENT_STORAGE_VERSION;
160
166
  const storageConfig = storage.STORAGE_VERSION_CONFIG[storageVersion];
161
- if (storageConfig == null) {
167
+ if (storageConfig == null || storageVersion >= storage.STORAGE_VERSION_4) {
162
168
  throw new framework.ServiceError(
163
169
  framework.ErrorCode.PSYNC_S1005,
164
- `Unsupported storage version ${storageVersion}`
170
+ `Unsupported storage version ${storageVersion} for PostgreSQL storage`
165
171
  );
166
172
  }
167
173
  await this.initializeStorageVersion(storageConfig);
@@ -187,7 +193,8 @@ export class PostgresBucketStorageFactory extends storage.BucketStorageFactory {
187
193
  sync_plan,
188
194
  state,
189
195
  slot_name,
190
- storage_version
196
+ storage_version,
197
+ version_label
191
198
  )
192
199
  VALUES
193
200
  (
@@ -211,7 +218,8 @@ export class PostgresBucketStorageFactory extends storage.BucketStorageFactory {
211
218
  '_',
212
219
  ${{ type: 'varchar', value: crypto.randomBytes(2).toString('hex') }}
213
220
  ),
214
- ${{ type: 'int4', value: storageVersion }}
221
+ ${{ type: 'int4', value: storageVersion }},
222
+ ${{ type: 'varchar', value: options.version_label ?? null }}
215
223
  )
216
224
  RETURNING
217
225
  *
@@ -28,7 +28,8 @@ export class PostgresStorageProvider implements storage.StorageProvider {
28
28
  const storageFactory = new PostgresBucketStorageFactory({
29
29
  config: normalizedConfig,
30
30
  replicationStreamNamePrefix: options.resolvedConfig.slot_name_prefix,
31
- checksumCacheTtlMs: options.resolvedConfig.api_parameters.bucket_count_cache_ttl_minutes * 60_000
31
+ checksumCacheTtlMs: options.resolvedConfig.api_parameters.bucket_count_cache_ttl_minutes * 60_000,
32
+ defaultStorageVersion: decodedConfig.default_storage_version
32
33
  });
33
34
 
34
35
  const reportStorageFactory = new PostgresReportStorage({
@@ -4,6 +4,8 @@ import {
4
4
  BucketChecksum,
5
5
  CHECKPOINT_INVALIDATE_ALL,
6
6
  CheckpointChanges,
7
+ CompactInitialReplicationOptions,
8
+ CompactInitialReplicationResults,
7
9
  GetCheckpointChangesOptions,
8
10
  InternalOpId,
9
11
  internalToExternalOpId,
@@ -11,11 +13,10 @@ import {
11
13
  maxLsn,
12
14
  ParameterSetLimitExceededError,
13
15
  PartialChecksum,
14
- PopulateChecksumCacheOptions,
15
- PopulateChecksumCacheResults,
16
16
  ReplicationCheckpoint,
17
17
  storage,
18
18
  StorageVersionConfig,
19
+ SyncRuleState,
19
20
  utils,
20
21
  WatchWriteCheckpointOptions
21
22
  } from '@powersync/service-core';
@@ -94,7 +95,7 @@ export class PostgresSyncRulesStorage
94
95
  this.factory = options.factory;
95
96
  this.storageConfig = options.replicationStream.getStorageConfig();
96
97
  this.currentDataStore = new PostgresCurrentDataStore(this.storageConfig);
97
- this.logger = options.replicationStream.logger;
98
+ this.logger = this.sync_rules.logger;
98
99
 
99
100
  this.writeCheckpointAPI = new PostgresWriteCheckpointAPI({
100
101
  db: this.db,
@@ -145,7 +146,19 @@ export class PostgresSyncRulesStorage
145
146
  `.execute();
146
147
  }
147
148
 
149
+ supportsIncrementalParameterCompaction(): boolean {
150
+ return false;
151
+ }
152
+
148
153
  async compact(options?: storage.CompactOptions): Promise<void> {
154
+ if (options?.incrementalOnly) {
155
+ // Not supported yet
156
+ this.logger.info('Incremental compacting is not supported on Postgres storage yet.');
157
+ return;
158
+ } else if (this.replicationStream.state != SyncRuleState.ACTIVE) {
159
+ this.logger.info(`Skipping compacting of replication stream in ${this.replicationStream.state} state.`);
160
+ return;
161
+ }
149
162
  let maxOpId = options?.maxOpId;
150
163
  if (maxOpId == null) {
151
164
  const checkpoint = await this.getCheckpoint();
@@ -160,7 +173,9 @@ export class PostgresSyncRulesStorage
160
173
  }).compact();
161
174
  }
162
175
 
163
- async populatePersistentChecksumCache(_options: PopulateChecksumCacheOptions): Promise<PopulateChecksumCacheResults> {
176
+ async compactInitialReplication(
177
+ _options: CompactInitialReplicationOptions
178
+ ): Promise<CompactInitialReplicationResults> {
164
179
  // no-op - checksum cache is not implemented for Postgres yet
165
180
  return { buckets: 0 };
166
181
  }
@@ -172,8 +187,8 @@ export class PostgresSyncRulesStorage
172
187
  });
173
188
  }
174
189
 
175
- setWriteCheckpointMode(mode: storage.WriteCheckpointMode): void {
176
- return this.writeCheckpointAPI.setWriteCheckpointMode(mode);
190
+ setWriteCheckpointMode(config: storage.WriteCheckpointModeConfig): void {
191
+ return this.writeCheckpointAPI.setWriteCheckpointMode(config);
177
192
  }
178
193
 
179
194
  createManagedWriteCheckpoints(
@@ -19,6 +19,7 @@ import {
19
19
  utils
20
20
  } from '@powersync/service-core';
21
21
  import * as sync_rules from '@powersync/service-sync-rules';
22
+ import { orNull } from '@powersync/service-types';
22
23
  import * as timers from 'timers/promises';
23
24
  import * as t from 'ts-codec';
24
25
  import * as uuid from 'uuid';
@@ -64,10 +65,10 @@ const StatefulCheckpoint = models.ActiveCheckpoint.and(t.object({ state: t.Enum(
64
65
  const CheckpointWithStatus = StatefulCheckpoint.and(
65
66
  t.object({
66
67
  snapshot_done: t.boolean,
67
- no_checkpoint_before: t.string.or(t.Null),
68
+ no_checkpoint_before: orNull(t.string),
68
69
  can_checkpoint: t.boolean,
69
- keepalive_op: bigint.or(t.Null),
70
- new_last_checkpoint: bigint.or(t.Null),
70
+ keepalive_op: orNull(bigint),
71
+ new_last_checkpoint: orNull(bigint),
71
72
  created_checkpoint: t.boolean
72
73
  })
73
74
  );
@@ -323,7 +324,9 @@ export class PostgresBucketBatch
323
324
  // TODO maybe share with abstract class
324
325
  const { after, before, sourceTable, tag } = record;
325
326
  const storeCurrentData = this.options.store_current_data && sourceTable.storeCurrentData;
326
- // Only the table designated as event carrier by resolveTables may fire events.
327
+ // PostgreSQL storage resolves each physical table to one SourceTable. syncEvent records whether
328
+ // that table matches any event definition; each matching definition is evaluated once here and
329
+ // may produce multiple payloads from its matching queries.
327
330
  if (sourceTable.syncEvent) {
328
331
  for (const event of this.getTableEvents(sourceTable)) {
329
332
  this.iterateListeners((cb) =>
@@ -1334,10 +1337,10 @@ export class PostgresBucketBatch
1334
1337
  }
1335
1338
 
1336
1339
  /**
1337
- * Gets relevant {@link SqlEventDescriptor}s for the given {@link SourceTable}
1340
+ * Gets relevant {@link HydratedEventDescriptor}s for the given {@link SourceTable}
1338
1341
  * TODO maybe share this with an abstract class
1339
1342
  */
1340
- protected getTableEvents(table: storage.SourceTable): sync_rules.SqlEventDescriptor[] {
1343
+ protected getTableEvents(table: storage.SourceTable): sync_rules.HydratedEventDescriptor[] {
1341
1344
  return this.sync_rules.eventDescriptors.filter((evt) =>
1342
1345
  [...evt.getSourceTables()].some((sourceTable) => sourceTable.matches(table.ref))
1343
1346
  );
@@ -21,8 +21,8 @@ export class PostgresWriteCheckpointAPI implements storage.WriteCheckpointAPI {
21
21
  return this._mode;
22
22
  }
23
23
 
24
- setWriteCheckpointMode(mode: storage.WriteCheckpointMode): void {
25
- this._mode = mode;
24
+ setWriteCheckpointMode(config: storage.WriteCheckpointModeConfig): void {
25
+ this._mode = config.mode;
26
26
  }
27
27
 
28
28
  async batchCreateCustomWriteCheckpoints(
@@ -14,7 +14,8 @@ export class PostgresPersistedSyncConfigContent extends storage.PersistedSyncCon
14
14
  compiled_plan: row.sync_plan,
15
15
  replicationStreamName: row.slot_name,
16
16
  storageVersion: row.storage_version ?? storage.LEGACY_STORAGE_VERSION,
17
- syncConfigState: row.state as storage.SyncRuleState
17
+ syncConfigState: row.state as storage.SyncRuleState,
18
+ version_label: row.version_label ?? undefined
18
19
  });
19
20
  }
20
21
 
@@ -61,6 +62,12 @@ export class PostgresPersistedReplicationStream extends storage.PersistedReplica
61
62
  state: row.state as storage.SyncRuleState,
62
63
  storageVersion: row.storage_version ?? storage.LEGACY_STORAGE_VERSION
63
64
  });
65
+ if (this.storageVersion >= storage.STORAGE_VERSION_4) {
66
+ throw new ServiceError(
67
+ ErrorCode.PSYNC_S1005,
68
+ `Unsupported storage version ${this.storageVersion} for PostgreSQL storage`
69
+ );
70
+ }
64
71
  this.syncConfigContent = [new PostgresPersistedSyncConfigContent(this.db, this.row)];
65
72
  }
66
73
 
@@ -1,3 +1,4 @@
1
+ import { orNull } from '@powersync/service-types';
1
2
  import * as t from 'ts-codec';
2
3
  import { bigint, pgwire_number } from '../codecs.js';
3
4
 
@@ -7,8 +8,8 @@ import { bigint, pgwire_number } from '../codecs.js';
7
8
  */
8
9
  export const ActiveCheckpoint = t.object({
9
10
  id: pgwire_number,
10
- last_checkpoint: t.Null.or(bigint),
11
- last_checkpoint_lsn: t.Null.or(t.string)
11
+ last_checkpoint: orNull(bigint),
12
+ last_checkpoint_lsn: orNull(t.string)
12
13
  });
13
14
 
14
15
  export type ActiveCheckpoint = t.Encoded<typeof ActiveCheckpoint>;
@@ -1,3 +1,4 @@
1
+ import { orNull } from '@powersync/service-types';
1
2
  import * as t from 'ts-codec';
2
3
  import { bigint, hexBuffer, pgwire_number } from '../codecs.js';
3
4
 
@@ -13,13 +14,13 @@ export const BucketData = t.object({
13
14
  bucket_name: t.string,
14
15
  op_id: bigint,
15
16
  op: t.Enum(OpType),
16
- source_table: t.Null.or(t.string),
17
- source_key: t.Null.or(hexBuffer),
18
- table_name: t.string.or(t.Null),
19
- row_id: t.string.or(t.Null),
17
+ source_table: orNull(t.string),
18
+ source_key: orNull(hexBuffer),
19
+ table_name: orNull(t.string),
20
+ row_id: orNull(t.string),
20
21
  checksum: bigint,
21
- data: t.Null.or(t.string),
22
- target_op: t.Null.or(bigint)
22
+ data: orNull(t.string),
23
+ target_op: orNull(bigint)
23
24
  });
24
25
 
25
26
  export type BucketData = t.Encoded<typeof BucketData>;
@@ -1,3 +1,4 @@
1
+ import { orNull } from '@powersync/service-types';
1
2
  import * as t from 'ts-codec';
2
3
  import { bigint, hexBuffer, jsonb, pgwire_number } from '../codecs.js';
3
4
 
@@ -26,7 +27,7 @@ export const V3CurrentData = t.object({
26
27
  lookups: t.array(hexBuffer),
27
28
  source_key: hexBuffer,
28
29
  source_table: t.string,
29
- pending_delete: t.Null.or(bigint)
30
+ pending_delete: orNull(bigint)
30
31
  });
31
32
 
32
33
  export type V1CurrentData = t.Encoded<typeof V1CurrentData>;
@@ -1,3 +1,4 @@
1
+ import { orNull } from '@powersync/service-types';
1
2
  import * as t from 'ts-codec';
2
3
  import { bigint, jsonb } from '../codecs.js';
3
4
 
@@ -11,12 +12,11 @@ export type Sdks = t.Encoded<typeof Sdks>;
11
12
 
12
13
  export const SdkReporting = t.object({
13
14
  users: bigint,
14
- sdks: t
15
- .object({
15
+ sdks: orNull(
16
+ t.object({
16
17
  data: jsonb<Sdks[]>(t.array(Sdks))
17
18
  })
18
- .optional()
19
- .or(t.Null)
19
+ ).optional()
20
20
  });
21
21
 
22
22
  export type SdkReporting = t.Encoded<typeof SdkReporting>;
@@ -1,4 +1,5 @@
1
1
  import { JsonValue } from '@powersync/service-core';
2
+ import { orNull } from '@powersync/service-types';
2
3
  import * as t from 'ts-codec';
3
4
  import { bigint, hexBuffer, jsonb, jsonb_raw, pgwire_number } from '../codecs.js';
4
5
 
@@ -22,18 +23,18 @@ export const SourceTable = t.object({
22
23
  id: t.string,
23
24
  group_id: pgwire_number,
24
25
  connection_id: bigint,
25
- relation_id: t.Null.or(jsonb_raw<StoredRelationId>()),
26
+ relation_id: orNull(jsonb_raw<StoredRelationId>()),
26
27
  schema_name: t.string,
27
28
  table_name: t.string,
28
- replica_id_columns: t.Null.or(jsonb(t.array(ColumnDescriptor))),
29
+ replica_id_columns: orNull(jsonb(t.array(ColumnDescriptor))),
29
30
  snapshot_done: t.boolean,
30
- snapshot_total_estimated_count: t.Null.or(bigint),
31
- snapshot_replicated_count: t.Null.or(bigint),
32
- snapshot_last_key: t.Null.or(hexBuffer),
31
+ snapshot_total_estimated_count: orNull(bigint),
32
+ snapshot_replicated_count: orNull(bigint),
33
+ snapshot_last_key: orNull(hexBuffer),
33
34
  /**
34
35
  * Source-specific metadata. Null for legacy records.
35
36
  */
36
- source_metadata: t.Null.or(jsonb_raw<JsonValue>())
37
+ source_metadata: orNull(jsonb_raw<JsonValue>())
37
38
  });
38
39
 
39
40
  export type SourceTable = t.Encoded<typeof SourceTable>;
@@ -1,5 +1,5 @@
1
1
  import { framework, storage } from '@powersync/service-core';
2
- import { ReplicationError } from '@powersync/service-types';
2
+ import { orNull, ReplicationError } from '@powersync/service-types';
3
3
  import * as t from 'ts-codec';
4
4
  import { bigint, pgwire_number } from '../codecs.js';
5
5
  import { jsonContainerObject } from './json.js';
@@ -16,42 +16,43 @@ export const SyncRules = t.object({
16
16
  /**
17
17
  * May be set if snapshot_done = false, if the replication stream requires it.
18
18
  */
19
- snapshot_lsn: t.Null.or(t.string),
19
+ snapshot_lsn: orNull(t.string),
20
20
  /**
21
21
  * The last consistent checkpoint.
22
22
  *
23
23
  * There may be higher OpIds used in the database if we're in the middle of replicating a large transaction.
24
24
  */
25
- last_checkpoint: t.Null.or(bigint),
25
+ last_checkpoint: orNull(bigint),
26
26
  /**
27
27
  * The LSN associated with the last consistent checkpoint.
28
28
  */
29
- last_checkpoint_lsn: t.Null.or(t.string),
29
+ last_checkpoint_lsn: orNull(t.string),
30
30
  /**
31
31
  * If set, no new checkpoints may be created < this value.
32
32
  */
33
- no_checkpoint_before: t.Null.or(t.string),
33
+ no_checkpoint_before: orNull(t.string),
34
34
  slot_name: t.string,
35
35
  /**
36
36
  * Last time we persisted a checkpoint.
37
37
  *
38
38
  * This may be old if no data is incoming.
39
39
  */
40
- last_checkpoint_ts: t.Null.or(framework.codecs.date),
40
+ last_checkpoint_ts: orNull(framework.codecs.date),
41
41
  /**
42
42
  * Last time we persisted a checkpoint or keepalive.
43
43
  *
44
44
  * This should stay fairly current while replicating.
45
45
  */
46
- last_keepalive_ts: t.Null.or(framework.codecs.date),
46
+ last_keepalive_ts: orNull(framework.codecs.date),
47
47
  /**
48
48
  * If an error is stopping replication, it will be stored here.
49
49
  */
50
- last_fatal_error: t.Null.or(t.string),
51
- keepalive_op: t.Null.or(bigint),
52
- storage_version: t.Null.or(pgwire_number).optional(),
50
+ last_fatal_error: orNull(t.string),
51
+ keepalive_op: orNull(bigint),
52
+ storage_version: orNull(pgwire_number).optional(),
53
+ version_label: orNull(t.string).optional(),
53
54
  content: t.string,
54
- sync_plan: t.Null.or(
55
+ sync_plan: orNull(
55
56
  jsonContainerObject(
56
57
  t.object({
57
58
  plan: t.any,
@@ -1,4 +1,5 @@
1
1
  import { framework } from '@powersync/service-core';
2
+ import { orNull } from '@powersync/service-types';
2
3
  import * as t from 'ts-codec';
3
4
  import { bigint, jsonb } from '../codecs.js';
4
5
 
@@ -6,7 +7,7 @@ export const WriteCheckpoint = t.object({
6
7
  user_id: t.string,
7
8
  lsns: jsonb(t.record(t.string)),
8
9
  write_checkpoint: bigint,
9
- checkpoint_requested_at: t.Null.or(framework.codecs.date)
10
+ checkpoint_requested_at: orNull(framework.codecs.date)
10
11
  });
11
12
 
12
13
  export type WriteCheckpoint = t.Encoded<typeof WriteCheckpoint>;
@@ -16,7 +17,7 @@ export const CustomWriteCheckpoint = t.object({
16
17
  user_id: t.string,
17
18
  write_checkpoint: bigint,
18
19
  sync_rules_id: bigint,
19
- checkpoint_requested_at: t.Null.or(framework.codecs.date)
20
+ checkpoint_requested_at: orNull(framework.codecs.date)
20
21
  });
21
22
 
22
23
  export type CustomWriteCheckpoint = t.Encoded<typeof CustomWriteCheckpoint>;