s3db.js 7.3.4 → 7.3.6

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.es.js CHANGED
@@ -3,8 +3,8 @@ import zlib from 'node:zlib';
3
3
  import { PromisePool } from '@supercharge/promise-pool';
4
4
  import { ReadableStream } from 'node:stream/web';
5
5
  import { mkdir, writeFile, readFile, stat, unlink, readdir, rm } from 'fs/promises';
6
- import { chunk, merge, isString as isString$1, isEmpty, invert, uniq, cloneDeep, get, set, isObject as isObject$1, isFunction as isFunction$1 } from 'lodash-es';
7
6
  import { createHash } from 'crypto';
7
+ import { chunk, merge, isString as isString$1, isEmpty, invert, uniq, cloneDeep, get, set, isObject as isObject$1, isFunction as isFunction$1 } from 'lodash-es';
8
8
  import jsonStableStringify from 'json-stable-stringify';
9
9
  import { S3Client, PutObjectCommand, GetObjectCommand, HeadObjectCommand, CopyObjectCommand, DeleteObjectCommand, DeleteObjectsCommand, ListObjectsV2Command } from '@aws-sdk/client-s3';
10
10
  import { flatten, unflatten } from 'flat';
@@ -7079,6 +7079,12 @@ class FilesystemCache extends Cache {
7079
7079
  }
