s3db.js 6.1.0 → 6.2.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/dist/s3db.cjs.js CHANGED
@@ -11066,7 +11066,7 @@ class Database extends EventEmitter {
11066
11066
  this.version = "1";
11067
11067
  this.s3dbVersion = (() => {
11068
11068
  try {
11069
- return true ? "6.0.0" : "latest";
11069
+ return true ? "6.1.0" : "latest";
11070
11070
  } catch (e) {
11071
11071
  return "latest";
11072
11072
  }
@@ -20043,23 +20043,63 @@ class SqsReplicator extends BaseReplicator {
20043
20043
  }
20044
20044
 
20045
20045
  class BigqueryReplicator extends BaseReplicator {
20046
- constructor(config = {}, resources = []) {
20046
+ constructor(config = {}, resources = {}) {
20047
20047
  super(config);
20048
- this.resources = resources;
20049
20048
  this.projectId = config.projectId;
20050
20049
  this.datasetId = config.datasetId;
20051
- this.tableId = config.tableId;
20052
- this.tableMap = config.tableMap || {};
20053
20050
  this.bigqueryClient = null;
20054
20051
  this.credentials = config.credentials;
20055
20052
  this.location = config.location || "US";
20056
- this.logOperations = config.logOperations !== false;
20053
+ this.logTable = config.logTable;
20054
+ this.resources = this.parseResourcesConfig(resources);
20055
+ }
20056
+ parseResourcesConfig(resources) {
20057
+ const parsed = {};
20058
+ for (const [resourceName, config] of Object.entries(resources)) {
20059
+ if (typeof config === "string") {
20060
+ parsed[resourceName] = [{
20061
+ table: config,
20062
+ actions: ["insert"]
20063
+ }];
20064
+ } else if (Array.isArray(config)) {
20065
+ parsed[resourceName] = config.map((item) => {
20066
+ if (typeof item === "string") {
20067
+ return { table: item, actions: ["insert"] };
20068
+ }
20069
+ return {
20070
+ table: item.table,
20071
+ actions: item.actions || ["insert"]
20072
+ };
20073
+ });
20074
+ } else if (typeof config === "object") {
20075
+ parsed[resourceName] = [{
20076
+ table: config.table,
20077
+ actions: config.actions || ["insert"]
20078
+ }];
20079
+ }
20080
+ }
20081
+ return parsed;
20057
20082
  }
20058
20083
  validateConfig() {
20059
20084
  const errors = [];
20060
20085
  if (!this.projectId) errors.push("projectId is required");
20061
20086
  if (!this.datasetId) errors.push("datasetId is required");
20062
- if (!this.tableId) errors.push("tableId is required");
20087
+ if (Object.keys(this.resources).length === 0) errors.push("At least one resource must be configured");
20088
+ for (const [resourceName, tables] of Object.entries(this.resources)) {
20089
+ for (const tableConfig of tables) {
20090
+ if (!tableConfig.table) {
20091
+ errors.push(`Table name is required for resource '${resourceName}'`);
20092
+ }
20093
+ if (!Array.isArray(tableConfig.actions) || tableConfig.actions.length === 0) {
20094
+ errors.push(`Actions array is required for resource '${resourceName}'`);
20095
+ }
20096
+ const validActions = ["insert", "update", "delete"];
20097
+ const invalidActions = tableConfig.actions.filter((action) => !validActions.includes(action));
20098
+ if (invalidActions.length > 0) {
20099
+ errors.push(`Invalid actions for resource '${resourceName}': ${invalidActions.join(", ")}. Valid actions: ${validActions.join(", ")}`);
20100
+ }
20101
+ }
20102
+ }
20063
20103
  return { isValid: errors.length === 0, errors };
20064
20104
  }
20065
20105
  async initialize(database) {
@@ -20075,78 +20115,117 @@ class BigqueryReplicator extends BaseReplicator {
20075
20115
  replicator: this.name,
20076
20116
  projectId: this.projectId,
20077
20117
  datasetId: this.datasetId,
20078
- tableId: this.tableId
20118
+ resources: Object.keys(this.resources)
20079
20119
  });
20080
20120
  } catch (error) {
20081
20121
  this.emit("initialization_error", { replicator: this.name, error: error.message });
20082
20122
  throw error;
20083
20123
  }
20084
20124
  }
20085
- getTableForResource(resourceName) {
20086
- return this.tableMap[resourceName] || this.tableId;
20125
+ shouldReplicateResource(resourceName) {
20126
+ return this.resources.hasOwnProperty(resourceName);
20127
+ }
20128
+ shouldReplicateAction(resourceName, operation) {
20129
+ if (!this.resources[resourceName]) return false;
20130
+ return this.resources[resourceName].some(
20131
+ (tableConfig) => tableConfig.actions.includes(operation)
20132
+ );
20133
+ }
20134
+ getTablesForResource(resourceName, operation) {
20135
+ if (!this.resources[resourceName]) return [];
20136
+ return this.resources[resourceName].filter((tableConfig) => tableConfig.actions.includes(operation)).map((tableConfig) => tableConfig.table);
20087
20137
  }
20088
20138
  async replicate(resourceName, operation, data, id, beforeData = null) {
20089
20139
  if (!this.enabled || !this.shouldReplicateResource(resourceName)) {
20090
20140
  return { skipped: true, reason: "resource_not_included" };
20091
20141
  }
20142
+ if (!this.shouldReplicateAction(resourceName, operation)) {
20143
+ return { skipped: true, reason: "action_not_included" };
20144
+ }
20145
+ const tables = this.getTablesForResource(resourceName, operation);
20146
+ if (tables.length === 0) {
20147
+ return { skipped: true, reason: "no_tables_for_action" };
20148
+ }
20149
+ const results = [];
20150
+ const errors = [];
20092
20151
  try {
20093
20152
  const dataset = this.bigqueryClient.dataset(this.datasetId);
20094
- const tableId = this.getTableForResource(resourceName);
20095
- const table = dataset.table(tableId);
20096
- let job;
20097
- if (operation === "insert") {
20098
- const row = { ...data };
20099
- job = await table.insert([row]);
20100
- } else if (operation === "update") {
20101
- const keys = Object.keys(data).filter((k) => k !== "id");
20102
- const setClause = keys.map((k) => `
20103
- ${k}=@${k}
20104
- `).join(", ");
20105
- const params = { id };
20106
- keys.forEach((k) => {
20107
- params[k] = data[k];
20108
- });
20109
- const query = `UPDATE \`${this.projectId}.${this.datasetId}.${tableId}\`
20110
- SET ${setClause}
20111
- WHERE id=@id`;
20112
- const [updateJob] = await this.bigqueryClient.createQueryJob({
20113
- query,
20114
- params
20115
- });
20116
- await updateJob.getQueryResults();
20117
- job = [updateJob];
20118
- } else if (operation === "delete") {
20119
- const query = `DELETE FROM \`${this.projectId}.${this.datasetId}.${tableId}\`
20120
- WHERE id=@id`;
20121
- const [deleteJob] = await this.bigqueryClient.createQueryJob({
20122
- query,
20123
- params: { id }
20124
- });
20125
- await deleteJob.getQueryResults();
20126
- job = [deleteJob];
20127
- } else {
20128
- throw new Error(`Unsupported operation: ${operation}`);
20129
- }
20130
- if (this.logOperations) {
20131
- const logTable = dataset.table(this.tableId);
20132
- await logTable.insert([{
20133
- resource_name: resourceName,
20134
- operation,
20135
- record_id: id,
20136
- data: JSON.stringify(data),
20137
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
20138
- source: "s3db-replication"
20139
- }]);
20153
+ for (const tableId of tables) {
20154
+ try {
20155
+ const table = dataset.table(tableId);
20156
+ let job;
20157
+ if (operation === "insert") {
20158
+ const row = { ...data };
20159
+ job = await table.insert([row]);
20160
+ } else if (operation === "update") {
20161
+ const keys = Object.keys(data).filter((k) => k !== "id");
20162
+ const setClause = keys.map((k) => `${k}=@${k}`).join(", ");
20163
+ const params = { id };
20164
+ keys.forEach((k) => {
20165
+ params[k] = data[k];
20166
+ });
20167
+ const query = `UPDATE \`${this.projectId}.${this.datasetId}.${tableId}\` SET ${setClause} WHERE id=@id`;
20168
+ const [updateJob] = await this.bigqueryClient.createQueryJob({
20169
+ query,
20170
+ params
20171
+ });
20172
+ await updateJob.getQueryResults();
20173
+ job = [updateJob];
20174
+ } else if (operation === "delete") {
20175
+ const query = `DELETE FROM \`${this.projectId}.${this.datasetId}.${tableId}\` WHERE id=@id`;
20176
+ const [deleteJob] = await this.bigqueryClient.createQueryJob({
20177
+ query,
20178
+ params: { id }
20179
+ });
20180
+ await deleteJob.getQueryResults();
20181
+ job = [deleteJob];
20182
+ } else {
20183
+ throw new Error(`Unsupported operation: ${operation}`);
20184
+ }
20185
+ results.push({
20186
+ table: tableId,
20187
+ success: true,
20188
+ jobId: job[0]?.id
20189
+ });
20190
+ } catch (error) {
20191
+ errors.push({
20192
+ table: tableId,
20193
+ error: error.message
20194
+ });
20195
+ }
20140
20196
  }
20197
+ if (this.logTable) {
20198
+ try {
20199
+ const logTable = dataset.table(this.logTable);
20200
+ await logTable.insert([{
20201
+ resource_name: resourceName,
20202
+ operation,
20203
+ record_id: id,
20204
+ data: JSON.stringify(data),
20205
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
20206
+ source: "s3db-replication"
20207
+ }]);
20208
+ } catch (error) {
20209
+ console.warn(`Failed to log operation to ${this.logTable}:`, error.message);
20210
+ }
20211
+ }
20212
+ const success = errors.length === 0;
20141
20213
  this.emit("replicated", {
20142
20214
  replicator: this.name,
20143
20215
  resourceName,
20144
20216
  operation,
20145
20217
  id,
20146
- jobId: job[0]?.id,
20147
- success: true
20218
+ tables,
20219
+ results,
20220
+ errors,
20221
+ success
20148
20222
  });
20149
- return { success: true, jobId: job[0]?.id };
20223
+ return {
20224
+ success,
20225
+ results,
20226
+ errors,
20227
+ tables
20228
+ };
20150
20229
  } catch (error) {
20151
20230
  this.emit("replication_error", {
20152
20231
  replicator: this.name,
@@ -20163,13 +20242,23 @@ class BigqueryReplicator extends BaseReplicator {
20163
20242
  const errors = [];
20164
20243
  for (const record of records) {
20165
20244
  try {
20166
- const res = await this.replicate(resourceName, record.operation, record.data, record.id, record.beforeData);
20245
+ const res = await this.replicate(
20246
+ resourceName,
20247
+ record.operation,
20248
+ record.data,
20249
+ record.id,
20250
+ record.beforeData
20251
+ );
20167
20252
  results.push(res);
20168
20253
  } catch (err) {
20169
20254
  errors.push({ id: record.id, error: err.message });
20170
20255
  }
20171
20256
  }
20172
- return { success: errors.length === 0, results, errors };
20257
+ return {
20258
+ success: errors.length === 0,
20259
+ results,
20260
+ errors
20261
+ };
20173
20262
  }
20174
20263
  async testConnection() {
20175
20264
  try {
@@ -20184,37 +20273,82 @@ class BigqueryReplicator extends BaseReplicator {
20184
20273
  }
20185
20274
  async cleanup() {
20186
20275
  }
20187
- shouldReplicateResource(resourceName) {
20188
- if (!this.resources || this.resources.length === 0) return true;
20189
- return this.resources.includes(resourceName);
20276
+ getStatus() {
20277
+ return {
20278
+ ...super.getStatus(),
20279
+ projectId: this.projectId,
20280
+ datasetId: this.datasetId,
20281
+ resources: this.resources,
20282
+ logTable: this.logTable
20283
+ };
20190
20284
  }
20191
20285
  }
20192
20286
 
20193
20287
  class PostgresReplicator extends BaseReplicator {
20194
- constructor(config = {}, resources = []) {
20288
+ constructor(config = {}, resources = {}) {
20195
20289
  super(config);
20196
- this.resources = resources;
20197
20290
  this.connectionString = config.connectionString;
20198
20291
  this.host = config.host;
20199
20292
  this.port = config.port || 5432;
20200
20293
  this.database = config.database;
20201
20294
  this.user = config.user;
20202
20295
  this.password = config.password;
20203
- this.tableName = config.tableName || "s3db_replication";
20204
- this.tableMap = config.tableMap || {};
20205
20296
  this.client = null;
20206
20297
  this.ssl = config.ssl;
20207
- this.logOperations = config.logOperations !== false;
20298
+ this.logTable = config.logTable;
20299
+ this.resources = this.parseResourcesConfig(resources);
20300
+ }
20301
+ parseResourcesConfig(resources) {
20302
+ const parsed = {};
20303
+ for (const [resourceName, config] of Object.entries(resources)) {
20304
+ if (typeof config === "string") {
20305
+ parsed[resourceName] = [{
20306
+ table: config,
20307
+ actions: ["insert"]
20308
+ }];
20309
+ } else if (Array.isArray(config)) {
20310
+ parsed[resourceName] = config.map((item) => {
20311
+ if (typeof item === "string") {
20312
+ return { table: item, actions: ["insert"] };
20313
+ }
20314
+ return {
20315
+ table: item.table,
20316
+ actions: item.actions || ["insert"]
20317
+ };
20318
+ });
20319
+ } else if (typeof config === "object") {
20320
+ parsed[resourceName] = [{
20321
+ table: config.table,
20322
+ actions: config.actions || ["insert"]
20323
+ }];
20324
+ }
20325
+ }
20326
+ return parsed;
20208
20327
  }
20209
20328
  validateConfig() {
20210
20329
  const errors = [];
20211
20330
  if (!this.connectionString && (!this.host || !this.database)) {
20212
20331
  errors.push("Either connectionString or host+database must be provided");
20213
20332
  }
20214
- return {
20215
- isValid: errors.length === 0,
20216
- errors
20217
- };
20333
+ if (Object.keys(this.resources).length === 0) {
20334
+ errors.push("At least one resource must be configured");
20335
+ }
20336
+ for (const [resourceName, tables] of Object.entries(this.resources)) {
20337
+ for (const tableConfig of tables) {
20338
+ if (!tableConfig.table) {
20339
+ errors.push(`Table name is required for resource '${resourceName}'`);
20340
+ }
20341
+ if (!Array.isArray(tableConfig.actions) || tableConfig.actions.length === 0) {
20342
+ errors.push(`Actions array is required for resource '${resourceName}'`);
20343
+ }
20344
+ const validActions = ["insert", "update", "delete"];
20345
+ const invalidActions = tableConfig.actions.filter((action) => !validActions.includes(action));
20346
+ if (invalidActions.length > 0) {
20347
+ errors.push(`Invalid actions for resource '${resourceName}': ${invalidActions.join(", ")}. Valid actions: ${validActions.join(", ")}`);
20348
+ }
20349
+ }
20350
+ }
20351
+ return { isValid: errors.length === 0, errors };
20218
20352
  }
20219
20353
  async initialize(database) {
20220
20354
  await super.initialize(database);
@@ -20233,11 +20367,13 @@ class PostgresReplicator extends BaseReplicator {
20233
20367
  };
20234
20368
  this.client = new Client(config);
20235
20369
  await this.client.connect();
20236
- if (this.logOperations) await this.createTableIfNotExists();
20370
+ if (this.logTable) {
20371
+ await this.createLogTableIfNotExists();
20372
+ }
20237
20373
  this.emit("initialized", {
20238
20374
  replicator: this.name,
20239
20375
  database: this.database || "postgres",
20240
- table: this.tableName
20376
+ resources: Object.keys(this.resources)
20241
20377
  });
20242
20378
  } catch (error) {
20243
20379
  this.emit("initialization_error", {
@@ -20247,9 +20383,9 @@ class PostgresReplicator extends BaseReplicator {
20247
20383
  throw error;
20248
20384
  }
20249
20385
  }
20250
- async createTableIfNotExists() {
20386
+ async createLogTableIfNotExists() {
20251
20387
  const createTableQuery = `
20252
- CREATE TABLE IF NOT EXISTS ${this.tableName} (
20388
+ CREATE TABLE IF NOT EXISTS ${this.logTable} (
20253
20389
  id SERIAL PRIMARY KEY,
20254
20390
  resource_name VARCHAR(255) NOT NULL,
20255
20391
  operation VARCHAR(50) NOT NULL,
@@ -20259,58 +20395,103 @@ class PostgresReplicator extends BaseReplicator {
20259
20395
  source VARCHAR(100) DEFAULT 's3db-replication',
20260
20396
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
20261
20397
  );
20262
- CREATE INDEX IF NOT EXISTS idx_${this.tableName}_resource_name ON ${this.tableName}(resource_name);
20263
- CREATE INDEX IF NOT EXISTS idx_${this.tableName}_operation ON ${this.tableName}(operation);
20264
- CREATE INDEX IF NOT EXISTS idx_${this.tableName}_record_id ON ${this.tableName}(record_id);
20265
- CREATE INDEX IF NOT EXISTS idx_${this.tableName}_timestamp ON ${this.tableName}(timestamp);
20398
+ CREATE INDEX IF NOT EXISTS idx_${this.logTable}_resource_name ON ${this.logTable}(resource_name);
20399
+ CREATE INDEX IF NOT EXISTS idx_${this.logTable}_operation ON ${this.logTable}(operation);
20400
+ CREATE INDEX IF NOT EXISTS idx_${this.logTable}_record_id ON ${this.logTable}(record_id);
20401
+ CREATE INDEX IF NOT EXISTS idx_${this.logTable}_timestamp ON ${this.logTable}(timestamp);
20266
20402
  `;
20267
20403
  await this.client.query(createTableQuery);
20268
20404
  }
20269
- getTableForResource(resourceName) {
20270
- return this.tableMap[resourceName] || resourceName;
20405
+ shouldReplicateResource(resourceName) {
20406
+ return this.resources.hasOwnProperty(resourceName);
20407
+ }
20408
+ shouldReplicateAction(resourceName, operation) {
20409
+ if (!this.resources[resourceName]) return false;
20410
+ return this.resources[resourceName].some(
20411
+ (tableConfig) => tableConfig.actions.includes(operation)
20412
+ );
20413
+ }
20414
+ getTablesForResource(resourceName, operation) {
20415
+ if (!this.resources[resourceName]) return [];
20416
+ return this.resources[resourceName].filter((tableConfig) => tableConfig.actions.includes(operation)).map((tableConfig) => tableConfig.table);
20271
20417
  }
20272
20418
  async replicate(resourceName, operation, data, id, beforeData = null) {
20273
20419
  if (!this.enabled || !this.shouldReplicateResource(resourceName)) {
20274
20420
  return { skipped: true, reason: "resource_not_included" };
20275
20421
  }
20422
+ if (!this.shouldReplicateAction(resourceName, operation)) {
20423
+ return { skipped: true, reason: "action_not_included" };
20424
+ }
20425
+ const tables = this.getTablesForResource(resourceName, operation);
20426
+ if (tables.length === 0) {
20427
+ return { skipped: true, reason: "no_tables_for_action" };
20428
+ }
20429
+ const results = [];
20430
+ const errors = [];
20276
20431
  try {
20277
- const table = this.getTableForResource(resourceName);
20278
- let result;
20279
- if (operation === "insert") {
20280
- const keys = Object.keys(data);
20281
- const values = keys.map((k) => data[k]);
20282
- const columns = keys.map((k) => `"${k}"`).join(", ");
20283
- const params = keys.map((_, i) => `$${i + 1}`).join(", ");
20284
- const sql = `INSERT INTO ${table} (${columns}) VALUES (${params}) ON CONFLICT (id) DO NOTHING RETURNING *`;
20285
- result = await this.client.query(sql, values);
20286
- } else if (operation === "update") {
20287
- const keys = Object.keys(data).filter((k) => k !== "id");
20288
- const setClause = keys.map((k, i) => `"${k}"=$${i + 1}`).join(", ");
20289
- const values = keys.map((k) => data[k]);
20290
- values.push(id);
20291
- const sql = `UPDATE ${table} SET ${setClause} WHERE id=$${keys.length + 1} RETURNING *`;
20292
- result = await this.client.query(sql, values);
20293
- } else if (operation === "delete") {
20294
- const sql = `DELETE FROM ${table} WHERE id=$1 RETURNING *`;
20295
- result = await this.client.query(sql, [id]);
20296
- } else {
20297
- throw new Error(`Unsupported operation: ${operation}`);
20432
+ for (const table of tables) {
20433
+ try {
20434
+ let result;
20435
+ if (operation === "insert") {
20436
+ const keys = Object.keys(data);
20437
+ const values = keys.map((k) => data[k]);
20438
+ const columns = keys.map((k) => `"${k}"`).join(", ");
20439
+ const params = keys.map((_, i) => `$${i + 1}`).join(", ");
20440
+ const sql = `INSERT INTO ${table} (${columns}) VALUES (${params}) ON CONFLICT (id) DO NOTHING RETURNING *`;
20441
+ result = await this.client.query(sql, values);
20442
+ } else if (operation === "update") {
20443
+ const keys = Object.keys(data).filter((k) => k !== "id");
20444
+ const setClause = keys.map((k, i) => `"${k}"=$${i + 1}`).join(", ");
20445
+ const values = keys.map((k) => data[k]);
20446
+ values.push(id);
20447
+ const sql = `UPDATE ${table} SET ${setClause} WHERE id=$${keys.length + 1} RETURNING *`;
20448
+ result = await this.client.query(sql, values);
20449
+ } else if (operation === "delete") {
20450
+ const sql = `DELETE FROM ${table} WHERE id=$1 RETURNING *`;
20451
+ result = await this.client.query(sql, [id]);
20452
+ } else {
20453
+ throw new Error(`Unsupported operation: ${operation}`);
20454
+ }
20455
+ results.push({
20456
+ table,
20457
+ success: true,
20458
+ rows: result.rows,
20459
+ rowCount: result.rowCount
20460
+ });
20461
+ } catch (error) {
20462
+ errors.push({
20463
+ table,
20464
+ error: error.message
20465
+ });
20466
+ }
20298
20467
  }
20299
- if (this.logOperations) {
20300
- await this.client.query(
20301
- `INSERT INTO ${this.tableName} (resource_name, operation, record_id, data, timestamp, source) VALUES ($1, $2, $3, $4, $5, $6)`,
20302
- [resourceName, operation, id, JSON.stringify(data), (/* @__PURE__ */ new Date()).toISOString(), "s3db-replication"]
20303
- );
20468
+ if (this.logTable) {
20469
+ try {
20470
+ await this.client.query(
20471
+ `INSERT INTO ${this.logTable} (resource_name, operation, record_id, data, timestamp, source) VALUES ($1, $2, $3, $4, $5, $6)`,
20472
+ [resourceName, operation, id, JSON.stringify(data), (/* @__PURE__ */ new Date()).toISOString(), "s3db-replication"]
20473
+ );
20474
+ } catch (error) {
20475
+ console.warn(`Failed to log operation to ${this.logTable}:`, error.message);
20476
+ }
20304
20477
  }
20478
+ const success = errors.length === 0;
20305
20479
  this.emit("replicated", {
20306
20480
  replicator: this.name,
20307
20481
  resourceName,
20308
20482
  operation,
20309
20483
  id,
20310
- result: result.rows,
20311
- success: true
20484
+ tables,
20485
+ results,
20486
+ errors,
20487
+ success
20312
20488
  });
20313
- return { success: true, rows: result.rows };
20489
+ return {
20490
+ success,
20491
+ results,
20492
+ errors,
20493
+ tables
20494
+ };
20314
20495
  } catch (error) {
20315
20496
  this.emit("replication_error", {
20316
20497
  replicator: this.name,
@@ -20327,13 +20508,23 @@ class PostgresReplicator extends BaseReplicator {
20327
20508
  const errors = [];
20328
20509
  for (const record of records) {
20329
20510
  try {
20330
- const res = await this.replicate(resourceName, record.operation, record.data, record.id, record.beforeData);
20511
+ const res = await this.replicate(
20512
+ resourceName,
20513
+ record.operation,
20514
+ record.data,
20515
+ record.id,
20516
+ record.beforeData
20517
+ );
20331
20518
  results.push(res);
20332
20519
  } catch (err) {
20333
20520
  errors.push({ id: record.id, error: err.message });
20334
20521
  }
20335
20522
  }
20336
- return { success: errors.length === 0, results, errors };
20523
+ return {
20524
+ success: errors.length === 0,
20525
+ results,
20526
+ errors
20527
+ };
20337
20528
  }
20338
20529
  async testConnection() {
20339
20530
  try {
@@ -20348,9 +20539,13 @@ class PostgresReplicator extends BaseReplicator {
20348
20539
  async cleanup() {
20349
20540
  if (this.client) await this.client.end();
20350
20541
  }
20351
- shouldReplicateResource(resourceName) {
20352
- if (!this.resources || this.resources.length === 0) return true;
20353
- return this.resources.includes(resourceName);
20542
+ getStatus() {
20543
+ return {
20544
+ ...super.getStatus(),
20545
+ database: this.database || "postgres",
20546
+ resources: this.resources,
20547
+ logTable: this.logTable
20548
+ };
20354
20549
  }
20355
20550
  }
20356
20551