s3db.js 4.0.2 → 4.1.0
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/README.md +463 -7
- package/dist/s3db.cjs.js +67 -6
- package/dist/s3db.cjs.min.js +6 -6
- package/dist/s3db.es.js +68 -7
- package/dist/s3db.es.min.js +6 -6
- package/dist/s3db.iife.js +67 -6
- package/dist/s3db.iife.min.js +8 -8
- package/package.json +1 -1
package/dist/s3db.es.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* istanbul ignore file */
|
|
2
2
|
import { customAlphabet, urlAlphabet } from 'nanoid';
|
|
3
|
-
import { chunk, merge,
|
|
3
|
+
import { chunk, merge, isEmpty, invert, uniq, cloneDeep, isString as isString$1, get as get$1, set, isFunction as isFunction$1 } from 'lodash-es';
|
|
4
4
|
import { PromisePool } from '@supercharge/promise-pool';
|
|
5
5
|
import { S3Client, PutObjectCommand, GetObjectCommand, HeadObjectCommand, CopyObjectCommand, DeleteObjectCommand, DeleteObjectsCommand, ListObjectsV2Command } from '@aws-sdk/client-s3';
|
|
6
6
|
import { createHash } from 'crypto';
|
|
@@ -3480,9 +3480,10 @@ class Schema {
|
|
|
3480
3480
|
this.attributes = attributes || {};
|
|
3481
3481
|
this.passphrase = passphrase ?? "secret";
|
|
3482
3482
|
this.options = merge({}, this.defaultOptions(), options);
|
|
3483
|
+
const processedAttributes = this.preprocessAttributesForValidation(this.attributes);
|
|
3483
3484
|
this.validator = new ValidatorManager({ autoEncrypt: false }).compile(merge(
|
|
3484
3485
|
{ $$async: true },
|
|
3485
|
-
|
|
3486
|
+
processedAttributes
|
|
3486
3487
|
));
|
|
3487
3488
|
if (this.options.generateAutoHooks) this.generateAutoHooks();
|
|
3488
3489
|
if (!isEmpty(map)) {
|
|
@@ -3628,6 +3629,26 @@ class Schema {
|
|
|
3628
3629
|
await this.applyHooksActions(rest, "afterUnmap");
|
|
3629
3630
|
return unflatten(rest);
|
|
3630
3631
|
}
|
|
3632
|
+
/**
|
|
3633
|
+
* Preprocess attributes to convert nested objects into validator-compatible format
|
|
3634
|
+
* @param {Object} attributes - Original attributes
|
|
3635
|
+
* @returns {Object} Processed attributes for validator
|
|
3636
|
+
*/
|
|
3637
|
+
preprocessAttributesForValidation(attributes) {
|
|
3638
|
+
const processed = {};
|
|
3639
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
3640
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
3641
|
+
processed[key] = {
|
|
3642
|
+
type: "object",
|
|
3643
|
+
properties: this.preprocessAttributesForValidation(value),
|
|
3644
|
+
strict: false
|
|
3645
|
+
};
|
|
3646
|
+
} else {
|
|
3647
|
+
processed[key] = value;
|
|
3648
|
+
}
|
|
3649
|
+
}
|
|
3650
|
+
return processed;
|
|
3651
|
+
}
|
|
3631
3652
|
}
|
|
3632
3653
|
|
|
3633
3654
|
var global$1 = (typeof global !== "undefined" ? global :
|
|
@@ -8943,7 +8964,7 @@ class Resource extends EventEmitter {
|
|
|
8943
8964
|
continue;
|
|
8944
8965
|
}
|
|
8945
8966
|
for (const fieldName of Object.keys(partitionDef.fields)) {
|
|
8946
|
-
if (!
|
|
8967
|
+
if (!this.fieldExistsInAttributes(fieldName)) {
|
|
8947
8968
|
throw new Error(
|
|
8948
8969
|
`Partition '${partitionName}' uses field '${fieldName}' which does not exist in resource version '${this.version}'. Available fields: ${currentAttributes.join(", ")}. This version of resource does not have support for this partition.`
|
|
8949
8970
|
);
|
|
@@ -8951,6 +8972,25 @@ class Resource extends EventEmitter {
|
|
|
8951
8972
|
}
|
|
8952
8973
|
}
|
|
8953
8974
|
}
|
|
8975
|
+
/**
|
|
8976
|
+
* Check if a field (including nested fields) exists in the current attributes
|
|
8977
|
+
* @param {string} fieldName - Field name (can be nested like 'utm.source')
|
|
8978
|
+
* @returns {boolean} True if field exists
|
|
8979
|
+
*/
|
|
8980
|
+
fieldExistsInAttributes(fieldName) {
|
|
8981
|
+
if (!fieldName.includes(".")) {
|
|
8982
|
+
return Object.keys(this.attributes || {}).includes(fieldName);
|
|
8983
|
+
}
|
|
8984
|
+
const keys = fieldName.split(".");
|
|
8985
|
+
let currentLevel = this.attributes || {};
|
|
8986
|
+
for (const key of keys) {
|
|
8987
|
+
if (!currentLevel || typeof currentLevel !== "object" || !(key in currentLevel)) {
|
|
8988
|
+
return false;
|
|
8989
|
+
}
|
|
8990
|
+
currentLevel = currentLevel[key];
|
|
8991
|
+
}
|
|
8992
|
+
return true;
|
|
8993
|
+
}
|
|
8954
8994
|
/**
|
|
8955
8995
|
* Apply a single partition rule to a field value
|
|
8956
8996
|
* @param {*} value - The field value
|
|
@@ -9013,17 +9053,38 @@ class Resource extends EventEmitter {
|
|
|
9013
9053
|
const partitionSegments = [];
|
|
9014
9054
|
const sortedFields = Object.entries(partition.fields).sort(([a], [b]) => a.localeCompare(b));
|
|
9015
9055
|
for (const [fieldName, rule] of sortedFields) {
|
|
9016
|
-
const fieldValue = this.
|
|
9017
|
-
|
|
9056
|
+
const fieldValue = this.getNestedFieldValue(data, fieldName);
|
|
9057
|
+
const transformedValue = this.applyPartitionRule(fieldValue, rule);
|
|
9058
|
+
if (transformedValue === void 0 || transformedValue === null) {
|
|
9018
9059
|
return null;
|
|
9019
9060
|
}
|
|
9020
|
-
partitionSegments.push(`${fieldName}=${
|
|
9061
|
+
partitionSegments.push(`${fieldName}=${transformedValue}`);
|
|
9021
9062
|
}
|
|
9022
9063
|
if (partitionSegments.length === 0) {
|
|
9023
9064
|
return null;
|
|
9024
9065
|
}
|
|
9025
9066
|
return join(`resource=${this.name}`, `partition=${partitionName}`, ...partitionSegments, `id=${id}`);
|
|
9026
9067
|
}
|
|
9068
|
+
/**
|
|
9069
|
+
* Get nested field value from data object using dot notation
|
|
9070
|
+
* @param {Object} data - Data object
|
|
9071
|
+
* @param {string} fieldPath - Field path (e.g., "utm.source", "address.city")
|
|
9072
|
+
* @returns {*} Field value
|
|
9073
|
+
*/
|
|
9074
|
+
getNestedFieldValue(data, fieldPath) {
|
|
9075
|
+
if (!fieldPath.includes(".")) {
|
|
9076
|
+
return data[fieldPath];
|
|
9077
|
+
}
|
|
9078
|
+
const keys = fieldPath.split(".");
|
|
9079
|
+
let value = data;
|
|
9080
|
+
for (const key of keys) {
|
|
9081
|
+
if (value === null || value === void 0 || typeof value !== "object") {
|
|
9082
|
+
return void 0;
|
|
9083
|
+
}
|
|
9084
|
+
value = value[key];
|
|
9085
|
+
}
|
|
9086
|
+
return value;
|
|
9087
|
+
}
|
|
9027
9088
|
async insert({ id, ...attributes }) {
|
|
9028
9089
|
if (this.options.timestamps) {
|
|
9029
9090
|
attributes.createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -9699,7 +9760,7 @@ class Database extends EventEmitter {
|
|
|
9699
9760
|
this.version = "1";
|
|
9700
9761
|
this.s3dbVersion = (() => {
|
|
9701
9762
|
try {
|
|
9702
|
-
return true ? "4.0.
|
|
9763
|
+
return true ? "4.0.2" : "latest";
|
|
9703
9764
|
} catch (e) {
|
|
9704
9765
|
return "latest";
|
|
9705
9766
|
}
|