s3db.js 13.2.1 → 13.2.2

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.cjs.js CHANGED
@@ -23939,7 +23939,7 @@ ${errorDetails}`,
23939
23939
  data = await this.applyVersionMapping(data, objectVersion, this.version);
23940
23940
  }
23941
23941
  data = await this.executeHooks("afterGet", data);
23942
- this._emitWithDeprecation("get", "fetched", data, data.id);
23942
+ this._emitStandardized("get", "fetched", data, data.id);
23943
23943
  const value = data;
23944
23944
  return value;
23945
23945
  }
@@ -24649,7 +24649,7 @@ ${errorDetails}`,
24649
24649
  await this.executeHooks("beforeDelete", objectData);
24650
24650
  const key = this.getResourceKey(id);
24651
24651
  const [ok2, err2, response] = await tryFn(() => this.client.deleteObject(key));
24652
- this._emitWithDeprecation("delete", "deleted", {
24652
+ this._emitStandardized("delete", "deleted", {
24653
24653
  ...objectData,
24654
24654
  $before: { ...objectData },
24655
24655
  $after: null
@@ -24777,7 +24777,7 @@ ${errorDetails}`,
24777
24777
  }
24778
24778
  const count = await this.client.count({ prefix });
24779
24779
  await this.executeHooks("afterCount", { count, partition, partitionValues });
24780
- this._emitWithDeprecation("count", "counted", count);
24780
+ this._emitStandardized("count", "counted", count);
24781
24781
  return count;
24782
24782
  }
24783
24783
  /**
@@ -24800,7 +24800,7 @@ ${errorDetails}`,
24800
24800
  const result = await this.insert(attributes);
24801
24801
  return result;
24802
24802
  });
24803
- this._emitWithDeprecation("insertMany", "inserted-many", objects.length);
24803
+ this._emitStandardized("insertMany", "inserted-many", objects.length);
24804
24804
  return results;
24805
24805
  }
24806
24806
  /**
@@ -24835,7 +24835,7 @@ ${errorDetails}`,
24835
24835
  return response;
24836
24836
  });
24837
24837
  await this.executeHooks("afterDeleteMany", { ids, results });
24838
- this._emitWithDeprecation("deleteMany", "deleted-many", ids.length);
24838
+ this._emitStandardized("deleteMany", "deleted-many", ids.length);
24839
24839
  return results;
24840
24840
  }
24841
24841
  async deleteAll() {
@@ -24844,7 +24844,7 @@ ${errorDetails}`,
24844
24844
  }
24845
24845
  const prefix = `resource=${this.name}/data`;
24846
24846
  const deletedCount = await this.client.deleteAll({ prefix });
24847
- this._emitWithDeprecation("deleteAll", "deleted-all", {
24847
+ this._emitStandardized("deleteAll", "deleted-all", {
24848
24848
  version: this.version,
24849
24849
  prefix,
24850
24850
  deletedCount
@@ -24861,7 +24861,7 @@ ${errorDetails}`,
24861
24861
  }
24862
24862
  const prefix = `resource=${this.name}`;
24863
24863
  const deletedCount = await this.client.deleteAll({ prefix });
24864
- this._emitWithDeprecation("deleteAllData", "deleted-all-data", {
24864
+ this._emitStandardized("deleteAllData", "deleted-all-data", {
24865
24865
  resource: this.name,
24866
24866
  prefix,
24867
24867
  deletedCount
@@ -24931,7 +24931,7 @@ ${errorDetails}`,
24931
24931
  const idPart = parts.find((part) => part.startsWith("id="));
24932
24932
  return idPart ? idPart.replace("id=", "") : null;
24933
24933
  }).filter(Boolean);
24934
- this._emitWithDeprecation("listIds", "listed-ids", ids.length);
24934
+ this._emitStandardized("listIds", "listed-ids", ids.length);
24935
24935
  return ids;
24936
24936
  }
24937
24937
  /**
@@ -24973,12 +24973,12 @@ ${errorDetails}`,
24973
24973
  const [ok, err, ids] = await tryFn(() => this.listIds({ limit, offset }));
24974
24974
  if (!ok) throw err;
24975
24975
  const results = await this.processListResults(ids, "main");
24976
- this._emitWithDeprecation("list", "listed", { count: results.length, errors: 0 });
24976
+ this._emitStandardized("list", "listed", { count: results.length, errors: 0 });
24977
24977
  return results;
24978
24978
  }
24979
24979
  async listPartition({ partition, partitionValues, limit, offset = 0 }) {
24980
24980
  if (!this.config.partitions?.[partition]) {
24981
- this._emitWithDeprecation("list", "listed", { partition, partitionValues, count: 0, errors: 0 });
24981
+ this._emitStandardized("list", "listed", { partition, partitionValues, count: 0, errors: 0 });
24982
24982
  return [];
24983
24983
  }
24984
24984
  const partitionDef = this.config.partitions[partition];
@@ -24988,7 +24988,7 @@ ${errorDetails}`,
24988
24988
  const ids = this.extractIdsFromKeys(keys).slice(offset);
24989
24989
  const filteredIds = limit ? ids.slice(0, limit) : ids;
24990
24990
  const results = await this.processPartitionResults(filteredIds, partition, partitionDef, keys);
24991
- this._emitWithDeprecation("list", "listed", { partition, partitionValues, count: results.length, errors: 0 });
24991
+ this._emitStandardized("list", "listed", { partition, partitionValues, count: results.length, errors: 0 });
24992
24992
  return results;
24993
24993
  }
24994
24994
  /**
@@ -25033,7 +25033,7 @@ ${errorDetails}`,
25033
25033
  }
25034
25034
  return this.handleResourceError(err, id, context);
25035
25035
  });
25036
- this._emitWithDeprecation("list", "listed", { count: results.length, errors: 0 });
25036
+ this._emitStandardized("list", "listed", { count: results.length, errors: 0 });
25037
25037
  return results;
25038
25038
  }
25039
25039
  /**
@@ -25096,10 +25096,10 @@ ${errorDetails}`,
25096
25096
  */
25097
25097
  handleListError(error, { partition, partitionValues }) {
25098
25098
  if (error.message.includes("Partition '") && error.message.includes("' not found")) {
25099
- this._emitWithDeprecation("list", "listed", { partition, partitionValues, count: 0, errors: 1 });
25099
+ this._emitStandardized("list", "listed", { partition, partitionValues, count: 0, errors: 1 });
25100
25100
  return [];
25101
25101
  }
25102
- this._emitWithDeprecation("list", "listed", { partition, partitionValues, count: 0, errors: 1 });
25102
+ this._emitStandardized("list", "listed", { partition, partitionValues, count: 0, errors: 1 });
25103
25103
  return [];
25104
25104
  }
25105
25105
  /**
@@ -25132,7 +25132,7 @@ ${errorDetails}`,
25132
25132
  throw err;
25133
25133
  });
25134
25134
  const finalResults = await this.executeHooks("afterGetMany", results);
25135
- this._emitWithDeprecation("getMany", "fetched-many", ids.length);
25135
+ this._emitStandardized("getMany", "fetched-many", ids.length);
25136
25136
  return finalResults;
25137
25137
  }
25138
25138
  /**
@@ -25218,7 +25218,7 @@ ${errorDetails}`,
25218
25218
  hasTotalItems: totalItems !== null
25219
25219
  }
25220
25220
  };
25221
- this._emitWithDeprecation("page", "paginated", result2);
25221
+ this._emitStandardized("page", "paginated", result2);
25222
25222
  return result2;
25223
25223
  });
25224
25224
  if (ok) return result;
@@ -25288,7 +25288,7 @@ ${errorDetails}`,
25288
25288
  contentType
25289
25289
  }));
25290
25290
  if (!ok2) throw err2;
25291
- this._emitWithDeprecation("setContent", "content-set", { id, contentType, contentLength: buffer.length }, id);
25291
+ this._emitStandardized("setContent", "content-set", { id, contentType, contentLength: buffer.length }, id);
25292
25292
  return updatedData;
25293
25293
  }
25294
25294
  /**
@@ -25317,7 +25317,7 @@ ${errorDetails}`,
25317
25317
  }
25318
25318
  const buffer = Buffer.from(await response.Body.transformToByteArray());
25319
25319
  const contentType = response.ContentType || null;
25320
- this._emitWithDeprecation("content", "content-fetched", { id, contentLength: buffer.length, contentType }, id);
25320
+ this._emitStandardized("content", "content-fetched", { id, contentLength: buffer.length, contentType }, id);
25321
25321
  return {
25322
25322
  buffer,
25323
25323
  contentType
@@ -25349,7 +25349,7 @@ ${errorDetails}`,
25349
25349
  metadata: existingMetadata
25350
25350
  }));
25351
25351
  if (!ok2) throw err2;
25352
- this._emitWithDeprecation("deleteContent", "content-deleted", id, id);
25352
+ this._emitStandardized("deleteContent", "content-deleted", id, id);
25353
25353
  return response;
25354
25354
  }
25355
25355
  /**
@@ -25661,7 +25661,7 @@ ${errorDetails}`,
25661
25661
  const data = await this.get(id);
25662
25662
  data._partition = partitionName;
25663
25663
  data._partitionValues = partitionValues;
25664
- this._emitWithDeprecation("getFromPartition", "partition-fetched", data, data.id);
25664
+ this._emitStandardized("getFromPartition", "partition-fetched", data, data.id);
25665
25665
  return data;
25666
25666
  }
25667
25667
  /**
@@ -25910,6 +25910,123 @@ ${errorDetails}`,
25910
25910
  }
25911
25911
  return out;
25912
25912
  }
25913
+ // ============================================================================
25914
+ // STATE MACHINE METHODS
25915
+ // ============================================================================
25916
+ /**
25917
+ * Send an event to trigger a state transition
25918
+ * @param {string} id - Entity ID
25919
+ * @param {string} event - Event name
25920
+ * @param {Object} [eventData] - Event data
25921
+ * @returns {Promise<Object>} Transition result
25922
+ * @throws {Error} If no state machine is configured for this resource
25923
+ * @example
25924
+ * await orders.state('order-123', 'CONFIRM', { confirmedBy: 'user-456' });
25925
+ */
25926
+ async state(id, event, eventData) {
25927
+ if (!this._stateMachine) {
25928
+ throw new Error(
25929
+ `No state machine configured for resource '${this.name}'. Ensure StateMachinePlugin is installed and configured for this resource.`
25930
+ );
25931
+ }
25932
+ return this._stateMachine.send(id, event, eventData);
25933
+ }
25934
+ /**
25935
+ * Get current state of an entity
25936
+ * @param {string} id - Entity ID
25937
+ * @returns {Promise<string>} Current state
25938
+ * @throws {Error} If no state machine is configured for this resource
25939
+ * @example
25940
+ * const currentState = await orders.getState('order-123');
25941
+ */
25942
+ async getState(id) {
25943
+ if (!this._stateMachine) {
25944
+ throw new Error(
25945
+ `No state machine configured for resource '${this.name}'. Ensure StateMachinePlugin is installed and configured for this resource.`
25946
+ );
25947
+ }
25948
+ return this._stateMachine.getState(id);
25949
+ }
25950
+ /**
25951
+ * Check if a transition is valid
25952
+ * @param {string} id - Entity ID
25953
+ * @param {string} event - Event name
25954
+ * @returns {Promise<boolean>} True if transition is valid
25955
+ * @throws {Error} If no state machine is configured for this resource
25956
+ * @example
25957
+ * const canConfirm = await orders.canTransition('order-123', 'CONFIRM');
25958
+ */
25959
+ async canTransition(id, event) {
25960
+ if (!this._stateMachine) {
25961
+ throw new Error(
25962
+ `No state machine configured for resource '${this.name}'. Ensure StateMachinePlugin is installed and configured for this resource.`
25963
+ );
25964
+ }
25965
+ return this._stateMachine.canTransition(id, event);
25966
+ }
25967
+ /**
25968
+ * Get all valid events for the current state
25969
+ * @param {string} id - Entity ID
25970
+ * @returns {Promise<Array<string>>} Array of valid event names
25971
+ * @throws {Error} If no state machine is configured for this resource
25972
+ * @example
25973
+ * const events = await orders.getValidEvents('order-123');
25974
+ * // Returns: ['SHIP', 'CANCEL']
25975
+ */
25976
+ async getValidEvents(id) {
25977
+ if (!this._stateMachine) {
25978
+ throw new Error(
25979
+ `No state machine configured for resource '${this.name}'. Ensure StateMachinePlugin is installed and configured for this resource.`
25980
+ );
25981
+ }
25982
+ return this._stateMachine.getValidEvents(id);
25983
+ }
25984
+ /**
25985
+ * Initialize entity with initial state
25986
+ * @param {string} id - Entity ID
25987
+ * @param {Object} [context] - Initial context data
25988
+ * @returns {Promise<void>}
25989
+ * @throws {Error} If no state machine is configured for this resource
25990
+ * @example
25991
+ * await orders.initializeState('order-456', { customerId: 'user-123' });
25992
+ */
25993
+ async initializeState(id, context) {
25994
+ if (!this._stateMachine) {
25995
+ throw new Error(
25996
+ `No state machine configured for resource '${this.name}'. Ensure StateMachinePlugin is installed and configured for this resource.`
25997
+ );
25998
+ }
25999
+ return this._stateMachine.initializeEntity(id, context);
26000
+ }
26001
+ /**
26002
+ * Get transition history for an entity
26003
+ * @param {string} id - Entity ID
26004
+ * @param {Object} [options] - Query options
26005
+ * @param {number} [options.limit=100] - Maximum number of transitions
26006
+ * @param {Date} [options.fromDate] - Filter from date
26007
+ * @param {Date} [options.toDate] - Filter to date
26008
+ * @returns {Promise<Array<Object>>} Transition history
26009
+ * @throws {Error} If no state machine is configured for this resource
26010
+ * @example
26011
+ * const history = await orders.getStateHistory('order-123', { limit: 50 });
26012
+ */
26013
+ async getStateHistory(id, options) {
26014
+ if (!this._stateMachine) {
26015
+ throw new Error(
26016
+ `No state machine configured for resource '${this.name}'. Ensure StateMachinePlugin is installed and configured for this resource.`
26017
+ );
26018
+ }
26019
+ return this._stateMachine.getTransitionHistory(id, options);
26020
+ }
26021
+ /**
26022
+ * Internal method to attach state machine instance
26023
+ * This is called by StateMachinePlugin during initialization
26024
+ * @private
26025
+ * @param {Object} stateMachine - State machine instance
26026
+ */
26027
+ _attachStateMachine(stateMachine) {
26028
+ this._stateMachine = stateMachine;
26029
+ }
25913
26030
  }
