Skip to content

Commit 42215c0

Browse files
committed
add new replaceFromCurrent() method
1 parent 92894b6 commit 42215c0

21 files changed

+3292
-2252
lines changed

docs/inject-store-state.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ function InjectStoreState({ store, on, children }) {
2323
`SS` = Sub State (which you are selecting to be returned in the child function):
2424

2525
```tsx
26-
interface IPropsInjectStoreState<S extends any = any, SS extends any = any> {
26+
interface IPropsInjectStoreState<S extends object = object, SS extends any = any> {
2727
store: Store<S>;
2828
on?: (state: S) => SS;
2929
children: (output: SS) => React.ReactElement;
@@ -63,4 +63,4 @@ const GreetUser = () => {
6363
</div>
6464
)
6565
}
66-
```
66+
```

package.json

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "pullstate",
3-
"version": "1.24.0",
3+
"version": "1.25.0",
44
"description": "Simple state stores using immer and React hooks",
55
"main": "dist/index.js",
66
"module": "dist/index.es.js",
@@ -16,7 +16,7 @@
1616
"test": "jest",
1717
"test-watch": "jest --watch",
1818
"clean": "rimraf ./dist",
19-
"build": "npm run clean && rollup -c",
19+
"build": "npm run clean && rollup -c --bundleConfigAsCjs",
2020
"uglify": "terser ./dist/index.js -o ./dist/index.js",
2121
"check-size": "minified-size ./dist/index.es.js",
2222
"check-size-cjs": "minified-size ./dist/index.js",
@@ -38,40 +38,43 @@
3838
"license": "MIT",
3939
"dependencies": {
4040
"fast-deep-equal": "^3.1.3",
41-
"immer": "^9.0.12"
41+
"immer": "^9.0.16"
4242
},
4343
"repository": "https://github.com/lostpebble/pullstate",
4444
"devDependencies": {
45-
"@testing-library/jest-dom": "^4.1.0",
46-
"@testing-library/react": "^9.1.4",
47-
"@types/benchmark": "^1.0.31",
48-
"@types/jest": "23.3.10",
49-
"@types/lodash": "^4.14.121",
50-
"@types/react": "16.9.21",
51-
"@types/react-dom": "16.9.5",
45+
"@testing-library/jest-dom": "^5.16.5",
46+
"@testing-library/react": "^13.4.0",
47+
"@types/benchmark": "^2.1.2",
48+
"@types/jest": "29.2.3",
49+
"@types/lodash": "^4.14.190",
50+
"@types/react": "18.0.25",
51+
"@types/react-dom": "18.0.9",
5252
"benchmark": "^2.1.4",
53-
"cross-env": "^5.2.0",
54-
"in-publish": "^2.0.0",
55-
"jest": "24.8.0",
53+
"cross-env": "^7.0.3",
54+
"in-publish": "^2.0.1",
55+
"jest": "29.3.1",
5656
"jest-dom": "^4.0.0",
57-
"jest-environment-jsdom": "24.8.0",
58-
"jest-environment-jsdom-global": "1.2.0",
59-
"js-beautify": "^1.9.0-beta5",
60-
"lodash": "^4.17.15",
61-
"prettier": "^2.0.5",
62-
"react-test-renderer": "^16.8.3",
63-
"@rollup/plugin-commonjs": "^11.0.2",
64-
"@rollup/plugin-typescript": "^4.1.2",
65-
"@rollup/plugin-node-resolve": "^9.0.0",
66-
"rollup-plugin-typescript2": "^0.28.0",
57+
"jest-environment-jsdom": "29.3.1",
58+
"jest-environment-jsdom-global": "4.0.0",
59+
"js-beautify": "^1.14.7",
60+
"lodash": "^4.17.21",
61+
"prettier": "^2.8.0",
62+
"react-test-renderer": "^18.2.0",
63+
"@rollup/plugin-commonjs": "^23.0.3",
64+
"@rollup/plugin-typescript": "^10.0.0",
65+
"@rollup/plugin-node-resolve": "^15.0.1",
66+
"react": "^18.2.0",
67+
"react-dom": "^18.2.0",
68+
"rollup-plugin-typescript2": "^0.34.1",
6769
"rollup-plugin-terser": "^7.0.2",
68-
"rollup": "^2.32.0",
70+
"rollup": "^3.5.0",
6971
"terser": "^3.16.1",
70-
"ts-jest": "^24.0.2",
71-
"ts-loader": "^6.0.2",
72-
"ts-node": "^8.2.0",
73-
"typedoc": "^0.19.2",
74-
"typescript": "4.0.3",
72+
"ts-jest": "^29.0.3",
73+
"ts-loader": "^9.4.1",
74+
"ts-node": "^10.9.1",
75+
"typedoc": "^0.23.21",
76+
"type-fest": "^3.3.0",
77+
"typescript": "4.9.3",
7578
"webpack": "^4.44.2",
7679
"webpack-cli": "^3.3.12"
7780
},

rollup.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import typescript from "rollup-plugin-typescript2";
22
import { terser } from "rollup-plugin-terser";
33
import { nodeResolve } from "@rollup/plugin-node-resolve";
44
import commonjs from "@rollup/plugin-commonjs";
5-
import pkg from "./package.json";
5+
import pkg from "./package.json" assert { type: "json" };
66
// import typescript from "@rollup/plugin-typescript";
77

88
export default [{

src/InjectStoreState.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ import React from "react";
22
import { Store } from "./Store";
33
import { useStoreState } from "./useStoreState";
44

5-
export interface IPropsInjectStoreState<S extends any = any, SS extends any = any> {
5+
export interface IPropsInjectStoreState<S extends object = any, SS extends any = any> {
66
store: Store<S>;
77
on?: (state: S) => SS;
88
children: (output: SS) => React.ReactElement;
99
}
1010

11-
export function InjectStoreState<S extends any = any, SS = any>({
11+
export function InjectStoreState<S extends object = any, SS = any>({
1212
store,
1313
on = s => s as any,
1414
children,

src/InjectStoreStateOpt.ts

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,24 @@
11
import React from "react";
22
import { Store } from "./Store";
33
import { useStoreStateOpt } from "./useStoreStateOpt";
4+
import { ObjectPath } from "./useStoreStateOpt-types";
5+
import type { GetWithPath } from "type-fest/get";
6+
7+
export interface IPropsInjectStoreStateOpt<
8+
T extends readonly unknown[],
9+
S extends object = object,
10+
P extends ObjectPath<S, T> = T extends ObjectPath<S, T> ? T : never
11+
> {
12+
store: Store<S>;
13+
paths: P;
14+
children: (output: GetWithPath<S, P>) => React.ReactElement;
15+
}
16+
17+
/*
418
import { DeepTypeOfArray, TAllPathsParameter } from "./useStoreStateOpt-types";
519
620
export interface IPropsInjectStoreStateOpt<
7-
S extends any = any,
21+
S extends object = object,
822
P extends TAllPathsParameter<S> = TAllPathsParameter<S>,
923
O extends [
1024
DeepTypeOfArray<S, P[0]>,
@@ -35,25 +49,13 @@ export interface IPropsInjectStoreStateOpt<
3549
store: Store<S>;
3650
paths: P;
3751
children: (output: O) => React.ReactElement;
38-
}
52+
}*/
3953

4054
export function InjectStoreStateOpt<
41-
S extends any,
42-
P extends TAllPathsParameter<S>,
43-
O extends [
44-
DeepTypeOfArray<S, P[0]>,
45-
DeepTypeOfArray<S, P[1]>,
46-
DeepTypeOfArray<S, P[2]>,
47-
DeepTypeOfArray<S, P[3]>,
48-
DeepTypeOfArray<S, P[4]>,
49-
DeepTypeOfArray<S, P[5]>,
50-
DeepTypeOfArray<S, P[6]>,
51-
DeepTypeOfArray<S, P[7]>,
52-
DeepTypeOfArray<S, P[8]>,
53-
DeepTypeOfArray<S, P[9]>,
54-
DeepTypeOfArray<S, P[10]>
55-
]
56-
>({ store, paths, children }: IPropsInjectStoreStateOpt<S, P, O>): React.ReactElement {
57-
const state = useStoreStateOpt(store, paths) as O;
55+
T extends readonly unknown[],
56+
S extends object = object,
57+
P extends ObjectPath<S, T> = T extends ObjectPath<S, T> ? T : never
58+
>({ store, paths, children }: IPropsInjectStoreStateOpt<T, S, P>): React.ReactElement {
59+
const state = useStoreStateOpt(store, paths) as GetWithPath<S, P>;
5860
return children(state);
5961
}

src/Store.ts

Lines changed: 23 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// @ts-ignore
22
import { applyPatches, Draft, enablePatches, Patch, PatchListener, produce, produceWithPatches } from "immer";
33
import { useStoreState } from "./useStoreState";
4-
import { DeepKeyOfArray } from "./useStoreStateOpt-types";
54

65
import isEqual from "fast-deep-equal/es6";
76
import { useLocalStore } from "./useLocalStore";
@@ -20,7 +19,7 @@ enablePatches();
2019

2120
export type TPullstateUpdateListener = () => void;
2221

23-
export interface IStoreInternalOptions<S extends any> {
22+
export interface IStoreInternalOptions<S extends object> {
2423
ssr: boolean;
2524
reactionCreators?: TReactionCreator<S>[];
2625
}
@@ -38,9 +37,9 @@ type TReactionFunction<S extends any, T> = (watched: T, draft: Draft<S>, origina
3837
*/
3938
type TRunReactionFunction = (forceRun?: boolean) => string[];
4039
type TRunSubscriptionFunction = () => void;
41-
type TReactionCreator<S extends any> = (store: Store<S>) => TRunReactionFunction;
40+
type TReactionCreator<S extends object> = (store: Store<S>) => TRunReactionFunction;
4241

43-
function makeSubscriptionFunction<S extends any, T>(
42+
function makeSubscriptionFunction<S extends object, T>(
4443
store: Store<S>,
4544
watch: (state: S) => T,
4645
listener: (watched: T, allState: S, previousWatched: T, uid?: string) => void
@@ -58,7 +57,7 @@ function makeSubscriptionFunction<S extends any, T>(
5857
};
5958
}
6059

61-
function makeReactionFunctionCreator<S extends any, T>(
60+
function makeReactionFunctionCreator<S extends object, T>(
6261
watch: (state: S) => T,
6362
reaction: TReactionFunction<S, T>
6463
): TReactionCreator<S> {
@@ -116,17 +115,17 @@ interface ICreateReactionOptions {
116115

117116
const optPathDivider = "~._.~";
118117

119-
export type TStoreActionUpdate<S extends any> = (
118+
export type TStoreActionUpdate<S extends object> = (
120119
updater: TUpdateFunction<S> | TUpdateFunction<S>[],
121120
patchesCallback?: (patches: Patch[], inversePatches: Patch[]) => void
122121
) => void;
123122

124-
export type TStoreAction<S extends any> = (update: TStoreActionUpdate<S>) => void;
123+
export type TStoreAction<S extends object> = (update: TStoreActionUpdate<S>) => void;
125124

126125
/**
127126
* @typeParam S Your store's state interface
128127
*/
129-
export class Store<S extends any = any> {
128+
export class Store<S extends object = object> {
130129
private updateListeners: TPullstateUpdateListener[] = [];
131130
private currentState: S;
132131
private readonly initialState: S;
@@ -256,26 +255,6 @@ export class Store<S extends any = any> {
256255
this.updateListeners.push(listener);
257256
}
258257

259-
/**
260-
* @internal
261-
* @param listener
262-
* @param ordKey
263-
* @param paths
264-
*/
265-
_addUpdateListenerOpt(listener: TPullstateUpdateListener, ordKey: string, paths: DeepKeyOfArray<S>[]) {
266-
this.optimizedUpdateListeners[ordKey] = listener;
267-
const listenerPathsKeyed: string[] = paths.map((path) => path.join(optPathDivider));
268-
this.optimizedUpdateListenerPaths[ordKey] = listenerPathsKeyed;
269-
for (const keyedPath of listenerPathsKeyed) {
270-
if (this.optimizedListenerPropertyMap[keyedPath] == null) {
271-
this.optimizedListenerPropertyMap[keyedPath] = [ordKey];
272-
} else {
273-
this.optimizedListenerPropertyMap[keyedPath].push(ordKey);
274-
}
275-
}
276-
this._optListenerCount++;
277-
}
278-
279258
/**
280259
* @internal
281260
* @param listener
@@ -462,12 +441,16 @@ export class Store<S extends any = any> {
462441
this._updateState(newState);
463442
}
464443

444+
replaceFromCurrent(replacer: (state: S) => S) {
445+
this._updateState(replacer(this.currentState));
446+
}
447+
465448
applyPatches(patches: Patch[]) {
466449
applyPatchesToStore(this, patches);
467450
}
468451
}
469452

470-
export function applyPatchesToStore<S extends any = any>(store: Store<S>, patches: Patch[]) {
453+
export function applyPatchesToStore<S extends object = object>(store: Store<S>, patches: Patch[]) {
471454
const currentState: S = store.getRawState();
472455
const nextState = applyPatches(currentState as any, patches);
473456
if (nextState !== currentState) {
@@ -521,14 +504,14 @@ function runUpdates<S extends any>(
521504
return func
522505
? (produceWithPatches(currentState, (s: S) => (updater as TUpdateFunction<S>)(s as Draft<S>, currentState)) as any)
523506
: ((updater as TUpdateFunction<S>[]).reduce(
524-
([nextState, patches, inversePatches], currentValue) => {
525-
const resp = produceWithPatches(nextState as any, (s: S) => currentValue(s as Draft<S>, nextState)) as any;
526-
patches.push(...resp[1]);
527-
inversePatches.push(...resp[2]);
528-
return [resp[0], patches, inversePatches];
529-
},
530-
[currentState, [], []] as [S, Patch[], Patch[]]
531-
) as [S, Patch[], Patch[]]);
507+
([nextState, patches, inversePatches], currentValue) => {
508+
const resp = produceWithPatches(nextState as any, (s: S) => currentValue(s as Draft<S>, nextState)) as any;
509+
patches.push(...resp[1]);
510+
inversePatches.push(...resp[2]);
511+
return [resp[0], patches, inversePatches];
512+
},
513+
[currentState, [], []] as [S, Patch[], Patch[]]
514+
) as [S, Patch[], Patch[]]);
532515
}
533516

534517
/**
@@ -537,7 +520,7 @@ function runUpdates<S extends any>(
537520
* @param updater The update function, or an array of update functions
538521
* @param patchesCallback A callback to keep track of the patches made during this update.
539522
*/
540-
export function update<S extends any = any>(
523+
export function update<S extends object = object>(
541524
store: Store<S>,
542525
updater: TUpdateFunction<S> | TUpdateFunction<S>[],
543526
patchesCallback?: (patches: Patch[], inversePatches: Patch[]) => void
@@ -577,8 +560,8 @@ export function update<S extends any = any>(
577560
func
578561
? (updater as TUpdateFunction<S>)(s as Draft<S>, currentState)
579562
: (updater as TUpdateFunction<S>[]).reduce((previousValue, currentUpdater) => {
580-
return produce(previousValue as any, (s: S) => currentUpdater(s as Draft<S>, previousValue)) as any;
581-
}, currentState)
563+
return produce(previousValue as any, (s: S) => currentUpdater(s as Draft<S>, previousValue)) as any;
564+
}, currentState)
582565
) as any;
583566
}
584567

src/async.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -665,7 +665,7 @@ further looping. Fix in your cacheBreakHook() is needed.`);
665665