7080
7080
  async _clear(prefix) {
7081
7081
  try {
7082
+ if (!await this._fileExists(this.directory)) {
7083
+ if (this.enableStats) {
7084
+ this.stats.clears++;
7085
+ }
7086
+ return true;
7087
+ }
7082
7088
  const files = await readdir(this.directory);
7083
7089
  const cacheFiles = files.filter((file) => {
7084
7090
  if (!file.startsWith(this.prefix)) return false;
@@ -8349,7 +8355,7 @@ class MetricsPlugin extends plugin_class_default {
8349
8355
  }
8350
8356
  async setup(database) {
8351
8357
  this.database = database;
8352
- if (process.env.NODE_ENV === "test") return;
8358
+ if (typeof process !== "undefined" && process.env.NODE_ENV === "test") return;
8353
8359
  const [ok, err] = await try_fn_default(async () => {
8354
8360
  const [ok1, err1, metricsResource] = await try_fn_default(() => database.createResource({
8355
8361
  name: "metrics",
@@ -8399,7 +8405,7 @@ class MetricsPlugin extends plugin_class_default {
8399
8405
  this.performanceResource = database.resources.performance_logs;
8400
8406
  }
8401
8407
  this.installMetricsHooks();
8402
- if (process.env.NODE_ENV !== "test") {
8408
+ if (typeof process !== "undefined" && process.env.NODE_ENV !== "test") {
8403
8409
  this.startFlushTimer();
8404
8410
  }
8405
8411
  }
@@ -8410,7 +8416,7 @@ class MetricsPlugin extends plugin_class_default {
8410
8416
  clearInterval(this.flushTimer);
8411
8417
  this.flushTimer = null;
8412
8418
  }
8413
- if (process.env.NODE_ENV !== "test") {
8419
+ if (typeof process !== "undefined" && process.env.NODE_ENV !== "test") {
8414
8420
  await this.flushMetrics();
8415
8421
  }
8416
8422
  }
@@ -8589,10 +8595,18 @@ class MetricsPlugin extends plugin_class_default {
8589
8595
  async flushMetrics() {
8590
8596
  if (!this.metricsResource) return;
8591
8597
  const [ok, err] = await try_fn_default(async () => {
8592
- const metadata = process.env.NODE_ENV === "test" ? {} : { global: "true" };
8593
- const perfMetadata = process.env.NODE_ENV === "test" ? {} : { perf: "true" };
8594
- const errorMetadata = process.env.NODE_ENV === "test" ? {} : { error: "true" };
8595
- const resourceMetadata = process.env.NODE_ENV === "test" ? {} : { resource: "true" };
8598
+ let metadata, perfMetadata, errorMetadata, resourceMetadata;
8599
+ if (typeof process !== "undefined" && process.env.NODE_ENV === "test") {
8600
+ metadata = {};
8601
+ perfMetadata = {};
8602
+ errorMetadata = {};
8603
+ resourceMetadata = {};
8604
+ } else {
8605
+ metadata = { global: "true" };
8606
+ perfMetadata = { perf: "true" };
8607
+ errorMetadata = { error: "true" };
8608
+ resourceMetadata = { resource: "true" };
8609
+ }
8596
8610
  for (const [operation, data] of Object.entries(this.metrics.operations)) {
8597
8611
  if (data.count > 0) {
8598
8612
  await this.metricsResource.insert({
@@ -8942,6 +8956,9 @@ class BigqueryReplicator extends base_replicator_class_default {
8942
8956
  await super.initialize(database);
8943
8957
  const [ok, err, sdk] = await try_fn_default(() => import('@google-cloud/bigquery'));
8944
8958
  if (!ok) {
8959
+ if (this.config.verbose) {
8960
+ console.warn(`[BigqueryReplicator] Failed to import BigQuery SDK: ${err.message}`);
8961
+ }
8945
8962
  this.emit("initialization_error", { replicator: this.name, error: err.message });
8946
8963
  throw err;
8947
8964
  }
@@ -9011,19 +9028,28 @@ class BigqueryReplicator extends base_replicator_class_default {
9011
9028
  const maxRetries = 2;
9012
9029
  let lastError = null;
9013
9030
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
9014
- try {
9031
+ const [ok2, error] = await try_fn_default(async () => {
9015
9032
  const [updateJob] = await this.bigqueryClient.createQueryJob({
9016
9033
  query,
9017
9034
  params,
9018
9035
  location: this.location
9019
9036
  });
9020
9037
  await updateJob.getQueryResults();
9021
- job = [updateJob];
9038
+ return [updateJob];
9039
+ });
9040
+ if (ok2) {
9041
+ job = ok2;
9022
9042
  break;
9023
- } catch (error) {
9043
+ } else {
9024
9044
  lastError = error;
9045
+ if (this.config.verbose) {
9046
+ console.warn(`[BigqueryReplicator] Update attempt ${attempt} failed: ${error.message}`);
9047
+ }
9025
9048
  if (error?.message?.includes("streaming buffer") && attempt < maxRetries) {
9026
9049
  const delaySeconds = 30;
9050
+ if (this.config.verbose) {
9051
+ console.warn(`[BigqueryReplicator] Retrying in ${delaySeconds} seconds due to streaming buffer issue`);
9052
+ }
9027
9053
  await new Promise((resolve) => setTimeout(resolve, delaySeconds * 1e3));
9028
9054
  continue;
9029
9055
  }
@@ -9090,6 +9116,9 @@ class BigqueryReplicator extends base_replicator_class_default {
9090
9116
  };
9091
9117
  });
9092
9118
  if (ok) return result;
9119
+ if (this.config.verbose) {
9120
+ console.warn(`[BigqueryReplicator] Replication failed for ${resourceName}: ${err.message}`);
9121
+ }
9093
9122
  this.emit("replicator_error", {
9094
9123
  replicator: this.name,
9095
9124
  resourceName,
@@ -9110,8 +9139,14 @@ class BigqueryReplicator extends base_replicator_class_default {
9110
9139
  record.id,
9111
9140
  record.beforeData
9112
9141
  ));
9113
- if (ok) results.push(res);
9114
- else errors.push({ id: record.id, error: err.message });
9142
+ if (ok) {
9143
+ results.push(res);
9144
+ } else {
9145
+ if (this.config.verbose) {
9146
+ console.warn(`[BigqueryReplicator] Batch replication failed for record ${record.id}: ${err.message}`);
9147
+ }
9148
+ errors.push({ id: record.id, error: err.message });
9149
+ }
9115
9150
  }
9116
9151
  return {
9117
9152
  success: errors.length === 0,
@@ -9127,6 +9162,9 @@ class BigqueryReplicator extends base_replicator_class_default {
9127
9162
  return true;
9128
9163
  });
9129
9164
  if (ok) return true;
9165
+ if (this.config.verbose) {
9166
+ console.warn(`[BigqueryReplicator] Connection test failed: ${err.message}`);
9167
+ }
9130
9168
  this.emit("connection_error", { replicator: this.name, error: err.message });
9131
9169
  return false;
9132
9170
  }
@@ -9214,6 +9252,9 @@ class PostgresReplicator extends base_replicator_class_default {
9214
9252
  await super.initialize(database);
9215
9253
  const [ok, err, sdk] = await try_fn_default(() => import('pg'));
9216
9254
  if (!ok) {
9255
+ if (this.config.verbose) {
9256
+ console.warn(`[PostgresReplicator] Failed to import pg SDK: ${err.message}`);
9257
+ }
9217
9258
  this.emit("initialization_error", {
9218
9259
  replicator: this.name,
9219
9260
  error: err.message
@@ -9355,6 +9396,9 @@ class PostgresReplicator extends base_replicator_class_default {
9355
9396
  };
9356
9397
  });
9357
9398
  if (ok) return result;
9399
+ if (this.config.verbose) {
9400
+ console.warn(`[PostgresReplicator] Replication failed for ${resourceName}: ${err.message}`);
9401
+ }
9358
9402
  this.emit("replicator_error", {
9359
9403
  replicator: this.name,
9360
9404
  resourceName,
@@ -9375,8 +9419,14 @@ class PostgresReplicator extends base_replicator_class_default {
9375
9419
  record.id,
9376
9420
  record.beforeData
9377
9421
  ));
9378
- if (ok) results.push(res);
9379
- else errors.push({ id: record.id, error: err.message });
9422
+ if (ok) {
9423
+ results.push(res);
9424
+ } else {
9425
+ if (this.config.verbose) {
9426
+ console.warn(`[PostgresReplicator] Batch replication failed for record ${record.id}: ${err.message}`);
9427
+ }
9428
+ errors.push({ id: record.id, error: err.message });
9429
+ }
9380
9430
  }
9381
9431
  return {
9382
9432
  success: errors.length === 0,
@@ -9391,6 +9441,9 @@ class PostgresReplicator extends base_replicator_class_default {
9391
9441
  return true;
9392
9442
  });
9393
9443
  if (ok) return true;
9444
+ if (this.config.verbose) {
9445
+ console.warn(`[PostgresReplicator] Connection test failed: ${err.message}`);
9446
+ }
9394
9447
  this.emit("connection_error", { replicator: this.name, error: err.message });
9395
9448
  return false;
9396
9449
  }
@@ -13125,7 +13178,7 @@ class Database extends EventEmitter {
13125
13178
  super();
13126
13179
  this.version = "1";
13127
13180
  this.s3dbVersion = (() => {
13128
- const [ok, err, version] = try_fn_default(() => true ? "7.3.4" : "latest");
13181
+ const [ok, err, version] = try_fn_default(() => true ? "7.3.6" : "latest");
13129
13182
  return ok ? version : "latest";
13130
13183
  })();
13131
13184
  this.resources = {};
@@ -13168,14 +13221,16 @@ class Database extends EventEmitter {
13168
13221
  this.keyPrefix = this.client.keyPrefix;
13169
13222
  if (!this._exitListenerRegistered) {
13170
13223
  this._exitListenerRegistered = true;
13171
- process.on("exit", async () => {
13172
- if (this.isConnected()) {
13173
- try {
13174
- await this.disconnect();
13175
- } catch (err) {
13224
+ if (typeof process !== "undefined") {
13225
+ process.on("exit", async () => {
13226
+ if (this.isConnected()) {
13227
+ try {
13228
+ await this.disconnect();
13229
+ } catch (err) {
13230
+ }
13176
13231
  }
13177
- }
13178
- });
13232
+ });
13233
+ }
13179
13234
  }
13180
13235
  }
13181
13236
  async connect() {
@@ -13627,9 +13682,8 @@ class S3dbReplicator extends base_replicator_class_default {
13627
13682
  const map = {};
13628
13683
  for (const res of resources) {
13629
13684
  if (typeof res === "string") map[normalizeResourceName$1(res)] = res;
13630
- else if (Array.isArray(res) && typeof res[0] === "string") map[normalizeResourceName$1(res[0])] = res;
13631
13685
  else if (typeof res === "object" && res.resource) {
13632
- map[normalizeResourceName$1(res.resource)] = { ...res };
13686
+ map[normalizeResourceName$1(res.resource)] = res;
13633
13687
  }
13634
13688
  }
13635
13689
  return map;
@@ -13642,15 +13696,14 @@ class S3dbReplicator extends base_replicator_class_default {
13642
13696
  else if (Array.isArray(dest)) {
13643
13697
  map[normSrc] = dest.map((item) => {
13644
13698
  if (typeof item === "string") return item;
13645
- if (typeof item === "function") return item;
13646
13699
  if (typeof item === "object" && item.resource) {
13647
- return { ...item };
13700
+ return item;
13648
13701
  }
13649
13702
  return item;
13650
13703
  });
13651
13704
  } else if (typeof dest === "function") map[normSrc] = dest;
13652
13705
  else if (typeof dest === "object" && dest.resource) {
13653
- map[normSrc] = { ...dest };
13706
+ map[normSrc] = dest;
13654
13707
  }
13655
13708
  }
13656
13709
  return map;
@@ -13658,10 +13711,6 @@ class S3dbReplicator extends base_replicator_class_default {
13658
13711
  if (typeof resources === "function") {
13659
13712
  return resources;
13660
13713
  }
13661
- if (typeof resources === "string") {
13662
- const map = { [normalizeResourceName$1(resources)]: resources };
13663
- return map;
13664
- }
13665
13714
  return {};
13666
13715
  }
13667
13716
  validateConfig() {
@@ -13675,8 +13724,8 @@ class S3dbReplicator extends base_replicator_class_default {
13675
13724
  return { isValid: errors.length === 0, errors };
13676
13725
  }
13677
13726
  async initialize(database) {
13678
- try {
13679
- await super.initialize(database);
13727
+ await super.initialize(database);
13728
+ const [ok, err] = await try_fn_default(async () => {
13680
13729
  if (this.client) {
13681
13730
  this.targetDatabase = this.client;
13682
13731
  } else if (this.connectionString) {
@@ -13695,7 +13744,11 @@ class S3dbReplicator extends base_replicator_class_default {
13695
13744
  replicator: this.name,
13696
13745
  target: this.connectionString || "client-provided"
13697
13746
  });
13698
- } catch (err) {
13747
+ });
13748
+ if (!ok) {
13749
+ if (this.config.verbose) {
13750
+ console.warn(`[S3dbReplicator] Initialization failed: ${err.message}`);
13751
+ }
13699
13752
  throw err;
13700
13753
  }
13701
13754
  }
@@ -13714,18 +13767,77 @@ class S3dbReplicator extends base_replicator_class_default {
13714
13767
  id = recordId;
13715
13768
  }
13716
13769
  const normResource = normalizeResourceName$1(resource);
13717
- const destResource = this._resolveDestResource(normResource, payload);
13718
- const destResourceObj = this._getDestResourceObj(destResource);
13719
- const transformedData = this._applyTransformer(normResource, payload);
13770
+ const entry = this.resourcesMap[normResource];
13771
+ if (!entry) {
13772
+ throw new Error(`[S3dbReplicator] Resource not configured: ${resource}`);
13773
+ }
13774
+ if (Array.isArray(entry)) {
13775
+ const results = [];
13776
+ for (const destConfig of entry) {
13777
+ const [ok, error, result] = await try_fn_default(async () => {
13778
+ return await this._replicateToSingleDestination(destConfig, normResource, op, payload, id);
13779
+ });
13780
+ if (!ok) {
13781
+ if (this.config && this.config.verbose) {
13782
+ console.warn(`[S3dbReplicator] Failed to replicate to destination ${JSON.stringify(destConfig)}: ${error.message}`);
13783
+ }
13784
+ throw error;
13785
+ }
13786
+ results.push(result);
13787
+ }
13788
+ return results;
13789
+ } else {
13790
+ const [ok, error, result] = await try_fn_default(async () => {
13791
+ return await this._replicateToSingleDestination(entry, normResource, op, payload, id);
13792
+ });
13793
+ if (!ok) {
13794
+ if (this.config && this.config.verbose) {
13795
+ console.warn(`[S3dbReplicator] Failed to replicate to destination ${JSON.stringify(entry)}: ${error.message}`);
13796
+ }
13797
+ throw error;
13798
+ }
13799
+ return result;
13800
+ }
13801
+ }
13802
+ async _replicateToSingleDestination(destConfig, sourceResource, operation, data, recordId) {
13803
+ let destResourceName;
13804
+ if (typeof destConfig === "string") {
13805
+ destResourceName = destConfig;
13806
+ } else if (typeof destConfig === "object" && destConfig.resource) {
13807
+ destResourceName = destConfig.resource;
13808
+ } else {
13809
+ destResourceName = sourceResource;
13810
+ }
13811
+ if (typeof destConfig === "object" && destConfig.actions && Array.isArray(destConfig.actions)) {
13812
+ if (!destConfig.actions.includes(operation)) {
13813
+ return { skipped: true, reason: "action_not_supported", action: operation, destination: destResourceName };
13814
+ }
13815
+ }
13816
+ const destResourceObj = this._getDestResourceObj(destResourceName);
13817
+ let transformedData;
13818
+ if (typeof destConfig === "object" && destConfig.transform && typeof destConfig.transform === "function") {
13819
+ transformedData = destConfig.transform(data);
13820
+ if (transformedData && data && data.id && !transformedData.id) {
13821
+ transformedData.id = data.id;
13822
+ }
13823
+ } else if (typeof destConfig === "object" && destConfig.transformer && typeof destConfig.transformer === "function") {
13824
+ transformedData = destConfig.transformer(data);
13825
+ if (transformedData && data && data.id && !transformedData.id) {
13826
+ transformedData.id = data.id;
13827
+ }
13828
+ } else {
13829
+ transformedData = data;
13830
+ }
13831
+ if (!transformedData && data) transformedData = data;
13720
13832
  let result;
13721
- if (op === "insert") {
13833
+ if (operation === "insert") {
13722
13834
  result = await destResourceObj.insert(transformedData);
13723
- } else if (op === "update") {
13724
- result = await destResourceObj.update(id, transformedData);
13725
- } else if (op === "delete") {
13726
- result = await destResourceObj.delete(id);
13835
+ } else if (operation === "update") {
13836
+ result = await destResourceObj.update(recordId, transformedData);
13837
+ } else if (operation === "delete") {
13838
+ result = await destResourceObj.delete(recordId);
13727
13839
  } else {
13728
- throw new Error(`Invalid operation: ${op}. Supported operations are: insert, update, delete`);
13840
+ throw new Error(`Invalid operation: ${operation}. Supported operations are: insert, update, delete`);
13729
13841
  }
13730
13842
  return result;
13731
13843
  }
@@ -13734,13 +13846,25 @@ class S3dbReplicator extends base_replicator_class_default {
13734
13846
  const entry = this.resourcesMap[normResource];
13735
13847
  let result;
13736
13848
  if (!entry) return data;
13737
- if (Array.isArray(entry) && typeof entry[1] === "function") {
13738
- result = entry[1](data);
13849
+ if (Array.isArray(entry)) {
13850
+ for (const item of entry) {
13851
+ if (typeof item === "object" && item.transform && typeof item.transform === "function") {
13852
+ result = item.transform(data);
13853
+ break;
13854
+ } else if (typeof item === "object" && item.transformer && typeof item.transformer === "function") {
13855
+ result = item.transformer(data);
13856
+ break;
13857
+ }
13858
+ }
13859
+ if (!result) result = data;
13860
+ } else if (typeof entry === "object") {
13861
+ if (typeof entry.transform === "function") {
13862
+ result = entry.transform(data);
13863
+ } else if (typeof entry.transformer === "function") {
13864
+ result = entry.transformer(data);
13865
+ }
13739
13866
  } else if (typeof entry === "function") {
13740
13867
  result = entry(data);
13741
- } else if (typeof entry === "object") {
13742
- if (typeof entry.transform === "function") result = entry.transform(data);
13743
- else if (typeof entry.transformer === "function") result = entry.transformer(data);
13744
13868
  } else {
13745
13869
  result = data;
13746
13870
  }
@@ -13753,18 +13877,19 @@ class S3dbReplicator extends base_replicator_class_default {
13753
13877
  const entry = this.resourcesMap[normResource];
13754
13878
  if (!entry) return resource;
13755
13879
  if (Array.isArray(entry)) {
13756
- if (typeof entry[0] === "string") return entry[0];
13757
- if (typeof entry[0] === "object" && entry[0].resource) return entry[0].resource;
13758
- if (typeof entry[0] === "function") return resource;
13880
+ for (const item of entry) {
13881
+ if (typeof item === "string") return item;
13882
+ if (typeof item === "object" && item.resource) return item.resource;
13883
+ }
13884
+ return resource;
13759
13885
  }
13760
13886
  if (typeof entry === "string") return entry;
13761
- if (resource && !targetResourceName) targetResourceName = resource;
13887
+ if (typeof entry === "function") return resource;
13762
13888
  if (typeof entry === "object" && entry.resource) return entry.resource;
13763
13889
  return resource;
13764
13890
  }
13765
13891
  _getDestResourceObj(resource) {
13766
- if (!this.client || !this.client.resources) return null;
13767
- const available = Object.keys(this.client.resources);
13892
+ const available = Object.keys(this.client.resources || {});
13768
13893
  const norm = normalizeResourceName$1(resource);
13769
13894
  const found = available.find((r) => normalizeResourceName$1(r) === norm);
13770
13895
  if (!found) {
@@ -13786,8 +13911,14 @@ class S3dbReplicator extends base_replicator_class_default {
13786
13911
  data: record.data,
13787
13912
  beforeData: record.beforeData
13788
13913
  }));
13789
- if (ok) results.push(result);
13790
- else errors.push({ id: record.id, error: err.message });
13914
+ if (ok) {
13915
+ results.push(result);
13916
+ } else {
13917
+ if (this.config.verbose) {
13918
+ console.warn(`[S3dbReplicator] Batch replication failed for record ${record.id}: ${err.message}`);
13919
+ }
13920
+ errors.push({ id: record.id, error: err.message });
13921
+ }
13791
13922
  }
13792
13923
  this.emit("batch_replicated", {
13793
13924
  replicator: this.name,
@@ -13805,18 +13936,20 @@ class S3dbReplicator extends base_replicator_class_default {
13805
13936
  }
13806
13937
  async testConnection() {
13807
13938
  const [ok, err] = await try_fn_default(async () => {
13808
- if (!this.targetDatabase) {
13809
- await this.initialize(this.database);
13939
+ if (!this.targetDatabase) throw new Error("No target database configured");
13940
+ if (typeof this.targetDatabase.connect === "function") {
13941
+ await this.targetDatabase.connect();
13810
13942
  }
13811
- await this.targetDatabase.listResources();
13812
13943
  return true;
13813
13944
  });
13814
- if (ok) return true;
13815
- this.emit("connection_error", {
13816
- replicator: this.name,
13817
- error: err.message
13818
- });
13819
- return false;
13945
+ if (!ok) {
13946
+ if (this.config.verbose) {
13947
+ console.warn(`[S3dbReplicator] Connection test failed: ${err.message}`);
13948
+ }
13949
+ this.emit("connection_error", { replicator: this.name, error: err.message });
13950
+ return false;
13951
+ }
13952
+ return true;
13820
13953
  }
13821
13954
  async getStatus() {
13822
13955
  const baseStatus = await super.getStatus();
@@ -13848,7 +13981,7 @@ class S3dbReplicator extends base_replicator_class_default {
13848
13981
  } else {
13849
13982
  return true;
13850
13983
  }
13851
- } else if (typeof item === "string" || typeof item === "function") {
13984
+ } else if (typeof item === "string") {
13852
13985
  return true;
13853
13986
  }
13854
13987
  }
@@ -13975,6 +14108,9 @@ class SqsReplicator extends base_replicator_class_default {
13975
14108
  if (!this.sqsClient) {
13976
14109
  const [ok, err, sdk] = await try_fn_default(() => import('@aws-sdk/client-sqs'));
13977
14110
  if (!ok) {
14111
+ if (this.config.verbose) {
14112
+ console.warn(`[SqsReplicator] Failed to import SQS SDK: ${err.message}`);
14113
+ }
13978
14114
  this.emit("initialization_error", {
13979
14115
  replicator: this.name,
13980
14116
  error: err.message
@@ -14026,6 +14162,9 @@ class SqsReplicator extends base_replicator_class_default {
14026
14162
  return { success: true, results };
14027
14163
  });
14028
14164
  if (ok) return result;
14165
+ if (this.config.verbose) {
14166
+ console.warn(`[SqsReplicator] Replication failed for ${resource}: ${err.message}`);
14167
+ }
14029
14168
  this.emit("replicator_error", {
14030
14169
  replicator: this.name,
14031
14170
  resource,
@@ -14098,6 +14237,9 @@ class SqsReplicator extends base_replicator_class_default {
14098
14237
  });
14099
14238
  if (ok) return result;
14100
14239
  const errorMessage = err?.message || err || "Unknown error";
14240
+ if (this.config.verbose) {
14241
+ console.warn(`[SqsReplicator] Batch replication failed for ${resource}: ${errorMessage}`);
14242
+ }
14101
14243
  this.emit("batch_replicator_error", {
14102
14244
  replicator: this.name,
14103
14245
  resource,
@@ -14119,6 +14261,9 @@ class SqsReplicator extends base_replicator_class_default {
14119
14261
  return true;
14120
14262
  });
14121
14263
  if (ok) return true;
14264
+ if (this.config.verbose) {
14265
+ console.warn(`[SqsReplicator] Connection test failed: ${err.message}`);
14266
+ }
14122
14267
  this.emit("connection_error", {
14123
14268
  replicator: this.name,
14124
14269
  error: err.message
@@ -14215,25 +14360,37 @@ class ReplicatorPlugin extends plugin_class_default {
14215
14360
  return;
14216
14361
  }
14217
14362
  resource.on("insert", async (data) => {
14218
- try {
14363
+ const [ok, error] = await try_fn_default(async () => {
14219
14364
  const completeData = { ...data, createdAt: (/* @__PURE__ */ new Date()).toISOString() };
14220
14365
  await plugin.processReplicatorEvent("insert", resource.name, completeData.id, completeData);
14221
- } catch (error) {
14366
+ });
14367
+ if (!ok) {
14368
+ if (this.config.verbose) {
14369
+ console.warn(`[ReplicatorPlugin] Insert event failed for resource ${resource.name}: ${error.message}`);
14370
+ }
14222
14371
  this.emit("error", { operation: "insert", error: error.message, resource: resource.name });
14223
14372
  }
14224
14373
  });
14225
14374
  resource.on("update", async (data, beforeData) => {
14226
- try {
14375
+ const [ok, error] = await try_fn_default(async () => {
14227
14376
  const completeData = { ...data, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
14228
14377
  await plugin.processReplicatorEvent("update", resource.name, completeData.id, completeData, beforeData);
14229
- } catch (error) {
14378
+ });
14379
+ if (!ok) {
14380
+ if (this.config.verbose) {
14381
+ console.warn(`[ReplicatorPlugin] Update event failed for resource ${resource.name}: ${error.message}`);
14382
+ }
14230
14383
  this.emit("error", { operation: "update", error: error.message, resource: resource.name });
14231
14384
  }
14232
14385
  });
14233
14386
  resource.on("delete", async (data) => {
14234
- try {
14387
+ const [ok, error] = await try_fn_default(async () => {
14235
14388
  await plugin.processReplicatorEvent("delete", resource.name, data.id, data);
14236
- } catch (error) {
14389
+ });
14390
+ if (!ok) {
14391
+ if (this.config.verbose) {
14392
+ console.warn(`[ReplicatorPlugin] Delete event failed for resource ${resource.name}: ${error.message}`);
14393
+ }
14237
14394
  this.emit("error", { operation: "delete", error: error.message, resource: resource.name });
14238
14395
  }
14239
14396
  });
@@ -14249,13 +14406,17 @@ class ReplicatorPlugin extends plugin_class_default {
14249
14406
  }
14250
14407
  async setup(database) {
14251
14408
  this.database = database;
14252
- try {
14409
+ const [initOk, initError] = await try_fn_default(async () => {
14253
14410
  await this.initializeReplicators(database);
14254
- } catch (error) {
14255
- this.emit("error", { operation: "setup", error: error.message });
14256
- throw error;
14411
+ });
14412
+ if (!initOk) {
14413
+ if (this.config.verbose) {
14414
+ console.warn(`[ReplicatorPlugin] Replicator initialization failed: ${initError.message}`);
14415
+ }
14416
+ this.emit("error", { operation: "setup", error: initError.message });
14417
+ throw initError;
14257
14418
  }
14258
- try {
14419
+ const [logOk, logError] = await try_fn_default(async () => {
14259
14420
  if (this.config.replicatorLogResource) {
14260
14421
  const logRes = await database.createResource({
14261
14422
  name: this.config.replicatorLogResource,
@@ -14272,7 +14433,15 @@ class ReplicatorPlugin extends plugin_class_default {
14272
14433
  }
14273
14434
  });
14274
14435
  }
14275
- } catch (error) {
14436
+ });
14437
+ if (!logOk) {
14438
+ if (this.config.verbose) {
14439
+ console.warn(`[ReplicatorPlugin] Failed to create log resource ${this.config.replicatorLogResource}: ${logError.message}`);
14440
+ }
14441
+ this.emit("replicator_log_resource_creation_error", {
14442
+ resourceName: this.config.replicatorLogResource,
14443
+ error: logError.message
14444
+ });
14276
14445
  }
14277
14446
  await this.uploadMetadataFile(database);
14278
14447
  const originalCreateResource = database.createResource.bind(database);
@@ -14307,49 +14476,36 @@ class ReplicatorPlugin extends plugin_class_default {
14307
14476
  }
14308
14477
  async stop() {
14309
14478
  }
14310
- filterInternalFields(data) {
14311
- if (!data || typeof data !== "object") return data;
14312
- const filtered = {};
14313
- for (const [key, value] of Object.entries(data)) {
14314
- if (!key.startsWith("_") && !key.startsWith("$")) {
14315
- filtered[key] = value;
14316
- }
14317
- }
14318
- return filtered;
14319
- }
14320
14479
  async uploadMetadataFile(database) {
14321
14480
  if (typeof database.uploadMetadataFile === "function") {
14322
14481
  await database.uploadMetadataFile();
14323
14482
  }
14324
14483
  }
14325
- async getCompleteData(resource, data) {
14326
- try {
14327
- const [ok, err, record] = await try_fn_default(() => resource.get(data.id));
14328
- if (ok && record) {
14329
- return record;
14330
- }
14331
- } catch (error) {
14332
- }
14333
- return data;
14334
- }
14335
14484
  async retryWithBackoff(operation, maxRetries = 3) {
14336
14485
  let lastError;
14337
14486
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
14338
- try {
14339
- return await operation();
14340
- } catch (error) {
14487
+ const [ok, error] = await try_fn_default(operation);
14488
+ if (ok) {
14489
+ return ok;
14490
+ } else {
14341
14491
  lastError = error;
14492
+ if (this.config.verbose) {
14493
+ console.warn(`[ReplicatorPlugin] Retry attempt ${attempt}/${maxRetries} failed: ${error.message}`);
14494
+ }
14342
14495
  if (attempt === maxRetries) {
14343
14496
  throw error;
14344
14497
  }
14345
14498
  const delay = Math.pow(2, attempt - 1) * 1e3;
14499
+ if (this.config.verbose) {
14500
+ console.warn(`[ReplicatorPlugin] Waiting ${delay}ms before retry...`);
14501
+ }
14346
14502
  await new Promise((resolve) => setTimeout(resolve, delay));
14347
14503
  }
14348
14504
  }
14349
14505
  throw lastError;
14350
14506
  }
14351
14507
  async logError(replicator, resourceName, operation, recordId, data, error) {
14352
- try {
14508
+ const [ok, logError] = await try_fn_default(async () => {
14353
14509
  const logResourceName = this.config.replicatorLogResource;
14354
14510
  if (this.database && this.database.resources && this.database.resources[logResourceName]) {
14355
14511
  const logResource = this.database.resources[logResourceName];
@@ -14364,7 +14520,19 @@ class ReplicatorPlugin extends plugin_class_default {
14364
14520
  status: "error"
14365
14521
  });
14366
14522
  }
14367
- } catch (logError) {
14523
+ });
14524
+ if (!ok) {
14525
+ if (this.config.verbose) {
14526
+ console.warn(`[ReplicatorPlugin] Failed to log error for ${resourceName}: ${logError.message}`);
14527
+ }
14528
+ this.emit("replicator_log_error", {
14529
+ replicator: replicator.name || replicator.id,
14530
+ resourceName,
14531
+ operation,
14532
+ recordId,
14533
+ originalError: error.message,
14534
+ logError: logError.message
14535
+ });
14368
14536
  }
14369
14537
  }
14370
14538
  async processReplicatorEvent(operation, resourceName, recordId, data, beforeData = null) {
@@ -14377,8 +14545,8 @@ class ReplicatorPlugin extends plugin_class_default {
14377
14545
  return;
14378
14546
  }
14379
14547
  const promises = applicableReplicators.map(async (replicator) => {
14380
- try {
14381
- const result = await this.retryWithBackoff(
14548
+ const [ok, error, result] = await try_fn_default(async () => {
14549
+ const result2 = await this.retryWithBackoff(
14382
14550
  () => replicator.replicate(resourceName, operation, data, recordId, beforeData),
14383
14551
  this.config.maxRetries
14384
14552
  );
@@ -14387,11 +14555,17 @@ class ReplicatorPlugin extends plugin_class_default {
14387
14555
  resourceName,
14388
14556
  operation,
14389
14557
  recordId,
14390
- result,
14558
+ result: result2,
14391
14559
  success: true
14392
14560
  });
14561
+ return result2;
14562
+ });
14563
+ if (ok) {
14393
14564
  return result;
14394
- } catch (error) {
14565
+ } else {
14566
+ if (this.config.verbose) {
14567
+ console.warn(`[ReplicatorPlugin] Replication failed for ${replicator.name || replicator.id} on ${resourceName}: ${error.message}`);
14568
+ }
14395
14569
  this.emit("replicator_error", {
14396
14570
  replicator: replicator.name || replicator.id,
14397
14571
  resourceName,
@@ -14416,11 +14590,14 @@ class ReplicatorPlugin extends plugin_class_default {
14416
14590
  return;
14417
14591
  }
14418
14592
  const promises = applicableReplicators.map(async (replicator) => {
14419
- try {
14593
+ const [wrapperOk, wrapperError] = await try_fn_default(async () => {
14420
14594
  const [ok, err, result] = await try_fn_default(
14421
14595
  () => replicator.replicate(item.resourceName, item.operation, item.data, item.recordId, item.beforeData)
14422
14596
  );
14423
14597
  if (!ok) {
14598
+ if (this.config.verbose) {
14599
+ console.warn(`[ReplicatorPlugin] Replicator item processing failed for ${replicator.name || replicator.id} on ${item.resourceName}: ${err.message}`);
14600
+ }
14424
14601
  this.emit("replicator_error", {
14425
14602
  replicator: replicator.name || replicator.id,
14426
14603
  resourceName: item.resourceName,
@@ -14442,18 +14619,24 @@ class ReplicatorPlugin extends plugin_class_default {
14442
14619
  success: true
14443
14620
  });
14444
14621
  return { success: true, result };
14445
- } catch (error) {
14622
+ });
14623
+ if (wrapperOk) {
14624
+ return wrapperOk;
14625
+ } else {
14626
+ if (this.config.verbose) {
14627
+ console.warn(`[ReplicatorPlugin] Wrapper processing failed for ${replicator.name || replicator.id} on ${item.resourceName}: ${wrapperError.message}`);
14628
+ }
14446
14629
  this.emit("replicator_error", {
14447
14630
  replicator: replicator.name || replicator.id,
14448
14631
  resourceName: item.resourceName,
14449
14632
  operation: item.operation,
14450
14633
  recordId: item.recordId,
14451
- error: error.message
14634
+ error: wrapperError.message
14452
14635
  });
14453
14636
  if (this.config.logErrors && this.database) {
14454
- await this.logError(replicator, item.resourceName, item.operation, item.recordId, item.data, error);
14637
+ await this.logError(replicator, item.resourceName, item.operation, item.recordId, item.data, wrapperError);
14455
14638
  }
14456
- return { success: false, error: error.message };
14639
+ return { success: false, error: wrapperError.message };
14457
14640
  }
14458
14641
  });
14459
14642
  return Promise.allSettled(promises);
@@ -14475,9 +14658,13 @@ class ReplicatorPlugin extends plugin_class_default {
14475
14658
  timestamp: typeof item.timestamp === "number" ? item.timestamp : Date.now(),
14476
14659
  createdAt: item.createdAt || (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)
14477
14660
  };
14478
- try {
14661
+ const [ok, err] = await try_fn_default(async () => {
14479
14662
  await logRes.insert(logItem);
14480
- } catch (err) {
14663
+ });
14664
+ if (!ok) {
14665
+ if (this.config.verbose) {
14666
+ console.warn(`[ReplicatorPlugin] Failed to log replicator item: ${err.message}`);
14667
+ }
14481
14668
  this.emit("replicator.log.failed", { error: err, item });
14482
14669
  }
14483
14670
  }
@@ -14583,14 +14770,23 @@ class ReplicatorPlugin extends plugin_class_default {
14583
14770
  this.emit("replicator.sync.completed", { replicatorId, stats: this.stats });
14584
14771
  }
14585
14772
  async cleanup() {
14586
- try {
14773
+ const [ok, error] = await try_fn_default(async () => {
14587
14774
  if (this.replicators && this.replicators.length > 0) {
14588
14775
  const cleanupPromises = this.replicators.map(async (replicator) => {
14589
- try {
14776
+ const [replicatorOk, replicatorError] = await try_fn_default(async () => {
14590
14777
  if (replicator && typeof replicator.cleanup === "function") {
14591
14778
  await replicator.cleanup();
14592
14779
  }
14593
- } catch (error) {
14780
+ });
14781
+ if (!replicatorOk) {
14782
+ if (this.config.verbose) {
14783
+ console.warn(`[ReplicatorPlugin] Failed to cleanup replicator ${replicator.name || replicator.id}: ${replicatorError.message}`);
14784
+ }
14785
+ this.emit("replicator_cleanup_error", {
14786
+ replicator: replicator.name || replicator.id || "unknown",
14787
+ driver: replicator.driver || "unknown",
14788
+ error: replicatorError.message
14789
+ });
14594
14790
  }
14595
14791
  });
14596
14792
  await Promise.allSettled(cleanupPromises);
@@ -14599,7 +14795,14 @@ class ReplicatorPlugin extends plugin_class_default {
14599
14795
  this.database = null;
14600
14796
  this.eventListenersInstalled.clear();
14601
14797
  this.removeAllListeners();
14602
- } catch (error) {
14798
+ });
14799
+ if (!ok) {
14800
+ if (this.config.verbose) {
14801
+ console.warn(`[ReplicatorPlugin] Failed to cleanup plugin: ${error.message}`);
14802
+ }
14803
+ this.emit("replicator_plugin_cleanup_error", {
14804
+ error: error.message
14805
+ });
14603
14806
  }
14604
14807
  }
14605
14808
  }