@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/src/generators.ts CHANGED
@@ -135,12 +135,12 @@ export function run<C extends any = any, M extends { context: C } & Record<strin
135
135
 
136
136
  // If the generator has returned (done), we have our final value
137
137
  if (done) {
138
- return value;
138
+ return value as T;
139
139
  }
140
140
 
141
141
  // Otherwise, the yielded value becomes our new current state
142
142
  // This state will be sent back into the generator on the next iteration
143
- current = value;
143
+ current = value as M;
144
144
  }
145
145
  }
146
146
 
@@ -346,10 +346,10 @@ export function runWithDebug<C extends any = any, M extends { context: C } & Rec
346
346
 
347
347
  if (done) {
348
348
  console.log('Final:', value);
349
- return value;
349
+ return value as T;
350
350
  }
351
351
 
352
- current = value;
352
+ current = value as M;
353
353
  stepCount++;
354
354
  logger(stepCount, current);
355
355
  }
@@ -391,10 +391,10 @@ export async function runAsync<C extends any = any, M extends { context: C } & R
391
391
  const { value, done } = await generator.next(current);
392
392
 
393
393
  if (done) {
394
- return value;
394
+ return value as T;
395
395
  }
396
396
 
397
- current = value;
397
+ current = value as M;
398
398
  }
399
399
  }
400
400
 
package/src/index.ts CHANGED
@@ -15,34 +15,66 @@
15
15
  export type MaybePromise<T> = T | Promise<T>;
16
16
 
17
17
  /**
18
- * The fundamental shape of any machine: a `context` object for state, and methods for transitions.
19
- * @template C - The context (state) object type.
18
+ * The fundamental shape of a synchronous machine. This is a highly advanced
19
+ * generic type that performs two critical functions at compile time:
20
+ *
21
+ * 1. **Extraction:** It intelligently infers the pure transitions object from
22
+ * the flexible argument `A` (which can be a plain object, a factory
23
+ * function, or the augmented `this` from another transition).
24
+ *
25
+ * 2. **Filtering:** After extracting the transitions, it filters them, keeping
26
+ * only the functions that return a valid `Machine`.
27
+ *
28
+ * This makes the `Machine` type itself the single source of truth for what
29
+ * constitutes a valid, type-safe machine, enabling a remarkably clean and
30
+ * powerful API for `createMachine`.
31
+ *
32
+ * @template C The context object type.
33
+ * @template A The raw, flexible argument for transitions (object, factory, or `this`).
20
34
  */
21
- export type Machine<C extends object> = {
22
- /** The readonly state of the machine. */
35
+ export type Machine<
36
+ C extends object,
37
+ T extends object = {}
38
+ > = {
23
39
  readonly context: C;
24
- } & Record<string, (...args: any[]) => Machine<any>>;
40
+ } & T;
25
41
 
26
42
  /**
27
43
  * The shape of an asynchronous machine, where transitions can return Promises.
28
44
  * Async transitions receive an AbortSignal as the last parameter for cancellation support.
29
45
  * @template C - The context object type.
30
46
  */
31
- export type AsyncMachine<C extends object> = {
32
- /** The readonly state of the machine. */
47
+ export type AsyncMachine<
48
+ C extends object,
49
+ T extends object = {}
50
+ > = {
33
51
  readonly context: C;
34
- } & Record<string, (...args: any[]) => MaybePromise<AsyncMachine<any>>>;
52
+ } & T;
35
53
 
36
54
  /**
37
55
  * Utility type to extract the parameters of an async transition function,
38
56
  * which includes TransitionOptions as the last parameter.
39
57
  */
40
- export type AsyncTransitionArgs<M extends AsyncMachine<any>, K extends keyof M & string> =
41
- M[K] extends (...args: infer A) => any
42
- ? A extends [...infer Rest, TransitionOptions]
43
- ? Rest
44
- : A
45
- : never;
58
+ export type AsyncTransitionArgs<M extends AsyncMachine<any, any>, K extends keyof M & string> =
59
+ M[K] extends (...a: infer A) => any
60
+ ? A extends [...infer Rest, TransitionOptions] ? Rest : A
61
+ : never;
62
+
63
+ /**
64
+ * A helper type to define a distinct state in a state machine (a "typestate").
65
+ * Allows defining the context and transitions in a single generic type.
66
+ * @template C - The context specific to this state.
67
+ * @template T - The transitions available in this state.
68
+ */
69
+ export type TypeState<C extends object, T extends object = {}> = Machine<C, T>;
70
+
71
+ /**
72
+ * A helper type to define a distinct async state in a state machine.
73
+ * @template C - The context specific to this state.
74
+ * @template T - The transitions available in this state.
75
+ */
76
+ export type AsyncTypeState<C extends object, T extends object = {}> = AsyncMachine<C, T>;
77
+
46
78
 
