s3db.js 4.1.2 → 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.iife.js CHANGED
@@ -9798,7 +9798,7 @@ ${JSON.stringify(validation, null, 2)}`
9798
9798
  this.version = "1";
9799
9799
  this.s3dbVersion = (() => {
9800
9800
  try {
9801
- return true ? "4.1.1" : "latest";
9801
+ return true ? "4.1.2" : "latest";
9802
9802
  } catch (e) {
9803
9803
  return "latest";
9804
9804
  }
@@ -9910,16 +9910,21 @@ ${JSON.stringify(validation, null, 2)}`
9910
9910
  /**
9911
9911
  * Generate a consistent hash for a resource definition
9912
9912
  * @param {Object} definition - Resource definition to hash
9913
+ * @param {string} behavior - Resource behavior
9913
9914
  * @returns {string} SHA256 hash
9914
9915
  */
9915
- generateDefinitionHash(definition) {
9916
+ generateDefinitionHash(definition, behavior = void 0) {
9916
9917
  const attributes = definition.attributes;
9917
9918
  const stableAttributes = { ...attributes };
9918
9919
  if (definition.options?.timestamps) {
9919
9920
  delete stableAttributes.createdAt;
9920
9921
  delete stableAttributes.updatedAt;
9921
9922
  }
9922
- const stableString = jsonStableStringify(stableAttributes);
9923
+ const hashObj = {
9924
+ attributes: stableAttributes,
9925
+ behavior: behavior || definition.behavior || "user-management"
9926
+ };
9927
+ const stableString = jsonStableStringify(hashObj);
9923
9928
  return `sha256:${crypto.createHash("sha256").update(stableString).digest("hex")}`;
9924
9929
  }
9925
9930
  /**
@@ -10006,6 +10011,73 @@ ${JSON.stringify(validation, null, 2)}`
10006
10011
  resources: {}
10007
10012
  };
10008
10013
  }
10014
+ /**
10015
+ * Check if a resource exists by name
10016
+ * @param {string} name - Resource name
10017
+ * @returns {boolean} True if resource exists, false otherwise
10018
+ */
10019
+ resourceExists(name) {
10020
+ return !!this.resources[name];
10021
+ }
10022
+ /**
10023
+ * Check if a resource exists with the same definition hash
10024
+ * @param {string} name - Resource name
10025
+ * @param {Object} attributes - Resource attributes
10026
+ * @param {Object} options - Resource options
10027
+ * @param {string} behavior - Resource behavior
10028
+ * @returns {Object} Object with exists flag and hash information
10029
+ */
10030
+ resourceExistsWithSameHash({ name, attributes, options = {}, behavior = "user-management" }) {
10031
+ if (!this.resources[name]) {
10032
+ return { exists: false, sameHash: false, hash: null };
10033
+ }
10034
+ const tempResource = new Resource({
10035
+ name,
10036
+ attributes,
10037
+ behavior,
10038
+ observers: [],
10039
+ client: this.client,
10040
+ version: "temp",
10041
+ options: {
10042
+ cache: this.cache,
10043
+ ...options
10044
+ }
10045
+ });
10046
+ const newHash = this.generateDefinitionHash(tempResource.export(), behavior);
10047
+ const existingHash = this.generateDefinitionHash(this.resources[name].export(), this.resources[name].behavior);
10048
+ return {
10049
+ exists: true,
10050
+ sameHash: newHash === existingHash,
10051
+ hash: newHash,
10052
+ existingHash
10053
+ };
10054
+ }
10055
+ /**
10056
+ * Create a resource only if it doesn't exist with the same definition hash
10057
+ * @param {Object} params - Resource parameters
10058
+ * @param {string} params.name - Resource name
10059
+ * @param {Object} params.attributes - Resource attributes
10060
+ * @param {Object} params.options - Resource options
10061
+ * @param {string} params.behavior - Resource behavior
10062
+ * @returns {Object} Object with resource and created flag
10063
+ */
10064
+ async createResourceIfNotExists({ name, attributes, options = {}, behavior = "user-management" }) {
10065
+ const alreadyExists = !!this.resources[name];
10066
+ const hashCheck = this.resourceExistsWithSameHash({ name, attributes, options, behavior });
10067
+ if (hashCheck.exists && hashCheck.sameHash) {
10068
+ return {
10069
+ resource: this.resources[name],
10070
+ created: false,
10071
+ reason: "Resource already exists with same definition hash"
10072
+ };
10073
+ }
10074
+ const resource = await this.createResource({ name, attributes, options, behavior });
10075
+ return {
10076
+ resource,
10077
+ created: !alreadyExists,
10078
+ reason: alreadyExists ? "Resource updated with new definition" : "New resource created"
10079
+ };
10080
+ }
10009
10081
  async createResource({ name, attributes, options = {}, behavior = "user-management" }) {
10010
10082
  if (this.resources[name]) {
10011
10083
  const existingResource = this.resources[name];
@@ -10017,7 +10089,13 @@ ${JSON.stringify(validation, null, 2)}`
10017
10089
  existingResource.behavior = behavior;
10018
10090
  }
10019
10091
  existingResource.updateAttributes(attributes);
10020
- await this.uploadMetadataFile();
10092
+ const newHash = this.generateDefinitionHash(existingResource.export(), existingResource.behavior);
10093
+ const existingMetadata2 = this.savedMetadata?.resources?.[name];
10094
+ const currentVersion = existingMetadata2?.currentVersion || "v0";
10095
+ const existingVersionData = existingMetadata2?.versions?.[currentVersion];
10096
+ if (!existingVersionData || existingVersionData.hash !== newHash) {
10097
+ await this.uploadMetadataFile();
10098
+ }
10021
10099
  this.emit("s3db.resourceUpdated", name);
10022
10100
  return existingResource;
10023
10101
  }