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.es.js CHANGED
@@ -9804,7 +9804,7 @@ class Database extends EventEmitter {
9804
9804
  this.version = "1";
9805
9805
  this.s3dbVersion = (() => {
9806
9806
  try {
9807
- return true ? "4.1.1" : "latest";
9807
+ return true ? "4.1.2" : "latest";
9808
9808
  } catch (e) {
9809
9809
  return "latest";
9810
9810
  }
@@ -9916,16 +9916,21 @@ class Database extends EventEmitter {
9916
9916
  /**
9917
9917
  * Generate a consistent hash for a resource definition
9918
9918
  * @param {Object} definition - Resource definition to hash
9919
+ * @param {string} behavior - Resource behavior
9919
9920
  * @returns {string} SHA256 hash
9920
9921
  */
9921
- generateDefinitionHash(definition) {
9922
+ generateDefinitionHash(definition, behavior = void 0) {
9922
9923
  const attributes = definition.attributes;
9923
9924
  const stableAttributes = { ...attributes };
9924
9925
  if (definition.options?.timestamps) {
9925
9926
  delete stableAttributes.createdAt;
9926
9927
  delete stableAttributes.updatedAt;
9927
9928
  }
9928
- const stableString = jsonStableStringify(stableAttributes);
9929
+ const hashObj = {
9930
+ attributes: stableAttributes,
9931
+ behavior: behavior || definition.behavior || "user-management"
9932
+ };
9933
+ const stableString = jsonStableStringify(hashObj);
9929
9934
  return `sha256:${createHash("sha256").update(stableString).digest("hex")}`;
9930
9935
  }
9931
9936
  /**
@@ -10012,6 +10017,73 @@ class Database extends EventEmitter {
10012
10017
  resources: {}
10013
10018
  };
10014
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
+ }
10015
10087
  async createResource({ name, attributes, options = {}, behavior = "user-management" }) {
10016
10088
  if (this.resources[name]) {
10017
10089
  const existingResource = this.resources[name];
@@ -10023,7 +10095,13 @@ class Database extends EventEmitter {
10023
10095
  existingResource.behavior = behavior;
10024
10096
  }
10025
10097
  existingResource.updateAttributes(attributes);
10026
- 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
+ }
10027
10105
  this.emit("s3db.resourceUpdated", name);
10028
10106
  return existingResource;
10029
10107
  }