@hkdigital/lib-core 0.4.24 → 0.4.26

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.
Files changed (30) hide show
  1. package/dist/logging/internal/adapters/pino.d.ts +7 -3
  2. package/dist/logging/internal/adapters/pino.js +200 -67
  3. package/dist/logging/internal/transports/pretty-transport.d.ts +17 -0
  4. package/dist/logging/internal/transports/pretty-transport.js +104 -0
  5. package/dist/logging/internal/transports/test-transport.d.ts +19 -0
  6. package/dist/logging/internal/transports/test-transport.js +79 -0
  7. package/dist/network/loaders/audio/AudioScene.svelte.d.ts +19 -10
  8. package/dist/network/loaders/audio/AudioScene.svelte.js +50 -75
  9. package/dist/network/loaders/image/ImageScene.svelte.d.ts +13 -13
  10. package/dist/network/loaders/image/ImageScene.svelte.js +56 -83
  11. package/dist/network/states/NetworkLoader.svelte.d.ts +6 -0
  12. package/dist/network/states/NetworkLoader.svelte.js +15 -6
  13. package/dist/services/service-base/ServiceBase.d.ts +12 -8
  14. package/dist/services/service-base/ServiceBase.js +8 -6
  15. package/dist/state/machines/finite-state-machine/FiniteStateMachine.svelte.d.ts +5 -9
  16. package/dist/state/machines/finite-state-machine/FiniteStateMachine.svelte.js +62 -32
  17. package/dist/state/machines/finite-state-machine/README.md +48 -46
  18. package/dist/state/machines/finite-state-machine/constants.d.ts +13 -0
  19. package/dist/state/machines/finite-state-machine/constants.js +15 -0
  20. package/dist/state/machines/finite-state-machine/index.d.ts +1 -0
  21. package/dist/state/machines/finite-state-machine/index.js +1 -0
  22. package/dist/state/machines/finite-state-machine/typedef.d.ts +3 -3
  23. package/dist/state/machines/finite-state-machine/typedef.js +21 -15
  24. package/dist/state/machines/loading-state-machine/LoadingStateMachine.svelte.d.ts +12 -0
  25. package/dist/state/machines/loading-state-machine/LoadingStateMachine.svelte.js +27 -2
  26. package/dist/state/machines/loading-state-machine/README.md +89 -41
  27. package/dist/state/machines/loading-state-machine/constants.d.ts +2 -0
  28. package/dist/state/machines/loading-state-machine/constants.js +2 -0
  29. package/package.json +1 -1
  30. package/dist/logging/internal/adapters/pino.js__ +0 -260
@@ -4,7 +4,11 @@
4
4
  * @see {@link https://runed.dev/docs/utilities/finite-state-machine}
5
5
  */
6
6
 
7
- /** @typedef {import('./typedef.js').StateTransitionMetadata} StateTransitionMetadata */
7
+ import { isTestEnv } from '../../../util/env.js';
8
+ import EventEmitter from '../../../generic/events/classes/EventEmitter.js';
9
+ import { ENTER, EXIT } from './constants.js';
10
+
11
+ /** @typedef {import('./typedef.js').TransitionData} TransitionData */
8
12
  /** @typedef {import('./typedef.js').OnEnterCallback} OnEnterCallback */
9
13
  /** @typedef {import('./typedef.js').OnExitCallback} OnExitCallback */
10
14
 
@@ -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
- this.#dispatch('_enter', {
60
+ const initialTransitionData = {
53
61
  from: null,
54
62
  to: initial,
55
63
  event: null,
56
64
  args: []
57
- });
65
+ };
66
+
67
+ this.#executeAction('_enter', initialTransitionData);
68
+
69
+ // Emit ENTER event for external listeners for initial state
70
+ this.emit(ENTER, { state: initial, transition: initialTransitionData });
58
71
  }
59
72
 
