Skip to content

Commit 2f5965c

Browse files
authored
shave some bytes (#78)
1 parent e27c85f commit 2f5965c

4 files changed

Lines changed: 59 additions & 53 deletions

File tree

packages/zundo/__tests__/options.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ describe('Middleware options', () => {
435435
store.temporal.getState() as TemporalStateWithInternals<MyState>;
436436
expect(__internal).toBeDefined();
437437
expect(__internal.handleUserSet).toBeInstanceOf(Function);
438-
expect(__internal.onSave).toBeInstanceOf(Function);
438+
expect(__internal.onSave).toBe(undefined);
439439
});
440440
describe('onSave', () => {
441441
it('should call onSave cb without adding a new state when onSave is set by user', () => {
@@ -452,6 +452,7 @@ describe('Middleware options', () => {
452452
act(() => {
453453
onSave(store.getState(), store.getState());
454454
});
455+
expect(__internal.onSave).toBeInstanceOf(Function);
455456
expect(store.temporal.getState().pastStates.length).toBe(0);
456457
expect(console.error).toHaveBeenCalledTimes(1);
457458
});

packages/zundo/src/index.ts

Lines changed: 45 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -27,54 +27,58 @@ declare module 'zustand/vanilla' {
2727
}
2828
}
2929

30-
type ZundoImpl = <TState>(
31-
config: StateCreator<TState, [], []>,
32-
options: ZundoOptions<TState>,
33-
) => StateCreator<TState, [], []>;
30+
const zundoImpl =
31+
<TState>(
32+
config: StateCreator<TState, [], []>,
33+
{
34+
partialize = (state: TState) => state,
35+
equality,
36+
onSave,
37+
limit,
38+
handleSet: userlandSetFactory = (handleSetCb) => handleSetCb,
39+
} = {} as ZundoOptions<TState>,
40+
): StateCreator<TState, [], []> =>
41+
(set, get, _store) => {
42+
type TState = ReturnType<typeof config>;
43+
type StoreAddition = StoreApi<TemporalState<TState>>;
3444

35-
const zundoImpl: ZundoImpl = (config, baseOptions) => (set, get, _store) => {
36-
type TState = ReturnType<typeof config>;
37-
type StoreAddition = StoreApi<TemporalState<TState>>;
45+
const temporalStore = createVanillaTemporal<TState>(set, get, {
46+
partialize,
47+
equality,
48+
onSave,
49+
limit,
50+
});
3851

39-
const options = {
40-
partialize: (state: TState) => state,
41-
handleSet: (handleSetCb: typeof set) => handleSetCb,
42-
...baseOptions,
43-
};
44-
const { partialize, handleSet: userlandSetFactory } = options;
45-
46-
const temporalStore = createVanillaTemporal<TState>(set, get, options);
52+
const store = _store as Mutate<
53+
StoreApi<TState>,
54+
[['temporal', StoreAddition]]
55+
>;
56+
const { setState } = store;
4757

48-
const store = _store as Mutate<
49-
StoreApi<TState>,
50-
[['temporal', StoreAddition]]
51-
>;
52-
const { setState } = store;
58+
// TODO: should temporal be only temporalStore.getState()?
59+
// We can hide the rest of the store in the secret internals.
60+
store.temporal = temporalStore;
5361

54-
// TODO: should temporal be only temporalStore.getState()?
55-
// We can hide the rest of the store in the secret internals.
56-
store.temporal = temporalStore;
62+
const curriedUserLandSet = userlandSetFactory(
63+
temporalStore.getState().__internal.handleUserSet,
64+
);
5765

58-
const curriedUserLandSet = userlandSetFactory(
59-
temporalStore.getState().__internal.handleUserSet,
60-
);
66+
const modifiedSetState: typeof setState = (state, replace) => {
67+
const pastState = partialize(get());
68+
setState(state, replace);
69+
curriedUserLandSet(pastState);
70+
};
71+
store.setState = modifiedSetState;
6172

62-
const modifiedSetState: typeof setState = (state, replace) => {
63-
const pastState = partialize(get());
64-
setState(state, replace);
65-
curriedUserLandSet(pastState);
66-
};
67-
store.setState = modifiedSetState;
73+
const modifiedSetter: typeof set = (state, replace) => {
74+
// Get most up to date state. Should this be the same as the state in the callback?
75+
const pastState = partialize(get());
76+
set(state, replace);
77+
curriedUserLandSet(pastState);
78+
};
6879

69-
const modifiedSetter: typeof set = (state, replace) => {
70-
// Get most up to date state. Should this be the same as the state in the callback?
71-
const pastState = partialize(get());
72-
set(state, replace);
73-
curriedUserLandSet(pastState);
80+
return config(modifiedSetter, get, _store);
7481
};
7582

76-
return config(modifiedSetter, get, _store);
77-
};
78-
7983
export const temporal = zundoImpl as unknown as Zundo;
80-
export type { ZundoOptions, Zundo, TemporalState };
84+
export type { ZundoOptions, Zundo, TemporalState };

packages/zundo/src/temporal.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
import { createStore, type StoreApi } from 'zustand';
2-
import type { TemporalStateWithInternals, ZundoOptions } from './types';
2+
import type { TemporalStateWithInternals, WithRequired, ZundoOptions } from './types';
33

44
export const createVanillaTemporal = <TState>(
55
userSet: StoreApi<TState>['setState'],
66
userGet: StoreApi<TState>['getState'],
7-
baseOptions?: ZundoOptions<TState>,
7+
{
8+
partialize,
9+
equality,
10+
onSave,
11+
limit,
12+
} = {} as Omit<WithRequired<ZundoOptions<TState>, | 'partialize'>, 'handleSet'>,
813
) => {
9-
const options = {
10-
partialize: (state: TState) => state,
11-
equality: (a: TState, b: TState) => false,
12-
onSave: () => {},
13-
...baseOptions,
14-
};
15-
const { partialize, onSave, limit, equality } = options;
1614

1715
return createStore<TemporalStateWithInternals<TState>>()((set, get) => {
1816
return {
@@ -73,7 +71,7 @@ export const createVanillaTemporal = <TState>(
7371
const currentState = partialize(userGet());
7472
if (
7573
trackingStatus === 'tracking' &&
76-
!equality(currentState, pastState)
74+
!equality?.(currentState, pastState)
7775
) {
7876
if (limit && ps.length >= limit) {
7977
ps.shift();

packages/zundo/src/types.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { StoreApi } from 'zustand';
22

3-
type onSave<TState> = (pastState: TState, currentState: TState) => void;
3+
type onSave<TState> = ((pastState: TState, currentState: TState) => void) | undefined;
44

55
export interface TemporalStateWithInternals<TState> {
66
pastStates: TState[];
@@ -37,3 +37,6 @@ export type TemporalState<TState> = Omit<
3737
TemporalStateWithInternals<TState>,
3838
'__internal'
3939
>;
40+
41+
// https://stackoverflow.com/a/69328045/9931154
42+
export type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] }

0 commit comments

Comments
 (0)