s3db.js 4.0.2 → 4.1.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/README.md +463 -7
- package/dist/s3db.cjs.js +127 -15
- package/dist/s3db.cjs.min.js +7 -7
- package/dist/s3db.es.js +128 -16
- package/dist/s3db.es.min.js +7 -7
- package/dist/s3db.iife.js +127 -15
- package/dist/s3db.iife.min.js +10 -10
- package/package.json +1 -1
package/dist/s3db.iife.js
CHANGED
|
@@ -930,7 +930,7 @@ ${JSON.stringify(validation, null, 2)}`
|
|
|
930
930
|
Key: this.config.keyPrefix ? path.join(this.config.keyPrefix, key) : key
|
|
931
931
|
};
|
|
932
932
|
try {
|
|
933
|
-
const response = await this.
|
|
933
|
+
const response = await this.sendCommand(new clientS3.HeadObjectCommand(options2));
|
|
934
934
|
this.emit("headObject", response, options2);
|
|
935
935
|
return response;
|
|
936
936
|
} catch (error) {
|
|
@@ -3474,9 +3474,10 @@ ${JSON.stringify(validation, null, 2)}`
|
|
|
3474
3474
|
this.attributes = attributes || {};
|
|
3475
3475
|
this.passphrase = passphrase ?? "secret";
|
|
3476
3476
|
this.options = lodashEs.merge({}, this.defaultOptions(), options);
|
|
3477
|
+
const processedAttributes = this.preprocessAttributesForValidation(this.attributes);
|
|
3477
3478
|
this.validator = new ValidatorManager({ autoEncrypt: false }).compile(lodashEs.merge(
|
|
3478
3479
|
{ $$async: true },
|
|
3479
|
-
|
|
3480
|
+
processedAttributes
|
|
3480
3481
|
));
|
|
3481
3482
|
if (this.options.generateAutoHooks) this.generateAutoHooks();
|
|
3482
3483
|
if (!lodashEs.isEmpty(map)) {
|
|
@@ -3557,6 +3558,7 @@ ${JSON.stringify(validation, null, 2)}`
|
|
|
3557
3558
|
version,
|
|
3558
3559
|
attributes
|
|
3559
3560
|
} = lodashEs.isString(data) ? JSON.parse(data) : data;
|
|
3561
|
+
attributes = Schema._importAttributes(attributes);
|
|
3560
3562
|
const schema = new Schema({
|
|
3561
3563
|
map,
|
|
3562
3564
|
name,
|
|
@@ -3566,22 +3568,60 @@ ${JSON.stringify(validation, null, 2)}`
|
|
|
3566
3568
|
});
|
|
3567
3569
|
return schema;
|
|
3568
3570
|
}
|
|
3571
|
+
/**
|
|
3572
|
+
* Recursively import attributes, parsing only stringified objects (legacy)
|
|
3573
|
+
*/
|
|
3574
|
+
static _importAttributes(attrs) {
|
|
3575
|
+
if (typeof attrs === "string") {
|
|
3576
|
+
try {
|
|
3577
|
+
const parsed = JSON.parse(attrs);
|
|
3578
|
+
if (typeof parsed === "object" && parsed !== null) {
|
|
3579
|
+
return Schema._importAttributes(parsed);
|
|
3580
|
+
}
|
|
3581
|
+
} catch (e) {
|
|
3582
|
+
}
|
|
3583
|
+
return attrs;
|
|
3584
|
+
}
|
|
3585
|
+
if (Array.isArray(attrs)) {
|
|
3586
|
+
return attrs.map((a) => Schema._importAttributes(a));
|
|
3587
|
+
}
|
|
3588
|
+
if (typeof attrs === "object" && attrs !== null) {
|
|
3589
|
+
const out = {};
|
|
3590
|
+
for (const [k, v] of Object.entries(attrs)) {
|
|
3591
|
+
out[k] = Schema._importAttributes(v);
|
|
3592
|
+
}
|
|
3593
|
+
return out;
|
|
3594
|
+
}
|
|
3595
|
+
return attrs;
|
|
3596
|
+
}
|
|
3569
3597
|
export() {
|
|
3570
3598
|
const data = {
|
|
3571
3599
|
version: this.version,
|
|
3572
3600
|
name: this.name,
|
|
3573
3601
|
options: this.options,
|
|
3574
|
-
attributes:
|
|
3602
|
+
attributes: this._exportAttributes(this.attributes),
|
|
3575
3603
|
map: this.map
|
|
3576
3604
|
};
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3605
|
+
return data;
|
|
3606
|
+
}
|
|
3607
|
+
/**
|
|
3608
|
+
* Recursively export attributes, keeping objects as objects and only serializing leaves as string
|
|
3609
|
+
*/
|
|
3610
|
+
_exportAttributes(attrs) {
|
|
3611
|
+
if (typeof attrs === "string") {
|
|
3612
|
+
return attrs;
|
|
3613
|
+
}
|
|
3614
|
+
if (Array.isArray(attrs)) {
|
|
3615
|
+
return attrs.map((a) => this._exportAttributes(a));
|
|
3616
|
+
}
|
|
3617
|
+
if (typeof attrs === "object" && attrs !== null) {
|
|
3618
|
+
const out = {};
|
|
3619
|
+
for (const [k, v] of Object.entries(attrs)) {
|
|
3620
|
+
out[k] = this._exportAttributes(v);
|
|
3582
3621
|
}
|
|
3622
|
+
return out;
|
|
3583
3623
|
}
|
|
3584
|
-
return
|
|
3624
|
+
return attrs;
|
|
3585
3625
|
}
|
|
3586
3626
|
async applyHooksActions(resourceItem, hook) {
|
|
3587
3627
|
for (const [attribute, actions] of Object.entries(this.options.hooks[hook])) {
|
|
@@ -3622,6 +3662,26 @@ ${JSON.stringify(validation, null, 2)}`
|
|
|
3622
3662
|
await this.applyHooksActions(rest, "afterUnmap");
|
|
3623
3663
|
return flat.unflatten(rest);
|
|
3624
3664
|
}
|
|
3665
|
+
/**
|
|
3666
|
+
* Preprocess attributes to convert nested objects into validator-compatible format
|
|
3667
|
+
* @param {Object} attributes - Original attributes
|
|
3668
|
+
* @returns {Object} Processed attributes for validator
|
|
3669
|
+
*/
|
|
3670
|
+
preprocessAttributesForValidation(attributes) {
|
|
3671
|
+
const processed = {};
|
|
3672
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
3673
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
3674
|
+
processed[key] = {
|
|
3675
|
+
type: "object",
|
|
3676
|
+
properties: this.preprocessAttributesForValidation(value),
|
|
3677
|
+
strict: false
|
|
3678
|
+
};
|
|
3679
|
+
} else {
|
|
3680
|
+
processed[key] = value;
|
|
3681
|
+
}
|
|
3682
|
+
}
|
|
3683
|
+
return processed;
|
|
3684
|
+
}
|
|
3625
3685
|
}
|
|
3626
3686
|
|
|
3627
3687
|
var global$1 = (typeof global !== "undefined" ? global :
|
|
@@ -8937,7 +8997,7 @@ ${JSON.stringify(validation, null, 2)}`
|
|
|
8937
8997
|
continue;
|
|
8938
8998
|
}
|
|
8939
8999
|
for (const fieldName of Object.keys(partitionDef.fields)) {
|
|
8940
|
-
if (!
|
|
9000
|
+
if (!this.fieldExistsInAttributes(fieldName)) {
|
|
8941
9001
|
throw new Error(
|
|
8942
9002
|
`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.`
|
|
8943
9003
|
);
|
|
@@ -8945,6 +9005,25 @@ ${JSON.stringify(validation, null, 2)}`
|
|
|
8945
9005
|
}
|
|
8946
9006
|
}
|
|
8947
9007
|
}
|
|
9008
|
+
/**
|
|
9009
|
+
* Check if a field (including nested fields) exists in the current attributes
|
|
9010
|
+
* @param {string} fieldName - Field name (can be nested like 'utm.source')
|
|
9011
|
+
* @returns {boolean} True if field exists
|
|
9012
|
+
*/
|
|
9013
|
+
fieldExistsInAttributes(fieldName) {
|
|
9014
|
+
if (!fieldName.includes(".")) {
|
|
9015
|
+
return Object.keys(this.attributes || {}).includes(fieldName);
|
|
9016
|
+
}
|
|
9017
|
+
const keys = fieldName.split(".");
|
|
9018
|
+
let currentLevel = this.attributes || {};
|
|
9019
|
+
for (const key of keys) {
|
|
9020
|
+
if (!currentLevel || typeof currentLevel !== "object" || !(key in currentLevel)) {
|
|
9021
|
+
return false;
|
|
9022
|
+
}
|
|
9023
|
+
currentLevel = currentLevel[key];
|
|
9024
|
+
}
|
|
9025
|
+
return true;
|
|
9026
|
+
}
|
|
8948
9027
|
/**
|
|
8949
9028
|
* Apply a single partition rule to a field value
|
|
8950
9029
|
* @param {*} value - The field value
|
|
@@ -9007,17 +9086,38 @@ ${JSON.stringify(validation, null, 2)}`
|
|
|
9007
9086
|
const partitionSegments = [];
|
|
9008
9087
|
const sortedFields = Object.entries(partition.fields).sort(([a], [b]) => a.localeCompare(b));
|
|
9009
9088
|
for (const [fieldName, rule] of sortedFields) {
|
|
9010
|
-
const fieldValue = this.
|
|
9011
|
-
|
|
9089
|
+
const fieldValue = this.getNestedFieldValue(data, fieldName);
|
|
9090
|
+
const transformedValue = this.applyPartitionRule(fieldValue, rule);
|
|
9091
|
+
if (transformedValue === void 0 || transformedValue === null) {
|
|
9012
9092
|
return null;
|
|
9013
9093
|
}
|
|
9014
|
-
partitionSegments.push(`${fieldName}=${
|
|
9094
|
+
partitionSegments.push(`${fieldName}=${transformedValue}`);
|
|
9015
9095
|
}
|
|
9016
9096
|
if (partitionSegments.length === 0) {
|
|
9017
9097
|
return null;
|
|
9018
9098
|
}
|
|
9019
9099
|
return join(`resource=${this.name}`, `partition=${partitionName}`, ...partitionSegments, `id=${id}`);
|
|
9020
9100
|
}
|
|
9101
|
+
/**
|
|
9102
|
+
* Get nested field value from data object using dot notation
|
|
9103
|
+
* @param {Object} data - Data object
|
|
9104
|
+
* @param {string} fieldPath - Field path (e.g., "utm.source", "address.city")
|
|
9105
|
+
* @returns {*} Field value
|
|
9106
|
+
*/
|
|
9107
|
+
getNestedFieldValue(data, fieldPath) {
|
|
9108
|
+
if (!fieldPath.includes(".")) {
|
|
9109
|
+
return data[fieldPath];
|
|
9110
|
+
}
|
|
9111
|
+
const keys = fieldPath.split(".");
|
|
9112
|
+
let value = data;
|
|
9113
|
+
for (const key of keys) {
|
|
9114
|
+
if (value === null || value === void 0 || typeof value !== "object") {
|
|
9115
|
+
return void 0;
|
|
9116
|
+
}
|
|
9117
|
+
value = value[key];
|
|
9118
|
+
}
|
|
9119
|
+
return value;
|
|
9120
|
+
}
|
|
9021
9121
|
async insert({ id, ...attributes }) {
|
|
9022
9122
|
if (this.options.timestamps) {
|
|
9023
9123
|
attributes.createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -9499,7 +9599,19 @@ ${JSON.stringify(validation, null, 2)}`
|
|
|
9499
9599
|
*/
|
|
9500
9600
|
getDefinitionHash() {
|
|
9501
9601
|
const exportedSchema = this.schema.export();
|
|
9502
|
-
const
|
|
9602
|
+
const stableSchema = {
|
|
9603
|
+
...exportedSchema,
|
|
9604
|
+
attributes: { ...exportedSchema.attributes }
|
|
9605
|
+
};
|
|
9606
|
+
if (this.options.timestamps) {
|
|
9607
|
+
delete stableSchema.attributes.createdAt;
|
|
9608
|
+
delete stableSchema.attributes.updatedAt;
|
|
9609
|
+
if (stableSchema.options && stableSchema.options.partitions) {
|
|
9610
|
+
delete stableSchema.options.partitions.byCreatedDate;
|
|
9611
|
+
delete stableSchema.options.partitions.byUpdatedDate;
|
|
9612
|
+
}
|
|
9613
|
+
}
|
|
9614
|
+
const stableString = jsonStableStringify(stableSchema);
|
|
9503
9615
|
return `sha256:${crypto.createHash("sha256").update(stableString).digest("hex")}`;
|
|
9504
9616
|
}
|
|
9505
9617
|
/**
|
|
@@ -9693,7 +9805,7 @@ ${JSON.stringify(validation, null, 2)}`
|
|
|
9693
9805
|
this.version = "1";
|
|
9694
9806
|
this.s3dbVersion = (() => {
|
|
9695
9807
|
try {
|
|
9696
|
-
return true ? "4.0
|
|
9808
|
+
return true ? "4.1.0" : "latest";
|
|
9697
9809
|
} catch (e) {
|
|
9698
9810
|
return "latest";
|
|
9699
9811
|
}
|