666666
const watchOrd = watchIdOrd++;
667667

668-
throw new Promise((resolve) => {
668+
throw new Promise<void>((resolve) => {
669669
cache.listeners[key][watchOrd] = () => {
670670
delete cache.listeners[key][watchOrd];
671671
resolve();

src/globalClientState.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export const globalClientState: {
44
storeOrdinal: number,
55
batching: boolean;
66
flushStores: {
7-
[storeName: number]: Store;
7+
[storeName: number]: Store<any>;
88
};
99
} = {
1010
storeOrdinal: 0,

src/index.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { useStoreState } from "./useStoreState";
2-
import { useStoreStateOpt } from "./useStoreStateOpt";
32
import { Store, TStoreAction, TUpdateFunction, update } from "./Store";
43
import { InjectStoreState } from "./InjectStoreState";
54
import type { PullstateSingleton } from "./PullstateCore";
@@ -15,7 +14,6 @@ import {
1514
} from "./PullstateCore";
1615
import { createAsyncAction, createAsyncActionDirect, errorResult, successResult } from "./async";
1716
import { EAsyncActionInjectType, InjectAsyncAction, TInjectAsyncActionProps } from "./InjectAsyncAction";
18-
import { InjectStoreStateOpt } from "./InjectStoreStateOpt";
1917
import { TUseResponse } from "./async-types";
2018
import { registerInDevtools } from "./reduxDevtools";
2119
import { useLocalStore } from "./useLocalStore";
@@ -25,12 +23,10 @@ export * from "./async-types";
2523

2624
export {
2725
useStoreState,
28-
useStoreStateOpt,
2926
useLocalStore,
3027
update,
3128
Store,
3229
InjectStoreState,
33-
InjectStoreStateOpt,
3430
PullstateProvider,
3531
useStores,
3632
useInstance,

src/useLocalStore.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Store } from "./Store";
22
import { useRef } from "react";
33
import isEqual from "fast-deep-equal/es6";
44

5-
function useLocalStore<S extends any>(initialState: (() => S) | S, deps?: ReadonlyArray<any>): Store<S> {
5+
function useLocalStore<S extends object>(initialState: (() => S) | S, deps?: ReadonlyArray<any>): Store<S> {
66
const storeRef = useRef<Store<S>>();
77

88
if (storeRef.current == null) {

src/useStoreState.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ export interface IUpdateRefNew {
2121

2222
const onServer = typeof window === "undefined";
2323

24-
function useStoreState<S extends any = any>(store: Store<S>): S;
25-
function useStoreState<S extends any = any, SS = any>(
24+
function useStoreState<S extends object = any>(store: Store<S>): S;
25+
function useStoreState<S extends object = any, SS = any>(
2626
store: Store<S>,
2727
getSubState: (state: S) => SS,
2828
deps?: ReadonlyArray<any>

0 commit comments

Comments
 (0)