@hkdigital/lib-core 0.4.25 → 0.4.27

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.
@@ -4,17 +4,18 @@ A specialized finite state machine designed for managing loading operations with
4
4
 
5
5
  ## Overview
6
6
 
7
- `LoadingStateMachine` extends `FiniteStateMachine` to provide a standardized way to handle loading workflows. It includes predefined states for initial, loading, loaded, unloading, cancelled, and error conditions.
7
+ `LoadingStateMachine` extends `FiniteStateMachine` to provide a standardized way to handle loading workflows. It includes predefined states for initial, loading, loaded, unloading, aborted, and error conditions.
8
8
 
9
9
  ## States
10
10
 
11
- The machine defines seven primary states:
11
+ The machine defines eight primary states:
12
12
 
13
13
  - **`INITIAL`** - Starting state, ready to begin loading
14
14
  - **`LOADING`** - Currently loading data or resources
15
15
  - **`LOADED`** - Successfully loaded, data available
16
16
  - **`UNLOADING`** - Cleaning up or releasing resources
17
- - **`CANCELLED`** - Loading operation was cancelled
17
+ - **`ABORTING`** - Currently aborting loading operation
18
+ - **`ABORTED`** - Loading operation was aborted
18
19
  - **`ERROR`** - An error occurred during loading
19
20
  - **`TIMEOUT`** - Loading operation exceeded time limit
20
21
 
@@ -25,7 +26,8 @@ Available events to trigger state transitions:
25
26
  - **`LOAD`** - Start loading operation
26
27
  - **`LOADED`** - Mark loading as complete
27
28
  - **`UNLOAD`** - Begin cleanup/unloading
28
- - **`CANCEL`** - Cancel the loading operation
29
+ - **`ABORT`** - Start aborting the loading operation
30
+ - **`ABORTED`** - Mark abort operation as complete
29
31
  - **`ERROR`** - Signal an error occurred
30
32
  - **`TIMEOUT`** - Signal operation has timed out
31
33
  - **`INITIAL`** - Return to initial state
@@ -44,7 +46,7 @@ import {
44
46
  LOAD,
45
47
  LOADED,
46
48
  ERROR,
47
- CANCEL
49
+ ABORT
48
50
  } from '$lib/state/machines.js';
49
51
 
50
52
  const loader = new LoadingStateMachine();
@@ -67,10 +69,11 @@ console.log(loader.current); // STATE_LOADED
67
69
 
68
70
  ```
69
71
  INITIAL → LOADING
70
- LOADING → LOADED | CANCELLED | ERROR | TIMEOUT
72
+ LOADING → LOADED | ABORTING | ERROR | TIMEOUT
71
73
  LOADED → LOADING | UNLOADING
72
74
  UNLOADING → INITIAL | ERROR
73
- CANCELLEDLOADING | UNLOADING
75
+ ABORTINGABORTED | ERROR
76
+ ABORTED → LOADING | UNLOADING
74
77
  ERROR → LOADING | UNLOADING
75
78
  TIMEOUT → LOADING | UNLOADING
76
79
  ```
@@ -78,26 +81,26 @@ TIMEOUT → LOADING | UNLOADING
78
81
  ### Transition Diagram
79
82
 
80
83
  ```
81
- ┌─────────┐
82
- │ INITIAL │
83
- └────┬────┘
84
- LOAD
85
-
86
- ┌─────────┐ CANCEL ┌───────────┐
87
- │ LOADING │──────────────→│ CANCELLED
88
- └────┬────┘ └─────┬─────┘
89
-
90
- LOADED│ ERROR TIMEOUT LOAD UNLOAD
91
- │ │
92
- ▼ ▼
93
- ┌────────┐ ┌───────┐ ┌─────────┐ ┌──────────┐
94
- │ LOADED │ │ ERROR │ │ TIMEOUT │ UNLOADING
95
- └────┬───┘ └───┬───┘ └────┬────┘ └────┬─────┘
96
- │ │
97
- UNLOAD│ LOAD UNLOAD LOAD│ UNLOAD INITIAL ERROR
98
- ▼ ▼
99
- ┌──────────┐◄──────────────────────────┘
100
- │UNLOADING
84
+ ┌─────────┐
85
+ │ INITIAL │
86
+ └────┬────┘
87
+ LOAD
88
+
89
+ ┌─────────┐ ABORT ┌──────────┐
90
+ │ LOADING │──────────────────────────────→│ ABORTING
91
+ └────┬────┘ └─────┬────┘
92
+
93
+ LOADED│ ERROR TIMEOUT ABORTEDERROR
94
+ │ │
95
+ ▼ ▼
96
+ ┌────────┐ ┌───────┐ ┌─────────┐ ┌─────────┐
97
+ │ LOADED │ │ ERROR │ │ TIMEOUT │ ABORTED
98
+ └────┬───┘ └───┬───┘ └────┬────┘ └────┬────┘
99
+ │ │
100
+ UNLOAD│ LOAD│UNLOAD LOAD│UNLOAD LOADUNLOAD
101
+ ▼ ▼
102
+ ┌──────────┐ │
103
+ │UNLOADING │◄────────────────────────────────┘
101
104
  └──────────┘
102
105
  ```
