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/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) => tableConfig.table);
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 tables = this.getTablesForResource(resourceName, operation);
8081
- if (tables.length === 0) {
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 tableId of tables) {
8103
+ for (const tableConfig of tableConfigs) {
8089
8104
  const [okTable, errTable] = await try_fn_default(async () => {
8090
- const table = dataset.table(tableId);
8105
+ const table = dataset.table(tableConfig.table);
8091
8106
  let job;
8092
8107
  if (operation === "insert") {
8093
- const row = { ...data };
8094
- job = await table.insert([row]);
8108
+ const transformedData = this.applyTransform(data, tableConfig.transform);
8109
+ job = await table.insert([transformedData]);
8095
8110
  } else if (operation === "update") {
8096
- const keys = Object.keys(data).filter((k) => k !== "id");
8097
- const setClause = keys.map((k) => `${k}=@${k}`).join(", ");
8098
- const params = { id };
8099
- keys.forEach((k) => {
8100
- params[k] = data[k];
8101
- });
8102
- const query = `UPDATE \`${this.projectId}.${this.datasetId}.${tableId}\` SET ${setClause} WHERE id=@id`;
8103
- const [updateJob] = await this.bigqueryClient.createQueryJob({
8104
- query,
8105
- params
8106
- });
8107
- await updateJob.getQueryResults();
8108
- job = [updateJob];
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}.${tableId}\` WHERE id=@id`;
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: tableId,
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: tableId,
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.1.0" : "latest");
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 = {};