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