floppy-disk 1.1.3 → 1.2.0-beta.1
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 +7 -2
- package/esm/react/create-mutation.d.ts +2 -2
- package/esm/react/create-query.d.ts +4 -4
- package/esm/react/create-query.js +5 -4
- package/esm/react/create-store.d.ts +2 -2
- package/esm/react/create-stores.d.ts +4 -4
- package/esm/react/with-context.d.ts +2 -2
- package/esm/vanilla.d.ts +8 -8
- package/lib/react/create-mutation.d.ts +2 -2
- package/lib/react/create-query.d.ts +4 -4
- package/lib/react/create-query.js +5 -4
- package/lib/react/create-store.d.ts +2 -2
- package/lib/react/create-stores.d.ts +4 -4
- package/lib/react/with-context.d.ts +2 -2
- package/lib/vanilla.d.ts +8 -8
- package/package.json +14 -10
- package/esm/__tests__/vanilla.test.d.ts +0 -1
- package/esm/__tests__/vanilla.test.js +0 -67
- package/lib/__tests__/vanilla.test.d.ts +0 -1
- package/lib/__tests__/vanilla.test.js +0 -69
package/README.md
CHANGED
|
@@ -563,13 +563,18 @@ const useLoginMutation = createMutation(
|
|
|
563
563
|
|
|
564
564
|
function Login() {
|
|
565
565
|
const { mutate, isWaiting } = useLoginMutation();
|
|
566
|
+
const showToast = useToast();
|
|
566
567
|
return (
|
|
567
568
|
<div>
|
|
568
569
|
<button
|
|
569
570
|
disabled={isWaiting}
|
|
570
571
|
onClick={() =>
|
|
571
|
-
mutate({ email: 'foo@bar.baz', password: 's3cREt' }).then(() => {
|
|
572
|
-
|
|
572
|
+
mutate({ email: 'foo@bar.baz', password: 's3cREt' }).then(({ response, error }) => {
|
|
573
|
+
if (error) {
|
|
574
|
+
showToast('Login failed');
|
|
575
|
+
} else {
|
|
576
|
+
showToast('Login success');
|
|
577
|
+
}
|
|
573
578
|
})
|
|
574
579
|
}
|
|
575
580
|
>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { InitStoreOptions } from '../vanilla';
|
|
2
|
-
export
|
|
2
|
+
export type MutationState<TVar, TResponse = any, TError = unknown> = {
|
|
3
3
|
/**
|
|
4
4
|
* Network fetching status.
|
|
5
5
|
*/
|
|
@@ -19,7 +19,7 @@ export declare type MutationState<TVar, TResponse = any, TError = unknown> = {
|
|
|
19
19
|
variables?: TVar;
|
|
20
20
|
}>;
|
|
21
21
|
};
|
|
22
|
-
export
|
|
22
|
+
export type CreateMutationOptions<TVar, TResponse = any, TError = unknown> = InitStoreOptions<MutationState<TVar, TResponse, TError>> & {
|
|
23
23
|
onMutate?: (variables: TVar | undefined, stateBeforeMutate: MutationState<TVar, TResponse, TError>) => void;
|
|
24
24
|
onSuccess?: (response: TResponse, variables: TVar | undefined, stateBeforeMutate: MutationState<TVar, TResponse, TError>) => void;
|
|
25
25
|
onError?: (error: TError, variables: TVar | undefined, stateBeforeMutate: MutationState<TVar, TResponse, TError>) => void;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CreateStoresOptions, StoreKey } from './create-stores';
|
|
2
|
-
export
|
|
3
|
-
export
|
|
2
|
+
export type QueryStatus = 'loading' | 'success' | 'error';
|
|
3
|
+
export type QueryState<TKey extends StoreKey = StoreKey, TResponse = any, TData = TResponse, TError = unknown> = {
|
|
4
4
|
/**
|
|
5
5
|
* Query store key, an object that will be hashed into a string as a query store identifier.
|
|
6
6
|
*/
|
|
@@ -95,7 +95,7 @@ export declare type QueryState<TKey extends StoreKey = StoreKey, TResponse = any
|
|
|
95
95
|
pageParams: any[];
|
|
96
96
|
hasNextPage: boolean;
|
|
97
97
|
};
|
|
98
|
-
export
|
|
98
|
+
export type CreateQueryOptions<TKey extends StoreKey = StoreKey, TResponse = any, TData = TResponse, TError = unknown> = CreateStoresOptions<TKey, QueryState<TKey, TResponse, TData, TError>> & {
|
|
99
99
|
select?: (response: TResponse, state: Pick<QueryState<TKey, TResponse, TData, TError>, 'data' | 'key'>) => TData;
|
|
100
100
|
/**
|
|
101
101
|
* Stale time in miliseconds.
|
|
@@ -108,7 +108,7 @@ export declare type CreateQueryOptions<TKey extends StoreKey = StoreKey, TRespon
|
|
|
108
108
|
*
|
|
109
109
|
* Defaults to `1`.
|
|
110
110
|
*/
|
|
111
|
-
|
|
111
|
+
maxRetryCount?: number | ((error: TError, key: TKey) => number);
|
|
112
112
|
/**
|
|
113
113
|
* Auto call the query when the component is mounted.
|
|
114
114
|
*
|
|
@@ -37,7 +37,7 @@ const useQueryDefaultDeps = (state) => [
|
|
|
37
37
|
state.hasNextPage,
|
|
38
38
|
];
|
|
39
39
|
export const createQuery = (queryFn, options = {}) => {
|
|
40
|
-
const { onFirstSubscribe = noop, onSubscribe = noop, onLastUnsubscribe = noop, onBeforeChangeKey = noop, defaultDeps = useQueryDefaultDeps, select = identityFn, staleTime = DEFAULT_STALE_TIME,
|
|
40
|
+
const { onFirstSubscribe = noop, onSubscribe = noop, onLastUnsubscribe = noop, onBeforeChangeKey = noop, defaultDeps = useQueryDefaultDeps, select = identityFn, staleTime = DEFAULT_STALE_TIME, maxRetryCount = 1, fetchOnMount = true, fetchOnWindowFocus = true, enabled = true, keepPreviousData, getNextPageParam = () => undefined, onSuccess = noop, onError = noop, onSettled = noop, ...createStoresOptions } = options;
|
|
41
41
|
const useQuery = createStores(({ key: _key, get, set }) => {
|
|
42
42
|
const key = _key;
|
|
43
43
|
const forceFetch = () => {
|
|
@@ -78,8 +78,8 @@ export const createQuery = (queryFn, options = {}) => {
|
|
|
78
78
|
isRefetching: false,
|
|
79
79
|
isRefetchError: false,
|
|
80
80
|
isPreviousData: false,
|
|
81
|
-
data: responseAllPages.reduce((prev,
|
|
82
|
-
return select(
|
|
81
|
+
data: responseAllPages.reduce((prev, responseCurrentPage) => {
|
|
82
|
+
return select(responseCurrentPage, { key, data: prev });
|
|
83
83
|
}, null),
|
|
84
84
|
response,
|
|
85
85
|
responseUpdatedAt: Date.now(),
|
|
@@ -116,7 +116,8 @@ export const createQuery = (queryFn, options = {}) => {
|
|
|
116
116
|
pageParam,
|
|
117
117
|
hasNextPage: pageParam !== undefined,
|
|
118
118
|
});
|
|
119
|
-
|
|
119
|
+
const retryCount = typeof maxRetryCount === 'function' ? maxRetryCount(error, key) : maxRetryCount;
|
|
120
|
+
if (typeof retryCount === 'number' && prevState.retryCount < retryCount) {
|
|
120
121
|
set({ retryCount: prevState.retryCount + 1, isGoingToRetry: true });
|
|
121
122
|
callQuery();
|
|
122
123
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { InitStoreOptions, SelectDeps, SetStoreData, StoreData, StoreInitializer, Subscribers } from '../vanilla';
|
|
2
|
-
export
|
|
2
|
+
export type WatchProps<T> = {
|
|
3
3
|
selectDeps?: SelectDeps<T>;
|
|
4
4
|
render: (state: T) => any;
|
|
5
5
|
};
|
|
6
|
-
export
|
|
6
|
+
export type UseStore<T extends StoreData> = {
|
|
7
7
|
/**
|
|
8
8
|
* @param selectDeps A function that return the dependency array (just like in `useEffect`), to trigger reactivity.
|
|
9
9
|
* Defaults to `undefined` (reactive to all state change) if you didn't set `defaultDeps` on `createStore`.
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { InitStoreOptions, SelectDeps, SetStoreData, StoreData, Subscribers } from '../vanilla';
|
|
2
2
|
import { WatchProps } from './create-store';
|
|
3
|
-
export
|
|
4
|
-
export
|
|
3
|
+
export type StoreKey = Record<string, any> | undefined;
|
|
4
|
+
export type StoresInitializer<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = (api: {
|
|
5
5
|
key: TKey;
|
|
6
6
|
get: () => T;
|
|
7
7
|
set: (value: SetStoreData<T>, silent?: boolean) => void;
|
|
8
8
|
}) => T;
|
|
9
|
-
export
|
|
9
|
+
export type UseStores<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = {
|
|
10
10
|
/**
|
|
11
11
|
* @param key (Optional) Store key, an object that will be hashed into a string as a store identifier.
|
|
12
12
|
*
|
|
@@ -27,7 +27,7 @@ export declare type UseStores<TKey extends StoreKey = StoreKey, T extends StoreD
|
|
|
27
27
|
storeKey?: TKey;
|
|
28
28
|
}) => any;
|
|
29
29
|
};
|
|
30
|
-
export
|
|
30
|
+
export type CreateStoresOptions<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = InitStoreOptions<T> & {
|
|
31
31
|
onBeforeChangeKey?: (nextKey: TKey, prevKey: TKey) => void;
|
|
32
32
|
defaultDeps?: SelectDeps<T>;
|
|
33
33
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ReactNode } from 'react';
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
2
|
export declare const withContext: <T>(initFn: () => T) => readonly [({ children, onInitialize, }: {
|
|
3
3
|
children: ReactNode;
|
|
4
4
|
onInitialize?: ((value: T) => void) | undefined;
|
|
5
|
-
}) => JSX.Element, () => T | null];
|
|
5
|
+
}) => React.JSX.Element, () => T | null];
|
package/esm/vanilla.d.ts
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export
|
|
5
|
-
export
|
|
1
|
+
export type StoreData = Record<string, any>;
|
|
2
|
+
export type SetStoreData<T> = Partial<T> | ((prevState: T) => Partial<T>);
|
|
3
|
+
export type SelectDeps<T> = ((state: T) => any[]) | undefined;
|
|
4
|
+
export type Subscribers<T> = Map<(state: T) => void, SelectDeps<T>>;
|
|
5
|
+
export type StoreInitializer<T> = (api: {
|
|
6
6
|
get: () => T;
|
|
7
7
|
set: (value: SetStoreData<T>, silent?: boolean) => void;
|
|
8
8
|
}) => T;
|
|
9
|
-
export
|
|
10
|
-
export
|
|
9
|
+
export type StoreEvent<T> = (state: T) => void;
|
|
10
|
+
export type InitStoreOptions<T> = {
|
|
11
11
|
intercept?: (nextState: T, prevState: T) => Partial<T>;
|
|
12
12
|
onFirstSubscribe?: StoreEvent<T>;
|
|
13
13
|
onSubscribe?: StoreEvent<T>;
|
|
14
14
|
onUnsubscribe?: StoreEvent<T>;
|
|
15
15
|
onLastUnsubscribe?: StoreEvent<T>;
|
|
16
16
|
};
|
|
17
|
-
export
|
|
17
|
+
export type InitStoreReturn<T> = {
|
|
18
18
|
get: () => T;
|
|
19
19
|
set: (value: SetStoreData<T>, silent?: boolean) => void;
|
|
20
20
|
subscribe: (fn: (state: T) => void, selectDeps?: SelectDeps<T>) => () => void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { InitStoreOptions } from '../vanilla';
|
|
2
|
-
export
|
|
2
|
+
export type MutationState<TVar, TResponse = any, TError = unknown> = {
|
|
3
3
|
/**
|
|
4
4
|
* Network fetching status.
|
|
5
5
|
*/
|
|
@@ -19,7 +19,7 @@ export declare type MutationState<TVar, TResponse = any, TError = unknown> = {
|
|
|
19
19
|
variables?: TVar;
|
|
20
20
|
}>;
|
|
21
21
|
};
|
|
22
|
-
export
|
|
22
|
+
export type CreateMutationOptions<TVar, TResponse = any, TError = unknown> = InitStoreOptions<MutationState<TVar, TResponse, TError>> & {
|
|
23
23
|
onMutate?: (variables: TVar | undefined, stateBeforeMutate: MutationState<TVar, TResponse, TError>) => void;
|
|
24
24
|
onSuccess?: (response: TResponse, variables: TVar | undefined, stateBeforeMutate: MutationState<TVar, TResponse, TError>) => void;
|
|
25
25
|
onError?: (error: TError, variables: TVar | undefined, stateBeforeMutate: MutationState<TVar, TResponse, TError>) => void;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CreateStoresOptions, StoreKey } from './create-stores';
|
|
2
|
-
export
|
|
3
|
-
export
|
|
2
|
+
export type QueryStatus = 'loading' | 'success' | 'error';
|
|
3
|
+
export type QueryState<TKey extends StoreKey = StoreKey, TResponse = any, TData = TResponse, TError = unknown> = {
|
|
4
4
|
/**
|
|
5
5
|
* Query store key, an object that will be hashed into a string as a query store identifier.
|
|
6
6
|
*/
|
|
@@ -95,7 +95,7 @@ export declare type QueryState<TKey extends StoreKey = StoreKey, TResponse = any
|
|
|
95
95
|
pageParams: any[];
|
|
96
96
|
hasNextPage: boolean;
|
|
97
97
|
};
|
|
98
|
-
export
|
|
98
|
+
export type CreateQueryOptions<TKey extends StoreKey = StoreKey, TResponse = any, TData = TResponse, TError = unknown> = CreateStoresOptions<TKey, QueryState<TKey, TResponse, TData, TError>> & {
|
|
99
99
|
select?: (response: TResponse, state: Pick<QueryState<TKey, TResponse, TData, TError>, 'data' | 'key'>) => TData;
|
|
100
100
|
/**
|
|
101
101
|
* Stale time in miliseconds.
|
|
@@ -108,7 +108,7 @@ export declare type CreateQueryOptions<TKey extends StoreKey = StoreKey, TRespon
|
|
|
108
108
|
*
|
|
109
109
|
* Defaults to `1`.
|
|
110
110
|
*/
|
|
111
|
-
|
|
111
|
+
maxRetryCount?: number | ((error: TError, key: TKey) => number);
|
|
112
112
|
/**
|
|
113
113
|
* Auto call the query when the component is mounted.
|
|
114
114
|
*
|
|
@@ -40,7 +40,7 @@ const useQueryDefaultDeps = (state) => [
|
|
|
40
40
|
state.hasNextPage,
|
|
41
41
|
];
|
|
42
42
|
const createQuery = (queryFn, options = {}) => {
|
|
43
|
-
const { onFirstSubscribe = utils_1.noop, onSubscribe = utils_1.noop, onLastUnsubscribe = utils_1.noop, onBeforeChangeKey = utils_1.noop, defaultDeps = useQueryDefaultDeps, select = utils_1.identityFn, staleTime = DEFAULT_STALE_TIME,
|
|
43
|
+
const { onFirstSubscribe = utils_1.noop, onSubscribe = utils_1.noop, onLastUnsubscribe = utils_1.noop, onBeforeChangeKey = utils_1.noop, defaultDeps = useQueryDefaultDeps, select = utils_1.identityFn, staleTime = DEFAULT_STALE_TIME, maxRetryCount = 1, fetchOnMount = true, fetchOnWindowFocus = true, enabled = true, keepPreviousData, getNextPageParam = () => undefined, onSuccess = utils_1.noop, onError = utils_1.noop, onSettled = utils_1.noop, ...createStoresOptions } = options;
|
|
44
44
|
const useQuery = (0, create_stores_1.createStores)(({ key: _key, get, set }) => {
|
|
45
45
|
const key = _key;
|
|
46
46
|
const forceFetch = () => {
|
|
@@ -81,8 +81,8 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
81
81
|
isRefetching: false,
|
|
82
82
|
isRefetchError: false,
|
|
83
83
|
isPreviousData: false,
|
|
84
|
-
data: responseAllPages.reduce((prev,
|
|
85
|
-
return select(
|
|
84
|
+
data: responseAllPages.reduce((prev, responseCurrentPage) => {
|
|
85
|
+
return select(responseCurrentPage, { key, data: prev });
|
|
86
86
|
}, null),
|
|
87
87
|
response,
|
|
88
88
|
responseUpdatedAt: Date.now(),
|
|
@@ -119,7 +119,8 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
119
119
|
pageParam,
|
|
120
120
|
hasNextPage: pageParam !== undefined,
|
|
121
121
|
});
|
|
122
|
-
|
|
122
|
+
const retryCount = typeof maxRetryCount === 'function' ? maxRetryCount(error, key) : maxRetryCount;
|
|
123
|
+
if (typeof retryCount === 'number' && prevState.retryCount < retryCount) {
|
|
123
124
|
set({ retryCount: prevState.retryCount + 1, isGoingToRetry: true });
|
|
124
125
|
callQuery();
|
|
125
126
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { InitStoreOptions, SelectDeps, SetStoreData, StoreData, StoreInitializer, Subscribers } from '../vanilla';
|
|
2
|
-
export
|
|
2
|
+
export type WatchProps<T> = {
|
|
3
3
|
selectDeps?: SelectDeps<T>;
|
|
4
4
|
render: (state: T) => any;
|
|
5
5
|
};
|
|
6
|
-
export
|
|
6
|
+
export type UseStore<T extends StoreData> = {
|
|
7
7
|
/**
|
|
8
8
|
* @param selectDeps A function that return the dependency array (just like in `useEffect`), to trigger reactivity.
|
|
9
9
|
* Defaults to `undefined` (reactive to all state change) if you didn't set `defaultDeps` on `createStore`.
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { InitStoreOptions, SelectDeps, SetStoreData, StoreData, Subscribers } from '../vanilla';
|
|
2
2
|
import { WatchProps } from './create-store';
|
|
3
|
-
export
|
|
4
|
-
export
|
|
3
|
+
export type StoreKey = Record<string, any> | undefined;
|
|
4
|
+
export type StoresInitializer<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = (api: {
|
|
5
5
|
key: TKey;
|
|
6
6
|
get: () => T;
|
|
7
7
|
set: (value: SetStoreData<T>, silent?: boolean) => void;
|
|
8
8
|
}) => T;
|
|
9
|
-
export
|
|
9
|
+
export type UseStores<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = {
|
|
10
10
|
/**
|
|
11
11
|
* @param key (Optional) Store key, an object that will be hashed into a string as a store identifier.
|
|
12
12
|
*
|
|
@@ -27,7 +27,7 @@ export declare type UseStores<TKey extends StoreKey = StoreKey, T extends StoreD
|
|
|
27
27
|
storeKey?: TKey;
|
|
28
28
|
}) => any;
|
|
29
29
|
};
|
|
30
|
-
export
|
|
30
|
+
export type CreateStoresOptions<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = InitStoreOptions<T> & {
|
|
31
31
|
onBeforeChangeKey?: (nextKey: TKey, prevKey: TKey) => void;
|
|
32
32
|
defaultDeps?: SelectDeps<T>;
|
|
33
33
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ReactNode } from 'react';
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
2
|
export declare const withContext: <T>(initFn: () => T) => readonly [({ children, onInitialize, }: {
|
|
3
3
|
children: ReactNode;
|
|
4
4
|
onInitialize?: ((value: T) => void) | undefined;
|
|
5
|
-
}) => JSX.Element, () => T | null];
|
|
5
|
+
}) => React.JSX.Element, () => T | null];
|
package/lib/vanilla.d.ts
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export
|
|
5
|
-
export
|
|
1
|
+
export type StoreData = Record<string, any>;
|
|
2
|
+
export type SetStoreData<T> = Partial<T> | ((prevState: T) => Partial<T>);
|
|
3
|
+
export type SelectDeps<T> = ((state: T) => any[]) | undefined;
|
|
4
|
+
export type Subscribers<T> = Map<(state: T) => void, SelectDeps<T>>;
|
|
5
|
+
export type StoreInitializer<T> = (api: {
|
|
6
6
|
get: () => T;
|
|
7
7
|
set: (value: SetStoreData<T>, silent?: boolean) => void;
|
|
8
8
|
}) => T;
|
|
9
|
-
export
|
|
10
|
-
export
|
|
9
|
+
export type StoreEvent<T> = (state: T) => void;
|
|
10
|
+
export type InitStoreOptions<T> = {
|
|
11
11
|
intercept?: (nextState: T, prevState: T) => Partial<T>;
|
|
12
12
|
onFirstSubscribe?: StoreEvent<T>;
|
|
13
13
|
onSubscribe?: StoreEvent<T>;
|
|
14
14
|
onUnsubscribe?: StoreEvent<T>;
|
|
15
15
|
onLastUnsubscribe?: StoreEvent<T>;
|
|
16
16
|
};
|
|
17
|
-
export
|
|
17
|
+
export type InitStoreReturn<T> = {
|
|
18
18
|
get: () => T;
|
|
19
19
|
set: (value: SetStoreData<T>, silent?: boolean) => void;
|
|
20
20
|
subscribe: (fn: (state: T) => void, selectDeps?: SelectDeps<T>) => () => void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "floppy-disk",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.0-beta.1",
|
|
4
4
|
"description": "FloppyDisk - lightweight, simple, and powerful state management library",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"state",
|
|
@@ -48,26 +48,30 @@
|
|
|
48
48
|
"semantic-release": "semantic-release"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
+
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
|
51
52
|
"@commitlint/cli": "^17.7.1",
|
|
52
53
|
"@commitlint/config-conventional": "^17.7.0",
|
|
54
|
+
"@testing-library/react-hooks": "^8.0.1",
|
|
53
55
|
"@types/jest": "^29.5.3",
|
|
54
|
-
"@types/react": "^18.
|
|
55
|
-
"@types/react-dom": "^18.
|
|
56
|
+
"@types/react": "^18.2.20",
|
|
57
|
+
"@types/react-dom": "^18.2.7",
|
|
56
58
|
"eslint": "^8.47.0",
|
|
57
59
|
"eslint-config-prettier": "^9.0.0",
|
|
58
60
|
"eslint-config-react-app": "^7.0.1",
|
|
59
61
|
"eslint-plugin-simple-import-sort": "^10.0.0",
|
|
60
|
-
"husky": "^8.0.
|
|
62
|
+
"husky": "^8.0.3",
|
|
61
63
|
"jest": "^29.6.2",
|
|
64
|
+
"jest-environment-jsdom": "^29.6.2",
|
|
62
65
|
"lint-staged": "^14.0.0",
|
|
63
|
-
"prettier": "^
|
|
64
|
-
"react": "^18.
|
|
65
|
-
"react-dom": "^18.
|
|
66
|
-
"
|
|
67
|
-
"
|
|
66
|
+
"prettier": "^3.0.2",
|
|
67
|
+
"react": "^18.2.0",
|
|
68
|
+
"react-dom": "^18.2.0",
|
|
69
|
+
"react-test-renderer": "^18.2.0",
|
|
70
|
+
"rimraf": "^5.0.1",
|
|
71
|
+
"semantic-release": "^21.0.9",
|
|
68
72
|
"ts-jest": "^29.1.1",
|
|
69
73
|
"ts-node": "^10.9.1",
|
|
70
|
-
"typescript": "^
|
|
74
|
+
"typescript": "^5.1.6"
|
|
71
75
|
},
|
|
72
76
|
"peerDependencies": {
|
|
73
77
|
"react": "^17.0.0 || ^18.0.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { initStore } from '../vanilla';
|
|
2
|
-
describe('initStore', () => {
|
|
3
|
-
const initialData = {
|
|
4
|
-
counter: 0,
|
|
5
|
-
text: 'initial text',
|
|
6
|
-
};
|
|
7
|
-
const onFirstSubscribeMock = jest.fn();
|
|
8
|
-
const onSubscribeMock = jest.fn();
|
|
9
|
-
const onUnsubscribeMock = jest.fn();
|
|
10
|
-
const onLastUnsubscribeMock = jest.fn();
|
|
11
|
-
const mockStoreInitializer = jest.fn(() => initialData);
|
|
12
|
-
const options = {
|
|
13
|
-
onFirstSubscribe: onFirstSubscribeMock,
|
|
14
|
-
onSubscribe: onSubscribeMock,
|
|
15
|
-
onUnsubscribe: onUnsubscribeMock,
|
|
16
|
-
onLastUnsubscribe: onLastUnsubscribeMock,
|
|
17
|
-
};
|
|
18
|
-
let store;
|
|
19
|
-
beforeEach(() => {
|
|
20
|
-
store = initStore(mockStoreInitializer, options);
|
|
21
|
-
});
|
|
22
|
-
afterEach(() => {
|
|
23
|
-
onFirstSubscribeMock.mockClear();
|
|
24
|
-
onSubscribeMock.mockClear();
|
|
25
|
-
onUnsubscribeMock.mockClear();
|
|
26
|
-
onLastUnsubscribeMock.mockClear();
|
|
27
|
-
});
|
|
28
|
-
it('should initialize the store with initial data', () => {
|
|
29
|
-
expect(store.get()).toEqual(initialData);
|
|
30
|
-
});
|
|
31
|
-
it('should call onFirstSubscribe & onSubscribe when subscriber is added', () => {
|
|
32
|
-
const subscriber1 = jest.fn();
|
|
33
|
-
const subscriber2 = jest.fn();
|
|
34
|
-
store.subscribe(subscriber1);
|
|
35
|
-
expect(onFirstSubscribeMock).toHaveBeenCalledWith(initialData);
|
|
36
|
-
expect(onSubscribeMock).toHaveBeenCalledWith(initialData);
|
|
37
|
-
store.subscribe(subscriber2);
|
|
38
|
-
expect(onFirstSubscribeMock).toHaveBeenCalledTimes(1);
|
|
39
|
-
expect(onSubscribeMock).toHaveBeenCalledWith(initialData);
|
|
40
|
-
});
|
|
41
|
-
it('should call onUnsubscribe & onLastUnsubscribe when subscriber is removed', () => {
|
|
42
|
-
const subscriber1 = jest.fn();
|
|
43
|
-
const subscriber2 = jest.fn();
|
|
44
|
-
const unsub1 = store.subscribe(subscriber1);
|
|
45
|
-
const unsub2 = store.subscribe(subscriber2);
|
|
46
|
-
unsub1();
|
|
47
|
-
expect(onUnsubscribeMock).toHaveBeenCalledWith(initialData);
|
|
48
|
-
expect(onLastUnsubscribeMock).not.toHaveBeenCalled();
|
|
49
|
-
unsub2();
|
|
50
|
-
expect(onUnsubscribeMock).toHaveBeenCalledWith(initialData);
|
|
51
|
-
expect(onLastUnsubscribeMock).toHaveBeenCalledTimes(1);
|
|
52
|
-
});
|
|
53
|
-
it('should update the store data when set is called with partial data', () => {
|
|
54
|
-
store.set({ counter: 1 });
|
|
55
|
-
expect(store.get().counter).toEqual(1);
|
|
56
|
-
expect(store.get().text).toEqual(initialData.text);
|
|
57
|
-
});
|
|
58
|
-
it('should call subscribers when set is called', () => {
|
|
59
|
-
const subscriber1 = jest.fn();
|
|
60
|
-
const subscriber2 = jest.fn();
|
|
61
|
-
store.subscribe(subscriber1);
|
|
62
|
-
store.subscribe(subscriber2);
|
|
63
|
-
store.set({ counter: 2 });
|
|
64
|
-
expect(subscriber1).toHaveBeenCalledWith(store.get());
|
|
65
|
-
expect(subscriber2).toHaveBeenCalledWith(store.get());
|
|
66
|
-
});
|
|
67
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const vanilla_1 = require("../vanilla");
|
|
4
|
-
describe('initStore', () => {
|
|
5
|
-
const initialData = {
|
|
6
|
-
counter: 0,
|
|
7
|
-
text: 'initial text',
|
|
8
|
-
};
|
|
9
|
-
const onFirstSubscribeMock = jest.fn();
|
|
10
|
-
const onSubscribeMock = jest.fn();
|
|
11
|
-
const onUnsubscribeMock = jest.fn();
|
|
12
|
-
const onLastUnsubscribeMock = jest.fn();
|
|
13
|
-
const mockStoreInitializer = jest.fn(() => initialData);
|
|
14
|
-
const options = {
|
|
15
|
-
onFirstSubscribe: onFirstSubscribeMock,
|
|
16
|
-
onSubscribe: onSubscribeMock,
|
|
17
|
-
onUnsubscribe: onUnsubscribeMock,
|
|
18
|
-
onLastUnsubscribe: onLastUnsubscribeMock,
|
|
19
|
-
};
|
|
20
|
-
let store;
|
|
21
|
-
beforeEach(() => {
|
|
22
|
-
store = (0, vanilla_1.initStore)(mockStoreInitializer, options);
|
|
23
|
-
});
|
|
24
|
-
afterEach(() => {
|
|
25
|
-
onFirstSubscribeMock.mockClear();
|
|
26
|
-
onSubscribeMock.mockClear();
|
|
27
|
-
onUnsubscribeMock.mockClear();
|
|
28
|
-
onLastUnsubscribeMock.mockClear();
|
|
29
|
-
});
|
|
30
|
-
it('should initialize the store with initial data', () => {
|
|
31
|
-
expect(store.get()).toEqual(initialData);
|
|
32
|
-
});
|
|
33
|
-
it('should call onFirstSubscribe & onSubscribe when subscriber is added', () => {
|
|
34
|
-
const subscriber1 = jest.fn();
|
|
35
|
-
const subscriber2 = jest.fn();
|
|
36
|
-
store.subscribe(subscriber1);
|
|
37
|
-
expect(onFirstSubscribeMock).toHaveBeenCalledWith(initialData);
|
|
38
|
-
expect(onSubscribeMock).toHaveBeenCalledWith(initialData);
|
|
39
|
-
store.subscribe(subscriber2);
|
|
40
|
-
expect(onFirstSubscribeMock).toHaveBeenCalledTimes(1);
|
|
41
|
-
expect(onSubscribeMock).toHaveBeenCalledWith(initialData);
|
|
42
|
-
});
|
|
43
|
-
it('should call onUnsubscribe & onLastUnsubscribe when subscriber is removed', () => {
|
|
44
|
-
const subscriber1 = jest.fn();
|
|
45
|
-
const subscriber2 = jest.fn();
|
|
46
|
-
const unsub1 = store.subscribe(subscriber1);
|
|
47
|
-
const unsub2 = store.subscribe(subscriber2);
|
|
48
|
-
unsub1();
|
|
49
|
-
expect(onUnsubscribeMock).toHaveBeenCalledWith(initialData);
|
|
50
|
-
expect(onLastUnsubscribeMock).not.toHaveBeenCalled();
|
|
51
|
-
unsub2();
|
|
52
|
-
expect(onUnsubscribeMock).toHaveBeenCalledWith(initialData);
|
|
53
|
-
expect(onLastUnsubscribeMock).toHaveBeenCalledTimes(1);
|
|
54
|
-
});
|
|
55
|
-
it('should update the store data when set is called with partial data', () => {
|
|
56
|
-
store.set({ counter: 1 });
|
|
57
|
-
expect(store.get().counter).toEqual(1);
|
|
58
|
-
expect(store.get().text).toEqual(initialData.text);
|
|
59
|
-
});
|
|
60
|
-
it('should call subscribers when set is called', () => {
|
|
61
|
-
const subscriber1 = jest.fn();
|
|
62
|
-
const subscriber2 = jest.fn();
|
|
63
|
-
store.subscribe(subscriber1);
|
|
64
|
-
store.subscribe(subscriber2);
|
|
65
|
-
store.set({ counter: 2 });
|
|
66
|
-
expect(subscriber1).toHaveBeenCalledWith(store.get());
|
|
67
|
-
expect(subscriber2).toHaveBeenCalledWith(store.get());
|
|
68
|
-
});
|
|
69
|
-
});
|