@powersync/service-module-postgres 0.0.0-dev-20250116115804 → 0.0.0-dev-20250122110924

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.
@@ -1,5 +1,11 @@
1
1
  import * as lib_postgres from '@powersync/lib-service-postgres';
2
- import { container, errors, logger } from '@powersync/lib-services-framework';
2
+ import {
3
+ container,
4
+ errors,
5
+ logger,
6
+ ReplicationAbortedError,
7
+ ReplicationAssertionError
8
+ } from '@powersync/lib-services-framework';
3
9
  import { getUuidReplicaIdentityBson, Metrics, SourceEntityDescriptor, storage } from '@powersync/service-core';
4
10
  import * as pgwire from '@powersync/service-jpgwire';
5
11
  import { DatabaseInputRow, SqliteRow, SqlSyncRules, TablePattern, toSyncRulesRow } from '@powersync/service-sync-rules';
@@ -133,7 +139,7 @@ export class WalStream {
133
139
  for (let row of tableRows) {
134
140
  const name = row.table_name as string;
135
141
  if (typeof row.relid != 'bigint') {
136
- throw new Error(`missing relid for ${name}`);
142
+ throw new ReplicationAssertionError(`Missing relid for ${name}`);
137
143
  }
138
144
  const relid = Number(row.relid as bigint);
139
145
 
@@ -294,7 +300,7 @@ export class WalStream {
294
300
  }
295
301
  }
296
302
 
297
- throw new Error('Unreachable');
303
+ throw new ReplicationAssertionError('Unreachable');
298
304
  }
299
305
 
300
306
  async estimatedCount(db: pgwire.PgConnection, table: storage.SourceTable): Promise<string> {
@@ -415,7 +421,7 @@ WHERE oid = $1::regclass`,
415
421
  lastLogIndex = at;
416
422
  }
417
423
  if (this.abort_signal.aborted) {
418
- throw new Error(`Aborted initial replication of ${this.slot_name}`);
424
+ throw new ReplicationAbortedError(`Aborted initial replication of ${this.slot_name}`);
419
425
  }
420
426
 
421
427
  for (const record of WalStream.getQueryData(rows)) {
@@ -441,7 +447,7 @@ WHERE oid = $1::regclass`,
441
447
 
442
448
  async handleRelation(batch: storage.BucketStorageBatch, descriptor: SourceEntityDescriptor, snapshot: boolean) {
443
449
  if (!descriptor.objectId && typeof descriptor.objectId != 'number') {
444
- throw new Error('objectId expected');
450
+ throw new ReplicationAssertionError(`objectId expected, got ${typeof descriptor.objectId}`);
445
451
  }
446
452
  const result = await this.storage.resolveTable({
447
453
  group_id: this.group_id,
@@ -484,6 +490,7 @@ WHERE oid = $1::regclass`,
484
490
  await db.query('COMMIT');
485
491
  } catch (e) {
486
492
  await db.query('ROLLBACK');
493
+ // TODO: Wrap with custom error type
487
494
  throw e;
488
495
  }
489
496
  } finally {
@@ -501,7 +508,7 @@ WHERE oid = $1::regclass`,
501
508
  if (table == null) {
502
509
  // We should always receive a replication message before the relation is used.
503
510
  // If we can't find it, it's a bug.
504
- throw new Error(`Missing relation cache for ${relationId}`);
511
+ throw new ReplicationAssertionError(`Missing relation cache for ${relationId}`);
505
512
  }
506
513
  return table;
507
514
  }
@@ -2,6 +2,7 @@ import { replication, storage } from '@powersync/service-core';
2
2
  import { ConnectionManagerFactory } from './ConnectionManagerFactory.js';
3
3
  import { cleanUpReplicationSlot } from './replication-utils.js';
4
4
  import { WalStreamReplicationJob } from './WalStreamReplicationJob.js';
5
+ import { PostgresModule } from '../module/PostgresModule.js';
5
6
 
6
7
  export interface WalStreamReplicatorOptions extends replication.AbstractReplicatorOptions {
7
8
  connectionFactory: ConnectionManagerFactory;
@@ -42,4 +43,8 @@ export class WalStreamReplicator extends replication.AbstractReplicator<WalStrea
42
43
  await super.stop();
43
44
  await this.connectionFactory.shutdown();
44
45
  }
46
+
47
+ async testConnection() {
48
+ return await PostgresModule.testConnection(this.connectionFactory.dbConnectionConfig);
49
+ }
45
50
  }
@@ -1,7 +1,7 @@
1
1
  import * as pgwire from '@powersync/service-jpgwire';
2
2
 
3
3
  import * as lib_postgres from '@powersync/lib-service-postgres';
4
- import { logger } from '@powersync/lib-services-framework';
4
+ import { ErrorCode, logger, ServiceError } from '@powersync/lib-services-framework';
5
5
  import { PatternResult, storage } from '@powersync/service-core';
6
6
  import * as sync_rules from '@powersync/service-sync-rules';
7
7
  import * as service_types from '@powersync/service-types';
@@ -117,17 +117,22 @@ $$ LANGUAGE plpgsql;`
117
117
  });
118
118
  const row = pgwire.pgwireRows(rs)[0];
119
119
  if (row == null) {
120
- throw new Error(
120
+ throw new ServiceError(
121
+ ErrorCode.PSYNC_S1141,
121
122
  `Publication '${publicationName}' does not exist. Run: \`CREATE PUBLICATION ${publicationName} FOR ALL TABLES\`, or read the documentation for details.`
122
123
  );
123
124
  }
124
125
  if (row.pubinsert == false || row.pubupdate == false || row.pubdelete == false || row.pubtruncate == false) {
125
- throw new Error(
126
+ throw new ServiceError(
127
+ ErrorCode.PSYNC_S1142,
126
128
  `Publication '${publicationName}' does not publish all changes. Create a publication using \`WITH (publish = "insert, update, delete, truncate")\` (the default).`
127
129
  );
128
130
  }
129
131
  if (row.pubviaroot) {
130
- throw new Error(`'${publicationName}' uses publish_via_partition_root, which is not supported.`);
132
+ throw new ServiceError(
133
+ ErrorCode.PSYNC_S1143,
134
+ `'${publicationName}' uses publish_via_partition_root, which is not supported.`
135
+ );
131
136
  }
132
137
  }
133
138
 
@@ -1,3 +1,4 @@
1
+ import { ServiceAssertionError } from '@powersync/lib-services-framework';
1
2
  import * as pgwire from '@powersync/service-jpgwire';
2
3
 
3
4
  export type MigrationFunction = (db: pgwire.PgConnection) => Promise<void>;
@@ -14,7 +15,7 @@ export class Migrations {
14
15
 
15
16
  add(id: number, name: string, up: MigrationFunction) {
16
17
  if (this.migrations.length > 0 && this.migrations[this.migrations.length - 1].id >= id) {
17
- throw new Error('Migration ids must be strictly incrementing');
18
+ throw new ServiceAssertionError('Migration ids must be strictly incrementing');
18
19
  }
19
20
  this.migrations.push({ id, up, name });
20
21
  }