103
106
 
@@ -108,8 +111,8 @@ The `onenter` callback provides a reliable way to react to state changes, design
108
111
  ```javascript
109
112
  const loader = new LoadingStateMachine();
110
113
 
111
- loader.onenter = (state) => {
112
- switch (state) {
114
+ loader.onenter = (currentState) => {
115
+ switch (currentState) {
113
116
  case STATE_LOADING:
114
117
  console.log('Started loading...');
115
118
  showSpinner();
@@ -141,8 +144,8 @@ $effect(() => {
141
144
  });
142
145
 
143
146
  // onenter catches every transition
144
- loader.onenter = (state) => {
145
- console.log(state); // Sees every state change
147
+ loader.onenter = (currentState) => {
148
+ console.log(currentState); // Sees every state change
146
149
  };
147
150
  ```
148
151
 
@@ -184,12 +187,12 @@ const loader = new LoadingStateMachine();
184
187
  // External timeout management
185
188
  const timeoutId = setTimeout(() => {
186
189
  if (loader.current === STATE_LOADING) {
187
- loader.doTimeout(); // Transitions to STATE_TIMEOUT
190
+ loader.timeout(); // Transitions to STATE_TIMEOUT
188
191
  }
189
192
  }, 10000); // 10 second timeout
190
193
 
