s3db.js 5.2.0 → 6.0.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 +1168 -54
- package/dist/s3db.cjs.js +128 -12
- package/dist/s3db.cjs.min.js +11 -11
- package/dist/s3db.es.js +128 -12
- package/dist/s3db.es.min.js +11 -11
- package/dist/s3db.iife.js +128 -12
- package/dist/s3db.iife.min.js +11 -11
- package/package.json +1 -1
package/dist/s3db.iife.js
CHANGED
|
@@ -8931,6 +8931,9 @@ ${JSON.stringify(validation, null, 2)}`, {
|
|
|
8931
8931
|
const AVAILABLE_BEHAVIORS = Object.keys(behaviors);
|
|
8932
8932
|
const DEFAULT_BEHAVIOR = "user-management";
|
|
8933
8933
|
|
|
8934
|
+
function createIdGeneratorWithSize(size) {
|
|
8935
|
+
return nanoid.customAlphabet(nanoid.urlAlphabet, size);
|
|
8936
|
+
}
|
|
8934
8937
|
class Resource extends EventEmitter {
|
|
8935
8938
|
/**
|
|
8936
8939
|
* Create a new Resource instance
|
|
@@ -8951,6 +8954,8 @@ ${JSON.stringify(validation, null, 2)}`, {
|
|
|
8951
8954
|
* @param {boolean} [config.allNestedObjectsOptional=false] - Make nested objects optional
|
|
8952
8955
|
* @param {Object} [config.hooks={}] - Custom hooks
|
|
8953
8956
|
* @param {Object} [config.options={}] - Additional options
|
|
8957
|
+
* @param {Function} [config.idGenerator] - Custom ID generator function
|
|
8958
|
+
* @param {number} [config.idSize=22] - Size for auto-generated IDs
|
|
8954
8959
|
* @example
|
|
8955
8960
|
* const users = new Resource({
|
|
8956
8961
|
* name: 'users',
|
|
@@ -8975,6 +8980,30 @@ ${JSON.stringify(validation, null, 2)}`, {
|
|
|
8975
8980
|
* }]
|
|
8976
8981
|
* }
|
|
8977
8982
|
* });
|
|
8983
|
+
*
|
|
8984
|
+
* // With custom ID size
|
|
8985
|
+
* const shortIdUsers = new Resource({
|
|
8986
|
+
* name: 'users',
|
|
8987
|
+
* client: s3Client,
|
|
8988
|
+
* attributes: { name: 'string|required' },
|
|
8989
|
+
* idSize: 8 // Generate 8-character IDs
|
|
8990
|
+
* });
|
|
8991
|
+
*
|
|
8992
|
+
* // With custom ID generator function
|
|
8993
|
+
* const customIdUsers = new Resource({
|
|
8994
|
+
* name: 'users',
|
|
8995
|
+
* client: s3Client,
|
|
8996
|
+
* attributes: { name: 'string|required' },
|
|
8997
|
+
* idGenerator: () => `user_${Date.now()}_${Math.random().toString(36).substr(2, 5)}`
|
|
8998
|
+
* });
|
|
8999
|
+
*
|
|
9000
|
+
* // With custom ID generator using size parameter
|
|
9001
|
+
* const longIdUsers = new Resource({
|
|
9002
|
+
* name: 'users',
|
|
9003
|
+
* client: s3Client,
|
|
9004
|
+
* attributes: { name: 'string|required' },
|
|
9005
|
+
* idGenerator: 32 // Generate 32-character IDs (same as idSize: 32)
|
|
9006
|
+
* });
|
|
8978
9007
|
*/
|
|
8979
9008
|
constructor(config) {
|
|
8980
9009
|
super();
|
|
@@ -8998,7 +9027,9 @@ ${validation.errors.join("\n")}`);
|
|
|
8998
9027
|
partitions = {},
|
|
8999
9028
|
paranoid = true,
|
|
9000
9029
|
allNestedObjectsOptional = true,
|
|
9001
|
-
hooks = {}
|
|
9030
|
+
hooks = {},
|
|
9031
|
+
idGenerator: customIdGenerator,
|
|
9032
|
+
idSize = 22
|
|
9002
9033
|
} = config;
|
|
9003
9034
|
this.name = name;
|
|
9004
9035
|
this.client = client;
|
|
@@ -9007,6 +9038,7 @@ ${validation.errors.join("\n")}`);
|
|
|
9007
9038
|
this.observers = observers;
|
|
9008
9039
|
this.parallelism = parallelism;
|
|
9009
9040
|
this.passphrase = passphrase ?? "secret";
|
|
9041
|
+
this.idGenerator = this.configureIdGenerator(customIdGenerator, idSize);
|
|
9010
9042
|
this.config = {
|
|
9011
9043
|
cache,
|
|
9012
9044
|
hooks,
|
|
@@ -9038,6 +9070,25 @@ ${validation.errors.join("\n")}`);
|
|
|
9038
9070
|
}
|
|
9039
9071
|
}
|
|
9040
9072
|
}
|
|
9073
|
+
/**
|
|
9074
|
+
* Configure ID generator based on provided options
|
|
9075
|
+
* @param {Function|number} customIdGenerator - Custom ID generator function or size
|
|
9076
|
+
* @param {number} idSize - Size for auto-generated IDs
|
|
9077
|
+
* @returns {Function} Configured ID generator function
|
|
9078
|
+
* @private
|
|
9079
|
+
*/
|
|
9080
|
+
configureIdGenerator(customIdGenerator, idSize) {
|
|
9081
|
+
if (typeof customIdGenerator === "function") {
|
|
9082
|
+
return customIdGenerator;
|
|
9083
|
+
}
|
|
9084
|
+
if (typeof customIdGenerator === "number" && customIdGenerator > 0) {
|
|
9085
|
+
return createIdGeneratorWithSize(customIdGenerator);
|
|
9086
|
+
}
|
|
9087
|
+
if (typeof idSize === "number" && idSize > 0) {
|
|
9088
|
+
return createIdGeneratorWithSize(idSize);
|
|
9089
|
+
}
|
|
9090
|
+
return idGenerator;
|
|
9091
|
+
}
|
|
9041
9092
|
/**
|
|
9042
9093
|
* Get resource options (for backward compatibility with tests)
|
|
9043
9094
|
*/
|
|
@@ -9386,7 +9437,7 @@ ${validation.errors.join("\n")}`);
|
|
|
9386
9437
|
validation: errors
|
|
9387
9438
|
});
|
|
9388
9439
|
}
|
|
9389
|
-
if (!id && id !== 0) id = idGenerator();
|
|
9440
|
+
if (!id && id !== 0) id = this.idGenerator();
|
|
9390
9441
|
const mappedData = await this.schema.mapper(validated);
|
|
9391
9442
|
const behaviorImpl = getBehavior(this.behavior);
|
|
9392
9443
|
const { mappedData: processedMetadata, body } = await behaviorImpl.handleInsert({
|
|
@@ -9395,10 +9446,19 @@ ${validation.errors.join("\n")}`);
|
|
|
9395
9446
|
mappedData
|
|
9396
9447
|
});
|
|
9397
9448
|
const key = this.getResourceKey(id);
|
|
9449
|
+
let contentType = void 0;
|
|
9450
|
+
if (body && body !== "") {
|
|
9451
|
+
try {
|
|
9452
|
+
JSON.parse(body);
|
|
9453
|
+
contentType = "application/json";
|
|
9454
|
+
} catch {
|
|
9455
|
+
}
|
|
9456
|
+
}
|
|
9398
9457
|
await this.client.putObject({
|
|
9399
9458
|
metadata: processedMetadata,
|
|
9400
9459
|
key,
|
|
9401
|
-
body
|
|
9460
|
+
body,
|
|
9461
|
+
contentType
|
|
9402
9462
|
});
|
|
9403
9463
|
const final = lodashEs.merge({ id }, validated);
|
|
9404
9464
|
await this.executeHooks("afterInsert", final);
|
|
@@ -9593,10 +9653,18 @@ ${validation.errors.join("\n")}`);
|
|
|
9593
9653
|
} catch (error) {
|
|
9594
9654
|
}
|
|
9595
9655
|
}
|
|
9656
|
+
let finalContentType = existingContentType;
|
|
9657
|
+
if (finalBody && finalBody !== "" && !finalContentType) {
|
|
9658
|
+
try {
|
|
9659
|
+
JSON.parse(finalBody);
|
|
9660
|
+
finalContentType = "application/json";
|
|
9661
|
+
} catch {
|
|
9662
|
+
}
|
|
9663
|
+
}
|
|
9596
9664
|
await this.client.putObject({
|
|
9597
9665
|
key,
|
|
9598
9666
|
body: finalBody,
|
|
9599
|
-
contentType:
|
|
9667
|
+
contentType: finalContentType,
|
|
9600
9668
|
metadata: processedMetadata
|
|
9601
9669
|
});
|
|
9602
9670
|
validated.id = id;
|
|
@@ -9693,9 +9761,7 @@ ${validation.errors.join("\n")}`);
|
|
|
9693
9761
|
} else {
|
|
9694
9762
|
prefix = `resource=${this.name}/v=${this.version}`;
|
|
9695
9763
|
}
|
|
9696
|
-
const count = await this.client.count({
|
|
9697
|
-
prefix
|
|
9698
|
-
});
|
|
9764
|
+
const count = await this.client.count({ prefix });
|
|
9699
9765
|
this.emit("count", count);
|
|
9700
9766
|
return count;
|
|
9701
9767
|
}
|
|
@@ -10363,10 +10429,19 @@ ${validation.errors.join("\n")}`);
|
|
|
10363
10429
|
...processedMetadata,
|
|
10364
10430
|
_version: this.version
|
|
10365
10431
|
};
|
|
10432
|
+
let contentType = void 0;
|
|
10433
|
+
if (body && body !== "") {
|
|
10434
|
+
try {
|
|
10435
|
+
JSON.parse(body);
|
|
10436
|
+
contentType = "application/json";
|
|
10437
|
+
} catch {
|
|
10438
|
+
}
|
|
10439
|
+
}
|
|
10366
10440
|
await this.client.putObject({
|
|
10367
10441
|
key: partitionKey,
|
|
10368
10442
|
metadata: partitionMetadata,
|
|
10369
|
-
body
|
|
10443
|
+
body,
|
|
10444
|
+
contentType
|
|
10370
10445
|
});
|
|
10371
10446
|
}
|
|
10372
10447
|
}
|
|
@@ -10538,10 +10613,19 @@ ${validation.errors.join("\n")}`);
|
|
|
10538
10613
|
_version: this.version
|
|
10539
10614
|
};
|
|
10540
10615
|
if (partitionMetadata.undefined !== void 0) delete partitionMetadata.undefined;
|
|
10616
|
+
let contentType = void 0;
|
|
10617
|
+
if (body && body !== "") {
|
|
10618
|
+
try {
|
|
10619
|
+
JSON.parse(body);
|
|
10620
|
+
contentType = "application/json";
|
|
10621
|
+
} catch {
|
|
10622
|
+
}
|
|
10623
|
+
}
|
|
10541
10624
|
await this.client.putObject({
|
|
10542
10625
|
key: newPartitionKey,
|
|
10543
10626
|
metadata: partitionMetadata,
|
|
10544
|
-
body
|
|
10627
|
+
body,
|
|
10628
|
+
contentType
|
|
10545
10629
|
});
|
|
10546
10630
|
} catch (error) {
|
|
10547
10631
|
console.warn(`New partition object could not be created for ${partitionName}:`, error.message);
|
|
@@ -10564,10 +10648,19 @@ ${validation.errors.join("\n")}`);
|
|
|
10564
10648
|
_version: this.version
|
|
10565
10649
|
};
|
|
10566
10650
|
if (partitionMetadata.undefined !== void 0) delete partitionMetadata.undefined;
|
|
10651
|
+
let contentType = void 0;
|
|
10652
|
+
if (body && body !== "") {
|
|
10653
|
+
try {
|
|
10654
|
+
JSON.parse(body);
|
|
10655
|
+
contentType = "application/json";
|
|
10656
|
+
} catch {
|
|
10657
|
+
}
|
|
10658
|
+
}
|
|
10567
10659
|
await this.client.putObject({
|
|
10568
10660
|
key: newPartitionKey,
|
|
10569
10661
|
metadata: partitionMetadata,
|
|
10570
|
-
body
|
|
10662
|
+
body,
|
|
10663
|
+
contentType
|
|
10571
10664
|
});
|
|
10572
10665
|
} catch (error) {
|
|
10573
10666
|
console.warn(`Partition object could not be updated for ${partitionName}:`, error.message);
|
|
@@ -10602,11 +10695,20 @@ ${validation.errors.join("\n")}`);
|
|
|
10602
10695
|
...processedMetadata,
|
|
10603
10696
|
_version: this.version
|
|
10604
10697
|
};
|
|
10698
|
+
let contentType = void 0;
|
|
10699
|
+
if (body && body !== "") {
|
|
10700
|
+
try {
|
|
10701
|
+
JSON.parse(body);
|
|
10702
|
+
contentType = "application/json";
|
|
10703
|
+
} catch {
|
|
10704
|
+
}
|
|
10705
|
+
}
|
|
10605
10706
|
try {
|
|
10606
10707
|
await this.client.putObject({
|
|
10607
10708
|
key: partitionKey,
|
|
10608
10709
|
metadata: partitionMetadata,
|
|
10609
|
-
body
|
|
10710
|
+
body,
|
|
10711
|
+
contentType
|
|
10610
10712
|
});
|
|
10611
10713
|
} catch (error) {
|
|
10612
10714
|
console.warn(`Partition object could not be updated for ${partitionName}:`, error.message);
|
|
@@ -10735,6 +10837,20 @@ ${validation.errors.join("\n")}`);
|
|
|
10735
10837
|
errors.push(`Resource '${field}' must be a boolean`);
|
|
10736
10838
|
}
|
|
10737
10839
|
}
|
|
10840
|
+
if (config.idGenerator !== void 0) {
|
|
10841
|
+
if (typeof config.idGenerator !== "function" && typeof config.idGenerator !== "number") {
|
|
10842
|
+
errors.push("Resource 'idGenerator' must be a function or a number (size)");
|
|
10843
|
+
} else if (typeof config.idGenerator === "number" && config.idGenerator <= 0) {
|
|
10844
|
+
errors.push("Resource 'idGenerator' size must be greater than 0");
|
|
10845
|
+
}
|
|
10846
|
+
}
|
|
10847
|
+
if (config.idSize !== void 0) {
|
|
10848
|
+
if (typeof config.idSize !== "number" || !Number.isInteger(config.idSize)) {
|
|
10849
|
+
errors.push("Resource 'idSize' must be an integer");
|
|
10850
|
+
} else if (config.idSize <= 0) {
|
|
10851
|
+
errors.push("Resource 'idSize' must be greater than 0");
|
|
10852
|
+
}
|
|
10853
|
+
}
|
|
10738
10854
|
if (config.partitions !== void 0) {
|
|
10739
10855
|
if (typeof config.partitions !== "object" || Array.isArray(config.partitions)) {
|
|
10740
10856
|
errors.push("Resource 'partitions' must be an object");
|
|
@@ -10790,7 +10906,7 @@ ${validation.errors.join("\n")}`);
|
|
|
10790
10906
|
this.version = "1";
|
|
10791
10907
|
this.s3dbVersion = (() => {
|
|
10792
10908
|
try {
|
|
10793
|
-
return true ? "5.
|
|
10909
|
+
return true ? "5.2.0" : "latest";
|
|
10794
10910
|
} catch (e) {
|
|
10795
10911
|
return "latest";
|
|
10796
10912
|
}
|