@doeixd/machine 0.0.12 → 0.0.17
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/README.md +90 -15
- package/dist/cjs/development/core.js +1852 -0
- package/dist/cjs/development/core.js.map +7 -0
- package/dist/cjs/development/index.js +1348 -1374
- package/dist/cjs/development/index.js.map +4 -4
- package/dist/cjs/production/core.js +1 -0
- package/dist/cjs/production/index.js +5 -5
- package/dist/esm/development/core.js +1829 -0
- package/dist/esm/development/core.js.map +7 -0
- package/dist/esm/development/index.js +1348 -1374
- package/dist/esm/development/index.js.map +4 -4
- package/dist/esm/production/core.js +1 -0
- package/dist/esm/production/index.js +5 -5
- package/dist/types/core.d.ts +18 -0
- package/dist/types/core.d.ts.map +1 -0
- package/dist/types/functional-combinators.d.ts +60 -5
- package/dist/types/functional-combinators.d.ts.map +1 -1
- package/dist/types/index.d.ts +242 -19
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/middleware/composition.d.ts +460 -0
- package/dist/types/middleware/composition.d.ts.map +1 -0
- package/dist/types/middleware/core.d.ts +196 -0
- package/dist/types/middleware/core.d.ts.map +1 -0
- package/dist/types/middleware/history.d.ts +54 -0
- package/dist/types/middleware/history.d.ts.map +1 -0
- package/dist/types/middleware/index.d.ts +10 -0
- package/dist/types/middleware/index.d.ts.map +1 -0
- package/dist/types/middleware/snapshot.d.ts +63 -0
- package/dist/types/middleware/snapshot.d.ts.map +1 -0
- package/dist/types/middleware/time-travel.d.ts +81 -0
- package/dist/types/middleware/time-travel.d.ts.map +1 -0
- package/package.json +19 -6
- package/src/core.ts +167 -0
- package/src/entry-react.ts +9 -0
- package/src/entry-solid.ts +9 -0
- package/src/functional-combinators.ts +76 -3
- package/src/index.ts +376 -102
- package/src/middleware/composition.ts +944 -0
- package/src/middleware/core.ts +573 -0
- package/src/middleware/history.ts +104 -0
- package/src/middleware/index.ts +13 -0
- package/src/middleware/snapshot.ts +153 -0
- package/src/middleware/time-travel.ts +236 -0
- package/src/middleware.ts +735 -1614
- package/src/prototype_functional.ts +46 -0
- package/src/reproduce_issue.ts +26 -0
- package/dist/types/middleware.d.ts +0 -1048
- package/dist/types/middleware.d.ts.map +0 -1
- package/dist/types/runtime-extract.d.ts +0 -53
- package/dist/types/runtime-extract.d.ts.map +0 -1
|
@@ -1,1048 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file Middleware/interception system for state machines
|
|
3
|
-
* @description Provides composable middleware for logging, analytics, validation, and more.
|
|
4
|
-
*/
|
|
5
|
-
import type { Context, BaseMachine } from './index';
|
|
6
|
-
/**
|
|
7
|
-
* Context object passed to middleware hooks containing transition metadata.
|
|
8
|
-
* @template C - The context object type
|
|
9
|
-
*/
|
|
10
|
-
export interface MiddlewareContext<C extends object> {
|
|
11
|
-
/** The name of the transition being called */
|
|
12
|
-
transitionName: string;
|
|
13
|
-
/** The current machine context before the transition */
|
|
14
|
-
context: Readonly<C>;
|
|
15
|
-
/** Arguments passed to the transition function */
|
|
16
|
-
args: any[];
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Result object passed to after hooks containing transition outcome.
|
|
20
|
-
* @template C - The context object type
|
|
21
|
-
*/
|
|
22
|
-
export interface MiddlewareResult<C extends object> {
|
|
23
|
-
/** The name of the transition that was called */
|
|
24
|
-
transitionName: string;
|
|
25
|
-
/** The context before the transition */
|
|
26
|
-
prevContext: Readonly<C>;
|
|
27
|
-
/** The context after the transition */
|
|
28
|
-
nextContext: Readonly<C>;
|
|
29
|
-
/** Arguments that were passed to the transition */
|
|
30
|
-
args: any[];
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Error context passed to error hooks.
|
|
34
|
-
* @template C - The context object type
|
|
35
|
-
*/
|
|
36
|
-
export interface MiddlewareError<C extends object> {
|
|
37
|
-
/** The name of the transition that failed */
|
|
38
|
-
transitionName: string;
|
|
39
|
-
/** The context when the error occurred */
|
|
40
|
-
context: Readonly<C>;
|
|
41
|
-
/** Arguments that were passed to the transition */
|
|
42
|
-
args: any[];
|
|
43
|
-
/** The error that was thrown */
|
|
44
|
-
error: Error;
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Configuration object for middleware hooks.
|
|
48
|
-
* All hooks are optional - provide only the ones you need.
|
|
49
|
-
* @template C - The context object type
|
|
50
|
-
*/
|
|
51
|
-
/**
|
|
52
|
-
* Strongly typed middleware hooks with precise context and return types.
|
|
53
|
-
* All hooks are optional - provide only the ones you need.
|
|
54
|
-
*
|
|
55
|
-
* @template C - The machine context type for precise type inference
|
|
56
|
-
*/
|
|
57
|
-
export interface MiddlewareHooks<C extends object> {
|
|
58
|
-
/**
|
|
59
|
-
* Called before a transition executes.
|
|
60
|
-
* Can be used for validation, logging, analytics, etc.
|
|
61
|
-
*
|
|
62
|
-
* @param ctx - Transition context with machine state and transition details
|
|
63
|
-
* @returns void to continue, CANCEL to abort silently, or Promise for async validation
|
|
64
|
-
*
|
|
65
|
-
* @example
|
|
66
|
-
* ```typescript
|
|
67
|
-
* before: ({ transitionName, args, context }) => {
|
|
68
|
-
* if (transitionName === 'withdraw' && context.balance < args[0]) {
|
|
69
|
-
* throw new Error('Insufficient funds');
|
|
70
|
-
* }
|
|
71
|
-
* }
|
|
72
|
-
* ```
|
|
73
|
-
*/
|
|
74
|
-
before?: (ctx: MiddlewareContext<C>) => void | typeof CANCEL | Promise<void | typeof CANCEL>;
|
|
75
|
-
/**
|
|
76
|
-
* Called after a transition successfully executes.
|
|
77
|
-
* Receives both the previous and next context.
|
|
78
|
-
* Cannot prevent the transition (it already happened).
|
|
79
|
-
*
|
|
80
|
-
* @param result - Transition result with before/after contexts and transition details
|
|
81
|
-
*
|
|
82
|
-
* @example
|
|
83
|
-
* ```typescript
|
|
84
|
-
* after: ({ transitionName, before, after }) => {
|
|
85
|
-
* console.log(`${transitionName}: ${before.count} -> ${after.count}`);
|
|
86
|
-
* }
|
|
87
|
-
* ```
|
|
88
|
-
*/
|
|
89
|
-
after?: (result: MiddlewareResult<C>) => void | Promise<void>;
|
|
90
|
-
/**
|
|
91
|
-
* Called if a transition throws an error.
|
|
92
|
-
* Can be used for error logging, Sentry reporting, fallback states, etc.
|
|
93
|
-
*
|
|
94
|
-
* @param error - Error context with transition details and the thrown error
|
|
95
|
-
* @returns
|
|
96
|
-
* - void/undefined/null: Re-throw the original error (default)
|
|
97
|
-
* - BaseMachine: Use this as fallback state instead of throwing
|
|
98
|
-
* - throw new Error: Transform the error
|
|
99
|
-
*
|
|
100
|
-
* @example
|
|
101
|
-
* ```typescript
|
|
102
|
-
* error: ({ transitionName, error, context }) => {
|
|
103
|
-
* // Log to error reporting service
|
|
104
|
-
* reportError(error, { transitionName, context });
|
|
105
|
-
*
|
|
106
|
-
* // Return fallback state for recoverable errors
|
|
107
|
-
* if (error.message.includes('network')) {
|
|
108
|
-
* return createMachine({ ...context, error: 'offline' }, transitions);
|
|
109
|
-
* }
|
|
110
|
-
* }
|
|
111
|
-
* ```
|
|
112
|
-
*/
|
|
113
|
-
error?: (error: MiddlewareError<C>) => void | null | BaseMachine<C> | Promise<void | null | BaseMachine<C>>;
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Options for middleware configuration.
|
|
117
|
-
*/
|
|
118
|
-
export interface MiddlewareOptions {
|
|
119
|
-
/**
|
|
120
|
-
* Execution mode for middleware hooks.
|
|
121
|
-
* - 'sync': Hooks must be synchronous, throws if hooks return Promise
|
|
122
|
-
* - 'async': Always await hooks and transition
|
|
123
|
-
* - 'auto' (default): Adaptive mode - starts synchronously, automatically handles async results if encountered
|
|
124
|
-
*
|
|
125
|
-
* Note: 'auto' mode provides the best of both worlds - zero overhead for sync transitions
|
|
126
|
-
* while seamlessly handling async ones when they occur.
|
|
127
|
-
* @default 'auto'
|
|
128
|
-
*/
|
|
129
|
-
mode?: 'sync' | 'async' | 'auto';
|
|
130
|
-
/**
|
|
131
|
-
* Properties to exclude from middleware interception.
|
|
132
|
-
* Useful for excluding utility methods or getters.
|
|
133
|
-
* @default ['context']
|
|
134
|
-
*/
|
|
135
|
-
exclude?: string[];
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* Special symbol that can be returned from before hooks to cancel a transition.
|
|
139
|
-
* When returned, the transition will not execute and the current machine state is preserved.
|
|
140
|
-
*
|
|
141
|
-
* @example
|
|
142
|
-
* createMiddleware(machine, {
|
|
143
|
-
* before: ({ transitionName, context }) => {
|
|
144
|
-
* if (shouldCancel(context)) {
|
|
145
|
-
* return CANCEL; // Abort transition without throwing
|
|
146
|
-
* }
|
|
147
|
-
* }
|
|
148
|
-
* });
|
|
149
|
-
*/
|
|
150
|
-
export declare const CANCEL: unique symbol;
|
|
151
|
-
/**
|
|
152
|
-
* Augmented machine type with history tracking capabilities.
|
|
153
|
-
* @template M - The base machine type
|
|
154
|
-
* @template C - The context type
|
|
155
|
-
*/
|
|
156
|
-
export type WithHistory<M extends BaseMachine<any>> = M & {
|
|
157
|
-
/** Array of recorded transition history entries */
|
|
158
|
-
history: HistoryEntry[];
|
|
159
|
-
/** Clear all history entries */
|
|
160
|
-
clearHistory: () => void;
|
|
161
|
-
};
|
|
162
|
-
/**
|
|
163
|
-
* Augmented machine type with snapshot tracking capabilities.
|
|
164
|
-
* @template M - The base machine type
|
|
165
|
-
* @template C - The context type
|
|
166
|
-
*/
|
|
167
|
-
export type WithSnapshot<M extends BaseMachine<any>, C extends object = Context<M>> = M & {
|
|
168
|
-
/** Array of recorded context snapshots */
|
|
169
|
-
snapshots: ContextSnapshot<C>[];
|
|
170
|
-
/** Clear all snapshots */
|
|
171
|
-
clearSnapshots: () => void;
|
|
172
|
-
/** Restore machine to a previous context state */
|
|
173
|
-
restoreSnapshot: (context: C) => M;
|
|
174
|
-
};
|
|
175
|
-
/**
|
|
176
|
-
* Augmented machine type with full time-travel debugging capabilities.
|
|
177
|
-
* Combines both history and snapshot tracking.
|
|
178
|
-
* @template M - The base machine type
|
|
179
|
-
* @template C - The context type
|
|
180
|
-
*/
|
|
181
|
-
export type WithTimeTravel<M extends BaseMachine<any>, C extends object = Context<M>> = M & {
|
|
182
|
-
/** Array of recorded transition history entries */
|
|
183
|
-
history: HistoryEntry[];
|
|
184
|
-
/** Array of recorded context snapshots */
|
|
185
|
-
snapshots: ContextSnapshot<C>[];
|
|
186
|
-
/** Clear all history and snapshots */
|
|
187
|
-
clearTimeTravel: () => void;
|
|
188
|
-
/** Restore machine to a previous context state */
|
|
189
|
-
restoreSnapshot: (context: C) => M;
|
|
190
|
-
/** Replay all transitions from a specific snapshot */
|
|
191
|
-
replayFrom: (snapshotIndex: number) => M;
|
|
192
|
-
};
|
|
193
|
-
/**
|
|
194
|
-
* Wraps a machine with middleware hooks that intercept all transitions.
|
|
195
|
-
* Uses direct property wrapping for optimal performance (3x faster than Proxy).
|
|
196
|
-
*
|
|
197
|
-
* The middleware preserves:
|
|
198
|
-
* - Full type safety (return type matches input machine)
|
|
199
|
-
* - `this` binding for transitions
|
|
200
|
-
* - Async and sync transitions
|
|
201
|
-
* - Machine immutability
|
|
202
|
-
*
|
|
203
|
-
* @template M - The machine type
|
|
204
|
-
* @param machine - The machine to wrap with middleware
|
|
205
|
-
* @param hooks - Middleware hooks (before, after, error)
|
|
206
|
-
* @param options - Configuration options
|
|
207
|
-
* @returns A new machine with middleware applied
|
|
208
|
-
*
|
|
209
|
-
* @example
|
|
210
|
-
* const instrumented = createMiddleware(counter, {
|
|
211
|
-
* before: ({ transitionName, context, args }) => {
|
|
212
|
-
* console.log(`→ ${transitionName}`, args);
|
|
213
|
-
* },
|
|
214
|
-
* after: ({ transitionName, prevContext, nextContext }) => {
|
|
215
|
-
* console.log(`✓ ${transitionName}`, nextContext);
|
|
216
|
-
* },
|
|
217
|
-
* error: ({ transitionName, error }) => {
|
|
218
|
-
* console.error(`✗ ${transitionName}:`, error);
|
|
219
|
-
* }
|
|
220
|
-
* });
|
|
221
|
-
*/
|
|
222
|
-
export declare function createMiddleware<M extends BaseMachine<any>>(machine: M, hooks: MiddlewareHooks<Context<M>>, options?: MiddlewareOptions): M;
|
|
223
|
-
/**
|
|
224
|
-
* Logging middleware that logs transition calls and results to console.
|
|
225
|
-
* Useful for debugging and development.
|
|
226
|
-
*
|
|
227
|
-
* @template M - The machine type
|
|
228
|
-
* @param machine - The machine to add logging to
|
|
229
|
-
* @param options - Optional configuration for logging format
|
|
230
|
-
* @returns A new machine with logging middleware
|
|
231
|
-
*
|
|
232
|
-
* @example
|
|
233
|
-
* const logged = withLogging(counter);
|
|
234
|
-
* logged.increment(); // Console: "→ increment []" then "✓ increment { count: 1 }"
|
|
235
|
-
*/
|
|
236
|
-
export declare function withLogging<M extends BaseMachine<any>>(machine: M, options?: {
|
|
237
|
-
/** Custom logger function (default: console.log) */
|
|
238
|
-
logger?: (message: string, ...args: any[]) => void;
|
|
239
|
-
/** Include context in logs (default: true) */
|
|
240
|
-
includeContext?: boolean;
|
|
241
|
-
/** Include arguments in logs (default: true) */
|
|
242
|
-
includeArgs?: boolean;
|
|
243
|
-
}): M;
|
|
244
|
-
/**
|
|
245
|
-
* Analytics middleware that tracks state transitions.
|
|
246
|
-
* Compatible with any analytics service (Segment, Mixpanel, GA, etc.).
|
|
247
|
-
*
|
|
248
|
-
* @template M - The machine type
|
|
249
|
-
* @param machine - The machine to track
|
|
250
|
-
* @param track - Analytics tracking function
|
|
251
|
-
* @param options - Optional configuration for event naming
|
|
252
|
-
* @returns A new machine with analytics middleware
|
|
253
|
-
*
|
|
254
|
-
* @example
|
|
255
|
-
* const tracked = withAnalytics(machine, (event, props) => {
|
|
256
|
-
* analytics.track(event, props);
|
|
257
|
-
* });
|
|
258
|
-
*/
|
|
259
|
-
export declare function withAnalytics<M extends BaseMachine<any>>(machine: M, track: (event: string, properties: Record<string, any>) => void | Promise<void>, options?: {
|
|
260
|
-
/** Prefix for event names (default: "state_transition") */
|
|
261
|
-
eventPrefix?: string;
|
|
262
|
-
/** Include previous context in properties (default: false) */
|
|
263
|
-
includePrevContext?: boolean;
|
|
264
|
-
/** Include arguments in properties (default: true) */
|
|
265
|
-
includeArgs?: boolean;
|
|
266
|
-
}): M;
|
|
267
|
-
/**
|
|
268
|
-
* Validation middleware that validates transitions before they execute.
|
|
269
|
-
* Throws an error if validation fails, preventing the transition.
|
|
270
|
-
*
|
|
271
|
-
* @template M - The machine type
|
|
272
|
-
* @param machine - The machine to validate
|
|
273
|
-
* @param validate - Validation function that throws or returns false on invalid transitions
|
|
274
|
-
* @returns A new machine with validation middleware
|
|
275
|
-
*
|
|
276
|
-
* @example
|
|
277
|
-
* const validated = withValidation(counter, ({ transitionName, context, args }) => {
|
|
278
|
-
* if (transitionName === 'decrement' && context.count === 0) {
|
|
279
|
-
* throw new Error('Cannot decrement below zero');
|
|
280
|
-
* }
|
|
281
|
-
* });
|
|
282
|
-
*/
|
|
283
|
-
export declare function withValidation<M extends BaseMachine<any>>(machine: M, validate: (ctx: MiddlewareContext<Context<M>>) => void | boolean | Promise<void | boolean>, options?: Pick<MiddlewareOptions, 'mode'>): M;
|
|
284
|
-
/**
|
|
285
|
-
* Permission/authorization middleware that checks if a transition is allowed.
|
|
286
|
-
* Useful for implementing role-based access control (RBAC) in state machines.
|
|
287
|
-
*
|
|
288
|
-
* @template M - The machine type
|
|
289
|
-
* @param machine - The machine to protect
|
|
290
|
-
* @param canPerform - Function that checks if the transition is allowed
|
|
291
|
-
* @returns A new machine with permission checks
|
|
292
|
-
*
|
|
293
|
-
* @example
|
|
294
|
-
* const protected = withPermissions(machine, (user) => ({ transitionName }) => {
|
|
295
|
-
* if (transitionName === 'delete' && user.role !== 'admin') {
|
|
296
|
-
* return false;
|
|
297
|
-
* }
|
|
298
|
-
* return true;
|
|
299
|
-
* });
|
|
300
|
-
*/
|
|
301
|
-
export declare function withPermissions<M extends BaseMachine<any>>(machine: M, canPerform: (ctx: MiddlewareContext<Context<M>>) => boolean | Promise<boolean>, options?: Pick<MiddlewareOptions, 'mode'>): M;
|
|
302
|
-
/**
|
|
303
|
-
* Error reporting middleware that sends errors to an error tracking service.
|
|
304
|
-
* Compatible with Sentry, Bugsnag, Rollbar, etc.
|
|
305
|
-
*
|
|
306
|
-
* @template M - The machine type
|
|
307
|
-
* @param machine - The machine to monitor
|
|
308
|
-
* @param captureError - Error capture function (e.g., Sentry.captureException)
|
|
309
|
-
* @param options - Optional configuration for error context
|
|
310
|
-
* @returns A new machine with error reporting
|
|
311
|
-
*
|
|
312
|
-
* @example
|
|
313
|
-
* const monitored = withErrorReporting(machine, (error, context) => {
|
|
314
|
-
* Sentry.captureException(error, { extra: context });
|
|
315
|
-
* });
|
|
316
|
-
*/
|
|
317
|
-
export declare function withErrorReporting<M extends BaseMachine<any>>(machine: M, captureError: (error: Error, context: Record<string, any>) => void | Promise<void>, options?: {
|
|
318
|
-
/** Include machine context in error report (default: true) */
|
|
319
|
-
includeContext?: boolean;
|
|
320
|
-
/** Include arguments in error report (default: true) */
|
|
321
|
-
includeArgs?: boolean;
|
|
322
|
-
/** Middleware execution mode */
|
|
323
|
-
mode?: MiddlewareOptions['mode'];
|
|
324
|
-
}): M;
|
|
325
|
-
/**
|
|
326
|
-
* Performance monitoring middleware that tracks transition execution time.
|
|
327
|
-
* Useful for identifying slow transitions and performance bottlenecks.
|
|
328
|
-
*
|
|
329
|
-
* @template M - The machine type
|
|
330
|
-
* @param machine - The machine to monitor
|
|
331
|
-
* @param onMetric - Callback to receive performance metrics
|
|
332
|
-
* @returns A new machine with performance monitoring
|
|
333
|
-
*
|
|
334
|
-
* @example
|
|
335
|
-
* const monitored = withPerformanceMonitoring(machine, ({ transition, duration }) => {
|
|
336
|
-
* if (duration > 100) {
|
|
337
|
-
* console.warn(`Slow transition: ${transition} took ${duration}ms`);
|
|
338
|
-
* }
|
|
339
|
-
* });
|
|
340
|
-
*/
|
|
341
|
-
export declare function withPerformanceMonitoring<M extends BaseMachine<any>>(machine: M, onMetric: (metric: {
|
|
342
|
-
transitionName: string;
|
|
343
|
-
duration: number;
|
|
344
|
-
context: Readonly<Context<M>>;
|
|
345
|
-
}) => void | Promise<void>): M;
|
|
346
|
-
/**
|
|
347
|
-
* Retry middleware that automatically retries failed transitions.
|
|
348
|
-
* Uses direct property wrapping for optimal performance.
|
|
349
|
-
* Useful for handling transient failures in async operations.
|
|
350
|
-
*
|
|
351
|
-
* @template M - The machine type
|
|
352
|
-
* @param machine - The machine to add retry logic to
|
|
353
|
-
* @param options - Retry configuration
|
|
354
|
-
* @returns A new machine with retry logic
|
|
355
|
-
*
|
|
356
|
-
* @example
|
|
357
|
-
* const resilient = withRetry(machine, {
|
|
358
|
-
* maxRetries: 3,
|
|
359
|
-
* delay: 1000,
|
|
360
|
-
* shouldRetry: (error) => error.message.includes('network')
|
|
361
|
-
* });
|
|
362
|
-
*/
|
|
363
|
-
export declare function withRetry<M extends BaseMachine<any>>(machine: M, options?: {
|
|
364
|
-
/** Maximum number of retry attempts (default: 3) */
|
|
365
|
-
maxRetries?: number;
|
|
366
|
-
/** Delay between retries in milliseconds (default: 1000) */
|
|
367
|
-
delay?: number;
|
|
368
|
-
/** Exponential backoff multiplier (default: 1, no backoff) */
|
|
369
|
-
backoffMultiplier?: number;
|
|
370
|
-
/** Function to determine if error should trigger retry (default: always retry) */
|
|
371
|
-
shouldRetry?: (error: Error) => boolean;
|
|
372
|
-
/** Callback when retry occurs */
|
|
373
|
-
onRetry?: (attempt: number, error: Error) => void;
|
|
374
|
-
}): M;
|
|
375
|
-
/**
|
|
376
|
-
* Guard configuration for a single transition.
|
|
377
|
-
*/
|
|
378
|
-
export interface GuardConfig<C extends object> {
|
|
379
|
-
/** Guard predicate function that returns true if transition is allowed */
|
|
380
|
-
guard: (ctx: MiddlewareContext<C>, ...args: any[]) => boolean | Promise<boolean>;
|
|
381
|
-
/**
|
|
382
|
-
* Action to take when guard fails.
|
|
383
|
-
* - 'throw': Throw an error (default)
|
|
384
|
-
* - 'ignore': Silently cancel the transition
|
|
385
|
-
*
|
|
386
|
-
* Note: For custom fallback machines, use the error hook in createMiddleware:
|
|
387
|
-
* @example
|
|
388
|
-
* createMiddleware(machine, {
|
|
389
|
-
* error: ({ error, context }) => {
|
|
390
|
-
* if (error.message.includes('Guard failed')) {
|
|
391
|
-
* return createMachine({ ...context, error: 'Unauthorized' }, machine);
|
|
392
|
-
* }
|
|
393
|
-
* }
|
|
394
|
-
* });
|
|
395
|
-
*/
|
|
396
|
-
onFail?: 'throw' | 'ignore';
|
|
397
|
-
}
|
|
398
|
-
/**
|
|
399
|
-
* Guard middleware that prevents transitions based on predicate functions.
|
|
400
|
-
* Implements fundamental FSM guard concept - transitions only occur when guards pass.
|
|
401
|
-
*
|
|
402
|
-
* @template M - The machine type
|
|
403
|
-
* @param machine - The machine to protect with guards
|
|
404
|
-
* @param guards - Object mapping transition names to guard configurations
|
|
405
|
-
* @returns A new machine with guard checks
|
|
406
|
-
*
|
|
407
|
-
* @example
|
|
408
|
-
* const guarded = withGuards(counter, {
|
|
409
|
-
* decrement: {
|
|
410
|
-
* guard: ({ context }) => context.count > 0,
|
|
411
|
-
* onFail: 'throw' // or 'ignore'
|
|
412
|
-
* },
|
|
413
|
-
* delete: {
|
|
414
|
-
* guard: ({ context }) => context.user?.isAdmin === true,
|
|
415
|
-
* onFail: 'throw'
|
|
416
|
-
* }
|
|
417
|
-
* });
|
|
418
|
-
*
|
|
419
|
-
* guarded.decrement(); // Throws if count === 0
|
|
420
|
-
*
|
|
421
|
-
* // For custom fallback machines, combine with error middleware:
|
|
422
|
-
* const guardedWithFallback = createMiddleware(guarded, {
|
|
423
|
-
* error: ({ error, context }) => {
|
|
424
|
-
* if (error.message.includes('Guard failed')) {
|
|
425
|
-
* return createMachine({ ...context, error: 'Unauthorized' }, machine);
|
|
426
|
-
* }
|
|
427
|
-
* }
|
|
428
|
-
* });
|
|
429
|
-
*/
|
|
430
|
-
export declare function withGuards<M extends BaseMachine<any>>(machine: M, guards: Record<string, GuardConfig<Context<M>> | ((ctx: MiddlewareContext<Context<M>>, ...args: any[]) => boolean | Promise<boolean>)>, options?: Pick<MiddlewareOptions, 'mode'>): M;
|
|
431
|
-
/**
|
|
432
|
-
* Creates conditional middleware that only applies to specific transitions.
|
|
433
|
-
* Useful for targeted instrumentation without affecting all transitions.
|
|
434
|
-
*
|
|
435
|
-
* @template M - The machine type
|
|
436
|
-
* @param machine - The machine to instrument
|
|
437
|
-
* @param config - Configuration specifying which transitions to instrument
|
|
438
|
-
* @returns A new machine with conditional middleware
|
|
439
|
-
*
|
|
440
|
-
* @example
|
|
441
|
-
* const conditional = createConditionalMiddleware(counter, {
|
|
442
|
-
* only: ['delete', 'update'], // Only these transitions
|
|
443
|
-
* hooks: {
|
|
444
|
-
* before: ({ transitionName }) => console.log('Sensitive operation:', transitionName),
|
|
445
|
-
* after: ({ transitionName }) => auditLog(transitionName)
|
|
446
|
-
* }
|
|
447
|
-
* });
|
|
448
|
-
*
|
|
449
|
-
* @example
|
|
450
|
-
* const excluding = createConditionalMiddleware(counter, {
|
|
451
|
-
* except: ['increment'], // All except these
|
|
452
|
-
* hooks: {
|
|
453
|
-
* before: ({ transitionName, args }) => validate(transitionName, args)
|
|
454
|
-
* }
|
|
455
|
-
* });
|
|
456
|
-
*/
|
|
457
|
-
export declare function createConditionalMiddleware<M extends BaseMachine<any>>(machine: M, config: {
|
|
458
|
-
/** Only apply to these transitions (mutually exclusive with except) */
|
|
459
|
-
only?: string[];
|
|
460
|
-
/** Apply to all except these transitions (mutually exclusive with only) */
|
|
461
|
-
except?: string[];
|
|
462
|
-
/** Middleware hooks to apply */
|
|
463
|
-
hooks: MiddlewareHooks<Context<M>>;
|
|
464
|
-
/** Middleware options */
|
|
465
|
-
options?: MiddlewareOptions;
|
|
466
|
-
}): M;
|
|
467
|
-
/**
|
|
468
|
-
* Creates state-dependent middleware that only applies when a predicate is true.
|
|
469
|
-
* Allows middleware behavior to change based on current context/state.
|
|
470
|
-
*
|
|
471
|
-
* @template M - The machine type
|
|
472
|
-
* @param machine - The machine to instrument
|
|
473
|
-
* @param config - Configuration with predicate and hooks
|
|
474
|
-
* @returns A new machine with state-dependent middleware
|
|
475
|
-
*
|
|
476
|
-
* @example
|
|
477
|
-
* const stateful = createStateMiddleware(counter, {
|
|
478
|
-
* when: (ctx) => ctx.debugMode === true,
|
|
479
|
-
* hooks: {
|
|
480
|
-
* before: (ctx) => console.log('Debug:', ctx),
|
|
481
|
-
* after: (result) => console.log('Debug result:', result)
|
|
482
|
-
* }
|
|
483
|
-
* });
|
|
484
|
-
*
|
|
485
|
-
* // Logging only happens when context.debugMode === true
|
|
486
|
-
*/
|
|
487
|
-
export declare function createStateMiddleware<M extends BaseMachine<any>>(machine: M, config: {
|
|
488
|
-
/** Predicate that determines if middleware should apply */
|
|
489
|
-
when: (ctx: Context<M>) => boolean | Promise<boolean>;
|
|
490
|
-
/** Middleware hooks to apply when predicate is true */
|
|
491
|
-
hooks: MiddlewareHooks<Context<M>>;
|
|
492
|
-
/** Middleware options */
|
|
493
|
-
options?: MiddlewareOptions;
|
|
494
|
-
}): M;
|
|
495
|
-
/**
|
|
496
|
-
* Represents a recorded transition call in the history.
|
|
497
|
-
*/
|
|
498
|
-
export interface HistoryEntry {
|
|
499
|
-
/** Unique ID for this history entry */
|
|
500
|
-
id: string;
|
|
501
|
-
/** The transition that was called */
|
|
502
|
-
transitionName: string;
|
|
503
|
-
/** Arguments passed to the transition */
|
|
504
|
-
args: any[];
|
|
505
|
-
/** Timestamp when the transition was called */
|
|
506
|
-
timestamp: number;
|
|
507
|
-
/** Optional serialized version of args (if serializer provided) */
|
|
508
|
-
serializedArgs?: string;
|
|
509
|
-
}
|
|
510
|
-
/**
|
|
511
|
-
* Generic serializer/deserializer interface.
|
|
512
|
-
* Used for serializing history arguments, context snapshots, etc.
|
|
513
|
-
* @template T - The type being serialized
|
|
514
|
-
*/
|
|
515
|
-
export interface Serializer<T = any> {
|
|
516
|
-
/** Serialize data to a string */
|
|
517
|
-
serialize: (data: T) => string;
|
|
518
|
-
/** Deserialize string back to data */
|
|
519
|
-
deserialize: (serialized: string) => T;
|
|
520
|
-
}
|
|
521
|
-
/**
|
|
522
|
-
* History tracking middleware that records all transition calls.
|
|
523
|
-
* Useful for debugging, replay, undo/redo, and audit logging.
|
|
524
|
-
*
|
|
525
|
-
* @template M - The machine type
|
|
526
|
-
* @param machine - The machine to track
|
|
527
|
-
* @param options - Configuration options
|
|
528
|
-
* @returns A new machine with history tracking and a history array
|
|
529
|
-
*
|
|
530
|
-
* Note: Arguments are shallow-cloned by default. If you need deep cloning or
|
|
531
|
-
* serialization for persistence, provide a serializer:
|
|
532
|
-
*
|
|
533
|
-
* @example
|
|
534
|
-
* const tracked = withHistory(counter, {
|
|
535
|
-
* maxSize: 100,
|
|
536
|
-
* serializer: {
|
|
537
|
-
* serialize: (args) => JSON.stringify(args), // For deep clone or persistence
|
|
538
|
-
* deserialize: (str) => JSON.parse(str)
|
|
539
|
-
* }
|
|
540
|
-
* });
|
|
541
|
-
*
|
|
542
|
-
* tracked.increment();
|
|
543
|
-
* tracked.add(5);
|
|
544
|
-
* console.log(tracked.history); // [{ transitionName: 'increment', args: [], ... }, ...]
|
|
545
|
-
* tracked.clearHistory(); // Clear history
|
|
546
|
-
*/
|
|
547
|
-
export declare function withHistory<M extends BaseMachine<any>>(machine: M, options?: {
|
|
548
|
-
/** Maximum number of entries to keep (default: unlimited) */
|
|
549
|
-
maxSize?: number;
|
|
550
|
-
/** Optional serializer for arguments */
|
|
551
|
-
serializer?: Serializer<any[]>;
|
|
552
|
-
/** Filter function to exclude certain transitions from history */
|
|
553
|
-
filter?: (transitionName: string, args: any[]) => boolean;
|
|
554
|
-
/** Callback when new entry is added */
|
|
555
|
-
onEntry?: (entry: HistoryEntry) => void;
|
|
556
|
-
/** Internal flag to prevent rewrapping */
|
|
557
|
-
_isRewrap?: boolean;
|
|
558
|
-
}): WithHistory<M>;
|
|
559
|
-
/**
|
|
560
|
-
* Represents a snapshot of context at a point in time.
|
|
561
|
-
* @template C - The context type
|
|
562
|
-
*/
|
|
563
|
-
export interface ContextSnapshot<C extends object = any> {
|
|
564
|
-
/** Unique ID for this snapshot */
|
|
565
|
-
id: string;
|
|
566
|
-
/** The transition that caused this change */
|
|
567
|
-
transitionName: string;
|
|
568
|
-
/** Context before the transition */
|
|
569
|
-
before: C;
|
|
570
|
-
/** Context after the transition */
|
|
571
|
-
after: C;
|
|
572
|
-
/** Timestamp of the snapshot */
|
|
573
|
-
timestamp: number;
|
|
574
|
-
/** Optional serialized version of contexts */
|
|
575
|
-
serializedBefore?: string;
|
|
576
|
-
serializedAfter?: string;
|
|
577
|
-
/** Optional diff information */
|
|
578
|
-
diff?: any;
|
|
579
|
-
}
|
|
580
|
-
/**
|
|
581
|
-
* Snapshot middleware that records context before/after each transition.
|
|
582
|
-
* Useful for time-travel debugging, undo/redo, and state inspection.
|
|
583
|
-
*
|
|
584
|
-
* @template M - The machine type
|
|
585
|
-
* @param machine - The machine to track
|
|
586
|
-
* @param options - Configuration options
|
|
587
|
-
* @returns A new machine with snapshot tracking and snapshots array
|
|
588
|
-
*
|
|
589
|
-
* @example
|
|
590
|
-
* const tracked = withSnapshot(counter, {
|
|
591
|
-
* maxSize: 50,
|
|
592
|
-
* serializer: {
|
|
593
|
-
* serialize: (ctx) => JSON.stringify(ctx),
|
|
594
|
-
* deserialize: (str) => JSON.parse(str)
|
|
595
|
-
* },
|
|
596
|
-
* captureSnapshot: (before, after) => ({
|
|
597
|
-
* changed: before.count !== after.count
|
|
598
|
-
* })
|
|
599
|
-
* });
|
|
600
|
-
*
|
|
601
|
-
* tracked.increment();
|
|
602
|
-
* console.log(tracked.snapshots); // [{ before: { count: 0 }, after: { count: 1 }, ... }]
|
|
603
|
-
*
|
|
604
|
-
* // Time-travel: restore to previous state
|
|
605
|
-
* const previousState = tracked.restoreSnapshot(tracked.snapshots[0].before);
|
|
606
|
-
*/
|
|
607
|
-
export declare function withSnapshot<M extends BaseMachine<any>>(machine: M, options?: {
|
|
608
|
-
/** Maximum number of snapshots to keep (default: unlimited) */
|
|
609
|
-
maxSize?: number;
|
|
610
|
-
/** Optional serializer for context */
|
|
611
|
-
serializer?: Serializer<Context<M>>;
|
|
612
|
-
/** Custom function to capture additional snapshot data */
|
|
613
|
-
captureSnapshot?: (before: Context<M>, after: Context<M>) => any;
|
|
614
|
-
/** Only capture snapshots where context actually changed */
|
|
615
|
-
onlyIfChanged?: boolean;
|
|
616
|
-
/** Filter function to exclude certain transitions from snapshots */
|
|
617
|
-
filter?: (transitionName: string) => boolean;
|
|
618
|
-
/** Callback when new snapshot is taken */
|
|
619
|
-
onSnapshot?: (snapshot: ContextSnapshot<Context<M>>) => void;
|
|
620
|
-
/** Additional properties to exclude from middleware (for composition) */
|
|
621
|
-
_extraExclusions?: string[];
|
|
622
|
-
/** Internal flag to prevent rewrapping */
|
|
623
|
-
_isRewrap?: boolean;
|
|
624
|
-
}): WithSnapshot<M, Context<M>>;
|
|
625
|
-
/**
|
|
626
|
-
* Combined history and snapshot middleware for full time-travel debugging.
|
|
627
|
-
* Records both transition calls and context changes.
|
|
628
|
-
*
|
|
629
|
-
* @template M - The machine type
|
|
630
|
-
* @param machine - The machine to track
|
|
631
|
-
* @param options - Configuration options
|
|
632
|
-
* @returns Machine with both history and snapshot tracking
|
|
633
|
-
*
|
|
634
|
-
* @example
|
|
635
|
-
* const tracker = withTimeTravel(counter, {
|
|
636
|
-
* maxSize: 100,
|
|
637
|
-
* serializer: {
|
|
638
|
-
* serialize: (data) => JSON.stringify(data),
|
|
639
|
-
* deserialize: (str) => JSON.parse(str)
|
|
640
|
-
* }
|
|
641
|
-
* });
|
|
642
|
-
*
|
|
643
|
-
* tracker.increment();
|
|
644
|
-
* tracker.add(5);
|
|
645
|
-
*
|
|
646
|
-
* console.log(tracker.history); // All transitions
|
|
647
|
-
* console.log(tracker.snapshots); // All state changes
|
|
648
|
-
*
|
|
649
|
-
* // Replay from a specific snapshot
|
|
650
|
-
* const replayed = tracker.replayFrom(0);
|
|
651
|
-
*
|
|
652
|
-
* // Restore to specific snapshot
|
|
653
|
-
* const restored = tracker.restoreSnapshot(tracker.snapshots[0].before);
|
|
654
|
-
*
|
|
655
|
-
* // Clear all tracking data
|
|
656
|
-
* tracker.clearTimeTravel();
|
|
657
|
-
*/
|
|
658
|
-
export declare function withTimeTravel<M extends BaseMachine<any>>(machine: M, options?: {
|
|
659
|
-
/** Maximum size for both history and snapshots */
|
|
660
|
-
maxSize?: number;
|
|
661
|
-
/** Serializer for both args and context */
|
|
662
|
-
serializer?: Serializer<any>;
|
|
663
|
-
/** Callback for each recorded action */
|
|
664
|
-
onRecord?: (type: 'history' | 'snapshot', data: any) => void;
|
|
665
|
-
}): WithTimeTravel<M, Context<M>>;
|
|
666
|
-
/**
|
|
667
|
-
* Compose multiple middleware functions into a single middleware stack.
|
|
668
|
-
* Middleware is applied left-to-right (first middleware wraps outermost).
|
|
669
|
-
*
|
|
670
|
-
* @template M - The machine type
|
|
671
|
-
* @param machine - The base machine
|
|
672
|
-
* @param middlewares - Array of middleware functions
|
|
673
|
-
* @returns A new machine with all middleware applied
|
|
674
|
-
*
|
|
675
|
-
* @example
|
|
676
|
-
* const instrumented = compose(
|
|
677
|
-
* counter,
|
|
678
|
-
* withLogging,
|
|
679
|
-
* withAnalytics(analytics.track),
|
|
680
|
-
* withValidation(validator),
|
|
681
|
-
* withErrorReporting(Sentry.captureException)
|
|
682
|
-
* );
|
|
683
|
-
*/
|
|
684
|
-
export declare function compose<M extends BaseMachine<any>>(machine: M, ...middlewares: Array<(m: M) => M>): M;
|
|
685
|
-
/**
|
|
686
|
-
* Create a reusable middleware function from hooks.
|
|
687
|
-
* Useful for defining custom middleware that can be applied to multiple machines.
|
|
688
|
-
*
|
|
689
|
-
* @template M - The machine type
|
|
690
|
-
* @param hooks - Middleware hooks configuration
|
|
691
|
-
* @param options - Middleware options
|
|
692
|
-
* @returns A middleware function that can be applied to machines
|
|
693
|
-
*
|
|
694
|
-
* @example
|
|
695
|
-
* const myMiddleware = createCustomMiddleware({
|
|
696
|
-
* before: ({ transitionName }) => console.log('Before:', transitionName),
|
|
697
|
-
* after: ({ transitionName }) => console.log('After:', transitionName)
|
|
698
|
-
* });
|
|
699
|
-
*
|
|
700
|
-
* const machine1 = myMiddleware(counter1);
|
|
701
|
-
* const machine2 = myMiddleware(counter2);
|
|
702
|
-
*/
|
|
703
|
-
export declare function createCustomMiddleware<M extends BaseMachine<any>>(hooks: MiddlewareHooks<Context<M>>, options?: MiddlewareOptions): (machine: M) => M;
|
|
704
|
-
/**
|
|
705
|
-
* A middleware function that transforms a machine.
|
|
706
|
-
* @template M - The input machine type
|
|
707
|
-
* @template R - The output machine type (usually extends M)
|
|
708
|
-
*/
|
|
709
|
-
/**
|
|
710
|
-
* A middleware function that transforms a machine.
|
|
711
|
-
* @template M - Input machine type
|
|
712
|
-
* @template R - Output machine type (defaults to same as input if no augmentation)
|
|
713
|
-
*/
|
|
714
|
-
export type MiddlewareFn<M extends BaseMachine<any>, R extends BaseMachine<any> = M> = (machine: M) => R;
|
|
715
|
-
/**
|
|
716
|
-
* A conditional middleware that may or may not be applied based on a predicate.
|
|
717
|
-
* @template M - The machine type
|
|
718
|
-
*/
|
|
719
|
-
export type ConditionalMiddleware<M extends BaseMachine<any>> = {
|
|
720
|
-
/** The middleware function to apply */
|
|
721
|
-
middleware: MiddlewareFn<M>;
|
|
722
|
-
/** Predicate function that determines if the middleware should be applied */
|
|
723
|
-
when: (machine: M) => boolean;
|
|
724
|
-
};
|
|
725
|
-
/**
|
|
726
|
-
* A named middleware entry for registry-based composition.
|
|
727
|
-
* @template M - The machine type
|
|
728
|
-
*/
|
|
729
|
-
export type NamedMiddleware<M extends BaseMachine<any>> = {
|
|
730
|
-
/** Unique name for the middleware */
|
|
731
|
-
name: string;
|
|
732
|
-
/** The middleware function */
|
|
733
|
-
middleware: MiddlewareFn<M>;
|
|
734
|
-
/** Optional description */
|
|
735
|
-
description?: string;
|
|
736
|
-
/** Optional priority for ordering (higher numbers = applied later) */
|
|
737
|
-
priority?: number;
|
|
738
|
-
};
|
|
739
|
-
/**
|
|
740
|
-
* Configuration for middleware pipeline execution.
|
|
741
|
-
*/
|
|
742
|
-
export interface PipelineConfig {
|
|
743
|
-
/** Whether to continue executing remaining middlewares if one fails */
|
|
744
|
-
continueOnError?: boolean;
|
|
745
|
-
/** Whether to log errors to console */
|
|
746
|
-
logErrors?: boolean;
|
|
747
|
-
/** Custom error handler */
|
|
748
|
-
onError?: (error: Error, middlewareName?: string) => void;
|
|
749
|
-
}
|
|
750
|
-
/**
|
|
751
|
-
* Result of pipeline execution.
|
|
752
|
-
*/
|
|
753
|
-
export interface PipelineResult<M extends BaseMachine<any>> {
|
|
754
|
-
/** The final machine after all middlewares */
|
|
755
|
-
machine: M;
|
|
756
|
-
/** Any errors that occurred during execution */
|
|
757
|
-
errors: Array<{
|
|
758
|
-
error: Error;
|
|
759
|
-
middlewareIndex: number;
|
|
760
|
-
middlewareName?: string;
|
|
761
|
-
}>;
|
|
762
|
-
/** Whether the pipeline completed successfully */
|
|
763
|
-
success: boolean;
|
|
764
|
-
}
|
|
765
|
-
/**
|
|
766
|
-
* Compose multiple middlewares with improved type inference.
|
|
767
|
-
* This is a more typesafe version of the basic compose function.
|
|
768
|
-
*
|
|
769
|
-
* @template M - The initial machine type
|
|
770
|
-
* @template Ms - Array of middleware functions
|
|
771
|
-
* @param machine - The initial machine
|
|
772
|
-
* @param middlewares - Array of middleware functions to apply
|
|
773
|
-
* @returns The machine with all middlewares applied
|
|
774
|
-
*
|
|
775
|
-
* @example
|
|
776
|
-
* const enhanced = composeTyped(
|
|
777
|
-
* counter,
|
|
778
|
-
* withHistory(),
|
|
779
|
-
* withSnapshot(),
|
|
780
|
-
* withTimeTravel()
|
|
781
|
-
* );
|
|
782
|
-
*/
|
|
783
|
-
/**
|
|
784
|
-
* Recursively applies middlewares to infer the final machine type.
|
|
785
|
-
* Provides precise type inference for middleware composition chains.
|
|
786
|
-
*/
|
|
787
|
-
type ComposeResult<M extends BaseMachine<any>, Ms extends readonly MiddlewareFn<any, any>[]> = Ms extends readonly [] ? M : Ms extends readonly [infer First, ...infer Rest] ? First extends MiddlewareFn<any, infer Output> ? Rest extends readonly MiddlewareFn<any, any>[] ? ComposeResult<Output, Rest> : Output : M : M;
|
|
788
|
-
/**
|
|
789
|
-
* Type-safe middleware composition with perfect inference.
|
|
790
|
-
* Composes multiple middlewares into a single transformation chain.
|
|
791
|
-
*
|
|
792
|
-
* @template M - The input machine type
|
|
793
|
-
* @template Ms - Array of middleware functions
|
|
794
|
-
* @param machine - The machine to enhance
|
|
795
|
-
* @param middlewares - Middleware functions to apply in order
|
|
796
|
-
* @returns The machine with all middlewares applied, with precise type inference
|
|
797
|
-
*
|
|
798
|
-
* @example
|
|
799
|
-
* ```typescript
|
|
800
|
-
* const enhanced = composeTyped(
|
|
801
|
-
* counter,
|
|
802
|
-
* withHistory(),
|
|
803
|
-
* withSnapshot(),
|
|
804
|
-
* withTimeTravel()
|
|
805
|
-
* );
|
|
806
|
-
* // enhanced: WithTimeTravel<WithSnapshot<WithHistory<Counter>>>
|
|
807
|
-
* // Perfect IntelliSense for all methods and properties
|
|
808
|
-
* ```
|
|
809
|
-
*/
|
|
810
|
-
export declare function composeTyped<M extends BaseMachine<any>, Ms extends readonly MiddlewareFn<any, any>[]>(machine: M, ...middlewares: Ms): ComposeResult<M, Ms>;
|
|
811
|
-
/**
|
|
812
|
-
* Type-safe middleware composition with fluent API.
|
|
813
|
-
* Allows building middleware chains with method chaining.
|
|
814
|
-
*
|
|
815
|
-
* @example
|
|
816
|
-
* ```typescript
|
|
817
|
-
* const enhanced = chain(counter)
|
|
818
|
-
* .with(withHistory())
|
|
819
|
-
* .with(withSnapshot())
|
|
820
|
-
* .with(withTimeTravel())
|
|
821
|
-
* .build();
|
|
822
|
-
* ```
|
|
823
|
-
*/
|
|
824
|
-
export declare function chain<M extends BaseMachine<any>>(machine: M): MiddlewareChainBuilder<M>;
|
|
825
|
-
/**
|
|
826
|
-
* Fluent middleware composer for building complex middleware chains.
|
|
827
|
-
* Provides excellent TypeScript inference and IntelliSense.
|
|
828
|
-
*/
|
|
829
|
-
declare class MiddlewareChainBuilder<M extends BaseMachine<any>> {
|
|
830
|
-
private machine;
|
|
831
|
-
constructor(machine: M);
|
|
832
|
-
/**
|
|
833
|
-
* Add a middleware to the composition chain.
|
|
834
|
-
* @param middleware - The middleware function to add
|
|
835
|
-
* @returns A new composer with the middleware applied
|
|
836
|
-
*/
|
|
837
|
-
with<M2 extends MiddlewareFn<any, any>>(middleware: M2): MiddlewareChainBuilder<ReturnType<M2> extends BaseMachine<any> ? ReturnType<M2> : M>;
|
|
838
|
-
/**
|
|
839
|
-
* Build the final machine with all middlewares applied.
|
|
840
|
-
*/
|
|
841
|
-
build(): M;
|
|
842
|
-
}
|
|
843
|
-
/**
|
|
844
|
-
* Common middleware combination types for better DX.
|
|
845
|
-
* These types help with inference when using popular middleware combinations.
|
|
846
|
-
*/
|
|
847
|
-
export type WithDebugging<M extends BaseMachine<any>> = WithTimeTravel<WithSnapshot<WithHistory<M>>>;
|
|
848
|
-
/**
|
|
849
|
-
* Convenience function for the most common debugging middleware stack.
|
|
850
|
-
* Combines history, snapshots, and time travel for full debugging capabilities.
|
|
851
|
-
*
|
|
852
|
-
* @example
|
|
853
|
-
* ```typescript
|
|
854
|
-
* const debugMachine = withDebugging(counter);
|
|
855
|
-
* debugMachine.increment();
|
|
856
|
-
* debugMachine.history; // Full transition history
|
|
857
|
-
* debugMachine.snapshots; // Context snapshots
|
|
858
|
-
* debugMachine.replayFrom(0); // Time travel
|
|
859
|
-
* ```
|
|
860
|
-
*/
|
|
861
|
-
export declare function withDebugging<M extends BaseMachine<any>>(machine: M): WithDebugging<M>;
|
|
862
|
-
/**
|
|
863
|
-
* Create a middleware pipeline with error handling and conditional execution.
|
|
864
|
-
*
|
|
865
|
-
* @template M - The machine type
|
|
866
|
-
* @param config - Pipeline configuration
|
|
867
|
-
* @returns A function that executes middlewares in a pipeline
|
|
868
|
-
*
|
|
869
|
-
* @example
|
|
870
|
-
* const pipeline = createPipeline({ continueOnError: true });
|
|
871
|
-
*
|
|
872
|
-
* const result = pipeline(
|
|
873
|
-
* counter,
|
|
874
|
-
* withHistory(),
|
|
875
|
-
* withSnapshot(),
|
|
876
|
-
* { middleware: withLogging(), when: (m) => m.context.debug }
|
|
877
|
-
* );
|
|
878
|
-
*/
|
|
879
|
-
export declare function createPipeline<M extends BaseMachine<any>>(config?: PipelineConfig): {
|
|
880
|
-
<Ms extends Array<MiddlewareFn<M> | ConditionalMiddleware<M>>>(machine: M, ...middlewares: Ms): PipelineResult<M>;
|
|
881
|
-
};
|
|
882
|
-
/**
|
|
883
|
-
* Create a middleware registry for named middleware composition.
|
|
884
|
-
* Useful for building complex middleware stacks from reusable components.
|
|
885
|
-
*
|
|
886
|
-
* @template M - The machine type
|
|
887
|
-
*
|
|
888
|
-
* @example
|
|
889
|
-
* const registry = createMiddlewareRegistry<CounterMachine>()
|
|
890
|
-
* .register('history', withHistory(), 'Track state changes')
|
|
891
|
-
* .register('snapshot', withSnapshot(), 'Take context snapshots', 10)
|
|
892
|
-
* .register('timeTravel', withTimeTravel(), 'Enable time travel debugging', 20);
|
|
893
|
-
*
|
|
894
|
-
* const machine = registry.apply(counter, ['history', 'snapshot', 'timeTravel']);
|
|
895
|
-
*/
|
|
896
|
-
export declare function createMiddlewareRegistry<M extends BaseMachine<any>>(): {
|
|
897
|
-
/**
|
|
898
|
-
* Register a middleware with a name and optional metadata.
|
|
899
|
-
*/
|
|
900
|
-
register(name: string, middleware: MiddlewareFn<M>, description?: string, priority?: number): {
|
|
901
|
-
register(name: string, middleware: MiddlewareFn<M>, description?: string, priority?: number): /*elided*/ any;
|
|
902
|
-
/**
|
|
903
|
-
* Unregister a middleware by name.
|
|
904
|
-
*/
|
|
905
|
-
unregister(name: string): boolean;
|
|
906
|
-
/**
|
|
907
|
-
* Check if a middleware is registered.
|
|
908
|
-
*/
|
|
909
|
-
has(name: string): boolean;
|
|
910
|
-
/**
|
|
911
|
-
* Get a registered middleware by name.
|
|
912
|
-
*/
|
|
913
|
-
get(name: string): NamedMiddleware<M> | undefined;
|
|
914
|
-
/**
|
|
915
|
-
* List all registered middlewares.
|
|
916
|
-
*/
|
|
917
|
-
list(): NamedMiddleware<M>[];
|
|
918
|
-
/**
|
|
919
|
-
* Apply a selection of registered middlewares to a machine.
|
|
920
|
-
* Middlewares are applied in priority order (lowest to highest).
|
|
921
|
-
*/
|
|
922
|
-
apply(machine: M, middlewareNames: string[]): M;
|
|
923
|
-
/**
|
|
924
|
-
* Apply all registered middlewares to a machine in priority order.
|
|
925
|
-
*/
|
|
926
|
-
applyAll(machine: M): M;
|
|
927
|
-
};
|
|
928
|
-
/**
|
|
929
|
-
* Unregister a middleware by name.
|
|
930
|
-
*/
|
|
931
|
-
unregister(name: string): boolean;
|
|
932
|
-
/**
|
|
933
|
-
* Check if a middleware is registered.
|
|
934
|
-
*/
|
|
935
|
-
has(name: string): boolean;
|
|
936
|
-
/**
|
|
937
|
-
* Get a registered middleware by name.
|
|
938
|
-
*/
|
|
939
|
-
get(name: string): NamedMiddleware<M> | undefined;
|
|
940
|
-
/**
|
|
941
|
-
* List all registered middlewares.
|
|
942
|
-
*/
|
|
943
|
-
list(): NamedMiddleware<M>[];
|
|
944
|
-
/**
|
|
945
|
-
* Apply a selection of registered middlewares to a machine.
|
|
946
|
-
* Middlewares are applied in priority order (lowest to highest).
|
|
947
|
-
*/
|
|
948
|
-
apply(machine: M, middlewareNames: string[]): M;
|
|
949
|
-
/**
|
|
950
|
-
* Apply all registered middlewares to a machine in priority order.
|
|
951
|
-
*/
|
|
952
|
-
applyAll(machine: M): M;
|
|
953
|
-
};
|
|
954
|
-
/**
|
|
955
|
-
* Create a conditional middleware that only applies when a predicate is true.
|
|
956
|
-
*
|
|
957
|
-
* @template M - The machine type
|
|
958
|
-
* @param middleware - The middleware to conditionally apply
|
|
959
|
-
* @param predicate - Function that determines when to apply the middleware
|
|
960
|
-
* @returns A conditional middleware that can be called directly or used in pipelines
|
|
961
|
-
*
|
|
962
|
-
* @example
|
|
963
|
-
* const debugMiddleware = when(
|
|
964
|
-
* withTimeTravel(),
|
|
965
|
-
* (machine) => machine.context.debugMode
|
|
966
|
-
* );
|
|
967
|
-
*
|
|
968
|
-
* // Can be called directly
|
|
969
|
-
* const machine = debugMiddleware(baseMachine);
|
|
970
|
-
*
|
|
971
|
-
* // Can also be used in pipelines
|
|
972
|
-
* const pipeline = createPipeline();
|
|
973
|
-
* const result = pipeline(machine, debugMiddleware);
|
|
974
|
-
*/
|
|
975
|
-
export declare function when<M extends BaseMachine<any>>(middleware: MiddlewareFn<M>, predicate: (machine: M) => boolean): ConditionalMiddleware<M> & MiddlewareFn<M>;
|
|
976
|
-
/**
|
|
977
|
-
* Create a middleware that only applies in development mode.
|
|
978
|
-
*
|
|
979
|
-
* @template M - The machine type
|
|
980
|
-
* @param middleware - The middleware to apply in development
|
|
981
|
-
* @returns A conditional middleware for development mode
|
|
982
|
-
*
|
|
983
|
-
* @example
|
|
984
|
-
* const devMachine = composeTyped(
|
|
985
|
-
* counter,
|
|
986
|
-
* inDevelopment(withTimeTravel())
|
|
987
|
-
* );
|
|
988
|
-
*/
|
|
989
|
-
export declare function inDevelopment<M extends BaseMachine<any>>(middleware: MiddlewareFn<M>): ConditionalMiddleware<M> & MiddlewareFn<M>;
|
|
990
|
-
/**
|
|
991
|
-
* Create a middleware that only applies when a context property matches a value.
|
|
992
|
-
*
|
|
993
|
-
* @template M - The machine type
|
|
994
|
-
* @template K - The context key
|
|
995
|
-
* @param key - The context property key
|
|
996
|
-
* @param value - The value to match
|
|
997
|
-
* @param middleware - The middleware to apply when the condition matches
|
|
998
|
-
* @returns A conditional middleware
|
|
999
|
-
*
|
|
1000
|
-
* @example
|
|
1001
|
-
* const adminMachine = composeTyped(
|
|
1002
|
-
* userMachine,
|
|
1003
|
-
* whenContext('role', 'admin', withAdminFeatures())
|
|
1004
|
-
* );
|
|
1005
|
-
*/
|
|
1006
|
-
export declare function whenContext<M extends BaseMachine<any>, K extends keyof Context<M>>(key: K, value: Context<M>[K], middleware: MiddlewareFn<M>): ConditionalMiddleware<M> & MiddlewareFn<M>;
|
|
1007
|
-
/**
|
|
1008
|
-
* Combine multiple middlewares with short-circuiting.
|
|
1009
|
-
* If any middleware returns a different type, the composition stops.
|
|
1010
|
-
*
|
|
1011
|
-
* @template M - The machine type
|
|
1012
|
-
* @param middlewares - Array of middlewares to combine
|
|
1013
|
-
* @returns A combined middleware function
|
|
1014
|
-
*
|
|
1015
|
-
* @example
|
|
1016
|
-
* const combined = combine(
|
|
1017
|
-
* withHistory(),
|
|
1018
|
-
* withSnapshot(),
|
|
1019
|
-
* withValidation()
|
|
1020
|
-
* );
|
|
1021
|
-
*/
|
|
1022
|
-
export declare function combine<M extends BaseMachine<any>>(...middlewares: Array<MiddlewareFn<M>>): MiddlewareFn<M>;
|
|
1023
|
-
/**
|
|
1024
|
-
* Create a middleware that applies different middlewares based on context.
|
|
1025
|
-
*
|
|
1026
|
-
* @template M - The machine type
|
|
1027
|
-
* @param branches - Array of [predicate, middleware] pairs
|
|
1028
|
-
* @param fallback - Optional fallback middleware if no predicates match
|
|
1029
|
-
* @returns A branching middleware
|
|
1030
|
-
*
|
|
1031
|
-
* @example
|
|
1032
|
-
* const smartMiddleware = branch(
|
|
1033
|
-
* [(m) => m.context.userType === 'admin', withAdminFeatures()],
|
|
1034
|
-
* [(m) => m.context.debug, withTimeTravel()],
|
|
1035
|
-
* withBasicLogging() // fallback
|
|
1036
|
-
* );
|
|
1037
|
-
*/
|
|
1038
|
-
export declare function branch<M extends BaseMachine<any>>(branches: Array<[predicate: (machine: M) => boolean, middleware: MiddlewareFn<M>]>, fallback?: MiddlewareFn<M>): MiddlewareFn<M>;
|
|
1039
|
-
/**
|
|
1040
|
-
* Type guard to check if a value is a middleware function.
|
|
1041
|
-
*/
|
|
1042
|
-
export declare function isMiddlewareFn<M extends BaseMachine<any>>(value: any): value is MiddlewareFn<M>;
|
|
1043
|
-
/**
|
|
1044
|
-
* Type guard to check if a value is a conditional middleware.
|
|
1045
|
-
*/
|
|
1046
|
-
export declare function isConditionalMiddleware<M extends BaseMachine<any>>(value: any): value is ConditionalMiddleware<M>;
|
|
1047
|
-
export {};
|
|
1048
|
-
//# sourceMappingURL=middleware.d.ts.map
|