s3db.js 7.1.0 → 7.2.1
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/PLUGINS.md +200 -10
- package/dist/s3db.cjs.js +62 -31
- package/dist/s3db.cjs.min.js +1 -1
- package/dist/s3db.d.ts +14 -15
- package/dist/s3db.es.js +62 -31
- package/dist/s3db.es.min.js +1 -1
- package/dist/s3db.iife.js +62 -31
- package/dist/s3db.iife.min.js +1 -1
- package/package.json +5 -1
- package/src/plugins/replicators/bigquery-replicator.class.js +102 -68
- package/src/plugins/replicators/postgres-replicator.class.js +19 -109
- package/src/plugins/replicators/s3db-replicator.class.js +21 -49
- package/src/plugins/replicators/sqs-replicator.class.js +17 -116
- package/src/s3db.d.ts +14 -15
package/dist/s3db.iife.js
CHANGED
|
@@ -7994,22 +7994,25 @@ ${JSON.stringify(validation, null, 2)}`,
|
|
|
7994
7994
|
if (typeof config === "string") {
|
|
7995
7995
|
parsed[resourceName] = [{
|
|
7996
7996
|
table: config,
|
|
7997
|
-
actions: ["insert"]
|
|
7997
|
+
actions: ["insert"],
|
|
7998
|
+
transform: null
|
|
7998
7999
|
}];
|
|
7999
8000
|
} else if (Array.isArray(config)) {
|
|
8000
8001
|
parsed[resourceName] = config.map((item) => {
|
|
8001
8002
|
if (typeof item === "string") {
|
|
8002
|
-
return { table: item, actions: ["insert"] };
|
|
8003
|
+
return { table: item, actions: ["insert"], transform: null };
|
|
8003
8004
|
}
|
|
8004
8005
|
return {
|
|
8005
8006
|
table: item.table,
|
|
8006
|
-
actions: item.actions || ["insert"]
|
|
8007
|
+
actions: item.actions || ["insert"],
|
|
8008
|
+
transform: item.transform || null
|
|
8007
8009
|
};
|
|
8008
8010
|
});
|
|
8009
8011
|
} else if (typeof config === "object") {
|
|
8010
8012
|
parsed[resourceName] = [{
|
|
8011
8013
|
table: config.table,
|
|
8012
|
-
actions: config.actions || ["insert"]
|
|
8014
|
+
actions: config.actions || ["insert"],
|
|
8015
|
+
transform: config.transform || null
|
|
8013
8016
|
}];
|
|
8014
8017
|
}
|
|
8015
8018
|
}
|
|
@@ -8033,6 +8036,9 @@ ${JSON.stringify(validation, null, 2)}`,
|
|
|
8033
8036
|
if (invalidActions.length > 0) {
|
|
8034
8037
|
errors.push(`Invalid actions for resource '${resourceName}': ${invalidActions.join(", ")}. Valid actions: ${validActions.join(", ")}`);
|
|
8035
8038
|
}
|
|
8039
|
+
if (tableConfig.transform && typeof tableConfig.transform !== "function") {
|
|
8040
|
+
errors.push(`Transform must be a function for resource '${resourceName}'`);
|
|
8041
|
+
}
|
|
8036
8042
|
}
|
|
8037
8043
|
}
|
|
8038
8044
|
return { isValid: errors.length === 0, errors };
|
|
@@ -8068,7 +8074,16 @@ ${JSON.stringify(validation, null, 2)}`,
|
|
|
8068
8074
|
}
|
|
8069
8075
|
getTablesForResource(resourceName, operation) {
|
|
8070
8076
|
if (!this.resources[resourceName]) return [];
|
|
8071
|
-
return this.resources[resourceName].filter((tableConfig) => tableConfig.actions.includes(operation)).map((tableConfig) =>
|
|
8077
|
+
return this.resources[resourceName].filter((tableConfig) => tableConfig.actions.includes(operation)).map((tableConfig) => ({
|
|
8078
|
+
table: tableConfig.table,
|
|
8079
|
+
transform: tableConfig.transform
|
|
8080
|
+
}));
|
|
8081
|
+
}
|
|
8082
|
+
applyTransform(data, transformFn) {
|
|
8083
|
+
if (!transformFn) return data;
|
|
8084
|
+
let transformedData = JSON.parse(JSON.stringify(data));
|
|
8085
|
+
if (transformedData._length) delete transformedData._length;
|
|
8086
|
+
return transformFn(transformedData);
|
|
8072
8087
|
}
|
|
8073
8088
|
async replicate(resourceName, operation, data, id, beforeData = null) {
|
|
8074
8089
|
if (!this.enabled || !this.shouldReplicateResource(resourceName)) {
|
|
@@ -8077,40 +8092,56 @@ ${JSON.stringify(validation, null, 2)}`,
|
|
|
8077
8092
|
if (!this.shouldReplicateAction(resourceName, operation)) {
|
|
8078
8093
|
return { skipped: true, reason: "action_not_included" };
|
|
8079
8094
|
}
|
|
8080
|
-
const
|
|
8081
|
-
if (
|
|
8095
|
+
const tableConfigs = this.getTablesForResource(resourceName, operation);
|
|
8096
|
+
if (tableConfigs.length === 0) {
|
|
8082
8097
|
return { skipped: true, reason: "no_tables_for_action" };
|
|
8083
8098
|
}
|
|
8084
8099
|
const results = [];
|
|
8085
8100
|
const errors = [];
|
|
8086
8101
|
const [ok, err, result] = await try_fn_default(async () => {
|
|
8087
8102
|
const dataset = this.bigqueryClient.dataset(this.datasetId);
|
|
8088
|
-
for (const
|
|
8103
|
+
for (const tableConfig of tableConfigs) {
|
|
8089
8104
|
const [okTable, errTable] = await try_fn_default(async () => {
|
|
8090
|
-
const table = dataset.table(
|
|
8105
|
+
const table = dataset.table(tableConfig.table);
|
|
8091
8106
|
let job;
|
|
8092
8107
|
if (operation === "insert") {
|
|
8093
|
-
const
|
|
8094
|
-
job = await table.insert([
|
|
8108
|
+
const transformedData = this.applyTransform(data, tableConfig.transform);
|
|
8109
|
+
job = await table.insert([transformedData]);
|
|
8095
8110
|
} else if (operation === "update") {
|
|
8096
|
-
const
|
|
8097
|
-
const
|
|
8098
|
-
const
|
|
8099
|
-
|
|
8100
|
-
|
|
8101
|
-
|
|
8102
|
-
|
|
8103
|
-
|
|
8104
|
-
|
|
8105
|
-
|
|
8106
|
-
|
|
8107
|
-
|
|
8108
|
-
|
|
8111
|
+
const transformedData = this.applyTransform(data, tableConfig.transform);
|
|
8112
|
+
const keys = Object.keys(transformedData).filter((k) => k !== "id");
|
|
8113
|
+
const setClause = keys.map((k) => `${k} = @${k}`).join(", ");
|
|
8114
|
+
const params = { id, ...transformedData };
|
|
8115
|
+
const query = `UPDATE \`${this.projectId}.${this.datasetId}.${tableConfig.table}\` SET ${setClause} WHERE id = @id`;
|
|
8116
|
+
const maxRetries = 2;
|
|
8117
|
+
let lastError = null;
|
|
8118
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
8119
|
+
try {
|
|
8120
|
+
const [updateJob] = await this.bigqueryClient.createQueryJob({
|
|
8121
|
+
query,
|
|
8122
|
+
params,
|
|
8123
|
+
location: this.location
|
|
8124
|
+
});
|
|
8125
|
+
await updateJob.getQueryResults();
|
|
8126
|
+
job = [updateJob];
|
|
8127
|
+
break;
|
|
8128
|
+
} catch (error) {
|
|
8129
|
+
lastError = error;
|
|
8130
|
+
if (error?.message?.includes("streaming buffer") && attempt < maxRetries) {
|
|
8131
|
+
const delaySeconds = 30;
|
|
8132
|
+
await new Promise((resolve) => setTimeout(resolve, delaySeconds * 1e3));
|
|
8133
|
+
continue;
|
|
8134
|
+
}
|
|
8135
|
+
throw error;
|
|
8136
|
+
}
|
|
8137
|
+
}
|
|
8138
|
+
if (!job) throw lastError;
|
|
8109
8139
|
} else if (operation === "delete") {
|
|
8110
|
-
const query = `DELETE FROM \`${this.projectId}.${this.datasetId}.${
|
|
8140
|
+
const query = `DELETE FROM \`${this.projectId}.${this.datasetId}.${tableConfig.table}\` WHERE id = @id`;
|
|
8111
8141
|
const [deleteJob] = await this.bigqueryClient.createQueryJob({
|
|
8112
8142
|
query,
|
|
8113
|
-
params: { id }
|
|
8143
|
+
params: { id },
|
|
8144
|
+
location: this.location
|
|
8114
8145
|
});
|
|
8115
8146
|
await deleteJob.getQueryResults();
|
|
8116
8147
|
job = [deleteJob];
|
|
@@ -8118,14 +8149,14 @@ ${JSON.stringify(validation, null, 2)}`,
|
|
|
8118
8149
|
throw new Error(`Unsupported operation: ${operation}`);
|
|
8119
8150
|
}
|
|
8120
8151
|
results.push({
|
|
8121
|
-
table:
|
|
8152
|
+
table: tableConfig.table,
|
|
8122
8153
|
success: true,
|
|
8123
8154
|
jobId: job[0]?.id
|
|
8124
8155
|
});
|
|
8125
8156
|
});
|
|
8126
8157
|
if (!okTable) {
|
|
8127
8158
|
errors.push({
|
|
8128
|
-
table:
|
|
8159
|
+
table: tableConfig.table,
|
|
8129
8160
|
error: errTable.message
|
|
8130
8161
|
});
|
|
8131
8162
|
}
|
|
@@ -8151,7 +8182,7 @@ ${JSON.stringify(validation, null, 2)}`,
|
|
|
8151
8182
|
resourceName,
|
|
8152
8183
|
operation,
|
|
8153
8184
|
id,
|
|
8154
|
-
tables,
|
|
8185
|
+
tables: tableConfigs.map((t) => t.table),
|
|
8155
8186
|
results,
|
|
8156
8187
|
errors,
|
|
8157
8188
|
success
|
|
@@ -8160,7 +8191,7 @@ ${JSON.stringify(validation, null, 2)}`,
|
|
|
8160
8191
|
success,
|
|
8161
8192
|
results,
|
|
8162
8193
|
errors,
|
|
8163
|
-
tables
|
|
8194
|
+
tables: tableConfigs.map((t) => t.table)
|
|
8164
8195
|
};
|
|
8165
8196
|
});
|
|
8166
8197
|
if (ok) return result;
|
|
@@ -12199,7 +12230,7 @@ ${JSON.stringify(validation, null, 2)}`,
|
|
|
12199
12230
|
super();
|
|
12200
12231
|
this.version = "1";
|
|
12201
12232
|
this.s3dbVersion = (() => {
|
|
12202
|
-
const [ok, err, version] = try_fn_default(() => true ? "7.
|
|
12233
|
+
const [ok, err, version] = try_fn_default(() => true ? "7.2.0" : "latest");
|
|
12203
12234
|
return ok ? version : "latest";
|
|
12204
12235
|
})();
|
|
12205
12236
|
this.resources = {};
|