@hkdigital/lib-core 0.4.24 → 0.4.25
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/logging/internal/adapters/pino.d.ts +7 -3
- package/dist/logging/internal/adapters/pino.js +200 -67
- package/dist/logging/internal/transports/pretty-transport.d.ts +17 -0
- package/dist/logging/internal/transports/pretty-transport.js +104 -0
- package/dist/logging/internal/transports/test-transport.d.ts +19 -0
- package/dist/logging/internal/transports/test-transport.js +79 -0
- package/dist/network/states/NetworkLoader.svelte.d.ts +6 -0
- package/dist/network/states/NetworkLoader.svelte.js +15 -2
- package/dist/services/service-base/ServiceBase.d.ts +12 -8
- package/dist/services/service-base/ServiceBase.js +8 -6
- package/dist/state/machines/finite-state-machine/FiniteStateMachine.svelte.d.ts +3 -7
- package/dist/state/machines/finite-state-machine/FiniteStateMachine.svelte.js +57 -27
- package/dist/state/machines/finite-state-machine/README.md +17 -15
- package/dist/state/machines/finite-state-machine/constants.d.ts +13 -0
- package/dist/state/machines/finite-state-machine/constants.js +15 -0
- package/dist/state/machines/finite-state-machine/index.d.ts +1 -0
- package/dist/state/machines/finite-state-machine/index.js +1 -0
- package/dist/state/machines/finite-state-machine/typedef.js +5 -5
- package/dist/state/machines/loading-state-machine/LoadingStateMachine.svelte.d.ts +12 -0
- package/dist/state/machines/loading-state-machine/LoadingStateMachine.svelte.js +27 -2
- package/dist/state/machines/loading-state-machine/README.md +66 -18
- package/dist/state/machines/loading-state-machine/constants.d.ts +2 -0
- package/dist/state/machines/loading-state-machine/constants.js +2 -0
- package/package.json +1 -1
- package/dist/logging/internal/adapters/pino.js__ +0 -260
|
@@ -13,7 +13,8 @@ import {
|
|
|
13
13
|
ERROR,
|
|
14
14
|
LOADED,
|
|
15
15
|
UNLOAD,
|
|
16
|
-
INITIAL
|
|
16
|
+
INITIAL,
|
|
17
|
+
CANCEL
|
|
17
18
|
} from '../../state/machines.js';
|
|
18
19
|
|
|
19
20
|
import * as expect from '../../util/expect.js';
|
|
@@ -129,7 +130,10 @@ export default class NetworkLoader {
|
|
|
129
130
|
case STATE_CANCELLED:
|
|
130
131
|
{
|
|
131
132
|
// console.log('NetworkLoader:cancelled');
|
|
132
|
-
|
|
133
|
+
if (this._abortLoading) {
|
|
134
|
+
this._abortLoading();
|
|
135
|
+
this._abortLoading = null;
|
|
136
|
+
}
|
|
133
137
|
}
|
|
134
138
|
break;
|
|
135
139
|
|
|
@@ -157,6 +161,15 @@ export default class NetworkLoader {
|
|
|
157
161
|
this._state.send(UNLOAD);
|
|
158
162
|
}
|
|
159
163
|
|
|
164
|
+
/**
|
|
165
|
+
* Abort the current loading operation
|
|
166
|
+
* - Only works when in STATE_LOADING
|
|
167
|
+
* - Aborts network requests and transitions to STATE_CANCELLED
|
|
168
|
+
*/
|
|
169
|
+
doAbort() {
|
|
170
|
+
this._state.send(CANCEL);
|
|
171
|
+
}
|
|
172
|
+
|
|
160
173
|
/**
|
|
161
174
|
* Get network data size in bytes
|
|
162
175
|
* - Info comes from the content length response header
|
|
@@ -156,36 +156,40 @@ export class ServiceBase extends EventEmitter {
|
|
|
156
156
|
/**
|
|
157
157
|
* Set the service state and emit event
|
|
158
158
|
*
|
|
159
|
-
* @
|
|
159
|
+
* @protected
|
|
160
|
+
*
|
|
160
161
|
* @param {ServiceState} newState - New state value
|
|
161
162
|
* @emits {StateChangeEvent} EVENT_STATE_CHANGED
|
|
162
163
|
*/
|
|
163
|
-
|
|
164
|
+
protected _setState(newState: ServiceState): void;
|
|
164
165
|
/**
|
|
165
166
|
* Set the service target state and emit event
|
|
166
167
|
*
|
|
167
|
-
* @
|
|
168
|
+
* @protected
|
|
169
|
+
*
|
|
168
170
|
* @param {ServiceState} newTargetState - New target state value
|
|
169
171
|
* @emits {TargetStateChangeEvent} EVENT_TARGET_STATE_CHANGED
|
|
170
172
|
*/
|
|
171
|
-
|
|
173
|
+
protected _setTargetState(newTargetState: ServiceState): void;
|
|
172
174
|
/**
|
|
173
175
|
* Set the health status and emit event if changed
|
|
174
176
|
*
|
|
175
|
-
* @
|
|
177
|
+
* @protected
|
|
178
|
+
*
|
|
176
179
|
* @param {boolean} healthy - New health status
|
|
177
180
|
* @emits {HealthChangeEvent} EVENT_HEALTH_CHANGED
|
|
178
181
|
*/
|
|
179
|
-
|
|
182
|
+
protected _setHealthy(healthy: boolean): void;
|
|
180
183
|
/**
|
|
181
184
|
* Set error state and emit error event
|
|
182
185
|
*
|
|
183
|
-
* @
|
|
186
|
+
* @protected
|
|
187
|
+
*
|
|
184
188
|
* @param {string} operation - Operation that failed
|
|
185
189
|
* @param {Error} error - Error that occurred
|
|
186
190
|
* @emits {ServiceErrorEvent} EVENT_ERROR
|
|
187
191
|
*/
|
|
188
|
-
|
|
192
|
+
protected _setError(operation: string, error: Error): void;
|
|
189
193
|
#private;
|
|
190
194
|
}
|
|
191
195
|
export default ServiceBase;
|
|
@@ -447,12 +447,11 @@ export class ServiceBase extends EventEmitter {
|
|
|
447
447
|
return {};
|
|
448
448
|
}
|
|
449
449
|
|
|
450
|
-
// Private methods
|
|
451
|
-
|
|
452
450
|
/**
|
|
453
451
|
* Set the service state and emit event
|
|
454
452
|
*
|
|
455
|
-
* @
|
|
453
|
+
* @protected
|
|
454
|
+
*
|
|
456
455
|
* @param {ServiceState} newState - New state value
|
|
457
456
|
* @emits {StateChangeEvent} EVENT_STATE_CHANGED
|
|
458
457
|
*/
|
|
@@ -473,7 +472,8 @@ export class ServiceBase extends EventEmitter {
|
|
|
473
472
|
/**
|
|
474
473
|
* Set the service target state and emit event
|
|
475
474
|
*
|
|
476
|
-
* @
|
|
475
|
+
* @protected
|
|
476
|
+
*
|
|
477
477
|
* @param {ServiceState} newTargetState - New target state value
|
|
478
478
|
* @emits {TargetStateChangeEvent} EVENT_TARGET_STATE_CHANGED
|
|
479
479
|
*/
|
|
@@ -493,7 +493,8 @@ export class ServiceBase extends EventEmitter {
|
|
|
493
493
|
/**
|
|
494
494
|
* Set the health status and emit event if changed
|
|
495
495
|
*
|
|
496
|
-
* @
|
|
496
|
+
* @protected
|
|
497
|
+
*
|
|
497
498
|
* @param {boolean} healthy - New health status
|
|
498
499
|
* @emits {HealthChangeEvent} EVENT_HEALTH_CHANGED
|
|
499
500
|
*/
|
|
@@ -515,7 +516,8 @@ export class ServiceBase extends EventEmitter {
|
|
|
515
516
|
/**
|
|
516
517
|
* Set error state and emit error event
|
|
517
518
|
*
|
|
518
|
-
* @
|
|
519
|
+
* @protected
|
|
520
|
+
*
|
|
519
521
|
* @param {string} operation - Operation that failed
|
|
520
522
|
* @param {Error} error - Error that occurred
|
|
521
523
|
* @emits {ServiceErrorEvent} EVENT_ERROR
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Initial code borrowed from:
|
|
3
|
-
*
|
|
4
|
-
* @see {@link https://runed.dev/docs/utilities/finite-state-machine}
|
|
5
|
-
*/
|
|
6
1
|
/** @typedef {import('./typedef.js').StateTransitionMetadata} StateTransitionMetadata */
|
|
7
2
|
/** @typedef {import('./typedef.js').OnEnterCallback} OnEnterCallback */
|
|
8
3
|
/** @typedef {import('./typedef.js').OnExitCallback} OnExitCallback */
|
|
@@ -13,9 +8,9 @@
|
|
|
13
8
|
*/
|
|
14
9
|
export function isLifecycleFnMeta(meta: any): boolean;
|
|
15
10
|
/**
|
|
16
|
-
* Defines a Finite State Machine
|
|
11
|
+
* Defines a Finite State Machine that extends EventEmitter
|
|
17
12
|
*/
|
|
18
|
-
export default class FiniteStateMachine {
|
|
13
|
+
export default class FiniteStateMachine extends EventEmitter {
|
|
19
14
|
/**
|
|
20
15
|
* Constructor
|
|
21
16
|
*
|
|
@@ -58,3 +53,4 @@ export default class FiniteStateMachine {
|
|
|
58
53
|
export type StateTransitionMetadata = import("./typedef.js").StateTransitionMetadata;
|
|
59
54
|
export type OnEnterCallback = import("./typedef.js").OnEnterCallback;
|
|
60
55
|
export type OnExitCallback = import("./typedef.js").OnExitCallback;
|
|
56
|
+
import EventEmitter from '../../../generic/events/classes/EventEmitter.js';
|
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
* @see {@link https://runed.dev/docs/utilities/finite-state-machine}
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { isTestEnv } from '../../../util/env.js';
|
|
8
|
+
import EventEmitter from '../../../generic/events/classes/EventEmitter.js';
|
|
9
|
+
import { ENTER, EXIT } from './constants.js';
|
|
10
|
+
|
|
7
11
|
/** @typedef {import('./typedef.js').StateTransitionMetadata} StateTransitionMetadata */
|
|
8
12
|
/** @typedef {import('./typedef.js').OnEnterCallback} OnEnterCallback */
|
|
9
13
|
/** @typedef {import('./typedef.js').OnExitCallback} OnExitCallback */
|
|
@@ -25,9 +29,9 @@ export function isLifecycleFnMeta(meta) {
|
|
|
25
29
|
}
|
|
26
30
|
|
|
27
31
|
/**
|
|
28
|
-
* Defines a Finite State Machine
|
|
32
|
+
* Defines a Finite State Machine that extends EventEmitter
|
|
29
33
|
*/
|
|
30
|
-
export default class FiniteStateMachine {
|
|
34
|
+
export default class FiniteStateMachine extends EventEmitter {
|
|
31
35
|
#current = $state();
|
|
32
36
|
states;
|
|
33
37
|
#timeout = {};
|
|
@@ -38,6 +42,9 @@ export default class FiniteStateMachine {
|
|
|
38
42
|
/** @type {OnExitCallback | null} */
|
|
39
43
|
onexit = null;
|
|
40
44
|
|
|
45
|
+
/** @type {boolean} */
|
|
46
|
+
#enableConsoleWarnings = !isTestEnv;
|
|
47
|
+
|
|
41
48
|
/**
|
|
42
49
|
* Constructor
|
|
43
50
|
*
|
|
@@ -45,16 +52,22 @@ export default class FiniteStateMachine {
|
|
|
45
52
|
* @param {{ [key: string]: { [key: string]: (string|((...args: any[])=>void)) } }} states
|
|
46
53
|
*/
|
|
47
54
|
constructor(initial, states) {
|
|
55
|
+
super();
|
|
48
56
|
this.#current = initial;
|
|
49
57
|
this.states = states;
|
|
50
58
|
|
|
51
59
|
// synthetically trigger _enter for the initial state.
|
|
52
|
-
|
|
60
|
+
const initialMetadata = {
|
|
53
61
|
from: null,
|
|
54
62
|
to: initial,
|
|
55
63
|
event: null,
|
|
56
64
|
args: []
|
|
57
|
-
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
this.#executeAction('_enter', initialMetadata);
|
|
68
|
+
|
|
69
|
+
// Emit ENTER event for external listeners for initial state
|
|
70
|
+
this.emit(ENTER, { state: initial, metadata: initialMetadata });
|
|
58
71
|
}
|
|
59
72
|
|
|
60
73
|
/**
|
|
@@ -70,45 +83,61 @@ export default class FiniteStateMachine {
|
|
|
70
83
|
|
|
71
84
|
// Call onexit callback before leaving current state
|
|
72
85
|
this.onexit?.(this.#current, metadata);
|
|
73
|
-
|
|
74
|
-
|
|
86
|
+
|
|
87
|
+
// Emit EXIT event for external listeners
|
|
88
|
+
this.emit(EXIT, { state: this.#current, metadata });
|
|
89
|
+
|
|
90
|
+
this.#executeAction('_exit', metadata);
|
|
75
91
|
this.#current = newState;
|
|
76
|
-
this.#
|
|
77
|
-
|
|
92
|
+
this.#executeAction('_enter', metadata);
|
|
93
|
+
|
|
94
|
+
// Emit ENTER event for external listeners
|
|
95
|
+
this.emit(ENTER, { state: newState, metadata });
|
|
96
|
+
|
|
78
97
|
// Call onenter callback after state change
|
|
79
98
|
this.onenter?.(newState, metadata);
|
|
80
99
|
}
|
|
81
100
|
|
|
82
101
|
/**
|
|
83
|
-
*
|
|
102
|
+
* Execute an action for the given event
|
|
84
103
|
*
|
|
85
104
|
* @param {string} event
|
|
86
105
|
* @param {any} args
|
|
87
106
|
*/
|
|
88
|
-
#
|
|
107
|
+
#executeAction(event, ...args) {
|
|
89
108
|
const action =
|
|
90
109
|
this.states[this.#current]?.[event] ?? this.states['*']?.[event];
|
|
110
|
+
|
|
91
111
|
if (action instanceof Function) {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
112
|
+
switch (event) {
|
|
113
|
+
// Internal lifecycle events
|
|
114
|
+
case ENTER:
|
|
115
|
+
case EXIT:
|
|
116
|
+
if (isLifecycleFnMeta(args[0])) {
|
|
117
|
+
return action(args[0]);
|
|
118
|
+
} else {
|
|
119
|
+
throw new Error(`Invalid metadata passed to lifecycle function`);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Normal state events
|
|
123
|
+
default:
|
|
124
|
+
return action(...args);
|
|
125
|
+
}
|
|
126
|
+
} else if (typeof action === 'string') {
|
|
127
|
+
// No function execution => just return target state
|
|
128
|
+
return action;
|
|
129
|
+
} else {
|
|
130
|
+
// No action found - only warn for non-lifecycle events
|
|
131
|
+
if (event !== ENTER && event !== EXIT) {
|
|
132
|
+
if (this.#enableConsoleWarnings) {
|
|
96
133
|
console.warn(
|
|
97
|
-
'
|
|
134
|
+
'No action defined for event',
|
|
135
|
+
event,
|
|
136
|
+
'in state',
|
|
137
|
+
this.#current
|
|
98
138
|
);
|
|
99
139
|
}
|
|
100
|
-
} else {
|
|
101
|
-
return action(...args);
|
|
102
140
|
}
|
|
103
|
-
} else if (typeof action === 'string') {
|
|
104
|
-
return action;
|
|
105
|
-
} else if (event !== '_enter' && event !== '_exit') {
|
|
106
|
-
console.warn(
|
|
107
|
-
'No action defined for event',
|
|
108
|
-
event,
|
|
109
|
-
'in state',
|
|
110
|
-
this.#current
|
|
111
|
-
);
|
|
112
141
|
}
|
|
113
142
|
}
|
|
114
143
|
/**
|
|
@@ -118,7 +147,8 @@ export default class FiniteStateMachine {
|
|
|
118
147
|
* @param {any[]} args
|
|
119
148
|
*/
|
|
120
149
|
send(event, ...args) {
|
|
121
|
-
const newState = this.#
|
|
150
|
+
const newState = this.#executeAction(event, ...args);
|
|
151
|
+
|
|
122
152
|
if (newState && newState !== this.#current) {
|
|
123
153
|
this.#transition(newState, event, args);
|
|
124
154
|
}
|
|
@@ -39,7 +39,7 @@ console.log(machine.current); // 'paused'
|
|
|
39
39
|
## Constructor
|
|
40
40
|
|
|
41
41
|
```javascript
|
|
42
|
-
new FiniteStateMachine(initialState, states)
|
|
42
|
+
new FiniteStateMachine(initialState, states);
|
|
43
43
|
```
|
|
44
44
|
|
|
45
45
|
- `initialState`: The starting state (string)
|
|
@@ -160,7 +160,7 @@ const machine = new FiniteStateMachine('idle', {
|
|
|
160
160
|
resume: 'running'
|
|
161
161
|
},
|
|
162
162
|
'*': {
|
|
163
|
-
reset: 'idle',
|
|
163
|
+
reset: 'idle', // Available from any state
|
|
164
164
|
error: 'error'
|
|
165
165
|
},
|
|
166
166
|
error: {
|
|
@@ -171,7 +171,7 @@ const machine = new FiniteStateMachine('idle', {
|
|
|
171
171
|
|
|
172
172
|
### Same-State Transitions
|
|
173
173
|
|
|
174
|
-
Same-state transitions (e.g., `idle → idle`) do NOT trigger enter/exit
|
|
174
|
+
Same-state transitions (e.g., `idle → idle`) do NOT trigger enter/exit
|
|
175
175
|
callbacks. The state remains unchanged.
|
|
176
176
|
|
|
177
177
|
```javascript
|
|
@@ -247,7 +247,7 @@ machine.onenter = (state, metadata) => {
|
|
|
247
247
|
The callbacks are executed in this specific order during state transitions:
|
|
248
248
|
|
|
249
249
|
1. **`onexit`** - Called before leaving current state
|
|
250
|
-
2. **`_exit`** - Individual state exit callback
|
|
250
|
+
2. **`_exit`** - Individual state exit callback
|
|
251
251
|
3. **`_enter`** - Individual state enter callback
|
|
252
252
|
4. **`onenter`** - Called after entering new state
|
|
253
253
|
|
|
@@ -268,7 +268,7 @@ machine.onexit = (state) => console.log(`3. onexit ${state}`);
|
|
|
268
268
|
machine.onenter = (state) => console.log(`6. onenter ${state}`);
|
|
269
269
|
|
|
270
270
|
// Initial state triggers _enter and onenter
|
|
271
|
-
// Output:
|
|
271
|
+
// Output:
|
|
272
272
|
// 2. idle _enter
|
|
273
273
|
// 6. onenter idle
|
|
274
274
|
|
|
@@ -276,7 +276,7 @@ machine.send('start');
|
|
|
276
276
|
// Output:
|
|
277
277
|
// 3. onexit idle
|
|
278
278
|
// 4. idle _exit
|
|
279
|
-
// 5. loading _enter
|
|
279
|
+
// 5. loading _enter
|
|
280
280
|
// 6. onenter loading
|
|
281
281
|
```
|
|
282
282
|
|
|
@@ -294,6 +294,7 @@ When using FiniteStateMachine with Svelte's reactive derived state, use this pat
|
|
|
294
294
|
### Pattern: Separate onenter from Reactive Monitoring
|
|
295
295
|
|
|
296
296
|
**✅ Use `onexit` and `onenter` for immediate state actions:**
|
|
297
|
+
|
|
297
298
|
```javascript
|
|
298
299
|
const machine = new FiniteStateMachine('idle', {
|
|
299
300
|
idle: { start: 'loading' },
|
|
@@ -326,6 +327,7 @@ machine.onenter = (state) => {
|
|
|
326
327
|
```
|
|
327
328
|
|
|
328
329
|
**✅ Use `$effect` for reactive state monitoring:**
|
|
330
|
+
|
|
329
331
|
```javascript
|
|
330
332
|
// Monitor derived/computed values and trigger transitions when conditions are met
|
|
331
333
|
$effect(() => {
|
|
@@ -341,8 +343,8 @@ $effect(() => {
|
|
|
341
343
|
### Why This Pattern?
|
|
342
344
|
|
|
343
345
|
- **`onexit`**: Handles cleanup and teardown when leaving states
|
|
344
|
-
- **`onenter`**: Handles setup and initialization when entering states
|
|
345
|
-
- **`$effect`**: Handles reactive monitoring of derived/computed values over time
|
|
346
|
+
- **`onenter`**: Handles setup and initialization when entering states
|
|
347
|
+
- **`$effect`**: Handles reactive monitoring of derived/computed values over time
|
|
346
348
|
- **Avoids timing issues**: Doesn't check completion status immediately on state entry
|
|
347
349
|
- **Leverages Svelte reactivity**: Automatically responds to changes in reactive variables
|
|
348
350
|
- **Clean separation**: State machine handles discrete transitions, effects handle continuous monitoring
|
|
@@ -365,9 +367,9 @@ export default class TaskProcessor {
|
|
|
365
367
|
finished: { reset: 'idle' },
|
|
366
368
|
failed: { retry: 'processing', reset: 'idle' }
|
|
367
369
|
});
|
|
368
|
-
|
|
370
|
+
|
|
369
371
|
#tasks = $state([]);
|
|
370
|
-
|
|
372
|
+
|
|
371
373
|
// Derived progress calculation
|
|
372
374
|
#progress = $derived.by(() => {
|
|
373
375
|
let completed = 0;
|
|
@@ -419,19 +421,19 @@ export default class TaskProcessor {
|
|
|
419
421
|
// Component.svelte
|
|
420
422
|
<script>
|
|
421
423
|
import { FiniteStateMachine } from '$lib/state/classes.js';
|
|
422
|
-
|
|
424
|
+
|
|
423
425
|
const machine = new FiniteStateMachine('idle', {
|
|
424
426
|
idle: { start: 'loading' },
|
|
425
427
|
loading: { complete: 'loaded', error: 'error' },
|
|
426
428
|
loaded: { reset: 'idle' },
|
|
427
429
|
error: { retry: 'loading', reset: 'idle' }
|
|
428
430
|
});
|
|
429
|
-
|
|
431
|
+
|
|
430
432
|
// Reactive state updates
|
|
431
433
|
$effect(() => {
|
|
432
434
|
console.log('State changed to:', machine.current);
|
|
433
435
|
});
|
|
434
|
-
|
|
436
|
+
|
|
435
437
|
// Handle state-specific actions
|
|
436
438
|
machine.onexit = (state) => {
|
|
437
439
|
switch (state) {
|
|
@@ -475,7 +477,7 @@ console.log(machine.current); // Still 'idle'
|
|
|
475
477
|
|
|
476
478
|
## Best Practices
|
|
477
479
|
|
|
478
|
-
1. **Clear state names**: Use descriptive state names like `loading`, `error`,
|
|
480
|
+
1. **Clear state names**: Use descriptive state names like `loading`, `error`,
|
|
479
481
|
`authenticated` rather than generic ones
|
|
480
482
|
2. **Minimal state count**: Keep the number of states manageable
|
|
481
483
|
3. **Explicit transitions**: Define all valid transitions explicitly
|
|
@@ -542,4 +544,4 @@ The state machine includes comprehensive tests covering:
|
|
|
542
544
|
- Immediate state access
|
|
543
545
|
- Callback execution order
|
|
544
546
|
|
|
545
|
-
See `FiniteStateMachine.test.js` for detailed examples.
|
|
547
|
+
See `FiniteStateMachine.test.js` for detailed examples.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Constants for FiniteStateMachine events
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Event emitted when entering a state
|
|
6
|
+
* @type {string}
|
|
7
|
+
*/
|
|
8
|
+
export const ENTER: string;
|
|
9
|
+
/**
|
|
10
|
+
* Event emitted when exiting a state
|
|
11
|
+
* @type {string}
|
|
12
|
+
*/
|
|
13
|
+
export const EXIT: string;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Constants for FiniteStateMachine events
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Event emitted when entering a state
|
|
7
|
+
* @type {string}
|
|
8
|
+
*/
|
|
9
|
+
export const ENTER = 'enter';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Event emitted when exiting a state
|
|
13
|
+
* @type {string}
|
|
14
|
+
*/
|
|
15
|
+
export const EXIT = 'exit';
|
|
@@ -4,25 +4,25 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Metadata object passed to state transition callbacks
|
|
7
|
-
*
|
|
7
|
+
*
|
|
8
8
|
* @typedef {object} StateTransitionMetadata
|
|
9
9
|
* @property {string} from - The state being exited
|
|
10
|
-
* @property {string} to - The state being entered
|
|
10
|
+
* @property {string} to - The state being entered
|
|
11
11
|
* @property {string} event - The event that triggered the transition
|
|
12
12
|
* @property {any[]} args - Arguments passed to the send() method
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Callback function called when entering a state
|
|
17
|
-
*
|
|
17
|
+
*
|
|
18
18
|
* @typedef {function(string, StateTransitionMetadata): void} OnEnterCallback
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* Callback function called when exiting a state
|
|
23
|
-
*
|
|
23
|
+
*
|
|
24
24
|
* @typedef {function(string, StateTransitionMetadata): void} OnExitCallback
|
|
25
25
|
*/
|
|
26
26
|
|
|
27
27
|
// Export types for external use (this is just for JSDoc, no actual exports needed)
|
|
28
|
-
export {};
|
|
28
|
+
export {};
|
|
@@ -5,6 +5,18 @@ export default class LoadingStateMachine extends FiniteStateMachine {
|
|
|
5
5
|
constructor();
|
|
6
6
|
/** The last error */
|
|
7
7
|
get error(): Error;
|
|
8
|
+
/**
|
|
9
|
+
* Transition to timeout state
|
|
10
|
+
* - Only valid when currently loading
|
|
11
|
+
* - Useful for external timeout management
|
|
12
|
+
*/
|
|
13
|
+
doTimeout(): void;
|
|
14
|
+
/**
|
|
15
|
+
* Transition to cancelled state
|
|
16
|
+
* - Only valid when currently loading
|
|
17
|
+
* - Useful for external cancellation management
|
|
18
|
+
*/
|
|
19
|
+
doCancel(): void;
|
|
8
20
|
#private;
|
|
9
21
|
}
|
|
10
22
|
import FiniteStateMachine from '../finite-state-machine/FiniteStateMachine.svelte.js';
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
STATE_LOADED,
|
|
11
11
|
STATE_CANCELLED,
|
|
12
12
|
STATE_ERROR,
|
|
13
|
+
STATE_TIMEOUT,
|
|
13
14
|
|
|
14
15
|
// > Signals
|
|
15
16
|
INITIAL,
|
|
@@ -17,7 +18,8 @@ import {
|
|
|
17
18
|
CANCEL,
|
|
18
19
|
ERROR,
|
|
19
20
|
LOADED,
|
|
20
|
-
UNLOAD
|
|
21
|
+
UNLOAD,
|
|
22
|
+
TIMEOUT
|
|
21
23
|
} from './constants.js';
|
|
22
24
|
|
|
23
25
|
/**
|
|
@@ -41,7 +43,8 @@ export default class LoadingStateMachine extends FiniteStateMachine {
|
|
|
41
43
|
// },
|
|
42
44
|
[CANCEL]: STATE_CANCELLED,
|
|
43
45
|
[ERROR]: STATE_ERROR,
|
|
44
|
-
[LOADED]: STATE_LOADED
|
|
46
|
+
[LOADED]: STATE_LOADED,
|
|
47
|
+
[TIMEOUT]: STATE_TIMEOUT
|
|
45
48
|
},
|
|
46
49
|
[STATE_LOADED]: {
|
|
47
50
|
// _enter: () => {
|
|
@@ -58,6 +61,10 @@ export default class LoadingStateMachine extends FiniteStateMachine {
|
|
|
58
61
|
[LOAD]: STATE_LOADING,
|
|
59
62
|
[UNLOAD]: STATE_UNLOADING
|
|
60
63
|
},
|
|
64
|
+
[STATE_TIMEOUT]: {
|
|
65
|
+
[LOAD]: STATE_LOADING,
|
|
66
|
+
[UNLOAD]: STATE_UNLOADING
|
|
67
|
+
},
|
|
61
68
|
[STATE_ERROR]: {
|
|
62
69
|
_enter: ({ /*from, to, event,*/ args }) => {
|
|
63
70
|
if (args[0] instanceof Error) {
|
|
@@ -86,4 +93,22 @@ export default class LoadingStateMachine extends FiniteStateMachine {
|
|
|
86
93
|
get error() {
|
|
87
94
|
return this.#error;
|
|
88
95
|
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Transition to timeout state
|
|
99
|
+
* - Only valid when currently loading
|
|
100
|
+
* - Useful for external timeout management
|
|
101
|
+
*/
|
|
102
|
+
doTimeout() {
|
|
103
|
+
this.send(TIMEOUT);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Transition to cancelled state
|
|
108
|
+
* - Only valid when currently loading
|
|
109
|
+
* - Useful for external cancellation management
|
|
110
|
+
*/
|
|
111
|
+
doCancel() {
|
|
112
|
+
this.send(CANCEL);
|
|
113
|
+
}
|
|
89
114
|
}
|