s3db.js 7.3.6 → 7.3.9
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 +117 -31
- package/dist/s3db.cjs.min.js +1 -1
- package/dist/s3db.es.js +117 -31
- package/dist/s3db.es.min.js +1 -1
- package/dist/s3db.iife.js +117 -31
- package/dist/s3db.iife.min.js +1 -1
- package/package.json +1 -1
- package/src/plugins/replicators/bigquery-replicator.class.js +106 -52
- package/src/plugins/replicators/postgres-replicator.class.js +34 -4
- package/src/plugins/replicators/s3db-replicator.class.js +34 -11
- package/src/plugins/replicators/sqs-replicator.class.js +28 -5
package/dist/s3db.es.js
CHANGED
|
@@ -8992,11 +8992,21 @@ class BigqueryReplicator extends base_replicator_class_default {
|
|
|
8992
8992
|
}));
|
|
8993
8993
|
}
|
|
8994
8994
|
applyTransform(data, transformFn) {
|
|
8995
|
-
|
|
8996
|
-
|
|
8997
|
-
|
|
8995
|
+
let cleanData = this._cleanInternalFields(data);
|
|
8996
|
+
if (!transformFn) return cleanData;
|
|
8997
|
+
let transformedData = JSON.parse(JSON.stringify(cleanData));
|
|
8998
8998
|
return transformFn(transformedData);
|
|
8999
8999
|
}
|
|
9000
|
+
_cleanInternalFields(data) {
|
|
9001
|
+
if (!data || typeof data !== "object") return data;
|
|
9002
|
+
const cleanData = { ...data };
|
|
9003
|
+
Object.keys(cleanData).forEach((key) => {
|
|
9004
|
+
if (key.startsWith("$") || key.startsWith("_")) {
|
|
9005
|
+
delete cleanData[key];
|
|
9006
|
+
}
|
|
9007
|
+
});
|
|
9008
|
+
return cleanData;
|
|
9009
|
+
}
|
|
9000
9010
|
async replicate(resourceName, operation, data, id, beforeData = null) {
|
|
9001
9011
|
if (!this.enabled || !this.shouldReplicateResource(resourceName)) {
|
|
9002
9012
|
return { skipped: true, reason: "resource_not_included" };
|
|
@@ -9018,7 +9028,17 @@ class BigqueryReplicator extends base_replicator_class_default {
|
|
|
9018
9028
|
let job;
|
|
9019
9029
|
if (operation === "insert") {
|
|
9020
9030
|
const transformedData = this.applyTransform(data, tableConfig.transform);
|
|
9021
|
-
|
|
9031
|
+
try {
|
|
9032
|
+
job = await table.insert([transformedData]);
|
|
9033
|
+
} catch (error) {
|
|
9034
|
+
const { errors: errors2, response } = error;
|
|
9035
|
+
if (this.config.verbose) {
|
|
9036
|
+
console.error("[BigqueryReplicator] BigQuery insert error details:");
|
|
9037
|
+
if (errors2) console.error("Errors:", JSON.stringify(errors2, null, 2));
|
|
9038
|
+
if (response) console.error("Response:", JSON.stringify(response, null, 2));
|
|
9039
|
+
}
|
|
9040
|
+
throw error;
|
|
9041
|
+
}
|
|
9022
9042
|
} else if (operation === "update") {
|
|
9023
9043
|
const transformedData = this.applyTransform(data, tableConfig.transform);
|
|
9024
9044
|
const keys = Object.keys(transformedData).filter((k) => k !== "id");
|
|
@@ -9044,6 +9064,10 @@ class BigqueryReplicator extends base_replicator_class_default {
|
|
|
9044
9064
|
lastError = error;
|
|
9045
9065
|
if (this.config.verbose) {
|
|
9046
9066
|
console.warn(`[BigqueryReplicator] Update attempt ${attempt} failed: ${error.message}`);
|
|
9067
|
+
if (error.errors) {
|
|
9068
|
+
console.error("[BigqueryReplicator] BigQuery update error details:");
|
|
9069
|
+
console.error("Errors:", JSON.stringify(error.errors, null, 2));
|
|
9070
|
+
}
|
|
9047
9071
|
}
|
|
9048
9072
|
if (error?.message?.includes("streaming buffer") && attempt < maxRetries) {
|
|
9049
9073
|
const delaySeconds = 30;
|
|
@@ -9059,13 +9083,23 @@ class BigqueryReplicator extends base_replicator_class_default {
|
|
|
9059
9083
|
if (!job) throw lastError;
|
|
9060
9084
|
} else if (operation === "delete") {
|
|
9061
9085
|
const query = `DELETE FROM \`${this.projectId}.${this.datasetId}.${tableConfig.table}\` WHERE id = @id`;
|
|
9062
|
-
|
|
9063
|
-
|
|
9064
|
-
|
|
9065
|
-
|
|
9066
|
-
|
|
9067
|
-
|
|
9068
|
-
|
|
9086
|
+
try {
|
|
9087
|
+
const [deleteJob] = await this.bigqueryClient.createQueryJob({
|
|
9088
|
+
query,
|
|
9089
|
+
params: { id },
|
|
9090
|
+
location: this.location
|
|
9091
|
+
});
|
|
9092
|
+
await deleteJob.getQueryResults();
|
|
9093
|
+
job = [deleteJob];
|
|
9094
|
+
} catch (error) {
|
|
9095
|
+
if (this.config.verbose) {
|
|
9096
|
+
console.error("[BigqueryReplicator] BigQuery delete error details:");
|
|
9097
|
+
console.error("Query:", query);
|
|
9098
|
+
if (error.errors) console.error("Errors:", JSON.stringify(error.errors, null, 2));
|
|
9099
|
+
if (error.response) console.error("Response:", JSON.stringify(error.response, null, 2));
|
|
9100
|
+
}
|
|
9101
|
+
throw error;
|
|
9102
|
+
}
|
|
9069
9103
|
} else {
|
|
9070
9104
|
throw new Error(`Unsupported operation: ${operation}`);
|
|
9071
9105
|
}
|
|
@@ -9098,6 +9132,9 @@ class BigqueryReplicator extends base_replicator_class_default {
|
|
|
9098
9132
|
}
|
|
9099
9133
|
}
|
|
9100
9134
|
const success = errors.length === 0;
|
|
9135
|
+
if (errors.length > 0) {
|
|
9136
|
+
console.warn(`[BigqueryReplicator] Replication completed with errors for ${resourceName}:`, errors);
|
|
9137
|
+
}
|
|
9101
9138
|
this.emit("replicated", {
|
|
9102
9139
|
replicator: this.name,
|
|
9103
9140
|
resourceName,
|
|
@@ -9148,6 +9185,9 @@ class BigqueryReplicator extends base_replicator_class_default {
|
|
|
9148
9185
|
errors.push({ id: record.id, error: err.message });
|
|
9149
9186
|
}
|
|
9150
9187
|
}
|
|
9188
|
+
if (errors.length > 0) {
|
|
9189
|
+
console.warn(`[BigqueryReplicator] Batch replication completed with ${errors.length} error(s) for ${resourceName}:`, errors);
|
|
9190
|
+
}
|
|
9151
9191
|
return {
|
|
9152
9192
|
success: errors.length === 0,
|
|
9153
9193
|
results,
|
|
@@ -9334,16 +9374,18 @@ class PostgresReplicator extends base_replicator_class_default {
|
|
|
9334
9374
|
const [okTable, errTable] = await try_fn_default(async () => {
|
|
9335
9375
|
let result2;
|
|
9336
9376
|
if (operation === "insert") {
|
|
9337
|
-
const
|
|
9338
|
-
const
|
|
9377
|
+
const cleanData = this._cleanInternalFields(data);
|
|
9378
|
+
const keys = Object.keys(cleanData);
|
|
9379
|
+
const values = keys.map((k) => cleanData[k]);
|
|
9339
9380
|
const columns = keys.map((k) => `"${k}"`).join(", ");
|
|
9340
9381
|
const params = keys.map((_, i) => `$${i + 1}`).join(", ");
|
|
9341
9382
|
const sql = `INSERT INTO ${table} (${columns}) VALUES (${params}) ON CONFLICT (id) DO NOTHING RETURNING *`;
|
|
9342
9383
|
result2 = await this.client.query(sql, values);
|
|
9343
9384
|
} else if (operation === "update") {
|
|
9344
|
-
const
|
|
9385
|
+
const cleanData = this._cleanInternalFields(data);
|
|
9386
|
+
const keys = Object.keys(cleanData).filter((k) => k !== "id");
|
|
9345
9387
|
const setClause = keys.map((k, i) => `"${k}"=$${i + 1}`).join(", ");
|
|
9346
|
-
const values = keys.map((k) =>
|
|
9388
|
+
const values = keys.map((k) => cleanData[k]);
|
|
9347
9389
|
values.push(id);
|
|
9348
9390
|
const sql = `UPDATE ${table} SET ${setClause} WHERE id=$${keys.length + 1} RETURNING *`;
|
|
9349
9391
|
result2 = await this.client.query(sql, values);
|
|
@@ -9378,6 +9420,9 @@ class PostgresReplicator extends base_replicator_class_default {
|
|
|
9378
9420
|
}
|
|
9379
9421
|
}
|
|
9380
9422
|
const success = errors.length === 0;
|
|
9423
|
+
if (errors.length > 0) {
|
|
9424
|
+
console.warn(`[PostgresReplicator] Replication completed with errors for ${resourceName}:`, errors);
|
|
9425
|
+
}
|
|
9381
9426
|
this.emit("replicated", {
|
|
9382
9427
|
replicator: this.name,
|
|
9383
9428
|
resourceName,
|
|
@@ -9428,6 +9473,9 @@ class PostgresReplicator extends base_replicator_class_default {
|
|
|
9428
9473
|
errors.push({ id: record.id, error: err.message });
|
|
9429
9474
|
}
|
|
9430
9475
|
}
|
|
9476
|
+
if (errors.length > 0) {
|
|
9477
|
+
console.warn(`[PostgresReplicator] Batch replication completed with ${errors.length} error(s) for ${resourceName}:`, errors);
|
|
9478
|
+
}
|
|
9431
9479
|
return {
|
|
9432
9480
|
success: errors.length === 0,
|
|
9433
9481
|
results,
|
|
@@ -9447,6 +9495,16 @@ class PostgresReplicator extends base_replicator_class_default {
|
|
|
9447
9495
|
this.emit("connection_error", { replicator: this.name, error: err.message });
|
|
9448
9496
|
return false;
|
|
9449
9497
|
}
|
|
9498
|
+
_cleanInternalFields(data) {
|
|
9499
|
+
if (!data || typeof data !== "object") return data;
|
|
9500
|
+
const cleanData = { ...data };
|
|
9501
|
+
Object.keys(cleanData).forEach((key) => {
|
|
9502
|
+
if (key.startsWith("$") || key.startsWith("_")) {
|
|
9503
|
+
delete cleanData[key];
|
|
9504
|
+
}
|
|
9505
|
+
});
|
|
9506
|
+
return cleanData;
|
|
9507
|
+
}
|
|
9450
9508
|
async cleanup() {
|
|
9451
9509
|
if (this.client) await this.client.end();
|
|
9452
9510
|
}
|
|
@@ -13178,7 +13236,7 @@ class Database extends EventEmitter {
|
|
|
13178
13236
|
super();
|
|
13179
13237
|
this.version = "1";
|
|
13180
13238
|
this.s3dbVersion = (() => {
|
|
13181
|
-
const [ok, err, version] = try_fn_default(() => true ? "7.3.
|
|
13239
|
+
const [ok, err, version] = try_fn_default(() => true ? "7.3.8" : "latest");
|
|
13182
13240
|
return ok ? version : "latest";
|
|
13183
13241
|
})();
|
|
13184
13242
|
this.resources = {};
|
|
@@ -13842,36 +13900,47 @@ class S3dbReplicator extends base_replicator_class_default {
|
|
|
13842
13900
|
return result;
|
|
13843
13901
|
}
|
|
13844
13902
|
_applyTransformer(resource, data) {
|
|
13903
|
+
let cleanData = this._cleanInternalFields(data);
|
|
13845
13904
|
const normResource = normalizeResourceName$1(resource);
|
|
13846
13905
|
const entry = this.resourcesMap[normResource];
|
|
13847
13906
|
let result;
|
|
13848
|
-
if (!entry) return
|
|
13907
|
+
if (!entry) return cleanData;
|
|
13849
13908
|
if (Array.isArray(entry)) {
|
|
13850
13909
|
for (const item of entry) {
|
|
13851
13910
|
if (typeof item === "object" && item.transform && typeof item.transform === "function") {
|
|
13852
|
-
result = item.transform(
|
|
13911
|
+
result = item.transform(cleanData);
|
|
13853
13912
|
break;
|
|
13854
13913
|
} else if (typeof item === "object" && item.transformer && typeof item.transformer === "function") {
|
|
13855
|
-
result = item.transformer(
|
|
13914
|
+
result = item.transformer(cleanData);
|
|
13856
13915
|
break;
|
|
13857
13916
|
}
|
|
13858
13917
|
}
|
|
13859
|
-
if (!result) result =
|
|
13918
|
+
if (!result) result = cleanData;
|
|
13860
13919
|
} else if (typeof entry === "object") {
|
|
13861
13920
|
if (typeof entry.transform === "function") {
|
|
13862
|
-
result = entry.transform(
|
|
13921
|
+
result = entry.transform(cleanData);
|
|
13863
13922
|
} else if (typeof entry.transformer === "function") {
|
|
13864
|
-
result = entry.transformer(
|
|
13923
|
+
result = entry.transformer(cleanData);
|
|
13865
13924
|
}
|
|
13866
13925
|
} else if (typeof entry === "function") {
|
|
13867
|
-
result = entry(
|
|
13926
|
+
result = entry(cleanData);
|
|
13868
13927
|
} else {
|
|
13869
|
-
result =
|
|
13928
|
+
result = cleanData;
|
|
13870
13929
|
}
|
|
13871
|
-
if (result &&
|
|
13872
|
-
if (!result &&
|
|
13930
|
+
if (result && cleanData && cleanData.id && !result.id) result.id = cleanData.id;
|
|
13931
|
+
if (!result && cleanData) result = cleanData;
|
|
13873
13932
|
return result;
|
|
13874
13933
|
}
|
|
13934
|
+
_cleanInternalFields(data) {
|
|
13935
|
+
if (!data || typeof data !== "object") return data;
|
|
13936
|
+
const cleanData = { ...data };
|
|
13937
|
+
Object.keys(cleanData).forEach((key) => {
|
|
13938
|
+
if (key.startsWith("$") || key.startsWith("_")) {
|
|
13939
|
+
delete cleanData[key];
|
|
13940
|
+
}
|
|
13941
|
+
});
|
|
13942
|
+
return cleanData;
|
|
13943
|
+
}
|
|
13875
13944
|
_resolveDestResource(resource, data) {
|
|
13876
13945
|
const normResource = normalizeResourceName$1(resource);
|
|
13877
13946
|
const entry = this.resourcesMap[normResource];
|
|
@@ -13920,6 +13989,9 @@ class S3dbReplicator extends base_replicator_class_default {
|
|
|
13920
13989
|
errors.push({ id: record.id, error: err.message });
|
|
13921
13990
|
}
|
|
13922
13991
|
}
|
|
13992
|
+
if (errors.length > 0) {
|
|
13993
|
+
console.warn(`[S3dbReplicator] Batch replication completed with ${errors.length} error(s) for ${resourceName}:`, errors);
|
|
13994
|
+
}
|
|
13923
13995
|
this.emit("batch_replicated", {
|
|
13924
13996
|
replicator: this.name,
|
|
13925
13997
|
resourceName,
|
|
@@ -14058,15 +14130,26 @@ class SqsReplicator extends base_replicator_class_default {
|
|
|
14058
14130
|
throw new Error(`No queue URL found for resource '${resource}'`);
|
|
14059
14131
|
}
|
|
14060
14132
|
_applyTransformer(resource, data) {
|
|
14133
|
+
let cleanData = this._cleanInternalFields(data);
|
|
14061
14134
|
const entry = this.resources[resource];
|
|
14062
|
-
let result =
|
|
14063
|
-
if (!entry) return
|
|
14135
|
+
let result = cleanData;
|
|
14136
|
+
if (!entry) return cleanData;
|
|
14064
14137
|
if (typeof entry.transform === "function") {
|
|
14065
|
-
result = entry.transform(
|
|
14138
|
+
result = entry.transform(cleanData);
|
|
14066
14139
|
} else if (typeof entry.transformer === "function") {
|
|
14067
|
-
result = entry.transformer(
|
|
14140
|
+
result = entry.transformer(cleanData);
|
|
14068
14141
|
}
|
|
14069
|
-
return result ||
|
|
14142
|
+
return result || cleanData;
|
|
14143
|
+
}
|
|
14144
|
+
_cleanInternalFields(data) {
|
|
14145
|
+
if (!data || typeof data !== "object") return data;
|
|
14146
|
+
const cleanData = { ...data };
|
|
14147
|
+
Object.keys(cleanData).forEach((key) => {
|
|
14148
|
+
if (key.startsWith("$") || key.startsWith("_")) {
|
|
14149
|
+
delete cleanData[key];
|
|
14150
|
+
}
|
|
14151
|
+
});
|
|
14152
|
+
return cleanData;
|
|
14070
14153
|
}
|
|
14071
14154
|
/**
|
|
14072
14155
|
* Create standardized message structure
|
|
@@ -14217,6 +14300,9 @@ class SqsReplicator extends base_replicator_class_default {
|
|
|
14217
14300
|
}
|
|
14218
14301
|
}
|
|
14219
14302
|
}
|
|
14303
|
+
if (errors.length > 0) {
|
|
14304
|
+
console.warn(`[SqsReplicator] Batch replication completed with ${errors.length} error(s) for ${resource}:`, errors);
|
|
14305
|
+
}
|
|
14220
14306
|
this.emit("batch_replicated", {
|
|
14221
14307
|
replicator: this.name,
|
|
14222
14308
|
resource,
|