@doeixd/machine 0.0.13 → 0.0.18

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 (54) hide show
  1. package/README.md +77 -25
  2. package/dist/cjs/development/core.js +1852 -0
  3. package/dist/cjs/development/core.js.map +7 -0
  4. package/dist/cjs/development/index.js +1377 -1372
  5. package/dist/cjs/development/index.js.map +4 -4
  6. package/dist/cjs/production/core.js +1 -0
  7. package/dist/cjs/production/index.js +5 -5
  8. package/dist/esm/development/core.js +1829 -0
  9. package/dist/esm/development/core.js.map +7 -0
  10. package/dist/esm/development/index.js +1377 -1372
  11. package/dist/esm/development/index.js.map +4 -4
  12. package/dist/esm/production/core.js +1 -0
  13. package/dist/esm/production/index.js +5 -5
  14. package/dist/types/core.d.ts +18 -0
  15. package/dist/types/core.d.ts.map +1 -0
  16. package/dist/types/extract.d.ts +15 -1
  17. package/dist/types/extract.d.ts.map +1 -1
  18. package/dist/types/functional-combinators.d.ts +3 -5
  19. package/dist/types/functional-combinators.d.ts.map +1 -1
  20. package/dist/types/index.d.ts +254 -18
  21. package/dist/types/index.d.ts.map +1 -1
  22. package/dist/types/middleware/composition.d.ts +460 -0
  23. package/dist/types/middleware/composition.d.ts.map +1 -0
  24. package/dist/types/middleware/core.d.ts +196 -0
  25. package/dist/types/middleware/core.d.ts.map +1 -0
  26. package/dist/types/middleware/history.d.ts +54 -0
  27. package/dist/types/middleware/history.d.ts.map +1 -0
  28. package/dist/types/middleware/index.d.ts +10 -0
  29. package/dist/types/middleware/index.d.ts.map +1 -0
  30. package/dist/types/middleware/snapshot.d.ts +63 -0
  31. package/dist/types/middleware/snapshot.d.ts.map +1 -0
  32. package/dist/types/middleware/time-travel.d.ts +81 -0
  33. package/dist/types/middleware/time-travel.d.ts.map +1 -0
  34. package/package.json +19 -6
  35. package/src/core.ts +167 -0
  36. package/src/entry-react.ts +9 -0
  37. package/src/entry-solid.ts +9 -0
  38. package/src/extract.ts +61 -61
  39. package/src/functional-combinators.ts +3 -3
  40. package/src/generators.ts +6 -6
  41. package/src/index.ts +389 -101
  42. package/src/middleware/composition.ts +944 -0
  43. package/src/middleware/core.ts +573 -0
  44. package/src/middleware/history.ts +104 -0
  45. package/src/middleware/index.ts +13 -0
  46. package/src/middleware/snapshot.ts +153 -0
  47. package/src/middleware/time-travel.ts +236 -0
  48. package/src/middleware.ts +735 -1614
  49. package/src/prototype_functional.ts +46 -0
  50. package/src/reproduce_issue.ts +26 -0
  51. package/dist/types/middleware.d.ts +0 -1048
  52. package/dist/types/middleware.d.ts.map +0 -1
  53. package/dist/types/runtime-extract.d.ts +0 -53
  54. package/dist/types/runtime-extract.d.ts.map +0 -1