47
79
  /**
48
80
  * Options passed to async transition functions, including cancellation support.
@@ -57,6 +89,8 @@ export interface TransitionOptions {
57
89
  // SECTION: TYPE UTILITIES & INTROSPECTION
58
90
  // =============================================================================
59
91
 
92
+
93
+
60
94
  /**
61
95
  * Extracts the context type `C` from a machine type `M`.
62
96
  * @template M - The machine type.
@@ -77,7 +111,6 @@ export type Transitions<M extends BaseMachine<any>> = Omit<M, "context">;
77
111
  */
78
112
  export type TransitionArgs<M extends Machine<any>, K extends keyof M & string> =
79
113
  M[K] extends (...args: infer A) => any ? A : never;
80
-
81
114
  /**
82
115
  * Extracts the names of all transitions as a string union type.
83
116
  * @template M - The machine type.
@@ -103,10 +136,10 @@ export type BaseMachine<C extends object> = {
103
136
  */
104
137
  export type DeepReadonly<T> = {
105
138
  readonly [P in keyof T]: T[P] extends object
106
- ? T[P] extends (...args: any[]) => any
107
- ? T[P]
108
- : DeepReadonly<T[P]>
109
- : T[P];
139
+ ? T[P] extends (...args: any[]) => any
140
+ ? T[P]
141
+ : DeepReadonly<T[P]>
142
+ : T[P];
110
143
  };
111
144
 
112
145
  /**
@@ -118,6 +151,10 @@ export type DeepReadonly<T> = {
118
151
  */
119
152
  export type InferMachine<F extends (...args: any[]) => any> = ReturnType<F>;
120
153
 
154
+
155
+ export type EventFromTransitions<T extends Record<string, (...args: any[]) => any>> =
156
+ { [K in keyof T & string]: { type: K; args: T[K] extends (...a: infer A) => any ? A : never } }[keyof T & string];
157
+
121
158
  /**
122
159
  * A discriminated union type representing an event that can be dispatched to a machine.
123
160
  * This is automatically generated from a machine's type signature, ensuring full type safety.
@@ -128,11 +165,153 @@ export type InferMachine<F extends (...args: any[]) => any> = ReturnType<F>;
128
165
  */
129
166
  export type Event<M extends BaseMachine<any>> = {
130
167
  [K in keyof Omit<M, "context"> & string]: M[K] extends (...args: infer A) => any
131
- ? { type: K; args: A }
132
- : never
168
+ ? { type: K; args: A }
169
+ : never
133
170
  }[keyof Omit<M, "context"> & string];
134
171
 
135
172
 
