s3db.js 4.0.1 → 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 +1815 -97
- 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.cjs.js
CHANGED
|
@@ -3482,9 +3482,10 @@ class Schema {
|
|
|
3482
3482
|
this.attributes = attributes || {};
|
|
3483
3483
|
this.passphrase = passphrase ?? "secret";
|
|
3484
3484
|
this.options = lodashEs.merge({}, this.defaultOptions(), options);
|
|
3485
|
+
const processedAttributes = this.preprocessAttributesForValidation(this.attributes);
|
|
3485
3486
|
this.validator = new ValidatorManager({ autoEncrypt: false }).compile(lodashEs.merge(
|
|
3486
3487
|
{ $$async: true },
|
|
3487
|
-
|
|
3488
|
+
processedAttributes
|
|
3488
3489
|
));
|
|
3489
3490
|
if (this.options.generateAutoHooks) this.generateAutoHooks();
|
|
3490
3491
|
if (!lodashEs.isEmpty(map)) {
|
|
@@ -3630,6 +3631,26 @@ class Schema {
|
|
|
3630
3631
|
await this.applyHooksActions(rest, "afterUnmap");
|
|
3631
3632
|
return flat.unflatten(rest);
|
|
3632
3633
|
}
|
|
3634
|
+
/**
|
|
3635
|
+
* Preprocess attributes to convert nested objects into validator-compatible format
|
|
3636
|
+
* @param {Object} attributes - Original attributes
|
|
3637
|
+
* @returns {Object} Processed attributes for validator
|
|
3638
|
+
*/
|
|
3639
|
+
preprocessAttributesForValidation(attributes) {
|
|
3640
|
+
const processed = {};
|
|
3641
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
3642
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
3643
|
+
processed[key] = {
|
|
3644
|
+
type: "object",
|
|
3645
|
+
properties: this.preprocessAttributesForValidation(value),
|
|
3646
|
+
strict: false
|
|
3647
|
+
};
|
|
3648
|
+
} else {
|
|
3649
|
+
processed[key] = value;
|
|
3650
|
+
}
|
|
3651
|
+
}
|
|
3652
|
+
return processed;
|
|
3653
|
+
}
|
|
3633
3654
|
}
|
|
3634
3655
|
|
|
3635
3656
|
var global$1 = (typeof global !== "undefined" ? global :
|
|
@@ -8945,7 +8966,7 @@ class Resource extends EventEmitter {
|
|
|
8945
8966
|
continue;
|
|
8946
8967
|
}
|
|
8947
8968
|
for (const fieldName of Object.keys(partitionDef.fields)) {
|
|
8948
|
-
if (!
|
|
8969
|
+
if (!this.fieldExistsInAttributes(fieldName)) {
|
|
8949
8970
|
throw new Error(
|
|
8950
8971
|
`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.`
|
|
8951
8972
|
);
|
|
@@ -8953,6 +8974,25 @@ class Resource extends EventEmitter {
|
|
|
8953
8974
|
}
|
|
8954
8975
|
}
|
|
8955
8976
|
}
|
|
8977
|
+
/**
|
|
8978
|
+
* Check if a field (including nested fields) exists in the current attributes
|
|
8979
|
+
* @param {string} fieldName - Field name (can be nested like 'utm.source')
|
|
8980
|
+
* @returns {boolean} True if field exists
|
|
8981
|
+
*/
|
|
8982
|
+
fieldExistsInAttributes(fieldName) {
|
|
8983
|
+
if (!fieldName.includes(".")) {
|
|
8984
|
+
return Object.keys(this.attributes || {}).includes(fieldName);
|
|
8985
|
+
}
|
|
8986
|
+
const keys = fieldName.split(".");
|
|
8987
|
+
let currentLevel = this.attributes || {};
|
|
8988
|
+
for (const key of keys) {
|
|
8989
|
+
if (!currentLevel || typeof currentLevel !== "object" || !(key in currentLevel)) {
|
|
8990
|
+
return false;
|
|
8991
|
+
}
|
|
8992
|
+
currentLevel = currentLevel[key];
|
|
8993
|
+
}
|
|
8994
|
+
return true;
|
|
8995
|
+
}
|
|
8956
8996
|
/**
|
|
8957
8997
|
* Apply a single partition rule to a field value
|
|
8958
8998
|
* @param {*} value - The field value
|
|
@@ -9015,17 +9055,38 @@ class Resource extends EventEmitter {
|
|
|
9015
9055
|
const partitionSegments = [];
|
|
9016
9056
|
const sortedFields = Object.entries(partition.fields).sort(([a], [b]) => a.localeCompare(b));
|
|
9017
9057
|
for (const [fieldName, rule] of sortedFields) {
|
|
9018
|
-
const fieldValue = this.
|
|
9019
|
-
|
|
9058
|
+
const fieldValue = this.getNestedFieldValue(data, fieldName);
|
|
9059
|
+
const transformedValue = this.applyPartitionRule(fieldValue, rule);
|
|
9060
|
+
if (transformedValue === void 0 || transformedValue === null) {
|
|
9020
9061
|
return null;
|
|
9021
9062
|
}
|
|
9022
|
-
partitionSegments.push(`${fieldName}=${
|
|
9063
|
+
partitionSegments.push(`${fieldName}=${transformedValue}`);
|
|
9023
9064
|
}
|
|
9024
9065
|
if (partitionSegments.length === 0) {
|
|
9025
9066
|
return null;
|
|
9026
9067
|
}
|
|
9027
9068
|
return join(`resource=${this.name}`, `partition=${partitionName}`, ...partitionSegments, `id=${id}`);
|
|
9028
9069
|
}
|
|
9070
|
+
/**
|
|
9071
|
+
* Get nested field value from data object using dot notation
|
|
9072
|
+
* @param {Object} data - Data object
|
|
9073
|
+
* @param {string} fieldPath - Field path (e.g., "utm.source", "address.city")
|
|
9074
|
+
* @returns {*} Field value
|
|
9075
|
+
*/
|
|
9076
|
+
getNestedFieldValue(data, fieldPath) {
|
|
9077
|
+
if (!fieldPath.includes(".")) {
|
|
9078
|
+
return data[fieldPath];
|
|
9079
|
+
}
|
|
9080
|
+
const keys = fieldPath.split(".");
|
|
9081
|
+
let value = data;
|
|
9082
|
+
for (const key of keys) {
|
|
9083
|
+
if (value === null || value === void 0 || typeof value !== "object") {
|
|
9084
|
+
return void 0;
|
|
9085
|
+
}
|
|
9086
|
+
value = value[key];
|
|
9087
|
+
}
|
|
9088
|
+
return value;
|
|
9089
|
+
}
|
|
9029
9090
|
async insert({ id, ...attributes }) {
|
|
9030
9091
|
if (this.options.timestamps) {
|
|
9031
9092
|
attributes.createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -9701,7 +9762,7 @@ class Database extends EventEmitter {
|
|
|
9701
9762
|
this.version = "1";
|
|
9702
9763
|
this.s3dbVersion = (() => {
|
|
9703
9764
|
try {
|
|
9704
|
-
return true ? "4.0.
|
|
9765
|
+
return true ? "4.0.2" : "latest";
|
|
9705
9766
|
} catch (e) {
|
|
9706
9767
|
return "latest";
|
|
9707
9768
|
}
|