@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/README.md +104 -4
- package/dist/index.cjs +105 -72
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +104 -72
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/types/index.d.ts +23 -0
- package/types/scheduler.d.ts +31 -1
- package/types/state_machine.d.ts +2 -0
- package/types/types.d.ts +13 -0
package/dist/index.js
CHANGED
|
@@ -8,7 +8,9 @@ var TimerScheduler = class {
|
|
|
8
8
|
intervalId = null;
|
|
9
9
|
pollingInterval = 100;
|
|
10
10
|
// ms
|
|
11
|
-
|
|
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 =
|
|
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 =
|
|
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:
|
|
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:
|
|
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:
|
|
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 =
|
|
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
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
}
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
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
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
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,
|
|
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 =
|
|
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
|
|
3417
|
-
if (
|
|
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,
|