173
+ /**
174
+ * A helper type for use with TypeScript's `satisfies` operator to provide
175
+ * strong, immediate type-checking for standalone transition objects.
176
+ *
177
+ * This solves the "chicken-and-egg" problem where you need the final machine
178
+ * type to correctly type the transitions object, but you need the transitions
179
+ * object to create the machine. By forward-declaring the machine type and using
180
+ * `satisfies TransitionsFor<...>`, you get full IntelliSense and error-checking
181
+ * at the exact location of your transition definitions.
182
+ *
183
+ * @template C The context object type for the machine.
184
+ * @template T The literal type of the transitions object itself (`typeof myTransitions`).
185
+ *
186
+ * @example
187
+ * import { createMachine, Machine, TransitionsFor } from '@doeixd/machine';
188
+ *
189
+ * // 1. Define the context for your machine.
190
+ * type CounterContext = { count: number };
191
+ *
192
+ * // 2. Forward-declare the final machine type. This is the key step that
193
+ * // breaks the circular dependency for the type checker.
194
+ * type CounterMachine = Machine<CounterContext> & typeof counterTransitions;
195
+ *
196
+ * // 3. Define the transitions object, using `satisfies` to apply the helper type.
197
+ * // This provides immediate type-checking and full autocompletion for `this`.
198
+ * const counterTransitions = {
199
+ * increment() {
200
+ * // `this` is now fully typed!
201
+ * // IntelliSense knows `this.count` is a number and
202
+ * // `this.transitions.add` is a function.
203
+ * return createMachine({ count: this.count + 1 }, this.transitions);
204
+ * },
205
+ * add(n: number) {
206
+ * return createMachine({ count: this.count + n }, this.transitions);
207
+ * },
208
+ * // ❌ TypeScript will immediately throw a compile error on the next line
209
+ * // because the return type 'string' does not satisfy 'Machine<any>'.
210
+ * invalidTransition() {
211
+ * return "this is not a machine";
212
+ * }
213
+ * } satisfies TransitionsFor<CounterContext, typeof counterTransitions>;
214
+ *
215
+ * // 4. Create the machine instance. The `createMachine` call is now
216
+ * // guaranteed to be type-safe because `counterTransitions` has already
217
+ * // been validated.
218
+ * export function createCounter(initialCount = 0): CounterMachine {
219
+ * return createMachine({ count: initialCount }, counterTransitions);
220
+ * }
221
+ */
222
+ export type TransitionsFor<C extends object, T extends Record<string, any>> = {
223
+ [K in keyof T]: (this: C & { transitions: T }, ...args: Parameters<T[K] extends (...a: infer A) => any ? (...a: A) => any : never>) => Machine<any, any>;
224
+ };
225
+
226
+ /**
227
+ * A helper type for use with the `satisfies` operator to provide strong
228
+ * type-checking for standalone asynchronous transition objects.
229
+ */
230
+ export type AsyncTransitionsFor<C extends object, T extends Record<string, any>> = {
231
+ [K in keyof T]: (this: C & { transitions: T }, ...args: Parameters<T[K] extends (...a: infer A) => any ? (...a: A) => any : never>) => MaybePromise<AsyncMachine<any, any>>;
232
+ };
233
+
234
+ /**
235
+ * A mapped type that iterates over a transitions object `T` and keeps only the
236
+ * keys whose functions return a valid `Machine`. This provides a "self-correcting"
237
+ * type that prevents the definition of invalid transitions at compile time.
238
+ *
239
+ * It acts as a filter at the type level. When used in the return type of a
240
+ * function like `createMachine`, it ensures that the resulting machine object
241
+ * will not have any properties corresponding to functions that were defined
242
+ * with an incorrect return type. This provides immediate, precise feedback to
243
+ * the developer, making it impossible to create a machine with an invalid
244
+ * transition shape.
245
+ *
246
+ * @template T The raw transitions object type provided by the user.
247
+ *
248
+ * @example
249
+ * import { createMachine, Machine } from '@doeixd/machine';
250
+ *
251
+ * const machine = createMachine({ value: 'A' }, {
252
+ * // This is a valid transition because it returns a `Machine`.
253
+ * // The key 'goToB' will be PRESERVED in the final type.
254
+ * goToB() {
255
+ * return createMachine({ value: 'B' }, this.transitions);
256
+ * },
257
+ *
258
+ * // This is an INVALID transition because it returns a string.
259
+ * // The key 'invalid' will be OMITTED from the final type.
260
+ * invalid() {
261
+ * return "This is not a Machine object";
262
+ * },
263
+ *
264
+ * // This is also invalid as it's not a function.
265
+ * // The key 'alsoInvalid' will be OMITTED from the final type.
266
+ * alsoInvalid: 123
267
+ * });
268
+ *
269
+ * // --- USAGE ---
270
+ *
271
+ * // ✅ This call is valid and works as expected.
272
+ * const nextState = machine.goToB();
273
+ *
274
+ * // ❌ This line will cause a COMPILE-TIME a ERROR because the `FilterValidTransitions`
275
+ * // type has removed the 'invalid' key from the `machine`'s type signature.
276
+ * //
277
+ * // Error: Property 'invalid' does not exist on type
278
+ * // 'Machine<{ value: string; }> & { goToB: () => Machine<...>; }'.
279
+ * //
280
+ * machine.invalid();
281
+ */
282
+ export type FilterValidTransitions<T> = {
283
+ [K in keyof T as T[K] extends (...args: any[]) => Machine<any> ? K : never]: T[K];
284
+ };
285
+
286
+ /**
287
+ * A conditional type that intelligently extracts the pure transitions object `T`
288
+ * from the flexible second argument of `createMachine`.
289
+ *
290
+ * It handles three cases:
291
+ * 1. If the argument is the augmented `this` context (`C & { transitions: T }`), it extracts `T`.
292
+ * 2. If the argument is a factory function `((ctx: C) => T)`, it infers and returns `T`.
293
+ * 3. If the argument is already the pure transitions object `T`, it returns it as is.
294
+ */
295
+ export type ExtractTransitions<Arg, C extends object> = Arg extends (
296
+ ...args: any[]
297
+ ) => infer R
298
+ ? R // Case 2: It's a factory function, extract the return type `R`.
299
+ : Arg extends C & { transitions: infer T }
300
+ ? T // Case 1: It's the augmented `this` context, extract `T` from `transitions`.
301
+ : Arg; // Case 3: It's already the plain transitions object.
302
+
303
+ /** Keep only keys whose value is a function that returns a Machine. */
304
+ export type ValidTransitions<T> = {
305
+ [K in keyof T as T[K] extends (...a: any[]) => Machine<any, any> ? K : never]:
306
+ T[K] extends (...a: infer A) => Machine<infer C2, infer T2> ? (...a: A) => Machine<C2, T2> : never;
307
+ };
308
+
309
+ /** Same for async transitions (functions returning MaybePromise<AsyncMachine>). */
310
+ export type ValidAsyncTransitions<T> = {
311
+ [K in keyof T as T[K] extends (...a: any[]) => MaybePromise<AsyncMachine<any, any>> ? K : never]:
312
+ T[K] extends (...a: infer A) => MaybePromise<AsyncMachine<infer C2, infer T2>> ? (...a: A) => MaybePromise<AsyncMachine<C2, T2>> : never;
313
+ };
314
+
136
315
  // =============================================================================