60
73
  /**
@@ -65,50 +78,66 @@ export default class FiniteStateMachine {
65
78
  * @param {any[]} [args]
66
79
  */
67
80
  #transition(newState, event, args) {
68
- /** @type {StateTransitionMetadata} */
69
- const metadata = { from: this.#current, to: newState, event, args };
81
+ /** @type {TransitionData} */
82
+ const transition = { from: this.#current, to: newState, event, args };
70
83
 
71
84
  // Call onexit callback before leaving current state
72
- this.onexit?.(this.#current, metadata);
73
-
74
- this.#dispatch('_exit', metadata);
85
+ this.onexit?.(this.#current, transition);
86
+
87
+ // Emit EXIT event for external listeners
88
+ this.emit(EXIT, { state: this.#current, transition });
89
+
90
+ this.#executeAction('_exit', transition);
75
91
  this.#current = newState;
76
- this.#dispatch('_enter', metadata);
77
-
92
+ this.#executeAction('_enter', transition);
93
+
94
+ // Emit ENTER event for external listeners
95
+ this.emit(ENTER, { state: newState, transition });
96
+
78
97
  // Call onenter callback after state change
79
- this.onenter?.(newState, metadata);
98
+ this.onenter?.(newState, transition);
80
99
  }
81
100
 
82
101
  /**
83
- * Dispatch an event
102
+ * Execute an action for the given event
84
103
  *
85
104
  * @param {string} event
86
105
  * @param {any} args
87
106
  */
88
- #dispatch(event, ...args) {
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
- if (event === '_enter' || event === '_exit') {
93
- if (isLifecycleFnMeta(args[0])) {
94
- action(args[0]);
95
- } else {
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 transition data 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
- 'Invalid metadata passed to lifecycle function of the FSM.'
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.#dispatch(event, ...args);
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)
@@ -56,16 +56,16 @@ Each state can define:
56
56
  ```javascript
57
57
  const machine = new FiniteStateMachine('idle', {
58
58
  idle: {
59
- _enter: (metadata) => {
59
+ _enter: (transition) => {
60
60
  console.log('Entered idle state');
61
61
  },
62
- _exit: (metadata) => {
62
+ _exit: (transition) => {
63
63
  console.log('Leaving idle state');
64
64
  },
65
65
  start: 'running'
66
66
  },
67
67
  running: {
68
- _enter: (metadata) => {
68
+ _enter: (transition) => {
69
69
  console.log('Started running');
70
70
  },
71
71
  stop: 'idle'
@@ -73,14 +73,14 @@ const machine = new FiniteStateMachine('idle', {
73
73
  });
74
74
  ```
75
75
 
76
- ## Callback Metadata
76
+ ## Callback TransitionData
77
77
 
78
- Enter and exit callbacks receive metadata about the transition:
78
+ Enter and exit callbacks receive transition data about the state change:
79
79
 
80
80
  ```javascript
81
- /** @typedef {import('./typedef.js').StateTransitionMetadata} StateTransitionMetadata */
81
+ /** @typedef {import('./typedef.js').TransitionData} TransitionData */
82
82
 
83
- // Metadata structure:
83
+ // TransitionData structure:
84
84
  {
85
85
  from: 'previousState', // State being exited
86
86
  to: 'newState', // State being entered
@@ -94,18 +94,18 @@ Enter and exit callbacks receive metadata about the transition:
94
94
  For better type safety, import the type definitions:
95
95
 
96
96
  ```javascript
97
- /** @typedef {import('./typedef.js').StateTransitionMetadata} StateTransitionMetadata */
97
+ /** @typedef {import('./typedef.js').TransitionData} TransitionData */
98
98
  /** @typedef {import('./typedef.js').OnEnterCallback} OnEnterCallback */
99
99
  /** @typedef {import('./typedef.js').OnExitCallback} OnExitCallback */
100
100
 
101
101
  /** @type {OnEnterCallback} */
102
- const handleEnter = (state, metadata) => {
103
- console.log(`Entering ${state} from ${metadata.from}`);
102
+ const handleEnter = (currentState, transition) => {
103
+ console.log(`Entering ${currentState} from ${transition.from}`);
104
104
  };
105
105
 
106
106
  /** @type {OnExitCallback} */
107
- const handleExit = (state, metadata) => {
108
- console.log(`Leaving ${state} to ${metadata.to}`);
107
+ const handleExit = (currentState, transition) => {
108
+ console.log(`Leaving ${currentState} to ${transition.to}`);
109
109
  };
110
110
 
111
111
  machine.onenter = handleEnter;
@@ -160,7 +160,7 @@ const machine = new FiniteStateMachine('idle', {
160
160
  resume: 'running'
161
161
  },
162
162
  '*': {
163
- reset: 'idle', // Available from any state
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
@@ -209,8 +209,8 @@ const machine = new FiniteStateMachine('idle', {
209
209
  error: { retry: 'loading', reset: 'idle' }
210
210
  });
211
211
 
212
- machine.onexit = (state, metadata) => {
213
- switch (state) {
212
+ machine.onexit = (currentState, transition) => {
213
+ switch (currentState) {
214
214
  case 'loading':
215
215
  console.log('Leaving loading state...');
216
216
  // Cancel ongoing requests
@@ -224,8 +224,8 @@ machine.onexit = (state, metadata) => {
224
224
  }
225
225
  };
226
226
 
227
- machine.onenter = (state, metadata) => {
228
- switch (state) {
227
+ machine.onenter = (currentState, transition) => {
228
+ switch (currentState) {
229
229
  case 'loading':
230
230
  console.log('Started loading...');
231
231
  showSpinner();
@@ -236,7 +236,7 @@ machine.onenter = (state, metadata) => {
236
236
  break;
237
237
  case 'error':
238
238
  console.log('Loading failed');
239
- showError(metadata.args[0]);
239
+ showError(transition.args[0]);
240
240
  break;
241
241
  }
242
242
  };
@@ -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
 
@@ -264,11 +264,11 @@ const machine = new FiniteStateMachine('idle', {
264
264
  }
265
265
  });
266
266
 
267
- machine.onexit = (state) => console.log(`3. onexit ${state}`);
268
- machine.onenter = (state) => console.log(`6. onenter ${state}`);
267
+ machine.onexit = (currentState) => console.log(`3. onexit ${currentState}`);
268
+ machine.onenter = (currentState) => console.log(`6. onenter ${currentState}`);
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' },
@@ -312,8 +313,8 @@ machine.onexit = (state) => {
312
313
  }
313
314
  };
314
315
 
315
- machine.onenter = (state) => {
316
- switch (state) {
316
+ machine.onenter = (label) => {
317
+ switch (label) {
317
318
  case 'loading':
318
319
  this.#startProcess(); // Start async process immediately
319
320
  break;
@@ -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;
@@ -379,8 +381,8 @@ export default class TaskProcessor {
379
381
 
380
382
  constructor() {
381
383
  // onexit: Handle cleanup when leaving states
382
- this.#machine.onexit = (state) => {
383
- switch (state) {
384
+ this.#machine.onexit = (currentState) => {
385
+ switch (currentState) {
384
386
  case 'processing':
385
387
  this.#cancelTasks(); // Cancel ongoing tasks if interrupted
386
388
  break;
@@ -388,8 +390,8 @@ export default class TaskProcessor {
388
390
  };
389
391
 
390
392
  // onenter: Handle immediate state actions
391
- this.#machine.onenter = (state) => {
392
- switch (state) {
393
+ this.#machine.onenter = (currentState) => {
394
+ switch (currentState) {
393
395
  case 'processing':
394
396
  this.#startAllTasks(); // Start processing immediately
395
397
  break;
@@ -397,7 +399,7 @@ export default class TaskProcessor {
397
399
  this.#notifyComplete(); // Cleanup/notify when done
398
400
  break;
399
401
  }
400
- this.state = state;
402
+ this.state = currentState;
401
403
  };
402
404
 
403
405
  // $effect: Monitor reactive completion
@@ -419,22 +421,22 @@ 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
- machine.onexit = (state) => {
437
- switch (state) {
438
+ machine.onexit = (currentState) => {
439
+ switch (currentState) {
438
440
  case 'loading':
439
441
  // Cancel any ongoing requests
440
442
  cancelRequests();
@@ -442,8 +444,8 @@ export default class TaskProcessor {
442
444
  }
443
445
  };
444
446
 
445
- machine.onenter = (state) => {
446
- switch (state) {
447
+ machine.onenter = (currentState) => {
448
+ switch (currentState) {
447
449
  case 'loading':
448
450
  loadData();
449
451
  break;
@@ -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
@@ -524,7 +526,7 @@ const auth = new FiniteStateMachine('anonymous', {
524
526
  failure: 'anonymous'
525
527
  },
526
528
  authenticated: {
527
- _enter: (meta) => console.log('Welcome!'),
529
+ _enter: (transition) => console.log('Welcome!'),
528
530
  logout: 'anonymous',
529
531
  expire: 'anonymous'
530
532
  }
@@ -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';
@@ -1 +1,2 @@
1
1
  export { default as FiniteStateMachine } from "./FiniteStateMachine.svelte.js";
2
+ export * from "./constants.js";
@@ -1 +1,2 @@
1
1
  export { default as FiniteStateMachine } from './FiniteStateMachine.svelte.js';
2
+ export * from './constants.js';
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Metadata object passed to state transition callbacks
3
3
  */
4
- export type StateTransitionMetadata = {
4
+ export type TransitionData = {
5
5
  /**
6
6
  * - The state being exited
7
7
  */
@@ -22,8 +22,8 @@ export type StateTransitionMetadata = {
22
22
  /**
23
23
  * Callback function called when entering a state
24
24
  */
25
- export type OnEnterCallback = (arg0: string, arg1: StateTransitionMetadata) => void;
25
+ export type OnEnterCallback = (currentState: string, transition: TransitionData) => void;
26
26
  /**
27
27
  * Callback function called when exiting a state
28
28
  */
29
- export type OnExitCallback = (arg0: string, arg1: StateTransitionMetadata) => void;
29
+ export type OnExitCallback = (currentState: string, transition: TransitionData) => void;
@@ -4,25 +4,31 @@
4
4
 
5
5
  /**
6
6
  * Metadata object passed to state transition callbacks
7
- *
8
- * @typedef {object} StateTransitionMetadata
7
+ *
8
+ * @typedef {object} TransitionData
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
- /**
16
- * Callback function called when entering a state
17
- *
18
- * @typedef {function(string, StateTransitionMetadata): void} OnEnterCallback
19
- */
15
+ /**
16
+ * Callback function called when entering a state
17
+ *
18
+ * @callback OnEnterCallback
19
+ * @param {string} currentState - The state being entered
20
+ * @param {TransitionData} transition - Details about the transition
21
+ * @returns {void}
22
+ */
20
23
 
21
- /**
22
- * Callback function called when exiting a state
23
- *
24
- * @typedef {function(string, StateTransitionMetadata): void} OnExitCallback
25
- */
24
+ /**
25
+ * Callback function called when exiting a state
26
+ *
27
+ * @callback OnExitCallback
28
+ * @param {string} currentState - The state being exited
29
+ * @param {TransitionData} transition - Details about the transition
30
+ * @returns {void}
31
+ */
26
32
 
27
- // Export types for external use (this is just for JSDoc, no actual exports needed)
28
- export {};
33
+ // Export types for JSdoc
34
+ 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
  }