package/README.md CHANGED
@@ -67,24 +67,24 @@ The library offers multiple patterns for different use cases. **šŸ“– [Pattern De
67
67
 
68
68
  ## Quick Start
69
69
 
70
- ### Basic Counter (Simple State)
70
+ ### Basic Counter (Functional Builder Pattern)
71
71
 
72
- **Immutable approach (recommended):**
72
+ **Recommended approach (type-safe and ergonomic):**
73
73
 
74
74
  ```typescript
75
75
  import { createMachine } from "@doeixd/machine";
76
76
 
77
77
  const counter = createMachine(
78
78
  { count: 0 }, // Initial state (sā‚€)
79
- {
80
- // Transitions (Ī“)
81
- increment: function() {
82
- return createMachine({ count: this.count + 1 }, this);
79
+ (next) => ({
80
+ // Transitions (Ī“) - `this` is automatically typed
81
+ increment() {
82
+ return next({ count: this.count + 1 });
83
83
  },
84
- add: function(n: number) {
85
- return createMachine({ count: this.count + n }, this);
84
+ add(n: number) {
85
+ return next({ count: this.count + n });
86
86
  }
87
- }
87
+ })
88
88
  );
89
89
 
90
90
  const next = counter.increment();
@@ -94,6 +94,26 @@ console.log(next.context.count); // 1
94
94
  console.log(counter.context.count); // 0
95
95
  ```
96
96
 
97
+ **Benefits:**
98
+ - **Type-safe**: Full TypeScript inference for `this` context
99
+ - **Ergonomic**: No need to manually pass transition objects
100
+ - **Clean**: Automatic binding and context inference
101
+ - **Composable**: Transitions are automatically available on all returned machines
102
+
103
+ **Traditional approach (also supported):**
104
+
105
+ ```typescript
106
+ const transitions = {
107
+ increment: function() {
108
+ return createMachine({ count: this.count + 1 }, transitions);
109
+ },
110
+ add: function(n: number) {
111
+ return createMachine({ count: this.count + n }, transitions);
112
+ }
113
+ };
114
+ const counter = createMachine({ count: 0 }, transitions);
115
+ ```
116
+
97
117
  **Mutable approach (also supported):**
98
118
 
99
119
  ```typescript
@@ -145,11 +165,11 @@ The most powerful pattern: different machine types represent different states.
145
165
  import { createMachine, Machine } from "@doeixd/machine";
146
166
 
147
167
  // Define distinct machine types for each state
148
- type LoggedOut = Machine<{ status: "loggedOut" }> & {
168
+ type LoggedOut = Machine<{ status: "loggedOut" }, {
149
169
  login: (username: string) => LoggedIn;
150
170
  };
151
171
 
152
- type LoggedIn = Machine<{ status: "loggedIn"; username: string }> & {
172
+ type LoggedIn = Machine<{ status: "loggedIn"; username: string }, {
153
173
  logout: () => LoggedOut;
154
174
  viewProfile: () => LoggedIn;
155
175
  };
@@ -216,12 +236,12 @@ logout(state); // Runtime error!
216
236
  **Type-State Approach (Compile-Time Enforcement):**
217
237
  ```typescript
218
238
  // āœ… States are distinct types - compiler enforces validity
219
- type LoggedOut = Machine<{ status: "loggedOut" }> & {
239
+ type LoggedOut = Machine<{ status: "loggedOut" }, {
220
240
  login: (user: string) => LoggedIn;
221
241
  // No logout method - impossible to call
222
242
  };
223
243
 
224
- type LoggedIn = Machine<{ status: "loggedIn"; username: string }> & {
244
+ type LoggedIn = Machine<{ status: "loggedIn"; username: string }, {
225
245
  logout: () => LoggedOut;
226
246
  // No login method - impossible to call
227
247
  };
@@ -288,7 +308,7 @@ if (hasState(machine, "status", "success")) {
288
308
 
289
309
  #### 5. Event Type Safety
290
310
  ```typescript
291
- type FetchMachine = AsyncMachine<{ status: string }> & {
311
+ type FetchMachine = AsyncMachine<{ status: string }, {
292
312
  fetch: (id: number) => Promise<FetchMachine>;
293
313
  retry: () => Promise<FetchMachine>;
294
314
  };
@@ -350,22 +370,22 @@ This shows the full power of Type-State Programming:
350
370
 
351
371
  ```typescript
352
372
  // Define the states as distinct types
353
- type IdleState = Machine<{ status: "idle" }> & {
373
+ type IdleState = Machine<{ status: "idle" }, {
354
374
  fetch: (url: string) => LoadingState;
355
375
  };
356
376
 
357
- type LoadingState = Machine<{ status: "loading"; url: string }> & {
377
+ type LoadingState = Machine<{ status: "loading"; url: string }, {
358
378
  cancel: () => IdleState;
359
379
  // Note: No fetch - can't start new request while loading
360
380
  };
361
381
 
362
- type SuccessState = Machine<{ status: "success"; data: any }> & {
382
+ type SuccessState = Machine<{ status: "success"; data: any }, {
363
383
  refetch: () => LoadingState;
364
384
  clear: () => IdleState;
365
385
  // Note: No cancel - nothing to cancel
366
386
  };
367
387
 
368
- type ErrorState = Machine<{ status: "error"; error: string }> & {
388
+ type ErrorState = Machine<{ status: "error"; error: string }, {
369
389
  retry: () => LoadingState;
370
390
  clear: () => IdleState;
371
391
  };
@@ -413,9 +433,25 @@ This is the essence of Type-State Programming: **Make illegal states unrepresent
413
433
 
414
434
  ### Machine Creation
415
435
 
416
- #### `createMachine<C, T>(context, transitions)`
436
+ #### `createMachine<C, T>(context, factory)`
417
437
 
418
- Creates a synchronous state machine.
438
+ Creates a synchronous state machine using the **Functional Builder** pattern. This is the recommended approach for type safety and ergonomics, as it automatically infers `this` context and binds transitions.
439
+
440
+ ```typescript
441
+ const machine = createMachine({ count: 0 }, (next) => ({
442
+ increment() {
443
+ // `this` is correctly inferred as Context
444
+ return next({ count: this.count + 1 });
445
+ },
446
+ add(n: number) {
447
+ return next({ count: this.count + n });
448
+ }
449
+ }));
450
+ ```
451
+
452
+ #### `createMachine<C, T>(context, transitions)` (Traditional)
453
+
454
+ Creates a synchronous state machine from a context and transition functions.
419
455
 
420
456
  ```typescript
421
457
  const machine = createMachine(
@@ -428,6 +464,22 @@ const machine = createMachine(
428
464
  );
429
465
  ```
430
466
 
467
+ #### `createMachine<C, T>(context, factory)`
468
+
469
+ Creates a synchronous state machine using the **Functional Builder** pattern. This is the recommended approach for type safety and ergonomics, as it automatically infers `this` context and binds transitions.
470
+
471
+ ```typescript
472
+ const machine = createMachine({ count: 0 }, (transition) => ({
473
+ increment() {
474
+ // `this` is correctly inferred as Context
475
+ return transition({ count: this.count + 1 });
476
+ },
477
+ add(n: number) {
478
+ return transition({ count: this.count + n });
479
+ }
480
+ }));
481
+ ```
482
+
431
483
  #### `createAsyncMachine<C, T>(context, transitions)`
432
484
 
433
485
  Creates an async state machine (for side effects, API calls, etc.).
@@ -435,16 +487,16 @@ Creates an async state machine (for side effects, API calls, etc.).
435
487
  ```typescript
436
488
  const machine = createAsyncMachine(
437
489
  { status: "idle", data: null },
438
- {
490
+ (next) => ({
439
491
  async fetch() {
440
492
  try {
441
493
  const data = await api.getData();
442
- return createAsyncMachine({ status: "success", data }, this);
494
+ return next({ status: "success", data });
443
495
  } catch (error) {
444
- return createAsyncMachine({ status: "error", data: null }, this);
496
+ return next({ status: "error", data: null });
445
497
  }
446
498
  }
447
- }
499
+ })
448
500
  );
449
501
  ```
450
502
 
@@ -727,7 +779,7 @@ const tracked = withAnalytics(machine, trackEvent);
727
779
  ```typescript
728
780
  import { Context, Transitions, Event, TransitionArgs } from "@doeixd/machine";
729
781
 
730
- type MyMachine = Machine<{ count: number }> & {
782
+ type MyMachine = Machine<{ count: number }, {
731
783
  add: (n: number) => MyMachine;
732
784
  };
733
785