s3db.js 5.1.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/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: existingContentType,
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.0.0" : "latest";
10909
+ return true ? "5.2.0" : "latest";
10794
10910
  } catch (e) {
10795
10911
  return "latest";
10796
10912
  }