25914
26031
  function validateResourceConfig(config) {
25915
26032
  const errors = [];
@@ -26070,7 +26187,7 @@ class Database extends EventEmitter {
26070
26187
  })();
26071
26188
  this.version = "1";
26072
26189
  this.s3dbVersion = (() => {
26073
- const [ok, err, version] = tryFn(() => true ? "13.2.1" : "latest");
26190
+ const [ok, err, version] = tryFn(() => true ? "13.2.2" : "latest");
26074
26191
  return ok ? version : "latest";
26075
26192
  })();
26076
26193
  this._resourcesMap = {};
@@ -30620,6 +30737,7 @@ class StateMachinePlugin extends Plugin {
30620
30737
  // entityId -> currentState
30621
30738
  });
30622
30739
  }
30740
+ await this._attachStateMachinesToResources();
30623
30741
  await this._setupTriggers();
30624
30742
  this.emit("db:plugin:initialized", { machines: Array.from(this.machines.keys()) });
30625
30743
  }
@@ -31461,6 +31579,58 @@ class StateMachinePlugin extends Plugin {
31461
31579
  }
31462
31580
  }
31463
31581
  }
31582
+ /**
31583
+ * Attach state machine instances to their associated resources
31584
+ * This enables the resource API: resource.state(id, event)
31585
+ * @private
31586
+ */
31587
+ async _attachStateMachinesToResources() {
31588
+ for (const [machineName, machineConfig] of Object.entries(this.config.stateMachines)) {
31589
+ const resourceConfig = machineConfig.config || machineConfig;
31590
+ if (!resourceConfig.resource) {
31591
+ if (this.config.verbose) {
31592
+ console.log(`[StateMachinePlugin] Machine '${machineName}' has no resource configured, skipping attachment`);
31593
+ }
31594
+ continue;
31595
+ }
31596
+ let resource;
31597
+ if (typeof resourceConfig.resource === "string") {
31598
+ resource = this.database.resources[resourceConfig.resource];
31599
+ if (!resource) {
31600
+ console.warn(
31601
+ `[StateMachinePlugin] Resource '${resourceConfig.resource}' not found for machine '${machineName}'. Resource API will not be available.`
31602
+ );
31603
+ continue;
31604
+ }
31605
+ } else {
31606
+ resource = resourceConfig.resource;
31607
+ }
31608
+ const machineProxy = {
31609
+ send: async (id, event, eventData) => {
31610
+ return this.send(machineName, id, event, eventData);
31611
+ },
31612
+ getState: async (id) => {
31613
+ return this.getState(machineName, id);
31614
+ },
31615
+ canTransition: async (id, event) => {
31616
+ return this.canTransition(machineName, id, event);
31617
+ },
31618
+ getValidEvents: async (id) => {
31619
+ return this.getValidEvents(machineName, id);
31620
+ },
31621
+ initializeEntity: async (id, context) => {
31622
+ return this.initializeEntity(machineName, id, context);
31623
+ },
31624
+ getTransitionHistory: async (id, options) => {
31625
+ return this.getTransitionHistory(machineName, id, options);
31626
+ }
31627
+ };
31628
+ resource._attachStateMachine(machineProxy);
31629
+ if (this.config.verbose) {
31630
+ console.log(`[StateMachinePlugin] Attached machine '${machineName}' to resource '${resource.name}'`);
31631
+ }
31632
+ }
31633
+ }
31464
31634
  async start() {
31465
31635
  if (this.config.verbose) {
31466
31636
  console.log(`[StateMachinePlugin] Started with ${this.machines.size} state machines`);