191
- loader.onenter = (state) => {
192
- switch (state) {
194
+ loader.onenter = (currentState) => {
195
+ switch (currentState) {
193
196
  case STATE_TIMEOUT:
194
197
  console.log('Loading timed out');
195
198
  showRetryButton();
@@ -201,13 +204,22 @@ loader.onenter = (state) => {
201
204
  };
202
205
  ```
203
206
 
204
- ### doTimeout Method
207
+ ### timeout Method
205
208
 
206
- Use `doTimeout()` to manually trigger a timeout transition:
209
+ Use `timeout()` to manually trigger a timeout transition:
207
210
 
208
211
  ```javascript
209
212
  // Only works when in STATE_LOADING
210
- loader.doTimeout(); // Sends TIMEOUT signal
213
+ loader.timeout(); // Sends TIMEOUT signal
214
+ ```
215
+
216
+ ### abort Method
217
+
218
+ Use `abort()` to manually trigger an abort transition:
219
+
220
+ ```javascript
221
+ // Only works when in STATE_LOADING
222
+ loader.abort(); // Sends ABORT signal, transitions to STATE_ABORTING
211
223
  ```
212
224
 
213
225
  ## Integration with Svelte Reactivity
@@ -220,8 +232,8 @@ LoadingStateMachine inherits the `onenter` callback and Svelte reactivity integr
220
232
  ```javascript
221
233
  const loader = new LoadingStateMachine();
222
234
 
223
- loader.onenter = (state) => {
224
- switch (state) {
235
+ loader.onenter = (currentState) => {
236
+ switch (currentState) {
225
237
  case STATE_LOADING:
226
238
  this.#startLoading(); // Start async process immediately
227
239
  break;
@@ -267,8 +279,8 @@ export default class MultiSourceLoader {
267
279
 
268
280
  constructor() {
269
281
  // Handle immediate loading state actions
270
- this.#loader.onenter = (state) => {
271
- switch (state) {
282
+ this.#loader.onenter = (currentState) => {
283
+ switch (currentState) {
272
284
  case STATE_LOADING:
273
285
  this.#startAllSources();
274
286
  break;
@@ -282,7 +294,7 @@ export default class MultiSourceLoader {
282
294
  this.#handleTimeout();
283
295
  break;
284
296
  }
285
- this.state = state;
297
+ this.state = currentState;
286
298
  };
287
299
 
288
300
  // Monitor reactive completion
@@ -313,14 +325,14 @@ export default class MultiSourceLoader {
313
325
  LOAD,
314
326
  LOADED,
315
327
  ERROR,
316
- CANCEL
328
+ ABORT
317
329
  } from '$lib/state/machines.js';
318
330
 
319
331
  const loader = new LoadingStateMachine();
320
332
  let data = $state(null);
321
333
 
322
- loader.onenter = (state) => {
323
- if (state === STATE_LOADING) {
334
+ loader.onenter = (currentState) => {
335
+ if (currentState === STATE_LOADING) {
324
336
  loadData();
325
337
  }
326
338
  };
@@ -351,7 +363,7 @@ export default class MultiSourceLoader {
351
363
  {/if}
352
364
  ```
353
365
 
354
- ### Advanced Component with Cancellation
366
+ ### Advanced Component with Abort Handling
355
367
 
356
368
  ```javascript
357
369
  <script>
@@ -360,24 +372,29 @@ export default class MultiSourceLoader {
360
372
  STATE_INITIAL,
361
373
  STATE_LOADING,
362
374
  STATE_LOADED,
363
- STATE_CANCELLED,
375
+ STATE_ABORTING,
376
+ STATE_ABORTED,
364
377
  STATE_ERROR,
365
378
  LOAD,
366
379
  LOADED,
367
380
  ERROR,
368
- CANCEL
381
+ ABORT,
382
+ ABORTED
369
383
  } from '$lib/state/machines.js';
370
384
 
371
385
  const loader = new LoadingStateMachine();
372
386
  let abortController = null;
373
387
 
374
- loader.onenter = (state) => {
375
- switch (state) {
388
+ loader.onenter = (currentState) => {
389
+ switch (currentState) {
376
390
  case STATE_LOADING:
377
391
  startLoad();
378
392
  break;
379
- case STATE_CANCELLED:
393
+ case STATE_ABORTING:
394
+ // Start abort process
380
395
  abortController?.abort();
396
+ // Simulate abort completion
397
+ setTimeout(() => loader.send(ABORTED), 100);
381
398
  break;
382
399
  }
383
400
  };
@@ -393,7 +410,7 @@ export default class MultiSourceLoader {
393
410
  loader.send(LOADED);
394
411
  } catch (error) {
395
412
  if (error.name === 'AbortError') {
396
- // Request was cancelled, machine already in cancelled state
413
+ // Request was aborted, machine will transition to STATE_ABORTED
397
414
  } else {
398
415
  loader.send(ERROR, error);
399
416
  }
@@ -405,13 +422,15 @@ export default class MultiSourceLoader {
405
422
  {#if loader.current === STATE_INITIAL}
406
423
  <button onclick={() => loader.send(LOAD)}>Start Loading</button>
407
424
  {:else if loader.current === STATE_LOADING}
408
- <button onclick={() => loader.send(CANCEL)}>Cancel Loading</button>
425
+ <button onclick={() => loader.send(ABORT)}>Abort Loading</button>
409
426
  <div>Loading data...</div>
427
+ {:else if loader.current === STATE_ABORTING}
428
+ <div>Aborting...</div>
410
429
  {:else if loader.current === STATE_LOADED}
411
430
  <div>Data loaded successfully!</div>
412
431
  <button onclick={() => loader.send(LOAD)}>Reload</button>
413
- {:else if loader.current === STATE_CANCELLED}
414
- <div>Loading cancelled</div>
432
+ {:else if loader.current === STATE_ABORTED}
433
+ <div>Loading aborted</div>
415
434
  <button onclick={() => loader.send(LOAD)}>Try Again</button>
416
435
  {:else if loader.current === STATE_ERROR}
417
436
  <div>Error: {loader.error.message}</div>
@@ -426,8 +445,8 @@ export default class MultiSourceLoader {
426
445
 
427
446
  ```javascript
428
447
  // ✅ Good - use onenter for reliable side effects
429
- loader.onenter = (state) => {
430
- if (state === STATE_LOADING) {
448
+ loader.onenter = (currentState) => {
449
+ if (currentState === STATE_LOADING) {
431
450
  analytics.track('loading_started');
432
451
  }
433
452
  };
@@ -443,14 +462,17 @@ $effect(() => {
443
462
  ### 2. Handle All Error States
444
463
 
445
464
  ```javascript
446
- loader.onenter = (state) => {
447
- switch (state) {
465
+ loader.onenter = (currentState) => {
466
+ switch (currentState) {
448
467
  case STATE_ERROR:
449
468
  showErrorToast(loader.error.message);
450
469
  logError(loader.error);
451
470
  break;
452
- case STATE_CANCELLED:
453
- showMessage('Operation cancelled');
471
+ case STATE_ABORTING:
472
+ showMessage('Aborting operation...');
473
+ break;
474
+ case STATE_ABORTED:
475
+ showMessage('Operation aborted');
454
476
  break;
455
477
  }
456
478
  };
@@ -459,14 +481,15 @@ loader.onenter = (state) => {
459
481
  ### 3. Implement Proper Cleanup
460
482
 
461
483
  ```javascript
462
- loader.onenter = (state) => {
463
- switch (state) {
484
+ loader.onenter = (currentState) => {
485
+ switch (currentState) {
464
486
  case STATE_LOADING:
465
487
  showProgressBar();
466
488
  break;
467
489
  case STATE_LOADED:
468
490
  case STATE_ERROR:
469
- case STATE_CANCELLED:
491
+ case STATE_ABORTING:
492
+ case STATE_ABORTED:
470
493
  hideProgressBar();
471
494
  break;
472
495
  case STATE_UNLOADING:
@@ -500,8 +523,8 @@ loader.send('load');
500
523
  const resourceLoader = new LoadingStateMachine();
501
524
  let resource = null;
502
525
 
503
- resourceLoader.onenter = async (state) => {
504
- switch (state) {
526
+ resourceLoader.onenter = async (currentState) => {
527
+ switch (currentState) {
505
528
  case STATE_LOADING:
506
529
  try {
507
530
  resource = await loadResource();
@@ -529,8 +552,8 @@ const retryLoader = new LoadingStateMachine();
529
552
  let retryCount = 0;
530
553
  const maxRetries = 3;
531
554
 
532
- retryLoader.onenter = async (state) => {
533
- switch (state) {
555
+ retryLoader.onenter = async (currentState) => {
556
+ switch (currentState) {
534
557
  case STATE_LOADING:
535
558
  try {
536
559
  await performLoad();
@@ -576,7 +599,8 @@ import {
576
599
  STATE_LOADING,
577
600
  STATE_LOADED,
578
601
  STATE_UNLOADING,
579
- STATE_CANCELLED,
602
+ STATE_ABORTING,
603
+ STATE_ABORTED,
580
604
  STATE_ERROR,
581
605
  STATE_TIMEOUT,
582
606
 
@@ -584,7 +608,8 @@ import {
584
608
  LOAD,
585
609
  LOADED,
586
610
  UNLOAD,
587
- CANCEL,
611
+ ABORT,
612
+ ABORTED,
588
613
  ERROR,
589
614
  INITIAL,
590
615
  TIMEOUT
@@ -2,12 +2,14 @@ export const STATE_INITIAL: "initial";
2
2
  export const STATE_LOADING: "loading";
3
3
  export const STATE_UNLOADING: "unloading";
4
4
  export const STATE_LOADED: "loaded";
5
- export const STATE_CANCELLED: "cancelled";
5
+ export const STATE_ABORTING: "aborting";
6
+ export const STATE_ABORTED: "aborted";
6
7
  export const STATE_ERROR: "error";
7
8
  export const STATE_TIMEOUT: "timeout";
8
9
  export const INITIAL: "initial";
9
10
  export const LOAD: "load";
10
- export const CANCEL: "cancel";
11
+ export const ABORT: "abort";
12
+ export const ABORTED: "aborted";
11
13
  export const ERROR: "error";
12
14
  export const LOADED: "loaded";
13
15
  export const UNLOAD: "unload";
@@ -3,7 +3,8 @@ export const STATE_LOADING = 'loading';
3
3
  export const STATE_UNLOADING = 'unloading';
4
4
  export const STATE_LOADED = 'loaded';
5
5
 
6
- export const STATE_CANCELLED = 'cancelled';
6
+ export const STATE_ABORTING = 'aborting';
7
+ export const STATE_ABORTED = 'aborted';
7
8
  export const STATE_ERROR = 'error';
8
9
  export const STATE_TIMEOUT = 'timeout';
9
10
 
@@ -11,7 +12,8 @@ export const STATE_TIMEOUT = 'timeout';
11
12
 
12
13
  export const INITIAL = 'initial';
13
14
  export const LOAD = 'load';
14
- export const CANCEL = 'cancel';
15
+ export const ABORT = 'abort';
16
+ export const ABORTED = 'aborted';
15
17
  export const ERROR = 'error';
16
18
  export const LOADED = 'loaded';
17
19
  export const UNLOAD = 'unload';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hkdigital/lib-core",
3
- "version": "0.4.25",
3
+ "version": "0.4.27",
4
4
  "author": {
5
5
  "name": "HKdigital",
6
6
  "url": "https://hkdigital.nl"