@vedmalex/statemachine 1.0.0-beta.2 → 1.0.0-beta.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/index.js CHANGED
@@ -8,7 +8,9 @@ var TimerScheduler = class {
8
8
  intervalId = null;
9
9
  pollingInterval = 100;
10
10
  // ms
11
- constructor() {
11
+ clock;
12
+ constructor(clock = Date.now) {
13
+ this.clock = clock;
12
14
  }
13
15
  /**
14
16
  * Настройка режима опроса
@@ -32,7 +34,7 @@ var TimerScheduler = class {
32
34
  */
33
35
  start() {
34
36
  if (this.intervalId) return;
35
- this.intervalId = setInterval(() => this.process(), this.pollingInterval);
37
+ this.intervalId = setInterval(() => this.process(this.clock()), this.pollingInterval);
36
38
  }
37
39
  /**
38
40
  * Остановка единого таймера
@@ -51,7 +53,7 @@ var TimerScheduler = class {
51
53
  */
52
54
  schedule(delay, callback) {
53
55
  const token = {};
54
- const executeAt = Date.now() + delay;
56
+ const executeAt = this.clock() + delay;
55
57
  const task = { token, executeAt, callback };
56
58
  this.activeTokens.add(token);
57
59
  this.insert(task);
@@ -67,7 +69,7 @@ var TimerScheduler = class {
67
69
  /**
68
70
  * Обработать очередь (вызывается таймером или вручную)
69
71
  */
70
- process(now = Date.now()) {
72
+ process(now = this.clock()) {
71
73
  while (this.heap.length > 0) {
72
74
  const task = this.heap[0];
73
75
  if (task === void 0) break;
@@ -158,6 +160,23 @@ var TimerScheduler = class {
158
160
  function createDefaultScheduler() {
159
161
  return new TimerScheduler();
160
162
  }
163
+ function createVirtualScheduler(clock) {
164
+ const inner = new TimerScheduler(clock);
165
+ return {
166
+ isActive() {
167
+ return true;
168
+ },
169
+ schedule(delay, callback) {
170
+ return inner.schedule(delay, callback);
171
+ },
172
+ cancel(token) {
173
+ inner.cancel(token);
174
+ },
175
+ process(now) {
176
+ inner.process(now ?? clock());
177
+ }
178
+ };
179
+ }
161
180
 
162
181
  // src/logger.ts
163
182
  var LogLevel = {
@@ -1704,6 +1723,8 @@ var StateMachine = class _StateMachine {
1704
1723
  monitor;
1705
1724
  scheduler;
1706
1725
  errorHandler;
1726
+ clock;
1727
+ schedulerProvided;
1707
1728
  // Свойства
1708
1729
  states;
1709
1730
  events;
@@ -1754,7 +1775,9 @@ var StateMachine = class _StateMachine {
1754
1775
  this.initialState = config.initialState;
1755
1776
  this.logger = options?.logger ?? ConsoleLogger;
1756
1777
  this.monitor = options?.monitor ?? createDefaultMonitor();
1778
+ this.schedulerProvided = options?.scheduler !== void 0;
1757
1779
  this.scheduler = options?.scheduler ?? createDefaultScheduler();
1780
+ this.clock = options?.clock ?? Date.now;
1758
1781
  this.errorHandler = options?.errorHandler ?? createDefaultErrorHandler();
1759
1782
  if (adaptee) {
1760
1783
  if (!isAdapter(adaptee)) {
@@ -1828,7 +1851,7 @@ var StateMachine = class _StateMachine {
1828
1851
  args,
1829
1852
  resolve,
1830
1853
  reject,
1831
- timestamp: Date.now(),
1854
+ timestamp: this.clock(),
1832
1855
  type: "external"
1833
1856
  });
1834
1857
  this.scheduleProcessing();
@@ -1839,7 +1862,7 @@ var StateMachine = class _StateMachine {
1839
1862
  eventName,
1840
1863
  obj,
1841
1864
  args,
1842
- timestamp: Date.now(),
1865
+ timestamp: this.clock(),
1843
1866
  type: "internal"
1844
1867
  });
1845
1868
  return Promise.resolve(true);
@@ -1850,7 +1873,7 @@ var StateMachine = class _StateMachine {
1850
1873
  eventName,
1851
1874
  obj,
1852
1875
  args,
1853
- timestamp: Date.now(),
1876
+ timestamp: this.clock(),
1854
1877
  type: "internal"
1855
1878
  });
1856
1879
  }
@@ -2011,7 +2034,7 @@ var StateMachine = class _StateMachine {
2011
2034
  };
2012
2035
  }
2013
2036
  getQueuedEvents() {
2014
- const now = Date.now();
2037
+ const now = this.clock();
2015
2038
  const mapEvent = (evt) => ({
2016
2039
  id: evt.id,
2017
2040
  event: evt.eventName,
@@ -2130,53 +2153,51 @@ var StateMachine = class _StateMachine {
2130
2153
  return currentParts.every((part, index) => part === expectedParts[index]);
2131
2154
  }
2132
2155
  attachToObject(object, eventMap) {
2133
- for (const objectEventName in eventMap) {
2134
- if (eventMap.hasOwnProperty(objectEventName)) {
2135
- const stateMachineEventName = eventMap[objectEventName];
2136
- if (stateMachineEventName === void 0) continue;
2137
- if (typeof object.addEventListener === "function") {
2138
- object.addEventListener(objectEventName, (...args) => {
2139
- this.fireEvent(stateMachineEventName, object, ...args).catch(
2140
- (e) => this.logger.error(
2141
- "Error firing event",
2142
- {
2143
- objectEventName,
2144
- stateMachineEventName
2145
- },
2146
- /* c8 ignore next */
2147
- e instanceof Error ? e : new Error(String(e))
2148
- )
2149
- );
2150
- });
2151
- } else if (typeof object.on === "function") {
2152
- object.on(objectEventName, (...args) => {
2153
- this.fireEvent(stateMachineEventName, object, ...args).catch(
2154
- (e) => this.logger.error(
2155
- "Error firing event",
2156
- {
2157
- objectEventName,
2158
- stateMachineEventName
2159
- },
2160
- /* c8 ignore next */
2161
- e instanceof Error ? e : new Error(String(e))
2162
- )
2163
- );
2164
- });
2165
- } else {
2166
- object[`on${objectEventName}`] = async (...args) => {
2167
- return this.fireEvent(stateMachineEventName, object, ...args).catch(
2168
- (e) => this.logger.error(
2169
- "Error firing event",
2170
- {
2171
- objectEventName,
2172
- stateMachineEventName
2173
- },
2174
- /* c8 ignore next */
2175
- e instanceof Error ? e : new Error(String(e))
2176
- )
2177
- );
2178
- };
2179
- }
2156
+ for (const objectEventName of Object.keys(eventMap)) {
2157
+ const stateMachineEventName = eventMap[objectEventName];
2158
+ if (stateMachineEventName === void 0) continue;
2159
+ if (typeof object.addEventListener === "function") {
2160
+ object.addEventListener(objectEventName, (...args) => {
2161
+ this.fireEvent(stateMachineEventName, object, ...args).catch(
2162
+ (e) => this.logger.error(
2163
+ "Error firing event",
2164
+ {
2165
+ objectEventName,
2166
+ stateMachineEventName
2167
+ },
2168
+ /* c8 ignore next */
2169
+ e instanceof Error ? e : new Error(String(e))
2170
+ )
2171
+ );
2172
+ });
2173
+ } else if (typeof object.on === "function") {
2174
+ object.on(objectEventName, (...args) => {
2175
+ this.fireEvent(stateMachineEventName, object, ...args).catch(
2176
+ (e) => this.logger.error(
2177
+ "Error firing event",
2178
+ {
2179
+ objectEventName,
2180
+ stateMachineEventName
2181
+ },
2182
+ /* c8 ignore next */
2183
+ e instanceof Error ? e : new Error(String(e))
2184
+ )
2185
+ );
2186
+ });
2187
+ } else {
2188
+ object[`on${objectEventName}`] = async (...args) => {
2189
+ return this.fireEvent(stateMachineEventName, object, ...args).catch(
2190
+ (e) => this.logger.error(
2191
+ "Error firing event",
2192
+ {
2193
+ objectEventName,
2194
+ stateMachineEventName
2195
+ },
2196
+ /* c8 ignore next */
2197
+ e instanceof Error ? e : new Error(String(e))
2198
+ )
2199
+ );
2200
+ };
2180
2201
  }
2181
2202
  }
2182
2203
  }
@@ -2966,19 +2987,22 @@ var StateMachine = class _StateMachine {
2966
2987
  }
2967
2988
  };
2968
2989
  if (this.transitionTimeout && this.transitionTimeout > 0) {
2969
- return Promise.race([
2970
- executeAction(),
2971
- new Promise(
2972
- (_, reject) => setTimeout(
2973
- () => reject(new StateMachineError("Transition timeout", {
2974
- /* c8 ignore next */
2975
- action: typeof actionName === "string" ? actionName : "anonymous",
2976
- phase: "action"
2977
- })),
2978
- this.transitionTimeout
2979
- )
2980
- )
2981
- ]);
2990
+ const timeoutMs = this.transitionTimeout;
2991
+ let timeoutHandle;
2992
+ const timeoutPromise = new Promise((_, reject) => {
2993
+ const fire = () => reject(new StateMachineError("Transition timeout", {
2994
+ /* c8 ignore next */
2995
+ action: typeof actionName === "string" ? actionName : "anonymous",
2996
+ phase: "action"
2997
+ }));
2998
+ timeoutHandle = this.setTimer(fire, timeoutMs);
2999
+ });
3000
+ if (this.schedulerProvided) {
3001
+ return Promise.race([executeAction(), timeoutPromise]).finally(() => {
3002
+ this.clearTimer(timeoutHandle);
3003
+ });
3004
+ }
3005
+ return Promise.race([executeAction(), timeoutPromise]);
2982
3006
  }
2983
3007
  return executeAction();
2984
3008
  }
@@ -3195,7 +3219,7 @@ var StateMachine = class _StateMachine {
3195
3219
  }
3196
3220
  if (toState.invoke && toState.invoke.length > 0) {
3197
3221
  if (!this.stateEntryTimes.has(toStateName)) {
3198
- this.stateEntryTimes.set(toStateName, Date.now());
3222
+ this.stateEntryTimes.set(toStateName, this.clock());
3199
3223
  }
3200
3224
  const timers = [];
3201
3225
  for (const invocation of toState.invoke) {
@@ -3241,6 +3265,9 @@ var StateMachine = class _StateMachine {
3241
3265
  */
3242
3266
  setTimer(callback, delay) {
3243
3267
  const scheduler = this.scheduler;
3268
+ if (this.schedulerProvided) {
3269
+ return scheduler.schedule(delay, callback);
3270
+ }
3244
3271
  if (scheduler.isActive()) {
3245
3272
  return scheduler.schedule(delay, callback);
3246
3273
  }
@@ -3251,6 +3278,10 @@ var StateMachine = class _StateMachine {
3251
3278
  */
3252
3279
  clearTimer(timerId) {
3253
3280
  const scheduler = this.scheduler;
3281
+ if (this.schedulerProvided) {
3282
+ if (timerId !== void 0) scheduler.cancel(timerId);
3283
+ return;
3284
+ }
3254
3285
  if (scheduler.isActive() && typeof timerId === "object" && timerId !== null && !("ref" in timerId)) {
3255
3286
  scheduler.cancel(timerId);
3256
3287
  } else {
@@ -3408,13 +3439,13 @@ var StateMachine = class _StateMachine {
3408
3439
  this.stateEntryTimes.delete(stateName);
3409
3440
  }
3410
3441
  }
3411
- const now = Date.now();
3442
+ const now = this.clock();
3412
3443
  for (const stateName of activeStates) {
3413
3444
  const state = this.states.get(stateName);
3414
3445
  if (!state || !state.invoke || state.invoke.length === 0) continue;
3415
3446
  const entryTime = this.stateEntryTimes.get(stateName);
3416
- const startTime = entryTime || now;
3417
- if (!entryTime) {
3447
+ const startTime = entryTime ?? now;
3448
+ if (entryTime === void 0) {
3418
3449
  this.stateEntryTimes.set(stateName, startTime);
3419
3450
  }
3420
3451
  const elapsed = now - startTime;
@@ -4350,6 +4381,7 @@ export {
4350
4381
  StateMachineError,
4351
4382
  createEnhancedError,
4352
4383
  createMachine,
4384
+ createVirtualScheduler,
4353
4385
  isAdapter,
4354
4386
  isRecoverableError,
4355
4387
  isValidConfig,