@systemfsoftware/xstate-store 0.0.0-bootstrap.0 → 5.0.0-beta.6

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.
@@ -0,0 +1,442 @@
1
+ /** The Standard Schema interface. */
2
+ interface StandardSchemaV1<Input = unknown, Output = Input> {
3
+ /** The Standard Schema properties. */
4
+ readonly '~standard': StandardSchemaV1.Props<Input, Output>;
5
+ }
6
+ declare namespace StandardSchemaV1 {
7
+ /** The Standard Schema properties interface. */
8
+ interface Props<Input = unknown, Output = Input> {
9
+ /** The version number of the standard. */
10
+ readonly version: 1;
11
+ /** The vendor name of the schema library. */
12
+ readonly vendor: string;
13
+ /** Validates unknown input values. */
14
+ readonly validate: (value: unknown, options?: StandardSchemaV1.Options | undefined) => Result<Output> | Promise<Result<Output>>;
15
+ /** Inferred types associated with the schema. */
16
+ readonly types?: Types<Input, Output> | undefined;
17
+ }
18
+ /** The result interface of the validate function. */
19
+ type Result<Output> = SuccessResult<Output> | FailureResult;
20
+ /** The result interface if validation succeeds. */
21
+ interface SuccessResult<Output> {
22
+ /** The typed output value. */
23
+ readonly value: Output;
24
+ /** A falsy value for `issues` indicates success. */
25
+ readonly issues?: undefined;
26
+ }
27
+ interface Options {
28
+ /** Explicit support for additional vendor-specific parameters, if needed. */
29
+ readonly libraryOptions?: Record<string, unknown> | undefined;
30
+ }
31
+ /** The result interface if validation fails. */
32
+ interface FailureResult {
33
+ /** The issues of failed validation. */
34
+ readonly issues: ReadonlyArray<Issue>;
35
+ }
36
+ /** The issue interface of the failure output. */
37
+ interface Issue {
38
+ /** The error message of the issue. */
39
+ readonly message: string;
40
+ /** The path of the issue, if any. */
41
+ readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;
42
+ }
43
+ /** The path segment interface of the issue. */
44
+ interface PathSegment {
45
+ /** The key representing a path segment. */
46
+ readonly key: PropertyKey;
47
+ }
48
+ /** The Standard Schema types interface. */
49
+ interface Types<Input = unknown, Output = Input> {
50
+ /** The input type of the schema. */
51
+ readonly input: Input;
52
+ /** The output type of the schema. */
53
+ readonly output: Output;
54
+ }
55
+ /** Infers the input type of a Standard Schema. */
56
+ type InferInput<Schema extends StandardSchemaV1> = NonNullable<Schema['~standard']['types']>['input'];
57
+ /** Infers the output type of a Standard Schema. */
58
+ type InferOutput<Schema extends StandardSchemaV1> = NonNullable<Schema['~standard']['types']>['output'];
59
+ }
60
+ type EventPayloadMap = Record<string, {} | null | undefined>;
61
+ type ExtractEvents<T extends EventPayloadMap> = Values<{ [K in keyof T & string]: T[K] & {
62
+ type: K;
63
+ }; }>;
64
+ type StandardSchemaMap = Record<string, StandardSchemaV1<unknown, object>>;
65
+ type InferSchemaOutput<TSchema extends StandardSchemaV1, TFallback> = Compute<StandardSchemaV1.InferOutput<TSchema> extends TFallback ? StandardSchemaV1.InferOutput<TSchema> : never>;
66
+ type InferSchemaPayloadMap<TSchemaMap extends StandardSchemaMap> = { [K in keyof TSchemaMap & string]: NormalizeSchemaPayload<InferSchemaOutput<TSchemaMap[K], EventPayloadMap[string]>>; };
67
+ type NormalizeSchemaPayload<TPayload> = string extends keyof TPayload ? {} : TPayload;
68
+ type StoreSchemas<TContextSchema extends StandardSchemaV1 | undefined = undefined, TEventSchemaMap extends StandardSchemaMap | undefined = undefined, TEmittedSchemaMap extends StandardSchemaMap | undefined = undefined> = {
69
+ context?: TContextSchema;
70
+ events?: TEventSchemaMap;
71
+ emitted?: TEmittedSchemaMap;
72
+ };
73
+ type ResolveStoreContext<TContext extends StoreContext, TContextSchema extends StandardSchemaV1 | undefined> = TContextSchema extends StandardSchemaV1 ? InferSchemaOutput<TContextSchema, StoreContext> : TContext;
74
+ type ResolveStoreEventPayloadMap<TEventPayloadMap extends EventPayloadMap, TEventSchemaMap extends StandardSchemaMap | undefined> = TEventSchemaMap extends StandardSchemaMap ? InferSchemaPayloadMap<TEventSchemaMap> : TEventPayloadMap;
75
+ type ResolveStoreEmittedPayloadMap<TEmittedPayloadMap extends EventPayloadMap, TEmittedSchemaMap extends StandardSchemaMap | undefined> = TEmittedSchemaMap extends StandardSchemaMap ? InferSchemaPayloadMap<TEmittedSchemaMap> : TEmittedPayloadMap;
76
+ type EventPayloadFromEvent<TEvent> = TEvent extends {
77
+ type: string;
78
+ } ? DistributiveOmit<TEvent, 'type'> : TEvent;
79
+ type EventPayloadMapFromTransitions<TTransitions> = { [K in keyof TTransitions & string]: TTransitions[K] extends ((context: any, event: infer TEvent, ...args: any[]) => unknown) ? EventPayloadFromEvent<TEvent> : {}; };
80
+ type StoreEventPayloadMapFromConfig<TConfig extends AnyStoreConfig> = TConfig extends {
81
+ schemas: {
82
+ events: infer TEventSchemaMap;
83
+ };
84
+ } ? TEventSchemaMap extends StandardSchemaMap ? InferSchemaPayloadMap<TEventSchemaMap> : {} : TConfig extends {
85
+ on: infer TTransitions;
86
+ } ? EventPayloadMapFromTransitions<TTransitions> : {};
87
+ type EmitterFunction<TEmittedEvent extends EventObject> = (...args: {
88
+ type: TEmittedEvent['type'];
89
+ } extends TEmittedEvent ? [DistributiveOmit<TEmittedEvent, 'type'>?] : [DistributiveOmit<TEmittedEvent, 'type'>]) => void;
90
+ type TriggerFunction<TEvent extends EventObject> = (...args: {
91
+ type: TEvent['type'];
92
+ } extends TEvent ? [DistributiveOmit<TEvent, 'type'>?] : [DistributiveOmit<TEvent, 'type'>]) => void;
93
+ type CanFunction<TEvent extends EventObject> = (...args: {
94
+ type: TEvent['type'];
95
+ } extends TEvent ? [DistributiveOmit<TEvent, 'type'>?] : [DistributiveOmit<TEvent, 'type'>]) => boolean;
96
+ type EventFromPayload<TKey extends string, TPayload> = {
97
+ type: TKey;
98
+ } & (TPayload extends null | undefined ? {} : TPayload);
99
+ type TriggerObject<TEventPayloadMap extends EventPayloadMap> = { [K in keyof TEventPayloadMap & string]: string extends K ? (...args: any[]) => void : TriggerFunction<EventFromPayload<K, TEventPayloadMap[K]>>; };
100
+ type CanObject<TEventPayloadMap extends EventPayloadMap> = { [K in keyof TEventPayloadMap & string]: string extends K ? (...args: any[]) => boolean : CanFunction<EventFromPayload<K, TEventPayloadMap[K]>>; };
101
+ /**
102
+ * The object passed to an effect function enqueued via `enq.effect(...)`. It
103
+ * allows effects to send events back into the store (e.g. after an async
104
+ * operation resolves) and read the latest store state, which is especially
105
+ * useful with `createStoreLogic(...)` where there is no store reference to
106
+ * close over.
107
+ *
108
+ * Use `trigger` for event-specific dispatch; `send` accepts the same event
109
+ * objects as `store.send(...)`. `getSnapshot()` returns the current snapshot at
110
+ * the time the effect runs, which is the correct way to read fresh context
111
+ * after an `await` (the `context` argument to the transition is stale by
112
+ * then).
113
+ */
114
+ type StoreEffectEnqueue<TContext extends StoreContext = StoreContext, TEventPayloadMap extends EventPayloadMap = {}> = {
115
+ trigger: TriggerObject<TEventPayloadMap>;
116
+ send: (event: EventObject) => void;
117
+ getSnapshot: () => StoreSnapshot<TContext>;
118
+ };
119
+ type EnqueueObject<TContext extends StoreContext, TEmittedEvent extends EventObject, TEventPayloadMap extends EventPayloadMap = {}> = {
120
+ emit: { [E in TEmittedEvent as E['type']]: EmitterFunction<E>; };
121
+ trigger: TriggerObject<TEventPayloadMap>;
122
+ effect: (fn: (enq: StoreEffectEnqueue<TContext, TEventPayloadMap>) => void) => void;
123
+ };
124
+ type StoreEffect<TEmitted extends EventObject> = ((enq?: StoreEffectEnqueue<any, any>) => void) | TEmitted;
125
+ type StoreAssigner<TContext extends StoreContext, TEvent extends EventObject, TEmitted extends EventObject, TEventPayloadMap extends EventPayloadMap = {}> = (context: TContext, event: TEvent, enq: EnqueueObject<TContext, TEmitted, TEventPayloadMap>) => TContext | void;
126
+ type Snapshot<TOutput> = {
127
+ status: 'active';
128
+ output: undefined;
129
+ error: undefined;
130
+ } | {
131
+ status: 'done';
132
+ output: TOutput;
133
+ error: undefined;
134
+ } | {
135
+ status: 'error';
136
+ output: undefined;
137
+ error: unknown;
138
+ } | {
139
+ status: 'stopped';
140
+ output: undefined;
141
+ error: undefined;
142
+ };
143
+ type StoreSnapshot<TContext> = Snapshot<undefined> & {
144
+ context: TContext;
145
+ };
146
+ /**
147
+ * An actor-like object that:
148
+ *
149
+ * - Has its own state
150
+ * - Can receive events
151
+ * - Is observable
152
+ */
153
+ interface Store<TContext extends StoreContext, TEventPayloadMap extends EventPayloadMap, TEmitted extends EventObject> extends Subscribable<StoreSnapshot<TContext>>, InteropObservable<StoreSnapshot<TContext>>, Readable<StoreSnapshot<TContext>> {
154
+ /** Standard Schema definitions for this store, if provided. */
155
+ readonly schemas?: StoreSchemas<any, any, any> | undefined;
156
+ send: (event: ExtractEvents<TEventPayloadMap>) => void;
157
+ getSnapshot: () => StoreSnapshot<TContext>;
158
+ /** Read the current snapshot as a `Readable` value. */
159
+ get: () => StoreSnapshot<TContext>;
160
+ getInitialSnapshot: () => StoreSnapshot<TContext>;
161
+ /**
162
+ * Subscribes to [inspection events](https://stately.ai/docs/inspection) from
163
+ * the store.
164
+ *
165
+ * Inspectors that call `store.inspect(…)` will immediately receive the
166
+ * current snapshot as an "\@xstate.transition" inspection event.
167
+ */
168
+ inspect: (observer: Observer<StoreInspectionEvent> | ((inspectionEvent: StoreInspectionEvent) => void)) => Subscription;
169
+ sessionId: string;
170
+ on: <TType extends TEmitted['type'] | '*'>(type: TType, handler: (emitted: Compute<TEmitted & (TType extends '*' ? unknown : {
171
+ type: TType;
172
+ })>) => void) => Subscription;
173
+ /**
174
+ * A trigger object that allows you to send events to the store without
175
+ * manually constructing event objects.
176
+ *
177
+ * @example
178
+ *
179
+ * ```ts
180
+ * // Equivalent to:
181
+ * // store.send({ type: 'increment', by: 1 });
182
+ * store.trigger.increment({ by: 1 });
183
+ * ```
184
+ */
185
+ trigger: TriggerObject<TEventPayloadMap>;
186
+ can: CanObject<TEventPayloadMap>;
187
+ select<TSelected>(selector: Selector<TContext, TSelected>, equalityFn?: (a: TSelected, b: TSelected) => boolean): Selection<TSelected>;
188
+ /**
189
+ * Returns the next state and effects for the given state and event, as a
190
+ * tuple.
191
+ *
192
+ * @example
193
+ *
194
+ * ```ts
195
+ * const [nextState, effects] = store.transition(store.getSnapshot(), {
196
+ * type: 'increment',
197
+ * by: 1
198
+ * });
199
+ * ```
200
+ */
201
+ transition: StoreTransition<TContext, ExtractEvents<TEventPayloadMap>, TEmitted>;
202
+ /**
203
+ * Extends the store with additional functionality via a store extension.
204
+ *
205
+ * @example
206
+ *
207
+ * ```ts
208
+ * const store = createStore({
209
+ * context: { count: 0 },
210
+ * on: { inc: (ctx) => ({ count: ctx.count + 1 }) }
211
+ * }).with(undoRedo());
212
+ *
213
+ * store.trigger.inc();
214
+ * store.trigger.undo(); // undoes the increment
215
+ * ```
216
+ */
217
+ with<TNewEventPayloadMap extends EventPayloadMap>(extension: StoreExtension<TContext, TEventPayloadMap, TNewEventPayloadMap, TEmitted>): Store<TContext, TEventPayloadMap & TNewEventPayloadMap, TEmitted>;
218
+ }
219
+ type StoreTransition<TContext extends StoreContext, TEvent extends EventObject, TEmitted extends EventObject> = (state: StoreSnapshot<TContext>, event: TEvent) => StoreTransitionResult<StoreSnapshot<TContext>, TEmitted>;
220
+ type StoreTransitionResult<TSnapshot extends StoreSnapshot<any>, TEmitted extends EventObject> = [TSnapshot, StoreEffect<TEmitted>[]] & {
221
+ _allowed?: boolean;
222
+ };
223
+ type StoreConfig<TContext extends StoreContext, TEventPayloadMap extends EventPayloadMap, TEmittedPayloadMap extends EventPayloadMap = {}, TContextSchema extends StandardSchemaV1 | undefined = undefined, TEventSchemaMap extends StandardSchemaMap | undefined = undefined, TEmittedSchemaMap extends StandardSchemaMap | undefined = undefined> = {
224
+ context: ResolveStoreContext<TContext, TContextSchema>;
225
+ schemas?: StoreSchemas<TContextSchema, TEventSchemaMap, TEmittedSchemaMap>;
226
+ warn?: (message: string) => void;
227
+ on: TEventSchemaMap extends StandardSchemaMap ? { [K in keyof ResolveStoreEventPayloadMap<TEventPayloadMap, TEventSchemaMap> & string]?: StoreAssigner<ResolveStoreContext<TContext, TContextSchema>, {
228
+ type: K;
229
+ } & ResolveStoreEventPayloadMap<TEventPayloadMap, TEventSchemaMap>[K], ExtractEvents<ResolveStoreEmittedPayloadMap<TEmittedPayloadMap, TEmittedSchemaMap>>, ResolveStoreEventPayloadMap<TEventPayloadMap, TEventSchemaMap>>; } : { [K in keyof TEventPayloadMap & string]: StoreAssigner<ResolveStoreContext<TContext, TContextSchema>, {
230
+ type: K;
231
+ } & TEventPayloadMap[K], ExtractEvents<ResolveStoreEmittedPayloadMap<TEmittedPayloadMap, TEmittedSchemaMap>>, ResolveStoreEventPayloadMap<TEventPayloadMap, TEventSchemaMap>>; };
232
+ };
233
+ type SpecificStoreConfig<TContext extends StoreContext, TEvent extends EventObject, TEmitted extends EventObject, TContextSchema extends StandardSchemaV1 | undefined = undefined, TEventSchemaMap extends StandardSchemaMap | undefined = undefined, TEmittedSchemaMap extends StandardSchemaMap | undefined = undefined> = {
234
+ context: ResolveStoreContext<TContext, TContextSchema>;
235
+ schemas?: StoreSchemas<TContextSchema, TEventSchemaMap, TEmittedSchemaMap>;
236
+ warn?: (message: string) => void;
237
+ on: { [E in TEvent as E['type']]?: StoreAssigner<ResolveStoreContext<TContext, TContextSchema>, E, TEmitted, EventPayloadMapFromEvents<TEvent>>; };
238
+ };
239
+ type EventPayloadMapFromEvents<TEvent extends EventObject> = { [E in TEvent as E['type']]: DistributiveOmit<E, 'type'>; };
240
+ type Compute<A> = A extends any ? { [K in keyof A]: A[K]; } : never;
241
+ type AnyStore = Store<any, any, any>;
242
+ type SnapshotFromStore<TStore extends Store<any, any, any>> = TStore extends Store<infer TContext, any, any> ? StoreSnapshot<TContext> : never;
243
+ /**
244
+ * Extract the type of events from a `Store`.
245
+ *
246
+ * @example
247
+ *
248
+ * ```ts
249
+ * const store = createStore(
250
+ * { count: 0 },
251
+ * {
252
+ * inc: (context, event: { by: number }) => ({
253
+ * count: context.count + event.by
254
+ * }),
255
+ * dec: (context, event: { by: number }) => ({
256
+ * count: context.count - event.by
257
+ * })
258
+ * }
259
+ * );
260
+ * type StoreEvent = EventFromStore<typeof store>;
261
+ * // ^? { type: 'inc', by: number } | { type: 'dec', by: number }
262
+ * ```
263
+ *
264
+ * @example
265
+ *
266
+ * Using utility types derived from `EventFromStore` to create individual
267
+ * type-safe event transition functions for a store:
268
+ *
269
+ * ```ts
270
+ * import {
271
+ * createStore,
272
+ * type EventFromStore,
273
+ * type Store
274
+ * } from '@systemfsoftware/xstate-store';
275
+ *
276
+ * // Extract the event where `Type` matches the event's `type` from the given
277
+ * // `Store`.
278
+ * type EventByType<
279
+ * TStore extends Store<any, any>,
280
+ * Type extends EventFromStore<TStore>['type']
281
+ * > = Extract<EventFromStore<TStore>, { type: Type }>;
282
+ *
283
+ * // Extract a specific store event's "input" type (the event type without the
284
+ * // `type` property).
285
+ * type EventInputByType<
286
+ * TStore extends Store<any, any>,
287
+ * Type extends EventFromStore<TStore>['type']
288
+ * > = Omit<EventByType<TStore, Type>, 'type'>;
289
+ *
290
+ * const store = createStore(
291
+ * { count: 0 },
292
+ * {
293
+ * add: (context, event: { addend: number }) => ({
294
+ * count: context.count + event.addend
295
+ * }),
296
+ * multiply: (context, event: { multiplier: number }) => ({
297
+ * count: context.count * event.multiplier
298
+ * })
299
+ * }
300
+ * );
301
+ *
302
+ * const add = (input: EventInputByType<typeof store, 'add'>) =>
303
+ * store.send({ type: 'add', addend: input.addend });
304
+ *
305
+ * add({ addend: 1 }); // sends { type: 'add', addend: 1 }
306
+ *
307
+ * const multiply = (input: EventInputByType<typeof store, 'multiply'>) =>
308
+ * store.send({ type: 'multiply', multiplier: input.multiplier });
309
+ *
310
+ * multiply({ multiplier: 2 }); // sends { type: 'multiply', multiplier: 2 }
311
+ * ```
312
+ */
313
+ type EventFromStore<TStore extends Store<any, any, any>> = TStore extends Store<infer _TContext, infer TEventPayloadMap, infer _TEmitted> ? ExtractEvents<TEventPayloadMap> : never;
314
+ interface InteropSubscribable<T> {
315
+ subscribe(observer: Observer<T>): Subscription;
316
+ }
317
+ interface InteropObservable<T> {
318
+ [Symbol.observable]: () => InteropSubscribable<T>;
319
+ }
320
+ type Observer<T> = {
321
+ next?: ((value: T) => void) | undefined;
322
+ error?: ((err: unknown) => void) | undefined;
323
+ complete?: (() => void) | undefined;
324
+ };
325
+ interface Subscription {
326
+ unsubscribe(): void;
327
+ }
328
+ interface Subscribable<T> extends InteropSubscribable<T> {
329
+ subscribe(observer: Observer<T>): Subscription;
330
+ subscribe(next: (value: T) => void, error?: (error: any) => void, complete?: () => void): Subscription;
331
+ }
332
+ type StoreContext = Record<string, any>;
333
+ /** The full definition of an event, with a string `type`. */
334
+ type EventObject = {
335
+ /** The type of event that is sent. */
336
+ type: string;
337
+ };
338
+ type Values<T> = T[keyof T];
339
+ interface StoreBaseInspectionEventProperties {
340
+ rootId: string;
341
+ /**
342
+ * The relevant actorRef for the inspection event.
343
+ *
344
+ * For store transition events, this is the `actorRef` of the store.
345
+ */
346
+ actorRef: ActorRefLike;
347
+ }
348
+ interface StoreInspectionEvent extends StoreBaseInspectionEventProperties {
349
+ type: '@xstate.transition';
350
+ event: AnyEventObject;
351
+ snapshot: Snapshot<unknown>;
352
+ }
353
+ interface AnyEventObject {
354
+ type: string;
355
+ [key: string]: any;
356
+ }
357
+ type StoreInspectedSnapshotEvent = StoreInspectionEvent;
358
+ type StoreInspectedActionEvent = StoreInspectionEvent;
359
+ type StoreInspectedEventEvent = StoreInspectionEvent;
360
+ type StoreInspectedActorEvent = StoreInspectionEvent;
361
+ type ActorRefLike = {
362
+ sessionId: string;
363
+ send: (event: any) => void;
364
+ getSnapshot: () => any;
365
+ };
366
+ type Selector<TContext, TSelected> = (context: TContext) => TSelected;
367
+ type Selection<TSelected> = Readable<TSelected>;
368
+ type StoreSelectorsConfig<TContext extends StoreContext> = Record<string, Selector<TContext, any>>;
369
+ type ResolvedStoreSelectors<TContext extends StoreContext, TSelectors extends StoreSelectorsConfig<TContext>> = { [K in keyof TSelectors]: Selection<ReturnType<TSelectors[K]>>; };
370
+ type StoreWithSelectors<TContext extends StoreContext, TEventPayloadMap extends EventPayloadMap, TEmitted extends EventObject, TSelectors extends StoreSelectorsConfig<TContext>> = Omit<Store<TContext, TEventPayloadMap, TEmitted>, 'with'> & {
371
+ selectors: ResolvedStoreSelectors<TContext, TSelectors>;
372
+ with<TNewEventPayloadMap extends EventPayloadMap>(extension: StoreExtension<TContext, TEventPayloadMap, TNewEventPayloadMap, TEmitted>): StoreWithSelectors<TContext, TEventPayloadMap & TNewEventPayloadMap, TEmitted, TSelectors>;
373
+ };
374
+ interface StoreLogicCreator<TContext extends StoreContext, TEventPayloadMap extends EventPayloadMap, TEmitted extends EventObject, TInput, TSelectors extends StoreSelectorsConfig<TContext>> {
375
+ createStore: undefined extends TInput ? (input?: TInput) => StoreWithSelectors<TContext, TEventPayloadMap, TEmitted, TSelectors> : (input: TInput) => StoreWithSelectors<TContext, TEventPayloadMap, TEmitted, TSelectors>;
376
+ }
377
+ type AnyStoreLogicCreator = StoreLogicCreator<any, any, any, any, any>;
378
+ type StoreFromStoreLogicCreator<TLogic extends AnyStoreLogicCreator> = TLogic extends StoreLogicCreator<infer TContext, infer TEventPayloadMap, infer TEmitted, any, infer TSelectors> ? StoreWithSelectors<TContext, TEventPayloadMap, TEmitted, TSelectors> : never;
379
+ type InputFromStoreLogicCreator<TLogic extends AnyStoreLogicCreator> = TLogic extends StoreLogicCreator<any, any, any, infer TInput, any> ? TInput : never;
380
+ interface Readable<T> extends Subscribable<T> {
381
+ get: () => T;
382
+ }
383
+ interface BaseAtom<T> extends Subscribable<T>, Readable<T> {}
384
+ interface Atom<T> extends BaseAtom<T> {
385
+ /** Sets the value of the atom using a function. */
386
+ set(fn: (prevVal: T) => T): void;
387
+ /** Sets the value of the atom. */
388
+ set(value: T): void;
389
+ }
390
+ interface ReducerAtom<TState, TEvent> extends BaseAtom<TState> {
391
+ send: (event: TEvent) => void;
392
+ }
393
+ interface AtomOptions<T> {
394
+ compare?: (prev: T, next: T) => boolean;
395
+ }
396
+ interface AtomConfig<TValue, TInput> {
397
+ createAtom: undefined extends TInput ? (input?: TInput) => Atom<TValue> : (input: TInput) => Atom<TValue>;
398
+ }
399
+ type AnyAtomConfig = AtomConfig<any, any>;
400
+ type ValueFromAtomConfig<TConfig extends AnyAtomConfig> = TConfig extends AtomConfig<infer TValue, any> ? TValue : never;
401
+ type InputFromAtomConfig<TConfig extends AnyAtomConfig> = TConfig extends AtomConfig<any, infer TInput> ? TInput : never;
402
+ type AnyAtom = BaseAtom<any>;
403
+ /**
404
+ * An atom that is read-only and cannot be set.
405
+ *
406
+ * @example
407
+ *
408
+ * ```ts
409
+ * const atom = createAtom(() => 42);
410
+ * // @ts-expect-error - Cannot set a readonly atom
411
+ * atom.set(43);
412
+ * ```
413
+ */
414
+ interface ReadonlyAtom<T> extends BaseAtom<T> {}
415
+ /** A version of `Omit` that works with distributive types. */
416
+ type DistributiveOmit<T, K extends PropertyKey> = T extends any ? Omit<T, K> : never;
417
+ type StoreLogic<TSnapshot extends StoreSnapshot<any>, TEvent extends EventObject, TEmitted extends EventObject> = {
418
+ eventTypes?: readonly string[] | undefined;
419
+ schemas?: StoreSchemas<any, any, any> | undefined;
420
+ warn?: ((message: string) => void) | undefined;
421
+ getInitialSnapshot: () => TSnapshot;
422
+ transition: (snapshot: TSnapshot, event: TEvent) => StoreTransitionResult<TSnapshot, TEmitted>;
423
+ };
424
+ /**
425
+ * A store extension that transforms store logic, optionally adding new events.
426
+ *
427
+ * @example
428
+ *
429
+ * ```ts
430
+ * const store = createStore({
431
+ * context: { count: 0 },
432
+ * on: { inc: (ctx) => ({ count: ctx.count + 1 }) }
433
+ * }).with(undoRedo());
434
+ * ```
435
+ */
436
+ type StoreExtension<TContext extends StoreContext, TEventPayloadMap extends EventPayloadMap, TNewEventPayloadMap extends EventPayloadMap, TEmitted extends EventObject> = (logic: StoreLogic<StoreSnapshot<TContext>, ExtractEvents<TEventPayloadMap>, TEmitted>) => StoreLogic<StoreSnapshot<TContext>, ExtractEvents<TEventPayloadMap> | ExtractEvents<TNewEventPayloadMap>, TEmitted>;
437
+ type AnyStoreConfig = StoreConfig<any, any, any, any, any, any>;
438
+ type EventFromStoreConfig<TStore extends AnyStoreConfig> = TStore extends StoreConfig<any, infer TEventPayloadMap, any, any, infer TEventSchemaMap, any> ? ExtractEvents<ResolveStoreEventPayloadMap<TEventPayloadMap, TEventSchemaMap>> : never;
439
+ type EmitsFromStoreConfig<TStore extends AnyStoreConfig> = TStore extends StoreConfig<any, any, infer TEmittedPayloadMap, any, any, infer TEmittedSchemaMap> ? ExtractEvents<ResolveStoreEmittedPayloadMap<TEmittedPayloadMap, TEmittedSchemaMap>> : never;
440
+ type ContextFromStoreConfig<TStore extends AnyStoreConfig> = TStore extends StoreConfig<infer TContext, any, any, infer TContextSchema, any, any> ? ResolveStoreContext<TContext, TContextSchema> : never;
441
+ type StoreFromStoreConfig<TConfig extends AnyStoreConfig> = TConfig extends StoreConfig<infer TContext, any, infer TEmittedPayloadMap, infer TContextSchema, any, infer TEmittedSchemaMap> ? Store<ResolveStoreContext<TContext, TContextSchema>, StoreEventPayloadMapFromConfig<TConfig>, ExtractEvents<ResolveStoreEmittedPayloadMap<TEmittedPayloadMap, TEmittedSchemaMap>>> : never;
442
+ export { StoreSchemas as $, ResolveStoreEventPayloadMap as A, StoreContext as B, InputFromStoreLogicCreator as C, ReducerAtom as D, ReadonlyAtom as E, SpecificStoreConfig as F, StoreFromStoreLogicCreator as G, StoreEffectEnqueue as H, StandardSchemaMap as I, StoreInspectedEventEvent as J, StoreInspectedActionEvent as K, Store as L, Selection as M, Selector as N, ResolveStoreContext as O, SnapshotFromStore as P, StoreLogicCreator as Q, StoreAssigner as R, InputFromAtomConfig as S, Readable as T, StoreExtension as U, StoreEffect as V, StoreFromStoreConfig as W, StoreInspectionEvent as X, StoreInspectedSnapshotEvent as Y, StoreLogic as Z, EventObject as _, AnyStoreConfig as a, TriggerObject as at, InferSchemaOutput as b, AtomConfig as c, CanObject as d, StoreSelectorsConfig as et, ContextFromStoreConfig as f, EventFromStoreConfig as g, EventFromStore as h, AnyStore as i, Subscription as it, ResolvedStoreSelectors as j, ResolveStoreEmittedPayloadMap as k, AtomOptions as l, EnqueueObject as m, AnyAtom as n, StoreWithSelectors as nt, AnyStoreLogicCreator as o, ValueFromAtomConfig as ot, EmitsFromStoreConfig as p, StoreInspectedActorEvent as q, AnyAtomConfig as r, Subscribable as rt, Atom as s, StandardSchemaV1 as st, ActorRefLike as t, StoreSnapshot as tt, BaseAtom as u, EventPayloadMap as v, Observer as w, InferSchemaPayloadMap as x, ExtractEvents as y, StoreConfig as z };
package/dist/undo.d.ts ADDED
@@ -0,0 +1,77 @@
1
+ import { B as StoreContext, U as StoreExtension, _ as EventObject, m as EnqueueObject, tt as StoreSnapshot, v as EventPayloadMap, y as ExtractEvents } from "./types-0n0RpfhK.js";
2
+ interface UndoRedoEventOptions<TContext extends StoreContext, TEvent extends EventObject> {
3
+ /** A function that returns the transaction ID of an event. */
4
+ getTransactionId?: (event: TEvent, snapshot: StoreSnapshot<TContext>) => string | null | undefined;
5
+ /**
6
+ * A function that returns whether an event should be skipped during
7
+ * undo/redo. Skipped events are not stored in history and are not replayed
8
+ * during undo/redo.
9
+ */
10
+ skipEvent?: (event: TEvent, snapshot: StoreSnapshot<TContext>) => boolean;
11
+ }
12
+ interface UndoRedoSnapshotOptions<TContext extends StoreContext, TEvent extends EventObject, TEmitted extends EventObject, TEventPayloadMap extends EventPayloadMap> {
13
+ /** A function that returns the transaction ID of an event. */
14
+ getTransactionId?: (event: TEvent, snapshot: StoreSnapshot<TContext>) => string | null | undefined;
15
+ /**
16
+ * A function that returns whether a snapshot should be skipped during
17
+ * undo/redo. Skipped events don't save snapshots to history.
18
+ */
19
+ skipEvent?: (event: TEvent, snapshot: StoreSnapshot<TContext>) => boolean;
20
+ /** Maximum number of snapshots to keep in history. Defaults to Infinity. */
21
+ historyLimit?: number;
22
+ /**
23
+ * A function to compare snapshots for equality. When true, the new snapshot
24
+ * will not be added to history. Useful for avoiding duplicate snapshots.
25
+ */
26
+ compare?: (pastSnapshot: StoreSnapshot<TContext>, currentSnapshot: StoreSnapshot<TContext>) => boolean;
27
+ /** Customizes the context restored by snapshot-based undo/redo. */
28
+ restore?: (args: {
29
+ current: TContext;
30
+ next: TContext;
31
+ direction: 'undo' | 'redo';
32
+ }, enqueue: EnqueueObject<TContext, TEmitted, TEventPayloadMap>) => TContext;
33
+ }
34
+ type UndoRedoStrategyOptions<TContext extends StoreContext, TEvent extends EventObject, TEmitted extends EventObject, TEventPayloadMap extends EventPayloadMap> = ({
35
+ strategy?: 'event';
36
+ } & UndoRedoEventOptions<TContext, TEvent>) | ({
37
+ strategy: 'snapshot';
38
+ } & UndoRedoSnapshotOptions<TContext, TEvent, TEmitted, TEventPayloadMap>);
39
+ /**
40
+ * Creates store logic with undo/redo functionality.
41
+ *
42
+ * Supports two strategies:
43
+ *
44
+ * - 'event' (default): Maintains event history and replays events
45
+ * - 'snapshot': Maintains snapshot history for faster undo/redo
46
+ *
47
+ * @example
48
+ *
49
+ * ```ts
50
+ * const store = createStore({
51
+ * context: { count: 0 },
52
+ * on: {
53
+ * inc: (ctx) => ({ count: ctx.count + 1 })
54
+ * }
55
+ * }).with(undoRedo());
56
+ *
57
+ * store.trigger.inc();
58
+ * store.trigger.undo(); // count = 0
59
+ * ```
60
+ *
61
+ * @example
62
+ *
63
+ * ```ts
64
+ * // Snapshot strategy
65
+ * const store = createStore({
66
+ * context: { count: 0 },
67
+ * on: { inc: (ctx) => ({ count: ctx.count + 1 }) }
68
+ * }).with(undoRedo({ strategy: 'snapshot', historyLimit: 10 }));
69
+ * ```
70
+ *
71
+ * @returns Store extension with additional `undo` and `redo` event handlers
72
+ */
73
+ export declare function undoRedo<TContext extends StoreContext, TEventPayloadMap extends EventPayloadMap, TEmitted extends EventObject>(options?: UndoRedoStrategyOptions<TContext, ExtractEvents<TEventPayloadMap>, TEmitted, TEventPayloadMap>): StoreExtension<TContext, TEventPayloadMap, {
74
+ undo: null;
75
+ redo: null;
76
+ }, TEmitted>;
77
+ export {};