137
316
  // SECTION: MACHINE CREATION (FUNCTIONAL & OOP)
138
317
  // =============================================================================
@@ -146,18 +325,145 @@ export type Event<M extends BaseMachine<any>> = {
146
325
  * @param fns - An object containing transition function definitions.
147
326
  * @returns A new machine instance.
148
327
  */
328
+ /**
329
+ * Helper to transform transition functions to be bound (no 'this' requirement).
330
+ */
331
+ export type BindTransitions<T> = {
332
+ [K in keyof T]: T[K] extends (this: any, ...args: infer A) => infer R
333
+ ? (...args: A) => R
334
+ : T[K];
335
+ };
336
+
337
+ /**
338
+ * Creates a synchronous state machine from a context and a factory function.
339
+ * This "Functional Builder" pattern allows for type-safe transitions without
340
+ * manually passing `this` or `transitions`.
341
+ *
342
+ * @template C - The context object type.
343
+ * @template T - The transitions object type.
344
+ * @param context - The initial state context.
345
+ * @param factory - A function that receives a `transition` helper and returns the transitions object.
346
+ * @returns A new machine instance.
347
+ */
348
+ export function createMachine<C extends object, T extends Record<string, (this: C, ...args: any[]) => any>>(
349
+ context: C,
350
+ factory: (transition: (newContext: C) => Machine<C, any>) => T
351
+ ): Machine<C, BindTransitions<T>>;
352
+
353
+ /**
354
+ * Creates a synchronous state machine from a context and transition functions.
355
+ * This is the core factory for the functional approach.
356
+ *
357
+ * @template C - The context object type.
358
+ * @param context - The initial state context.
359
+ * @param fns - An object containing transition function definitions.
360
+ * @returns A new machine instance.
361
+ */
362
+ export function createMachine<C extends object, T extends Record<string, (this: { context: C } & T, ...args: any[]) => any> & { context?: any }>(
363
+ context: C,
364
+ fns: T
365
+ ): { context: C } & T;
366
+
367
+ /**
368
+ * Creates a synchronous state machine by copying context and transitions from an existing machine.
369
+ * This is useful for creating a new machine with updated context but the same transitions.
370
+ *
371
+ * @template C - The context object type.
372
+ * @template M - The machine type to copy transitions from.
373
+ * @param context - The new context.
374
+ * @param machine - The machine to copy transitions from.
375
+ * @returns A new machine instance with the given context and copied transitions.
376
+ */
377
+ export function createMachine<C extends object, M extends BaseMachine<C>>(
378
+ context: C,
379
+ machine: M
380
+ ): Machine<C, Transitions<M>>;
381
+
382
+ /**
383
+ * Creates a synchronous state machine from a context and transition functions that expect `this` to be the context object.
384
+ * This is used internally by utilities that need to bind transitions to context objects.
385
+ *
386
+ * @template C - The context object type.
387
+ * @param context - The initial state context.
388
+ * @param fns - An object containing transition function definitions that expect `this` to be the context.
389
+ * @returns A new machine instance.
390
+ */
149
391
  export function createMachine<C extends object, T extends Record<string, (this: C, ...args: any[]) => any>>(
150
392
  context: C,
151
393
  fns: T
152
- ): { context: C } & T {
394
+ ): Machine<C, T>;
395
+
396
+ export function createMachine(context: any, fnsOrFactory: any): any {
397
+ if (typeof fnsOrFactory === 'function') {
398
+ let transitions: any;
399
+ const transition = (newContext: any) => {
400
+ const machine = createMachine(newContext, transitions);
401
+ // Re-bind transitions to the new context
402
+ const boundTransitions = Object.fromEntries(
403
+ Object.entries(transitions).map(([key, fn]) => [
404
+ key,
405
+ (fn as Function).bind(newContext)
406
+ ])
407
+ );
408
+ return Object.assign(machine, boundTransitions);
409
+ };
410
+ transitions = fnsOrFactory(transition);
411
+
412
+ // Bind transitions to initial context
413
+ const boundTransitions = Object.fromEntries(
414
+ Object.entries(transitions).map(([key, fn]) => [
415
+ key,
416
+ (fn as Function).bind(context)
417
+ ])
418
+ );
419
+
420
+ return Object.assign({ context }, boundTransitions);
421
+ }
422
+
153
423
  // If fns is a machine (has context property), extract just the transition functions
154
- const transitions = 'context' in fns ? Object.fromEntries(
155
- Object.entries(fns).filter(([key]) => key !== 'context')
156
- ) : fns;
424
+ const transitions = 'context' in fnsOrFactory ? Object.fromEntries(
425
+ Object.entries(fnsOrFactory).filter(([key]) => key !== 'context')
426
+ ) : fnsOrFactory;
427
+
428
+ // For normal object transitions, we might also need binding if they use `this`
429
+ // But existing code expects `this` to be the machine (context + transitions).
430
+ // The new API expects `this` to be just context.
431
+
157
432
  const machine = Object.assign({ context }, transitions);
158
- return machine as { context: C } & T;
433
+ return machine;
159
434
  }
160
435
 
436
+ /**
437
+ * Creates an asynchronous state machine from a context and a factory function.
438
+ * This "Functional Builder" pattern allows for type-safe transitions without
439
+ * manually passing `this` or `transitions`.
440
+ *
441
+ * @template C - The context object type.
442
+ * @template T - The transitions object type.
443
+ * @param context - The initial state context.
444
+ * @param factory - A function that receives a `transition` helper and returns the transitions object.
445
+ * @returns A new async machine instance.
446
+ */
447
+ export function createAsyncMachine<C extends object, T extends Record<string, (this: C, ...args: any[]) => any>>(
448
+ context: C,
449
+ factory: (transition: (newContext: C) => AsyncMachine<C, T>) => T
450
+ ): AsyncMachine<C, BindTransitions<T>>;
451
+
452
+ /**
453
+ * Creates an asynchronous state machine by copying context and transitions from an existing machine.
454
+ * This is useful for creating a new machine with updated context but the same transitions.
455
+ *
456
+ * @template C - The context object type.
457
+ * @template M - The machine type to copy transitions from.
458
+ * @param context - The new context.
459
+ * @param machine - The machine to copy transitions from.
460
+ * @returns A new async machine instance with the given context and copied transitions.
461
+ */
462
+ export function createAsyncMachine<C extends object, M extends BaseMachine<C>>(
463
+ context: C,
464
+ machine: M
465
+ ): AsyncMachine<C, Transitions<M>>;
466
+
161
467
  /**
162
468
  * Creates an asynchronous state machine from a context and async transition functions.
163
469
  *
@@ -169,8 +475,42 @@ export function createMachine<C extends object, T extends Record<string, (this:
169
475
  export function createAsyncMachine<C extends object, T extends Record<string, (this: C, ...args: any[]) => any>>(
170
476
  context: C,
171
477
  fns: T
172
- ): { context: C } & T {
173
- return Object.assign({ context }, fns);
478
+ ): AsyncMachine<C, T>;
479
+
480
+ export function createAsyncMachine(context: any, fnsOrFactory: any): any {
481
+ if (typeof fnsOrFactory === 'function') {
482
+ let transitions: any;
483
+ const transition = (newContext: any) => {
484
+ const machine = createAsyncMachine(newContext, transitions);
485
+ // Re-bind transitions to the new context
486
+ const boundTransitions = Object.fromEntries(
487
+ Object.entries(transitions).map(([key, fn]) => [
488
+ key,
489
+ (fn as Function).bind(newContext)
490
+ ])
491
+ );
492
+ return Object.assign(machine, boundTransitions);
493
+ };
494
+ transitions = fnsOrFactory(transition);
495
+
496
+ // Bind transitions to initial context
497
+ const boundTransitions = Object.fromEntries(
498
+ Object.entries(transitions).map(([key, fn]) => [
499
+ key,
500
+ (fn as Function).bind(context)
501
+ ])
502
+ );
503
+
504
+ return Object.assign({ context }, boundTransitions);
505
+ }
506
+
507
+ // If fns is a machine (has context property), extract just the transition functions
508
+ const transitions = 'context' in fnsOrFactory ? Object.fromEntries(
509
+ Object.entries(fnsOrFactory).filter(([key]) => key !== 'context')
510
+ ) : fnsOrFactory;
511
+
512
+ const machine = Object.assign({ context }, transitions);
513
+ return machine;
174
514
  }
175
515
 
176
516
  /**
@@ -196,16 +536,16 @@ export function createMachineFactory<C extends object>() {
196
536
  ) => {
197
537
  type MachineFns = {
198
538
  [K in keyof T]: (
199
- this: C,
539
+ this: Machine<C>,
200
540
  ...args: T[K] extends (ctx: C, ...args: infer A) => C ? A : never
201
- ) => Machine<C>;
541
+ ) => MaybePromise<Machine<C>>;
202
542
  };
203
543
 
204
544
  const fns = Object.fromEntries(
205
545
  Object.entries(transformers).map(([key, transform]) => [
206
546
  key,
207
- function (this: C, ...args: any[]) {
208
- const newContext = (transform as any)(this, ...args);
547
+ function (this: Machine<C>, ...args: any[]) {
548
+ const newContext = (transform as any)(this.context, ...args);
209
549
  return createMachine(newContext, fns as any);
210
550
  },
211
551
  ])
@@ -241,7 +581,7 @@ export function setContext<M extends Machine<any>>(
241
581
  ? (newContextOrFn as (ctx: Readonly<Context<M>>) => Context<M>)(context)
242
582
  : newContextOrFn;
243
583
 
244
- return createMachine(newContext, transitions) as M;
584
+ return createMachine(newContext, transitions as any) as M;
245
585
  }
246
586
 
247
587
  /**
@@ -263,7 +603,7 @@ export function overrideTransitions<
263
603
  ): Machine<Context<M>> & Omit<Transitions<M>, keyof T> & T {
264
604
  const { context, ...originalTransitions } = machine;
265
605
  const newTransitions = { ...originalTransitions, ...overrides };
266
- return createMachine(context, newTransitions) as any;
606
+ return createMachine(context, newTransitions as any) as any;
267
607
  }
268
608
 
269
609
  /**
@@ -285,7 +625,7 @@ export function extendTransitions<
285
625
  >(machine: M, newTransitions: T): M & T {
286
626
  const { context, ...originalTransitions } = machine;
287
627
  const combinedTransitions = { ...originalTransitions, ...newTransitions };
288
- return createMachine(context, combinedTransitions) as M & T;
628
+ return createMachine(context, combinedTransitions as any) as M & T;
289
629
  }
290
630
 
291
631
  /**
@@ -339,8 +679,8 @@ export function combineFactories<
339
679
  ): (
340
680
  ...args: Parameters<F1>
341
681
  ) => Machine<Context<ReturnType<F1>> & Context<ReturnType<F2>>> &
342
- Omit<ReturnType<F1>, 'context'> &
343
- Omit<ReturnType<F2>, 'context'> {
682
+ Omit<ReturnType<F1>, 'context'> &
683
+ Omit<ReturnType<F2>, 'context'> {
344
684
  return (...args: Parameters<F1>) => {
345
685
  // Create instances from both factories
346
686
  const machine1 = factory1(...args);
@@ -357,7 +697,7 @@ export function combineFactories<
357
697
  const combinedTransitions = { ...transitions1, ...transitions2 };
358
698
 
359
699
  // Create the combined machine
360
- return createMachine(combinedContext, combinedTransitions) as any;
700
+ return createMachine(combinedContext, combinedTransitions as any) as any;
361
701
  };
362
702
  }
363
703
 
@@ -375,7 +715,7 @@ export function createMachineBuilder<M extends Machine<any>>(
375
715
  ): (context: Context<M>) => M {
376
716
  const { context, ...transitions } = templateMachine;
377
717
  return (newContext: Context<M>): M => {
378
- return createMachine(newContext, transitions) as M;
718
+ return createMachine(newContext, transitions as any) as M;
379
719
  };
380
720
  }
381
721
 
@@ -607,7 +947,7 @@ export function next<C extends object>(
607
947
  update: (ctx: Readonly<C>) => C
608
948
  ): Machine<C> {
609
949
  const { context, ...transitions } = m;
610
- return createMachine(update(context), transitions) as Machine<C>;
950
+ return createMachine(update(context), transitions as any) as Machine<C>;
611
951
  }
612
952
 
613
953
  /**
@@ -694,30 +1034,17 @@ export {
694
1034
  } from './primitives';
695
1035
 
696
1036
  // =============================================================================
697
- // SECTION: STATECHART EXTRACTION
1037
+ // SECTION: STATECHART EXTRACTION (Build-time only)
698
1038
  // =============================================================================
699
1039
 
700
- export {
701
- extractMachine,
702
- extractMachines,
703
- generateChart,
704
- type MachineConfig,
705
- type ExtractionConfig
706
- } from './extract';
707
-
708
- // =============================================================================
709
- // SECTION: RUNTIME EXTRACTION
710
- // =============================================================================
1040
+ // Note: Extraction tools are available as dev dependencies for build-time use
1041
+ // They are not included in the runtime bundle for size optimization
1042
+ // Use: npx tsx scripts/extract-statechart.ts
711
1043
 
712
- export {
713
- extractFunctionMetadata,
714
- extractStateNode,
715
- generateStatechart,
716
- extractFromInstance
717
- } from './runtime-extract';
718
-
719
- // Export runtime metadata symbol and type (for advanced use)
720
- export { RUNTIME_META, type RuntimeTransitionMeta } from './primitives';
1044
+ export type {
1045
+ MachineConfig,
1046
+ ExtractionConfig
1047
+ } from './extract';
721
1048
 
722
1049
 
723
1050
  export * from './multi'
@@ -730,46 +1057,7 @@ export * from './extract'
730
1057
  // SECTION: MIDDLEWARE & INTERCEPTION
731
1058
  // =============================================================================
732
1059
 
733
- export {
734
- createMiddleware,
735
- withLogging,
736
- withAnalytics,
737
- withValidation,
738
- withPermissions,
739
- withErrorReporting,
740
- withPerformanceMonitoring,
741
- withRetry,
742
- withHistory,
743
- withSnapshot,
744
- withTimeTravel,
745
- compose,
746
- composeTyped,
747
- createPipeline,
748
- createMiddlewareRegistry,
749
- when,
750
- inDevelopment,
751
- whenContext,
752
- combine,
753
- branch,
754
- isMiddlewareFn,
755
- isConditionalMiddleware,
756
- createCustomMiddleware,
757
- type MiddlewareHooks,
758
- type MiddlewareOptions,
759
- type MiddlewareContext,
760
- type MiddlewareResult,
761
- type MiddlewareError,
762
- type HistoryEntry,
763
- type ContextSnapshot,
764
- type Serializer,
765
- type MiddlewareFn,
766
- type ConditionalMiddleware,
767
- type NamedMiddleware,
768
- type PipelineConfig,
769
- type PipelineResult,
770
- chain,
771
- withDebugging
772
- } from './middleware';
1060
+ export * from './middleware/index';
773
1061
 
774
1062
  // =============================================================================
775
1063
  // SECTION: UTILITIES & HELPERS