@radio-garden/rematch 1.0.0

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,543 @@
1
+ import { ActionCreator, Action, Middleware, StoreCreator, compose, StoreEnhancer } from 'redux';
2
+ import { createSelector } from 'reselect';
3
+
4
+ interface DevToolOptions {
5
+ /**
6
+ * the instance name to be showed on the monitor page. Default value is `document.title`.
7
+ * If not specified and there's no document title, it will consist of `tabId` and `instanceId`.
8
+ */
9
+ name?: string;
10
+ /**
11
+ * action creators functions to be available in the Dispatcher.
12
+ */
13
+ actionCreators?: ActionCreator<any>[] | {
14
+ [key: string]: ActionCreator<any>;
15
+ };
16
+ /**
17
+ * if more than one action is dispatched in the indicated interval, all new actions will be collected and sent at once.
18
+ * It is the joint between performance and speed. When set to `0`, all actions will be sent instantly.
19
+ * Set it to a higher value when experiencing perf issues (also `maxAge` to a lower value).
20
+ *
21
+ * @default 500 ms.
22
+ */
23
+ latency?: number;
24
+ /**
25
+ * (> 1) - maximum allowed actions to be stored in the history tree. The oldest actions are removed once maxAge is reached. It's critical for performance.
26
+ *
27
+ * @default 50
28
+ */
29
+ maxAge?: number;
30
+ /**
31
+ * Customizes how actions and state are serialized and deserialized. Can be a boolean or object. If given a boolean, the behavior is the same as if you
32
+ * were to pass an object and specify `options` as a boolean. Giving an object allows fine-grained customization using the `replacer` and `reviver`
33
+ * functions.
34
+ */
35
+ serialize?: boolean | {
36
+ /**
37
+ * - `undefined` - will use regular `JSON.stringify` to send data (it's the fast mode).
38
+ * - `false` - will handle also circular references.
39
+ * - `true` - will handle also date, regex, undefined, error objects, symbols, maps, sets and functions.
40
+ * - object, which contains `date`, `regex`, `undefined`, `error`, `symbol`, `map`, `set` and `function` keys.
41
+ * For each of them you can indicate if to include (by setting as `true`).
42
+ * For `function` key you can also specify a custom function which handles serialization.
43
+ * See [`jsan`](https://github.com/kolodny/jsan) for more details.
44
+ */
45
+ options?: undefined | boolean | {
46
+ date?: true;
47
+ regex?: true;
48
+ undefined?: true;
49
+ error?: true;
50
+ symbol?: true;
51
+ map?: true;
52
+ set?: true;
53
+ function?: true | ((fn: (...args: any[]) => any) => string);
54
+ };
55
+ /**
56
+ * [JSON replacer function](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The_replacer_parameter) used for both actions and states stringify.
57
+ * In addition, you can specify a data type by adding a [`__serializedType__`](https://github.com/zalmoxisus/remotedev-serialize/blob/master/helpers/index.js#L4)
58
+ * key. So you can deserialize it back while importing or persisting data.
59
+ * Moreover, it will also [show a nice preview showing the provided custom type](https://cloud.githubusercontent.com/assets/7957859/21814330/a17d556a-d761-11e6-85ef-159dd12f36c5.png):
60
+ */
61
+ replacer?: (key: string, value: unknown) => any;
62
+ /**
63
+ * [JSON `reviver` function](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#Using_the_reviver_parameter)
64
+ * used for parsing the imported actions and states. See [`remotedev-serialize`](https://github.com/zalmoxisus/remotedev-serialize/blob/master/immutable/serialize.js#L8-L41)
65
+ * as an example on how to serialize special data types and get them back.
66
+ */
67
+ reviver?: (key: string, value: unknown) => any;
68
+ /**
69
+ * Automatically serialize/deserialize immutablejs via [remotedev-serialize](https://github.com/zalmoxisus/remotedev-serialize).
70
+ * Just pass the Immutable library. It will support all ImmutableJS structures. You can even export them into a file and get them back.
71
+ * The only exception is `Record` class, for which you should pass this in addition the references to your classes in `refs`.
72
+ */
73
+ immutable?: any;
74
+ /**
75
+ * ImmutableJS `Record` classes used to make possible restore its instances back when importing, persisting...
76
+ */
77
+ refs?: any;
78
+ };
79
+ /**
80
+ * function which takes `action` object and id number as arguments, and should return `action` object back.
81
+ */
82
+ actionSanitizer?: <A extends Action>(action: A, id: number) => A;
83
+ /**
84
+ * function which takes `state` object and index as arguments, and should return `state` object back.
85
+ */
86
+ stateSanitizer?: <S>(state: S, index: number) => S;
87
+ /**
88
+ * *string or array of strings as regex* - actions types to be hidden / shown in the monitors (while passed to the reducers).
89
+ * If `actionsAllowlist` specified, `actionsDenylist` is ignored.
90
+ */
91
+ actionsDenylist?: string | string[];
92
+ /**
93
+ * *string or array of strings as regex* - actions types to be hidden / shown in the monitors (while passed to the reducers).
94
+ * If `actionsAllowlist` specified, `actionsDenylist` is ignored.
95
+ */
96
+ actionsAllowlist?: string | string[];
97
+ /**
98
+ * called for every action before sending, takes `state` and `action` object, and returns `true` in case it allows sending the current data to the monitor.
99
+ * Use it as a more advanced version of `actionsDenylist`/`actionsAllowlist` parameters.
100
+ */
101
+ predicate?: <S, A extends Action>(state: S, action: A) => boolean;
102
+ /**
103
+ * if specified as `false`, it will not record the changes till clicking on `Start recording` button.
104
+ * Available only for Redux enhancer, for others use `autoPause`.
105
+ *
106
+ * @default true
107
+ */
108
+ shouldRecordChanges?: boolean;
109
+ /**
110
+ * if specified, whenever clicking on `Pause recording` button and there are actions in the history log, will add this action type.
111
+ * If not specified, will commit when paused. Available only for Redux enhancer.
112
+ *
113
+ * @default "@@PAUSED""
114
+ */
115
+ pauseActionType?: string;
116
+ /**
117
+ * auto pauses when the extension’s window is not opened, and so has zero impact on your app when not in use.
118
+ * Not available for Redux enhancer (as it already does it but storing the data to be sent).
119
+ *
120
+ * @default false
121
+ */
122
+ autoPause?: boolean;
123
+ /**
124
+ * if specified as `true`, it will not allow any non-monitor actions to be dispatched till clicking on `Unlock changes` button.
125
+ * Available only for Redux enhancer.
126
+ *
127
+ * @default false
128
+ */
129
+ shouldStartLocked?: boolean;
130
+ /**
131
+ * if set to `false`, will not recompute the states on hot reloading (or on replacing the reducers). Available only for Redux enhancer.
132
+ *
133
+ * @default true
134
+ */
135
+ shouldHotReload?: boolean;
136
+ /**
137
+ * if specified as `true`, whenever there's an exception in reducers, the monitors will show the error message, and next actions will not be dispatched.
138
+ *
139
+ * @default false
140
+ */
141
+ shouldCatchErrors?: boolean;
142
+ /**
143
+ * If you want to restrict the extension, specify the features you allow.
144
+ * If not specified, all of the features are enabled. When set as an object, only those included as `true` will be allowed.
145
+ * Note that except `true`/`false`, `import` and `export` can be set as `custom` (which is by default for Redux enhancer), meaning that the importing/exporting occurs on the client side.
146
+ * Otherwise, you'll get/set the data right from the monitor part.
147
+ */
148
+ features?: {
149
+ /**
150
+ * start/pause recording of dispatched actions
151
+ */
152
+ pause?: boolean;
153
+ /**
154
+ * lock/unlock dispatching actions and side effects
155
+ */
156
+ lock?: boolean;
157
+ /**
158
+ * persist states on page reloading
159
+ */
160
+ persist?: boolean;
161
+ /**
162
+ * export history of actions in a file
163
+ */
164
+ export?: boolean | 'custom';
165
+ /**
166
+ * import history of actions from a file
167
+ */
168
+ import?: boolean | 'custom';
169
+ /**
170
+ * jump back and forth (time travelling)
171
+ */
172
+ jump?: boolean;
173
+ /**
174
+ * skip (cancel) actions
175
+ */
176
+ skip?: boolean;
177
+ /**
178
+ * drag and drop actions in the history list
179
+ */
180
+ reorder?: boolean;
181
+ /**
182
+ * dispatch custom actions or action creators
183
+ */
184
+ dispatch?: boolean;
185
+ /**
186
+ * generate tests for the selected actions
187
+ */
188
+ test?: boolean;
189
+ };
190
+ /**
191
+ * Set to true or a stacktrace-returning function to record call stack traces for dispatched actions.
192
+ * Defaults to false.
193
+ */
194
+ trace?: boolean | (<A extends Action>(action: A) => string);
195
+ /**
196
+ * The maximum number of stack trace entries to record per action. Defaults to 10.
197
+ */
198
+ traceLimit?: number;
199
+ }
200
+ declare global {
201
+ interface Window {
202
+ __REDUX_DEVTOOLS_EXTENSION_COMPOSE__?: any;
203
+ }
204
+ }
205
+
206
+ /**
207
+ * Utility type taken by type-fest repository
208
+ * https://github.com/sindresorhus/type-fest/blob/main/source/merge-exclusive.d.ts
209
+ * Merges Exclusively two types into one
210
+ * Used to fix this https://github.com/rematch/rematch/issues/912
211
+ */
212
+ type Without<FirstType, SecondType> = {
213
+ [KeyType in Exclude<keyof FirstType, keyof SecondType>]: never;
214
+ };
215
+ type MergeExclusive<FirstType, SecondType> = FirstType | SecondType extends object ? (Without<FirstType, SecondType> & SecondType) | (Without<SecondType, FirstType> & FirstType) : FirstType | SecondType;
216
+ /**
217
+ * Custom Action interface, adds an additional field - `payload`.
218
+ *
219
+ * Strings (instead of Symbols) are used as the type for `type` field inherited
220
+ * from Redux, because strings are serializable.
221
+ *
222
+ * @template TPayload The type of the action's payload.
223
+ */
224
+ interface RematchAction<TPayload = any, TMeta = any> extends Action<string> {
225
+ payload?: TPayload;
226
+ meta?: TMeta;
227
+ }
228
+ /**
229
+ * Custom reducer which instead of an action (like in Redux), accepts payload as
230
+ * as a second argument.
231
+ *
232
+ * @template TState The type of state consumed and produced by this reducer.
233
+ */
234
+ type Reducer<TState = any> = (state: TState, payload?: RematchAction['payload'], meta?: RematchAction['meta']) => TState;
235
+ /** ************************** Model *************************** */
236
+ /**
237
+ * Mapping from a model key to model object.
238
+ *
239
+ * @template TModels List of all models
240
+ */
241
+ interface Models<TModels extends Models<TModels>> {
242
+ [key: string]: Model<TModels>;
243
+ }
244
+ interface NamedModel<TModels extends Models<TModels>, TState = any> extends Model<TModels, TState> {
245
+ name: string;
246
+ reducers: ModelReducers<TState>;
247
+ }
248
+ interface Model<TModels extends Models<TModels>, TState = any> {
249
+ name?: string;
250
+ state: TState;
251
+ reducers?: ModelReducers<TState>;
252
+ effects?: ModelEffects<TModels> | ModelEffectsCreator<TModels>;
253
+ selectors?: ModelSelectorsCreator<TModels>;
254
+ }
255
+ type ModelSelectors<TModels extends Models<TModels>> = {
256
+ [key: string]: (state: ExtractRematchStateFromModels<TModels>) => any;
257
+ };
258
+ type ModelSelectorsCreator<TModels extends Models<TModels>> = (store: RematchStore<TModels>) => ModelSelectors<TModels>;
259
+ type ModelReducers<TState = any> = {
260
+ [key: string]: Reducer<TState>;
261
+ };
262
+ interface ModelEffects<TModels extends Models<TModels>> {
263
+ [key: string]: ModelEffect<TModels>;
264
+ }
265
+ type ModelEffectThisTyped = {
266
+ [key: string]: (payload?: any, meta?: any) => RematchAction<any, any>;
267
+ };
268
+ type ModelEffect<TModels extends Models<TModels>> = (this: ModelEffectThisTyped, payload: RematchAction['payload'], rootState: RematchRootState<TModels>, meta: RematchAction['meta']) => any;
269
+ type ModelEffectsCreator<TModels extends Models<TModels>> = (store: RematchStore<TModels>) => ModelEffects<TModels>;
270
+ type ExposedFunction<TModels extends Models<TModels>> = (rematch: RematchStore<TModels>, ...args: any) => any;
271
+ /** ************************** Rematch *************************** */
272
+ /**
273
+ * Initial, optional configuration provided by the user which describes how
274
+ * Rematch store should be configured.
275
+ */
276
+ interface InitConfig<TModels extends Models<TModels>> {
277
+ name?: string;
278
+ models?: TModels | Partial<TModels>;
279
+ redux?: InitConfigRedux;
280
+ }
281
+ /**
282
+ * Config created out of the InitConfig by filling in missing properties with
283
+ * default values
284
+ */
285
+ interface Config<TModels extends Models<TModels>> extends InitConfig<TModels> {
286
+ name: string;
287
+ models: TModels | Partial<TModels>;
288
+ redux: ConfigRedux;
289
+ }
290
+ /** ************************** Rematch-Redux *************************** */
291
+ /**
292
+ * Initial, optional configuration for Redux, provided by the user. It allows
293
+ * to gain full control over the way Redux is configured by Rematch and
294
+ * override any defaults.
295
+ */
296
+ interface InitConfigRedux {
297
+ middlewares?: Middleware[];
298
+ createStore?: StoreCreator | undefined;
299
+ devtoolOptions?: DevToolOptions & {
300
+ disabled?: boolean;
301
+ };
302
+ /**
303
+ * Custom compose function for DevTools integration.
304
+ * Use this for React Native with Flipper or Reactotron.
305
+ * If not provided, browser Redux DevTools Extension is auto-detected.
306
+ */
307
+ devtoolCompose?: (options?: DevToolOptions) => typeof compose;
308
+ }
309
+ /**
310
+ * Config created out of InitConfigRedux by supplying default values in place
311
+ * of missing properties.
312
+ */
313
+ interface ConfigRedux extends InitConfigRedux {
314
+ enhancers: StoreEnhancer[];
315
+ middlewares: Middleware[];
316
+ }
317
+ type OmitIndexSignature<T> = {
318
+ [K in keyof T as K extends string ? K : never]: T[K];
319
+ };
320
+ type WithoutParametersObject<T> = {
321
+ [K in keyof T]: T[K] extends (...args: any[]) => infer R ? () => R : T;
322
+ };
323
+ type ExtractModelSelectors<TSelectors extends Model<TModels>['selectors'], TModels extends Models<TModels>> = TSelectors extends ModelSelectorsCreator<TModels> ? ReturnType<TSelectors> : object;
324
+ interface RematchStore<TModels extends Models<TModels>, RootState = OmitIndexSignature<{
325
+ [modelKey in keyof TModels]: TModels[modelKey]['state'];
326
+ }>> {
327
+ name: string;
328
+ dispatch: RematchDispatch<TModels>;
329
+ getState: () => RematchRootState<TModels>;
330
+ createSelector: <T extends ReturnType<typeof createSelector.withTypes<RematchRootState<TModels>>>, S extends (create: T) => ReturnType<T>>(callback: S) => ReturnType<S>;
331
+ selector: {
332
+ [K in keyof TModels]: ((state: RootState) => TModels[K]['state']) & Required<{
333
+ [P in keyof TModels[K]['state']]: (state: RootState) => TModels[K]['state'][P];
334
+ }> & ExtractModelSelectors<TModels[K]['selectors'], TModels>;
335
+ };
336
+ select: {
337
+ [K in keyof TModels]: (() => TModels[K]['state']) & Required<{
338
+ [P in keyof TModels[K]['state']]: () => TModels[K]['state'][P];
339
+ }> & WithoutParametersObject<ExtractModelSelectors<TModels[K]['selectors'], TModels>>;
340
+ };
341
+ /**
342
+ * Watches one or more selectors for changes and triggers a callback when their values change.
343
+ *
344
+ * @template T - Type of the selector function
345
+ *
346
+ * @param selector - A single selector function or array of selector functions to watch
347
+ * @param onChange - Callback function that receives new and old values when state changes
348
+ * @param options - Configuration options
349
+ * @param options.initial - If true, the onChange callback will be called in the next event loop tick
350
+ * with the current value of the selector and also the current value for the previous state.
351
+ *
352
+ * @returns Unsubscribe function to stop watching
353
+ *
354
+ * @example
355
+ * // Watch a single selector
356
+ * const unsubscribe1 = store.watchSelector(
357
+ * (state) => state.users.currentUser,
358
+ * (newUser, oldUser) => {
359
+ * console.log('User changed from', oldUser, 'to', newUser);
360
+ * }
361
+ * );
362
+ *
363
+ * // Watch multiple selectors
364
+ * const unsubscribe2 = store.watchSelector(
365
+ * [
366
+ * (state) => state.users.currentUser,
367
+ * (state) => state.posts.recentPosts
368
+ * ],
369
+ * ([newUser, newPosts], [oldUser, oldPosts]) => {
370
+ * // Handle changes to either user or posts
371
+ * },
372
+ * { initial: true }
373
+ * );
374
+ *
375
+ * // Later: stop watching
376
+ * unsubscribe1();
377
+ * unsubscribe2();
378
+ */
379
+ watchSelector<T extends (state: ExtractRematchStateFromModels<TModels>) => any, const TSelectors extends T[], TReturnValues extends {
380
+ [T in keyof TSelectors]: ReturnType<TSelectors[T]>;
381
+ }>(selector: TSelectors, onChange: (newValue: TReturnValues, oldValue: TReturnValues) => void | Promise<void>, options?: {
382
+ initial?: boolean;
383
+ }): () => void;
384
+ watchSelector<T extends (state: ExtractRematchStateFromModels<TModels>) => any>(selector: T, onChange: (newValue: ReturnType<T>, oldValue: ReturnType<T>) => void | Promise<void>, options?: {
385
+ initial?: boolean;
386
+ }): () => void;
387
+ /**
388
+ * Subscribes to store state changes. This is the underlying Redux subscribe method.
389
+ *
390
+ * @param listener - Callback function that will be called whenever state changes
391
+ * @returns Unsubscribe function to stop listening
392
+ */
393
+ subscribe(listener: () => void): () => void;
394
+ }
395
+ /** ************************** Root State *************************** */
396
+ /**
397
+ * The type of state held by a store.
398
+ */
399
+ type RematchRootState<TModels extends Models<TModels> = Record<string, never>> = ExtractRematchStateFromModels<TModels>;
400
+ /**
401
+ * A mapping from each model's name to a type of state it holds.
402
+ */
403
+ type ExtractRematchStateFromModels<TModels extends Models<TModels>> = {
404
+ [modelKey in keyof TModels]: TModels[modelKey]['state'];
405
+ };
406
+ /** ************************** Dispatch *************************** */
407
+ /**
408
+ * Rematch dispatch is a combination of regular redux dispatch method and
409
+ * an object allowing to dispatch specific actions by calling it the form of
410
+ * dispatch[modelName][reducerName | effectName](payload).
411
+ */
412
+ type RematchDispatch<TModels extends Models<TModels>> = ExtractRematchDispatchersFromModels<TModels>;
413
+ /**
414
+ * Goes over all models and extracts from each a type for dispatcher object
415
+ * created by Rematch.
416
+ */
417
+ type ExtractRematchDispatchersFromModels<TModels extends Models<TModels>> = {
418
+ [modelKey in keyof TModels]: TModels[modelKey] extends Model<TModels> ? ModelDispatcher<TModels[modelKey], TModels> : never;
419
+ };
420
+ /**
421
+ * Combines together types extracted from reducers and effects for a model.
422
+ */
423
+ type ModelDispatcher<TModel extends Model<TModels>, TModels extends Models<TModels>> = MergeExclusive<ExtractRematchDispatchersFromEffects<TModel['effects'], TModels>, ExtractRematchDispatchersFromReducers<TModel['state'], TModel['reducers'], TModels>>;
424
+ /**
425
+ * Get return type of rematch dispatcher
426
+ */
427
+ type ReturnOfDispatcher<IsEffect extends boolean, TParam extends unknown[] = [], TReturn = any> = IsEffect extends true ? TReturn : RematchAction<TParam[0], TParam[1]>;
428
+ /**
429
+ * When `TParam` is of type empty array, it describes 'empty' dispatcher - meaning
430
+ * it's a function not taking any arguments and returning an action.
431
+ * Otherwise, it describes dispatcher which accepts two optional argument (payload/meta)
432
+ * and returns an action.
433
+ */
434
+ type RematchDispatcher<IsEffect extends boolean, TParam extends unknown[] = [], TReturn = any> = ((...args: TParam) => ReturnOfDispatcher<IsEffect, TParam, TReturn>) & {
435
+ isEffect: IsEffect;
436
+ };
437
+ /** ************************ Reducers Dispatcher ************************* */
438
+ /**
439
+ * Utility type used to extract the `[payload?, meta?]` parameters type
440
+ * from reducer parameters.
441
+ */
442
+ type ExtractParametersFromReducer<P extends unknown[]> = P extends [] ? [] : P extends [p?: infer TPayload] ? P extends [infer TPayloadMayUndefined] ? [p: TPayloadMayUndefined] : [p?: TPayload] : P extends [p?: infer TPayload, m?: infer TMeta, ...args: unknown[]] ? P extends [
443
+ infer TPayloadMayUndefined,
444
+ infer TMetaMayUndefined,
445
+ ...unknown[]
446
+ ] ? [p: TPayloadMayUndefined, m: TMetaMayUndefined] : P extends [infer TPayloadMayUndefined, unknown?, ...unknown[]] ? [p: TPayloadMayUndefined, m?: TMeta] : [p?: TPayload, m?: TMeta] : [];
447
+ /**
448
+ * Extracts a dispatcher for each reducer that is defined for a model.
449
+ */
450
+ type ExtractRematchDispatchersFromReducers<TState, TReducers extends Model<TModels, TState>['reducers'], TModels extends Models<TModels>> = {
451
+ [reducerKey in keyof TReducers]: ExtractRematchDispatcherFromReducer<TState, TReducers[reducerKey]>;
452
+ };
453
+ /**
454
+ * Matches a reducer to different forms and based on the form, selects an
455
+ * appropriate type for a dispatcher. Mapping goes like this:
456
+ * - reducer not taking any parameters -> 'empty' dispatcher
457
+ * - reducer only taking state -> 'empty' dispatcher
458
+ * - reducer taking state and optional payload (and may also taking optional meta)
459
+ * -> dispatcher accepting payload and meta as arguments
460
+ */
461
+ type ExtractRematchDispatcherFromReducer<TState, TReducer> = TReducer extends (state: TState, ...args: infer TRest) => TState | void ? RematchDispatcher<false, ExtractParametersFromReducer<TRest>> : never;
462
+ /** ************************ Effects Dispatcher ************************* */
463
+ /**
464
+ * Based on the shape of 'effects' property it extracts dispatchers from it.
465
+ * 'effects' can be:
466
+ * - empty - in this case the type is just never
467
+ * - an object defining effects
468
+ * - a function returning effects
469
+ * If it's a function it infers its return type which must define effects.
470
+ */
471
+ type ExtractRematchDispatchersFromEffects<TEffects extends Model<TModels>['effects'], TModels extends Models<TModels>> = TEffects extends (...args: any[]) => infer R ? R extends ModelEffects<TModels> ? ExtractRematchDispatchersFromEffectsObject<R, TModels> : never : TEffects extends ModelEffects<TModels> ? ExtractRematchDispatchersFromEffectsObject<TEffects, TModels> : never;
472
+ /**
473
+ * Extracts a dispatcher for each effect that is defined for a model.
474
+ */
475
+ type ExtractRematchDispatchersFromEffectsObject<TEffects extends ModelEffects<TModels>, TModels extends Models<TModels>> = {
476
+ [effectKey in keyof TEffects]: ExtractRematchDispatcherFromEffect<TEffects[effectKey], TModels>;
477
+ };
478
+ /**
479
+ * Utility type used to extract the [payload?, meta?] parameters type
480
+ * from effect parameters.
481
+ */
482
+ type ExtractParametersFromEffect<P extends unknown[]> = P extends [] ? [] : P extends [p?: infer TPayload, s?: unknown] ? P extends [infer TPayloadMayUndefined, ...unknown[]] ? [p: TPayloadMayUndefined] : [p?: TPayload] : P extends [
483
+ p?: infer TPayload,
484
+ s?: unknown,
485
+ m?: infer TMeta,
486
+ ...args: unknown[]
487
+ ] ? P extends [
488
+ infer TPayloadMayUndefined,
489
+ unknown,
490
+ infer TMetaMayUndefined,
491
+ ...unknown[]
492
+ ] ? [p: TPayloadMayUndefined, m: TMetaMayUndefined] : P extends [
493
+ infer TPayloadMayUndefined,
494
+ unknown?,
495
+ unknown?,
496
+ ...unknown[]
497
+ ] ? [p: TPayloadMayUndefined, m?: TMeta] : [p?: TPayload, m?: TMeta] : [];
498
+ /**
499
+ * Extracts a dispatcher for a specific effect that is defined for a model.
500
+ */
501
+ type ExtractRematchDispatcherFromEffect<TEffect extends ModelEffect<TModels>, TModels extends Models<TModels>> = TEffect extends (...args: infer TRest) => infer TReturn ? RematchDispatcher<true, ExtractParametersFromEffect<TRest>, TReturn> : never;
502
+ /**
503
+ * `ConvertOptionalToUndefined<T>` is a utility type that transforms the optional properties of type `T`
504
+ * to explicitly include `undefined` while keeping the required properties unchanged.
505
+ *
506
+ * @template T - The original object type with optional and required properties.
507
+ *
508
+ * This type works by merging the original type `T` with a new type where:
509
+ * - The optional properties are identified using a conditional type.
510
+ * - These optional properties are then transformed to explicitly include `undefined`.
511
+ * - The required properties remain unchanged.
512
+ */
513
+ type ConvertOptionalToUndefined<T> = {
514
+ [K in keyof T | {
515
+ [k in keyof T]-?: undefined extends T[k] ? k : never;
516
+ }[keyof T]]: K extends {
517
+ [k in keyof T]-?: undefined extends T[k] ? k : never;
518
+ }[keyof T] ? T[K & keyof T] | undefined : K extends keyof T ? T[K] : never;
519
+ };
520
+ interface ModelCreator {
521
+ <S, RM extends Models<RM>>(): <R extends ModelReducers<S> | undefined, E extends ModelEffects<RM> | ModelEffectsCreator<RM> | undefined, MS extends ModelSelectorsCreator<RM> | undefined>(mo: {
522
+ name?: string;
523
+ state: ConvertOptionalToUndefined<S>;
524
+ reducers?: R;
525
+ effects?: E;
526
+ selectors?: MS;
527
+ }) => {
528
+ name?: string;
529
+ state: S;
530
+ } & (E extends undefined ? object : {
531
+ effects: E;
532
+ }) & (R extends undefined ? object : {
533
+ reducers: R;
534
+ }) & (MS extends undefined ? object : {
535
+ selectors: MS;
536
+ });
537
+ }
538
+
539
+ declare function createRematchStore<TModels extends Models<TModels>>(initConfig: InitConfig<TModels>): RematchStore<TModels>;
540
+
541
+ declare const createModel: ModelCreator;
542
+
543
+ export { type Config, type ConfigRedux, type ExposedFunction, type ExtractRematchDispatcherFromEffect, type ExtractRematchDispatcherFromReducer, type ExtractRematchDispatchersFromEffects, type ExtractRematchDispatchersFromEffectsObject, type ExtractRematchDispatchersFromModels, type ExtractRematchDispatchersFromReducers, type ExtractRematchStateFromModels, type InitConfig, type InitConfigRedux, type Model, type ModelCreator, type ModelDispatcher, type ModelEffect, type ModelEffectThisTyped, type ModelEffects, type ModelEffectsCreator, type ModelReducers, type ModelSelectors, type ModelSelectorsCreator, type Models, type NamedModel, type Reducer, type RematchAction, type RematchDispatch, type RematchDispatcher, type RematchRootState, type RematchStore, createModel, createRematchStore };