s3db.js 4.1.1 → 4.1.3

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.es.js CHANGED
@@ -9604,20 +9604,13 @@ class Resource extends EventEmitter {
9604
9604
  * @returns {string} SHA256 hash of the schema definition
9605
9605
  */
9606
9606
  getDefinitionHash() {
9607
- const exportedSchema = this.schema.export();
9608
- const stableSchema = {
9609
- ...exportedSchema,
9610
- attributes: { ...exportedSchema.attributes }
9611
- };
9607
+ const attributes = this.schema.export().attributes;
9608
+ const stableAttributes = { ...attributes };
9612
9609
  if (this.options.timestamps) {
9613
- delete stableSchema.attributes.createdAt;
9614
- delete stableSchema.attributes.updatedAt;
9615
- if (stableSchema.options && stableSchema.options.partitions) {
9616
- delete stableSchema.options.partitions.byCreatedDate;
9617
- delete stableSchema.options.partitions.byUpdatedDate;
9618
- }
9610
+ delete stableAttributes.createdAt;
9611
+ delete stableAttributes.updatedAt;
9619
9612
  }
9620
- const stableString = jsonStableStringify(stableSchema);
9613
+ const stableString = jsonStableStringify(stableAttributes);
9621
9614
  return `sha256:${createHash("sha256").update(stableString).digest("hex")}`;
9622
9615
  }
9623
9616
  /**
@@ -9811,7 +9804,7 @@ class Database extends EventEmitter {
9811
9804
  this.version = "1";
9812
9805
  this.s3dbVersion = (() => {
9813
9806
  try {
9814
- return true ? "4.1.0" : "latest";
9807
+ return true ? "4.1.2" : "latest";
9815
9808
  } catch (e) {
9816
9809
  return "latest";
9817
9810
  }
@@ -9923,10 +9916,21 @@ class Database extends EventEmitter {
9923
9916
  /**
9924
9917
  * Generate a consistent hash for a resource definition
9925
9918
  * @param {Object} definition - Resource definition to hash
9919
+ * @param {string} behavior - Resource behavior
9926
9920
  * @returns {string} SHA256 hash
9927
9921
  */
9928
- generateDefinitionHash(definition) {
9929
- const stableString = jsonStableStringify(definition);
9922
+ generateDefinitionHash(definition, behavior = void 0) {
9923
+ const attributes = definition.attributes;
9924
+ const stableAttributes = { ...attributes };
9925
+ if (definition.options?.timestamps) {
9926
+ delete stableAttributes.createdAt;
9927
+ delete stableAttributes.updatedAt;
9928
+ }
9929
+ const hashObj = {
9930
+ attributes: stableAttributes,
9931
+ behavior: behavior || definition.behavior || "user-management"
9932
+ };
9933
+ const stableString = jsonStableStringify(hashObj);
9930
9934
  return `sha256:${createHash("sha256").update(stableString).digest("hex")}`;
9931
9935
  }
9932
9936
  /**
@@ -10013,6 +10017,73 @@ class Database extends EventEmitter {
10013
10017
  resources: {}
10014
10018
  };
10015
10019
  }
10020
+ /**
10021
+ * Check if a resource exists by name
10022
+ * @param {string} name - Resource name
10023
+ * @returns {boolean} True if resource exists, false otherwise
10024
+ */
10025
+ resourceExists(name) {
10026
+ return !!this.resources[name];
10027
+ }
10028
+ /**
10029
+ * Check if a resource exists with the same definition hash
10030
+ * @param {string} name - Resource name
10031
+ * @param {Object} attributes - Resource attributes
10032
+ * @param {Object} options - Resource options
10033
+ * @param {string} behavior - Resource behavior
10034
+ * @returns {Object} Object with exists flag and hash information
10035
+ */
10036
+ resourceExistsWithSameHash({ name, attributes, options = {}, behavior = "user-management" }) {
10037
+ if (!this.resources[name]) {
10038
+ return { exists: false, sameHash: false, hash: null };
10039
+ }
10040
+ const tempResource = new Resource({
10041
+ name,
10042
+ attributes,
10043
+ behavior,
10044
+ observers: [],
10045
+ client: this.client,
10046
+ version: "temp",
10047
+ options: {
10048
+ cache: this.cache,
10049
+ ...options
10050
+ }
10051
+ });
10052
+ const newHash = this.generateDefinitionHash(tempResource.export(), behavior);
10053
+ const existingHash = this.generateDefinitionHash(this.resources[name].export(), this.resources[name].behavior);
10054
+ return {
10055
+ exists: true,
10056
+ sameHash: newHash === existingHash,
10057
+ hash: newHash,
10058
+ existingHash
10059
+ };
10060
+ }
10061
+ /**
10062
+ * Create a resource only if it doesn't exist with the same definition hash
10063
+ * @param {Object} params - Resource parameters
10064
+ * @param {string} params.name - Resource name
10065
+ * @param {Object} params.attributes - Resource attributes
10066
+ * @param {Object} params.options - Resource options
10067
+ * @param {string} params.behavior - Resource behavior
10068
+ * @returns {Object} Object with resource and created flag
10069
+ */
10070
+ async createResourceIfNotExists({ name, attributes, options = {}, behavior = "user-management" }) {
10071
+ const alreadyExists = !!this.resources[name];
10072
+ const hashCheck = this.resourceExistsWithSameHash({ name, attributes, options, behavior });
10073
+ if (hashCheck.exists && hashCheck.sameHash) {
10074
+ return {
10075
+ resource: this.resources[name],
10076
+ created: false,
10077
+ reason: "Resource already exists with same definition hash"
10078
+ };
10079
+ }
10080
+ const resource = await this.createResource({ name, attributes, options, behavior });
10081
+ return {
10082
+ resource,
10083
+ created: !alreadyExists,
10084
+ reason: alreadyExists ? "Resource updated with new definition" : "New resource created"
10085
+ };
10086
+ }
10016
10087
  async createResource({ name, attributes, options = {}, behavior = "user-management" }) {
10017
10088
  if (this.resources[name]) {
10018
10089
  const existingResource = this.resources[name];
@@ -10024,7 +10095,13 @@ class Database extends EventEmitter {
10024
10095
  existingResource.behavior = behavior;
10025
10096
  }
10026
10097
  existingResource.updateAttributes(attributes);
10027
- await this.uploadMetadataFile();
10098
+ const newHash = this.generateDefinitionHash(existingResource.export(), existingResource.behavior);
10099
+ const existingMetadata2 = this.savedMetadata?.resources?.[name];
10100
+ const currentVersion = existingMetadata2?.currentVersion || "v0";
10101
+ const existingVersionData = existingMetadata2?.versions?.[currentVersion];
10102
+ if (!existingVersionData || existingVersionData.hash !== newHash) {
10103
+ await this.uploadMetadataFile();
10104
+ }
10028
10105
  this.emit("s3db.resourceUpdated", name);
10029
10106
  return existingResource;
10030
10107
  }