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.cjs.js
CHANGED
|
@@ -8996,11 +8996,21 @@ class BigqueryReplicator extends base_replicator_class_default {
|
|
|
8996
8996
|
}));
|
|
8997
8997
|
}
|
|
8998
8998
|
applyTransform(data, transformFn) {
|
|
8999
|
-
|
|
9000
|
-
|
|
9001
|
-
|
|
8999
|
+
let cleanData = this._cleanInternalFields(data);
|
|
9000
|
+
if (!transformFn) return cleanData;
|
|
9001
|
+
let transformedData = JSON.parse(JSON.stringify(cleanData));
|
|
9002
9002
|
return transformFn(transformedData);
|
|
9003
9003
|
}
|
|
9004
|
+
_cleanInternalFields(data) {
|
|
9005
|
+
if (!data || typeof data !== "object") return data;
|
|
9006
|
+
const cleanData = { ...data };
|
|
9007
|
+
Object.keys(cleanData).forEach((key) => {
|
|
9008
|
+
if (key.startsWith("$") || key.startsWith("_")) {
|
|
9009
|
+
delete cleanData[key];
|
|
9010
|
+
}
|
|
9011
|
+
});
|
|
9012
|
+
return cleanData;
|
|
9013
|
+
}
|
|
9004
9014
|
async replicate(resourceName, operation, data, id, beforeData = null) {
|
|
9005
9015
|
if (!this.enabled || !this.shouldReplicateResource(resourceName)) {
|
|
9006
9016
|
return { skipped: true, reason: "resource_not_included" };
|
|
@@ -9022,7 +9032,17 @@ class BigqueryReplicator extends base_replicator_class_default {
|
|
|
9022
9032
|
let job;
|
|
9023
9033
|
if (operation === "insert") {
|
|
9024
9034
|
const transformedData = this.applyTransform(data, tableConfig.transform);
|
|
9025
|
-
|
|
9035
|
+
try {
|
|
9036
|
+
job = await table.insert([transformedData]);
|
|
9037
|
+
} catch (error) {
|
|
9038
|
+
const { errors: errors2, response } = error;
|
|
9039
|
+
if (this.config.verbose) {
|
|
9040
|
+
console.error("[BigqueryReplicator] BigQuery insert error details:");
|
|
9041
|
+
if (errors2) console.error("Errors:", JSON.stringify(errors2, null, 2));
|
|
9042
|
+
if (response) console.error("Response:", JSON.stringify(response, null, 2));
|
|
9043
|
+
}
|
|
9044
|
+
throw error;
|
|
9045
|
+
}
|
|
9026
9046
|
} else if (operation === "update") {
|
|
9027
9047
|
const transformedData = this.applyTransform(data, tableConfig.transform);
|
|
9028
9048
|
const keys = Object.keys(transformedData).filter((k) => k !== "id");
|
|
@@ -9048,6 +9068,10 @@ class BigqueryReplicator extends base_replicator_class_default {
|
|
|
9048
9068
|
lastError = error;
|
|
9049
9069
|
if (this.config.verbose) {
|
|
9050
9070
|
console.warn(`[BigqueryReplicator] Update attempt ${attempt} failed: ${error.message}`);
|
|
9071
|
+
if (error.errors) {
|
|
9072
|
+
console.error("[BigqueryReplicator] BigQuery update error details:");
|
|
9073
|
+
console.error("Errors:", JSON.stringify(error.errors, null, 2));
|
|
9074
|
+
}
|
|
9051
9075
|
}
|
|
9052
9076
|
if (error?.message?.includes("streaming buffer") && attempt < maxRetries) {
|
|
9053
9077
|
const delaySeconds = 30;
|
|
@@ -9063,13 +9087,23 @@ class BigqueryReplicator extends base_replicator_class_default {
|
|
|
9063
9087
|
if (!job) throw lastError;
|
|
9064
9088
|
} else if (operation === "delete") {
|
|
9065
9089
|
const query = `DELETE FROM \`${this.projectId}.${this.datasetId}.${tableConfig.table}\` WHERE id = @id`;
|
|
9066
|
-
|
|
9067
|
-
|
|
9068
|
-
|
|
9069
|
-
|
|
9070
|
-
|
|
9071
|
-
|
|
9072
|
-
|
|
9090
|
+
try {
|
|
9091
|
+
const [deleteJob] = await this.bigqueryClient.createQueryJob({
|
|
9092
|
+
query,
|
|
9093
|
+
params: { id },
|
|
9094
|
+
location: this.location
|
|
9095
|
+
});
|
|
9096
|
+
await deleteJob.getQueryResults();
|
|
9097
|
+
job = [deleteJob];
|
|
9098
|
+
} catch (error) {
|
|
9099
|
+
if (this.config.verbose) {
|
|
9100
|
+
console.error("[BigqueryReplicator] BigQuery delete error details:");
|
|
9101
|
+
console.error("Query:", query);
|
|
9102
|
+
if (error.errors) console.error("Errors:", JSON.stringify(error.errors, null, 2));
|
|
9103
|
+
if (error.response) console.error("Response:", JSON.stringify(error.response, null, 2));
|
|
9104
|
+
}
|
|
9105
|
+
throw error;
|
|
9106
|
+
}
|
|
9073
9107
|
} else {
|
|
9074
9108
|
throw new Error(`Unsupported operation: ${operation}`);
|
|
9075
9109
|
}
|
|
@@ -9102,6 +9136,9 @@ class BigqueryReplicator extends base_replicator_class_default {
|
|
|
9102
9136
|
}
|
|
9103
9137
|
}
|
|
9104
9138
|
const success = errors.length === 0;
|
|
9139
|
+
if (errors.length > 0) {
|
|
9140
|
+
console.warn(`[BigqueryReplicator] Replication completed with errors for ${resourceName}:`, errors);
|
|
9141
|
+
}
|
|
9105
9142
|
this.emit("replicated", {
|
|
9106
9143
|
replicator: this.name,
|
|
9107
9144
|
resourceName,
|
|
@@ -9152,6 +9189,9 @@ class BigqueryReplicator extends base_replicator_class_default {
|
|
|
9152
9189
|
errors.push({ id: record.id, error: err.message });
|
|
9153
9190
|
}
|
|
9154
9191
|
}
|
|
9192
|
+
if (errors.length > 0) {
|
|
9193
|
+
console.warn(`[BigqueryReplicator] Batch replication completed with ${errors.length} error(s) for ${resourceName}:`, errors);
|
|
9194
|
+
}
|
|
9155
9195
|
return {
|
|
9156
9196
|
success: errors.length === 0,
|
|
9157
9197
|
results,
|
|
@@ -9338,16 +9378,18 @@ class PostgresReplicator extends base_replicator_class_default {
|
|
|
9338
9378
|
const [okTable, errTable] = await try_fn_default(async () => {
|
|
9339
9379
|
let result2;
|
|
9340
9380
|
if (operation === "insert") {
|
|
9341
|
-
const
|
|
9342
|
-
const
|
|
9381
|
+
const cleanData = this._cleanInternalFields(data);
|
|
9382
|
+
const keys = Object.keys(cleanData);
|
|
9383
|
+
const values = keys.map((k) => cleanData[k]);
|
|
9343
9384
|
const columns = keys.map((k) => `"${k}"`).join(", ");
|
|
9344
9385
|
const params = keys.map((_, i) => `$${i + 1}`).join(", ");
|
|
9345
9386
|
const sql = `INSERT INTO ${table} (${columns}) VALUES (${params}) ON CONFLICT (id) DO NOTHING RETURNING *`;
|
|
9346
9387
|
result2 = await this.client.query(sql, values);
|
|
9347
9388
|
} else if (operation === "update") {
|
|
9348
|
-
const
|
|
9389
|
+
const cleanData = this._cleanInternalFields(data);
|
|
9390
|
+
const keys = Object.keys(cleanData).filter((k) => k !== "id");
|
|
9349
9391
|
const setClause = keys.map((k, i) => `"${k}"=$${i + 1}`).join(", ");
|
|
9350
|
-
const values = keys.map((k) =>
|
|
9392
|
+
const values = keys.map((k) => cleanData[k]);
|
|
9351
9393
|
values.push(id);
|
|
9352
9394
|
const sql = `UPDATE ${table} SET ${setClause} WHERE id=$${keys.length + 1} RETURNING *`;
|
|
9353
9395
|
result2 = await this.client.query(sql, values);
|
|
@@ -9382,6 +9424,9 @@ class PostgresReplicator extends base_replicator_class_default {
|
|
|
9382
9424
|
}
|
|
9383
9425
|
}
|
|
9384
9426
|
const success = errors.length === 0;
|
|
9427
|
+
if (errors.length > 0) {
|
|
9428
|
+
console.warn(`[PostgresReplicator] Replication completed with errors for ${resourceName}:`, errors);
|
|
9429
|
+
}
|
|
9385
9430
|
this.emit("replicated", {
|
|
9386
9431
|
replicator: this.name,
|
|
9387
9432
|
resourceName,
|
|
@@ -9432,6 +9477,9 @@ class PostgresReplicator extends base_replicator_class_default {
|
|
|
9432
9477
|
errors.push({ id: record.id, error: err.message });
|
|
9433
9478
|
}
|
|
9434
9479
|
}
|
|
9480
|
+
if (errors.length > 0) {
|
|
9481
|
+
console.warn(`[PostgresReplicator] Batch replication completed with ${errors.length} error(s) for ${resourceName}:`, errors);
|
|
9482
|
+
}
|
|
9435
9483
|
return {
|
|
9436
9484
|
success: errors.length === 0,
|
|
9437
9485
|
results,
|
|
@@ -9451,6 +9499,16 @@ class PostgresReplicator extends base_replicator_class_default {
|
|
|
9451
9499
|
this.emit("connection_error", { replicator: this.name, error: err.message });
|
|
9452
9500
|
return false;
|
|
9453
9501
|
}
|
|
9502
|
+
_cleanInternalFields(data) {
|
|
9503
|
+
if (!data || typeof data !== "object") return data;
|
|
9504
|
+
const cleanData = { ...data };
|
|
9505
|
+
Object.keys(cleanData).forEach((key) => {
|
|
9506
|
+
if (key.startsWith("$") || key.startsWith("_")) {
|
|
9507
|
+
delete cleanData[key];
|
|
9508
|
+
}
|
|
9509
|
+
});
|
|
9510
|
+
return cleanData;
|
|
9511
|
+
}
|
|
9454
9512
|
async cleanup() {
|
|
9455
9513
|
if (this.client) await this.client.end();
|
|
9456
9514
|
}
|
|
@@ -13182,7 +13240,7 @@ class Database extends EventEmitter {
|
|
|
13182
13240
|
super();
|
|
13183
13241
|
this.version = "1";
|
|
13184
13242
|
this.s3dbVersion = (() => {
|
|
13185
|
-
const [ok, err, version] = try_fn_default(() => true ? "7.3.
|
|
13243
|
+
const [ok, err, version] = try_fn_default(() => true ? "7.3.8" : "latest");
|
|
13186
13244
|
return ok ? version : "latest";
|
|
13187
13245
|
})();
|
|
13188
13246
|
this.resources = {};
|
|
@@ -13846,36 +13904,47 @@ class S3dbReplicator extends base_replicator_class_default {
|
|
|
13846
13904
|
return result;
|
|
13847
13905
|
}
|
|
13848
13906
|
_applyTransformer(resource, data) {
|
|
13907
|
+
let cleanData = this._cleanInternalFields(data);
|
|
13849
13908
|
const normResource = normalizeResourceName$1(resource);
|
|
13850
13909
|
const entry = this.resourcesMap[normResource];
|
|
13851
13910
|
let result;
|
|
13852
|
-
if (!entry) return
|
|
13911
|
+
if (!entry) return cleanData;
|
|
13853
13912
|
if (Array.isArray(entry)) {
|
|
13854
13913
|
for (const item of entry) {
|
|
13855
13914
|
if (typeof item === "object" && item.transform && typeof item.transform === "function") {
|
|
13856
|
-
result = item.transform(
|
|
13915
|
+
result = item.transform(cleanData);
|
|
13857
13916
|
break;
|
|
13858
13917
|
} else if (typeof item === "object" && item.transformer && typeof item.transformer === "function") {
|
|
13859
|
-
result = item.transformer(
|
|
13918
|
+
result = item.transformer(cleanData);
|
|
13860
13919
|
break;
|
|
13861
13920
|
}
|
|
13862
13921
|
}
|
|
13863
|
-
if (!result) result =
|
|
13922
|
+
if (!result) result = cleanData;
|
|
13864
13923
|
} else if (typeof entry === "object") {
|
|
13865
13924
|
if (typeof entry.transform === "function") {
|
|
13866
|
-
result = entry.transform(
|
|
13925
|
+
result = entry.transform(cleanData);
|
|
13867
13926
|
} else if (typeof entry.transformer === "function") {
|
|
13868
|
-
result = entry.transformer(
|
|
13927
|
+
result = entry.transformer(cleanData);
|
|
13869
13928
|
}
|
|
13870
13929
|
} else if (typeof entry === "function") {
|
|
13871
|
-
result = entry(
|
|
13930
|
+
result = entry(cleanData);
|
|
13872
13931
|
} else {
|
|
13873
|
-
result =
|
|
13932
|
+
result = cleanData;
|
|
13874
13933
|
}
|
|
13875
|
-
if (result &&
|
|
13876
|
-
if (!result &&
|
|
13934
|
+
if (result && cleanData && cleanData.id && !result.id) result.id = cleanData.id;
|
|
13935
|
+
if (!result && cleanData) result = cleanData;
|
|
13877
13936
|
return result;
|
|
13878
13937
|
}
|
|
13938
|
+
_cleanInternalFields(data) {
|
|
13939
|
+
if (!data || typeof data !== "object") return data;
|
|
13940
|
+
const cleanData = { ...data };
|
|
13941
|
+
Object.keys(cleanData).forEach((key) => {
|
|
13942
|
+
if (key.startsWith("$") || key.startsWith("_")) {
|
|
13943
|
+
delete cleanData[key];
|
|
13944
|
+
}
|
|
13945
|
+
});
|
|
13946
|
+
return cleanData;
|
|
13947
|
+
}
|
|
13879
13948
|
_resolveDestResource(resource, data) {
|
|
13880
13949
|
const normResource = normalizeResourceName$1(resource);
|
|
13881
13950
|
const entry = this.resourcesMap[normResource];
|
|
@@ -13924,6 +13993,9 @@ class S3dbReplicator extends base_replicator_class_default {
|
|
|
13924
13993
|
errors.push({ id: record.id, error: err.message });
|
|
13925
13994
|
}
|
|
13926
13995
|
}
|
|
13996
|
+
if (errors.length > 0) {
|
|
13997
|
+
console.warn(`[S3dbReplicator] Batch replication completed with ${errors.length} error(s) for ${resourceName}:`, errors);
|
|
13998
|
+
}
|
|
13927
13999
|
this.emit("batch_replicated", {
|
|
13928
14000
|
replicator: this.name,
|
|
13929
14001
|
resourceName,
|
|
@@ -14062,15 +14134,26 @@ class SqsReplicator extends base_replicator_class_default {
|
|
|
14062
14134
|
throw new Error(`No queue URL found for resource '${resource}'`);
|
|
14063
14135
|
}
|
|
14064
14136
|
_applyTransformer(resource, data) {
|
|
14137
|
+
let cleanData = this._cleanInternalFields(data);
|
|
14065
14138
|
const entry = this.resources[resource];
|
|
14066
|
-
let result =
|
|
14067
|
-
if (!entry) return
|
|
14139
|
+
let result = cleanData;
|
|
14140
|
+
if (!entry) return cleanData;
|
|
14068
14141
|
if (typeof entry.transform === "function") {
|
|
14069
|
-
result = entry.transform(
|
|
14142
|
+
result = entry.transform(cleanData);
|
|
14070
14143
|
} else if (typeof entry.transformer === "function") {
|
|
14071
|
-
result = entry.transformer(
|
|
14144
|
+
result = entry.transformer(cleanData);
|
|
14072
14145
|
}
|
|
14073
|
-
return result ||
|
|
14146
|
+
return result || cleanData;
|
|
14147
|
+
}
|
|
14148
|
+
_cleanInternalFields(data) {
|
|
14149
|
+
if (!data || typeof data !== "object") return data;
|
|
14150
|
+
const cleanData = { ...data };
|
|
14151
|
+
Object.keys(cleanData).forEach((key) => {
|
|
14152
|
+
if (key.startsWith("$") || key.startsWith("_")) {
|
|
14153
|
+
delete cleanData[key];
|
|
14154
|
+
}
|
|
14155
|
+
});
|
|
14156
|
+
return cleanData;
|
|
14074
14157
|
}
|
|
14075
14158
|
/**
|
|
14076
14159
|
* Create standardized message structure
|
|
@@ -14221,6 +14304,9 @@ class SqsReplicator extends base_replicator_class_default {
|
|
|
14221
14304
|
}
|
|
14222
14305
|
}
|
|
14223
14306
|
}
|
|
14307
|
+
if (errors.length > 0) {
|
|
14308
|
+
console.warn(`[SqsReplicator] Batch replication completed with ${errors.length} error(s) for ${resource}:`, errors);
|
|
14309
|
+
}
|
|
14224
14310
|
this.emit("batch_replicated", {
|
|
14225
14311
|
replicator: this.name,
|
|
14226
14312
|
resource,
|