@chhsiao1981/use-thunk 12.0.0 → 13.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.
- package/README.md +143 -80
- package/package.json +10 -16
- package/src/action/ActionOrThunk.ts +1 -1
- package/src/action/index.ts +3 -3
- package/src/action/thunk.ts +6 -2
- package/src/defaultThunks/index.ts +15 -0
- package/src/defaultThunks/init/index.ts +27 -0
- package/src/{init → defaultThunks/init}/initCore.ts +2 -2
- package/src/{remove.ts → defaultThunks/remove.ts} +2 -2
- package/src/{setDefaultID.ts → defaultThunks/setDefaultID.ts} +4 -3
- package/src/{update.ts → defaultThunks/update.ts} +2 -2
- package/src/defaultThunks/upsert.ts +27 -0
- package/src/dispatch.ts +7 -0
- package/src/get.ts +3 -2
- package/src/index.ts +43 -27
- package/src/reducer/createReducer.ts +18 -0
- package/src/reducer/defaultReduceMap.ts +26 -0
- package/src/{reducer.ts → reducer/index.ts} +5 -2
- package/src/reducer/reduceMap.ts +6 -0
- package/src/{createThunk.ts → registerThunk.ts} +9 -4
- package/src/set/index.ts +9 -0
- package/src/{setMap.ts → set/setMap.ts} +12 -18
- package/src/states/index.ts +84 -0
- package/src/{stateTypes.ts → states/types.ts} +6 -5
- package/src/thunkContext/index.ts +9 -0
- package/src/{thunkContextMap.ts → thunkContext/thunkContextMap.ts} +2 -2
- package/src/{thunkContextTypes.ts → thunkContext/types.ts} +1 -1
- package/src/thunkModule/defaultDoModule.ts +13 -0
- package/src/thunkModule/index.ts +11 -10
- package/src/{useThunk.ts → useThunk/index.ts} +6 -8
- package/src/{useThunkReducer.ts → useThunk/useThunkReducer.ts} +41 -11
- package/src/utils/deepCopy.ts +30 -0
- package/src/utils/genID.ts +6 -0
- package/src/utils/index.ts +3 -0
- package/types/action/ActionOrThunk.d.ts +1 -1
- package/types/action/index.d.ts +2 -2
- package/types/action/thunk.d.ts +4 -2
- package/types/defaultThunks/index.d.ts +10 -0
- package/types/defaultThunks/init/index.d.ts +9 -0
- package/types/{init → defaultThunks/init}/initCore.d.ts +2 -2
- package/types/{remove.d.ts → defaultThunks/remove.d.ts} +2 -2
- package/types/{setDefaultID.d.ts → defaultThunks/setDefaultID.d.ts} +2 -2
- package/types/{update.d.ts → defaultThunks/update.d.ts} +2 -2
- package/types/defaultThunks/upsert.d.ts +5 -0
- package/types/dispatch.d.ts +4 -4
- package/types/get.d.ts +3 -2
- package/types/index.d.ts +11 -15
- package/types/reducer/createReducer.d.ts +3 -0
- package/types/reducer/defaultReduceMap.d.ts +2 -0
- package/types/{reducer.d.ts → reducer/index.d.ts} +4 -2
- package/types/reducer/reduceMap.d.ts +5 -0
- package/types/{createThunk.d.ts → registerThunk.d.ts} +1 -1
- package/types/set/index.d.ts +5 -0
- package/types/set/setMap.d.ts +16 -0
- package/types/states/index.d.ts +10 -0
- package/types/{stateTypes.d.ts → states/types.d.ts} +5 -4
- package/types/thunkContext/index.d.ts +6 -0
- package/types/{thunkContextMap.d.ts → thunkContext/thunkContextMap.d.ts} +2 -2
- package/types/{thunkContextTypes.d.ts → thunkContext/types.d.ts} +1 -1
- package/types/thunkModule/defaultDoModule.d.ts +5 -0
- package/types/thunkModule/index.d.ts +7 -9
- package/types/useThunk/index.d.ts +9 -0
- package/types/{useThunkReducer.d.ts → useThunk/useThunkReducer.d.ts} +3 -3
- package/types/utils/deepCopy.d.ts +2 -0
- package/types/utils/genID.d.ts +1 -0
- package/types/utils/index.d.ts +3 -0
- package/src/createReducer.ts +0 -24
- package/src/genUUID.ts +0 -38
- package/src/init/index.ts +0 -26
- package/src/reduceMap.ts +0 -22
- package/src/set.ts +0 -7
- package/src/states.ts +0 -50
- package/src/thunkModule/defaultThunkModuleFuncMap.ts +0 -15
- package/types/createReducer.d.ts +0 -4
- package/types/dispatchFuncMap.d.ts +0 -17
- package/types/genUUID.d.ts +0 -1
- package/types/init/index.d.ts +0 -7
- package/types/reduceMap.d.ts +0 -6
- package/types/set.d.ts +0 -4
- package/types/setMap.d.ts +0 -17
- package/types/states.d.ts +0 -9
- package/types/thunkModule/defaultThunkModuleFuncMap.d.ts +0 -5
- package/types/useThunk.d.ts +0 -9
- /package/src/{ThunkContext.tsx → thunkContext/ThunkContext.tsx} +0 -0
- /package/types/{ThunkContext.d.ts → thunkContext/ThunkContext.d.ts} +0 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import {
|
|
2
|
+
INIT,
|
|
3
|
+
REMOVE,
|
|
4
|
+
reduceInit,
|
|
5
|
+
reduceRemove,
|
|
6
|
+
reduceSetDefaultID,
|
|
7
|
+
reduceUpdate,
|
|
8
|
+
reduceUpsert,
|
|
9
|
+
SET_DEFAULT_ID,
|
|
10
|
+
UPDATE,
|
|
11
|
+
UPSERT,
|
|
12
|
+
} from '../defaultThunks'
|
|
13
|
+
import type { ReduceMap } from './reduceMap'
|
|
14
|
+
|
|
15
|
+
// biome-ignore lint/suspicious/noExplicitAny: DEFAULT_REDUCE_MAP can apply to any States.
|
|
16
|
+
export const DEFAULT_REDUCE_MAP: ReduceMap<any> = {
|
|
17
|
+
[INIT]: reduceInit,
|
|
18
|
+
[UPDATE]: reduceUpdate,
|
|
19
|
+
[REMOVE]: reduceRemove,
|
|
20
|
+
[UPSERT]: reduceUpsert,
|
|
21
|
+
|
|
22
|
+
// setDefaultID.
|
|
23
|
+
// Typically we don't need this in programming.
|
|
24
|
+
// The defaultID is automatically determined if defaultID is not set.
|
|
25
|
+
[SET_DEFAULT_ID]: reduceSetDefaultID,
|
|
26
|
+
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type { Reducer as rReducer } from 'react'
|
|
2
|
-
import type BaseAction from '
|
|
3
|
-
import type { ModuleState, State } from '
|
|
2
|
+
import type { BaseAction } from '../action'
|
|
3
|
+
import type { ModuleState, State } from '../states'
|
|
4
|
+
|
|
5
|
+
import { createReducer } from './createReducer'
|
|
6
|
+
export { createReducer }
|
|
4
7
|
|
|
5
8
|
// Reducer
|
|
6
9
|
export type Reducer<S extends State> = rReducer<ModuleState<S>, BaseAction>
|
|
@@ -1,13 +1,18 @@
|
|
|
1
|
+
// Reason for registerThunk instead of createThunk:
|
|
2
|
+
// I feel that createThunk needs to return some object
|
|
3
|
+
// as the proof of successful creation.
|
|
4
|
+
// However, we register Thunks to the global state management
|
|
5
|
+
// system and return void.
|
|
1
6
|
import { createContext, type Dispatch, type SetStateAction } from 'react'
|
|
2
|
-
import type { ModuleState, State } from './
|
|
3
|
-
import { THUNK_CONTEXT_MAP } from './
|
|
7
|
+
import type { ModuleState, State } from './states'
|
|
8
|
+
import { THUNK_CONTEXT_MAP } from './thunkContext'
|
|
4
9
|
import type { ThunkModule } from './thunkModule'
|
|
5
10
|
|
|
6
11
|
export default <S extends State>(theDo: ThunkModule<S>) => {
|
|
7
12
|
const { name, defaultState } = theDo
|
|
8
13
|
|
|
9
14
|
if (THUNK_CONTEXT_MAP.theMap[name]) {
|
|
10
|
-
console.warn('
|
|
15
|
+
console.warn('registerThunk: already init:', name)
|
|
11
16
|
return
|
|
12
17
|
}
|
|
13
18
|
|
|
@@ -20,5 +25,5 @@ export default <S extends State>(theDo: ThunkModule<S>) => {
|
|
|
20
25
|
const theList = Object.keys(THUNK_CONTEXT_MAP.theMap).sort()
|
|
21
26
|
THUNK_CONTEXT_MAP.theList = theList
|
|
22
27
|
|
|
23
|
-
console.info('
|
|
28
|
+
console.info('registerThunk: done:', name)
|
|
24
29
|
}
|
package/src/set/index.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// XXX requiring to import directly from action/ActionOrThunk, or it will cause looping.
|
|
2
|
+
import type { ActionOrThunk } from '../action'
|
|
3
|
+
import type { State } from '../states'
|
|
4
|
+
|
|
5
|
+
import { constructSetMap, type DefaultSetMap, type setMap, type setMapByModuleMap } from './setMap'
|
|
6
|
+
export { constructSetMap, type DefaultSetMap, type setMap, type setMapByModuleMap }
|
|
7
|
+
|
|
8
|
+
// set
|
|
9
|
+
export type set<S extends State> = (actionOrID: ActionOrThunk<S> | string, data?: Partial<S>) => void
|
|
@@ -1,31 +1,25 @@
|
|
|
1
|
-
import type { ActionFunc } from '
|
|
2
|
-
import type { set } from '
|
|
3
|
-
import type { State } from '
|
|
4
|
-
import type {
|
|
5
|
-
import {
|
|
6
|
-
DEFAULT_THUNK_MODULE_FUNC_MAP,
|
|
7
|
-
type DefaultThunkModuleFuncMap,
|
|
8
|
-
} from './thunkModule/defaultThunkModuleFuncMap'
|
|
1
|
+
import type { ActionFunc } from '../action'
|
|
2
|
+
import type { set } from '../set'
|
|
3
|
+
import type { State } from '../states'
|
|
4
|
+
import type { doModule, ThunkModule } from '../thunkModule'
|
|
5
|
+
import { DEFAULT_DO_MODULE, type defaultDoModule } from '../thunkModule'
|
|
9
6
|
|
|
10
7
|
// biome-ignore lint/suspicious/noExplicitAny: unknown requires same type in list, use any for possible different types.
|
|
11
8
|
type VoidReturnType<T extends (...params: any[]) => unknown> = (...params: Parameters<T>) => void
|
|
12
9
|
|
|
13
|
-
export type setMap<S extends State, T extends
|
|
10
|
+
export type setMap<S extends State, T extends doModule<S>> = {
|
|
14
11
|
[action in keyof T]: VoidReturnType<T[action]>
|
|
15
12
|
} & Omit<DefaultSetMap, keyof T>
|
|
16
13
|
|
|
17
14
|
export type DefaultSetMap = {
|
|
18
|
-
[action in keyof
|
|
15
|
+
[action in keyof defaultDoModule]: VoidReturnType<defaultDoModule[action]>
|
|
19
16
|
}
|
|
20
17
|
|
|
21
|
-
export interface setMapByModuleMap<S extends State, T extends
|
|
22
|
-
[
|
|
18
|
+
export interface setMapByModuleMap<S extends State, T extends doModule<S>> {
|
|
19
|
+
[moduleMap: string]: setMap<S, T>
|
|
23
20
|
}
|
|
24
21
|
|
|
25
|
-
|
|
26
|
-
export const SET_MAP_BY_MODULE_MAP: setMapByModuleMap<any, any> = {}
|
|
27
|
-
|
|
28
|
-
export const constructSetMap = <S extends State, T extends ThunkModuleFunc<S>>(
|
|
22
|
+
export const constructSetMap = <S extends State, T extends doModule<S>>(
|
|
29
23
|
theDo: ThunkModule<S>,
|
|
30
24
|
set: set<S>,
|
|
31
25
|
setMap: setMap<S, T>,
|
|
@@ -48,12 +42,12 @@ export const constructSetMap = <S extends State, T extends ThunkModuleFunc<S>>(
|
|
|
48
42
|
return val
|
|
49
43
|
}, setMap)
|
|
50
44
|
|
|
51
|
-
Object.keys(
|
|
45
|
+
Object.keys(DEFAULT_DO_MODULE).reduce((val, eachAction) => {
|
|
52
46
|
if (val[eachAction]) {
|
|
53
47
|
return val
|
|
54
48
|
}
|
|
55
49
|
|
|
56
|
-
const action =
|
|
50
|
+
const action = DEFAULT_DO_MODULE[eachAction]
|
|
57
51
|
|
|
58
52
|
// @ts-expect-error eachAction is in setMap<S, R>
|
|
59
53
|
// biome-ignore lint/suspicious/noExplicitAny: action parameters can be any types.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { setMap } from '../set'
|
|
2
|
+
import type { doModule } from '../thunkModule'
|
|
3
|
+
import type { UseThunk } from '../useThunk'
|
|
4
|
+
import { deepCopy } from '../utils'
|
|
5
|
+
import type { ModuleState, NodeState, NodeStateMap, State } from './types'
|
|
6
|
+
|
|
7
|
+
export type { ModuleState, NodeState, State, NodeStateMap }
|
|
8
|
+
|
|
9
|
+
export const getDefaultID = <S extends State>(moduleState: ModuleState<S>): string => {
|
|
10
|
+
return moduleState.defaultID ?? ''
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const getNodeOrNull = <S extends State>(
|
|
14
|
+
moduleState: ModuleState<S>,
|
|
15
|
+
myID?: string,
|
|
16
|
+
): Readonly<NodeState<S> | null> => {
|
|
17
|
+
const theID = myID ? myID : getDefaultID(moduleState)
|
|
18
|
+
if (!theID) {
|
|
19
|
+
return null
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return moduleState.nodes[theID] || null
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const getStateOrNullByModule = <S extends State>(
|
|
26
|
+
moduleState: ModuleState<S>,
|
|
27
|
+
myID?: string,
|
|
28
|
+
): Readonly<S | null> => {
|
|
29
|
+
const theID = myID ? myID : getDefaultID(moduleState)
|
|
30
|
+
if (!theID) {
|
|
31
|
+
return null
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const me = moduleState.nodes[theID]
|
|
35
|
+
if (!me) {
|
|
36
|
+
return null
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return me.state
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const getStateByModule = <S extends State>(
|
|
43
|
+
moduleState: ModuleState<S>,
|
|
44
|
+
myID?: string,
|
|
45
|
+
): Readonly<S> => {
|
|
46
|
+
const theID = myID ? myID : getDefaultID(moduleState)
|
|
47
|
+
if (!theID) {
|
|
48
|
+
return moduleState.defaultState
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const state = getStateOrNullByModule(moduleState, theID)
|
|
52
|
+
if (state) {
|
|
53
|
+
return state
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// XXX magic for new nodes
|
|
57
|
+
// 1. reduceInit
|
|
58
|
+
const newState = deepCopy(moduleState.defaultState)
|
|
59
|
+
const newNode = { id: theID, state: newState }
|
|
60
|
+
moduleState.nodes[theID] = newNode
|
|
61
|
+
|
|
62
|
+
// 2. already init default-id, no need to init default-id here.
|
|
63
|
+
if (moduleState.isInitDefaultID) {
|
|
64
|
+
return newState
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// 3. check defaultID
|
|
68
|
+
if (!moduleState.defaultID) {
|
|
69
|
+
moduleState.defaultID = theID
|
|
70
|
+
moduleState.isInitDefaultID = true
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return newState
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export const getState = <S extends State, R extends doModule<S>>(
|
|
77
|
+
theUseThunk: UseThunk<S, R>,
|
|
78
|
+
myID?: string,
|
|
79
|
+
): [Readonly<S>, setMap<S, R>, string] => {
|
|
80
|
+
const [moduleState, theDo] = theUseThunk
|
|
81
|
+
const theID = myID ? myID : getDefaultID(moduleState)
|
|
82
|
+
const state = getStateByModule(moduleState, theID)
|
|
83
|
+
return [state, theDo, theID]
|
|
84
|
+
}
|
|
@@ -9,14 +9,15 @@ export type NodeState<S extends State> = {
|
|
|
9
9
|
state: S
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
export type NodeStateMap<S extends State> = {
|
|
13
|
-
[key: string]: NodeState<S>
|
|
14
|
-
}
|
|
15
|
-
|
|
16
12
|
// ModuleState
|
|
17
13
|
export type ModuleState<S extends State> = {
|
|
18
14
|
name: string
|
|
19
|
-
defaultID?: string | null
|
|
20
15
|
nodes: NodeStateMap<S>
|
|
21
16
|
defaultState: S
|
|
17
|
+
defaultID?: string | null
|
|
18
|
+
isInitDefaultID?: boolean
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type NodeStateMap<S extends State> = {
|
|
22
|
+
[key: string]: NodeState<S>
|
|
22
23
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Context } from './types'
|
|
2
|
+
export type { Context }
|
|
3
|
+
|
|
4
|
+
// THUNK_CONTEXT_MAP is used in registerThunk and useThunkReducer
|
|
5
|
+
import { THUNK_CONTEXT_MAP, type ThunkContextMap } from './thunkContextMap'
|
|
6
|
+
export { THUNK_CONTEXT_MAP, type ThunkContextMap }
|
|
7
|
+
|
|
8
|
+
import ThunkContext from './ThunkContext'
|
|
9
|
+
export { ThunkContext }
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Context as rContext } from 'react'
|
|
2
|
-
import type { ModuleState } from '
|
|
3
|
-
import type { Context } from './
|
|
2
|
+
import type { ModuleState } from '../states'
|
|
3
|
+
import type { Context } from './types'
|
|
4
4
|
|
|
5
5
|
export type ThunkContextMap = {
|
|
6
6
|
theMap: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Dispatch, SetStateAction } from 'react'
|
|
2
|
-
import type { ModuleState, State } from '
|
|
2
|
+
import type { ModuleState, State } from '../states'
|
|
3
3
|
|
|
4
4
|
export type Context<S extends State> = {
|
|
5
5
|
// INFO: we use refModuleState to reference across all the useThunk of the same module in different ops.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ActionFunc } from '../action'
|
|
2
|
+
import { init, remove, update } from '../defaultThunks'
|
|
3
|
+
|
|
4
|
+
export const DEFAULT_DO_MODULE: defaultDoModule = {
|
|
5
|
+
init,
|
|
6
|
+
update,
|
|
7
|
+
remove,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type defaultDoModule = {
|
|
11
|
+
// biome-ignore lint/suspicious/noExplicitAny: defaultDoModule can be any type.
|
|
12
|
+
[action: string]: ActionFunc<any>
|
|
13
|
+
}
|
package/src/thunkModule/index.ts
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import type { ThunkFunc } from '../action'
|
|
2
|
-
import type {
|
|
3
|
-
import type
|
|
2
|
+
import type { State } from '../states'
|
|
3
|
+
import { DEFAULT_DO_MODULE, type defaultDoModule } from './defaultDoModule'
|
|
4
|
+
export { DEFAULT_DO_MODULE, type defaultDoModule }
|
|
4
5
|
|
|
5
|
-
export interface
|
|
6
|
-
[idx: string]: ThunkFunc<S> | string | Reducer<S> | S | undefined
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export interface ThunkModuleFunc<S extends State> extends ThunkModuleBase<S> {
|
|
6
|
+
export interface doModule<S extends State> {
|
|
10
7
|
[action: string]: ThunkFunc<S>
|
|
11
8
|
}
|
|
12
9
|
|
|
13
10
|
// This is used as the parameter for useThunk.
|
|
14
11
|
export type ThunkModule<S extends State> = {
|
|
15
12
|
name: string
|
|
16
|
-
default?: Reducer<S>
|
|
17
13
|
defaultState: S
|
|
18
|
-
} & ThunkModuleBase<S>
|
|
19
14
|
|
|
20
|
-
|
|
15
|
+
// The rest of the variables are doModule.
|
|
16
|
+
// Specifying index-signatures to include all the variables.
|
|
17
|
+
[action: string]: ThunkFunc<S> | string | S
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// biome-ignore lint/suspicious/noExplicitAny: ok for type utility functions.
|
|
21
|
+
export type toDoModule<T extends ThunkModule<any>> = Omit<T, 'name' | 'default' | 'defaultState'>
|
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
import { useMemo } from 'react'
|
|
2
|
-
import { createReducer } from '
|
|
3
|
-
import { constructSetMap, type setMap, type setMapByModuleMap } from '
|
|
4
|
-
import type { ModuleState, State } from '
|
|
5
|
-
import type {
|
|
2
|
+
import { createReducer } from '../reducer'
|
|
3
|
+
import { constructSetMap, type setMap, type setMapByModuleMap } from '../set'
|
|
4
|
+
import type { ModuleState, State } from '../states'
|
|
5
|
+
import type { doModule, ThunkModule } from '../thunkModule'
|
|
6
6
|
import useThunkReducer from './useThunkReducer'
|
|
7
7
|
|
|
8
8
|
// biome-ignore lint/suspicious/noExplicitAny: SET_MAP_BY_MODULE can by any type
|
|
9
9
|
const SET_MAP_BY_MODULE: setMapByModuleMap<any, any> = {}
|
|
10
10
|
|
|
11
|
-
export type UseThunk<S extends State, R extends
|
|
11
|
+
export type UseThunk<S extends State, R extends doModule<S>> = [Readonly<ModuleState<S>>, setMap<S, R>]
|
|
12
12
|
|
|
13
13
|
/**********
|
|
14
14
|
* useThunk
|
|
15
15
|
**********/
|
|
16
|
-
export default <S extends State, R extends
|
|
17
|
-
theDo: ThunkModule<S>,
|
|
18
|
-
): UseThunk<S, R> => {
|
|
16
|
+
export default <S extends State, R extends doModule<S>>(theDo: ThunkModule<S>): UseThunk<S, R> => {
|
|
19
17
|
const { name } = theDo
|
|
20
18
|
|
|
21
19
|
// 1. It requires shared nodes for the same module to have the same setMap.
|
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
//https://github.com/nathanbuchar/react-hook-thunk-reducer/blob/master/src/thunk-reducer.js
|
|
3
3
|
|
|
4
4
|
import { useCallback, useContext } from 'react'
|
|
5
|
-
import type BaseAction from '
|
|
6
|
-
import
|
|
7
|
-
import type {
|
|
8
|
-
import {
|
|
9
|
-
import type {
|
|
10
|
-
import {
|
|
5
|
+
import type { BaseAction } from '../action'
|
|
6
|
+
import { upsert } from '../defaultThunks/upsert'
|
|
7
|
+
import type { dispatch } from '../dispatch'
|
|
8
|
+
import type { get, getOrNull } from '../get'
|
|
9
|
+
import type { Reducer } from '../reducer'
|
|
10
|
+
import type { set } from '../set'
|
|
11
|
+
import { getStateByModule, getStateOrNullByModule, type ModuleState, type State } from '../states'
|
|
12
|
+
import { THUNK_CONTEXT_MAP } from '../thunkContext'
|
|
11
13
|
|
|
12
14
|
/**
|
|
13
15
|
* useThunkReducer
|
|
@@ -31,7 +33,7 @@ export default <S extends State>(reducer: Reducer<S>, moduleName: string): [Modu
|
|
|
31
33
|
[refModuleState, setModuleState_c],
|
|
32
34
|
)
|
|
33
35
|
|
|
34
|
-
const
|
|
36
|
+
const getOrNull: getOrNull<S> = useCallback(
|
|
35
37
|
(id?: string) => {
|
|
36
38
|
const moduleState = getModuleState()
|
|
37
39
|
const state = getStateOrNullByModule(moduleState, id)
|
|
@@ -40,7 +42,15 @@ export default <S extends State>(reducer: Reducer<S>, moduleName: string): [Modu
|
|
|
40
42
|
[getModuleState],
|
|
41
43
|
)
|
|
42
44
|
|
|
43
|
-
|
|
45
|
+
const get: get<S> = useCallback(
|
|
46
|
+
(id?: string) => {
|
|
47
|
+
const moduleState = getModuleState()
|
|
48
|
+
const state = getStateByModule(moduleState, id)
|
|
49
|
+
return state
|
|
50
|
+
},
|
|
51
|
+
[getModuleState],
|
|
52
|
+
)
|
|
53
|
+
|
|
44
54
|
const reduce = useCallback(
|
|
45
55
|
(action: BaseAction): ModuleState<S> => {
|
|
46
56
|
const moduleState = getModuleState()
|
|
@@ -50,12 +60,11 @@ export default <S extends State>(reducer: Reducer<S>, moduleName: string): [Modu
|
|
|
50
60
|
[reducer, getModuleState],
|
|
51
61
|
)
|
|
52
62
|
|
|
53
|
-
|
|
54
|
-
const set: set<S> = useCallback(
|
|
63
|
+
const dispatch: dispatch<S> = useCallback(
|
|
55
64
|
(action) => {
|
|
56
65
|
if (typeof action === 'function') {
|
|
57
66
|
// action is Thunk<S, A>
|
|
58
|
-
action(set, get, getModuleState)
|
|
67
|
+
action(set, get, getOrNull, dispatch, getModuleState)
|
|
59
68
|
return
|
|
60
69
|
}
|
|
61
70
|
|
|
@@ -66,5 +75,26 @@ export default <S extends State>(reducer: Reducer<S>, moduleName: string): [Modu
|
|
|
66
75
|
[getModuleState, setModuleState, reduce],
|
|
67
76
|
)
|
|
68
77
|
|
|
78
|
+
const set: set<S> = useCallback(
|
|
79
|
+
(actionOrID, data) => {
|
|
80
|
+
if (typeof actionOrID === 'string') {
|
|
81
|
+
// actionOrID is id
|
|
82
|
+
if (!data) {
|
|
83
|
+
return
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// we have the data, we can do upsert.
|
|
87
|
+
const action = upsert(actionOrID, data)
|
|
88
|
+
const newModuleState = reduce(action)
|
|
89
|
+
setModuleState(newModuleState)
|
|
90
|
+
return
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// actionOrID is action
|
|
94
|
+
dispatch(actionOrID)
|
|
95
|
+
},
|
|
96
|
+
[getModuleState, setModuleState, reduce],
|
|
97
|
+
)
|
|
98
|
+
|
|
69
99
|
return [refModuleState.current, set]
|
|
70
100
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// biome-ignore lint/suspicious/noExplicitAny: obj in deepCopy can be any type.
|
|
2
|
+
const deepCopy = (obj: any): any => {
|
|
3
|
+
// Handle primitives, functions, null, or undefined
|
|
4
|
+
if (obj === null || typeof obj !== 'object') {
|
|
5
|
+
return obj
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
// Handle Date objects
|
|
9
|
+
if (obj instanceof Date) {
|
|
10
|
+
return new Date(obj.getTime())
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Handle Arrays
|
|
14
|
+
if (Array.isArray(obj)) {
|
|
15
|
+
return obj.map((item) => deepCopy(item))
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Handle Objects
|
|
19
|
+
// biome-ignore lint/suspicious/noExplicitAny: clonedObj can be any type.
|
|
20
|
+
const clonedObj: any = {}
|
|
21
|
+
for (const key in obj) {
|
|
22
|
+
if (obj.hasOwnProperty(key)) {
|
|
23
|
+
clonedObj[key] = deepCopy(obj[key])
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return clonedObj
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export default deepCopy
|
package/types/action/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { ModuleState, State } from '../
|
|
1
|
+
import type { ModuleState, State } from '../states';
|
|
2
2
|
import type { ActionOrThunk } from './ActionOrThunk';
|
|
3
3
|
import type BaseAction from './baseAction';
|
|
4
4
|
import type { Thunk } from './thunk';
|
|
5
5
|
export type { Thunk, ActionOrThunk, BaseAction };
|
|
6
6
|
export type ActionFunc<S extends State> = (...params: any[]) => ActionOrThunk<S>;
|
|
7
7
|
export type ThunkFunc<S extends State> = (...params: any[]) => Thunk<S>;
|
|
8
|
-
export type
|
|
8
|
+
export type getModuleState<S extends State> = () => ModuleState<S>;
|
package/types/action/thunk.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { dispatch } from '../dispatch';
|
|
2
|
+
import type { get, getOrNull } from '../get';
|
|
1
3
|
import type { set } from '../set';
|
|
2
|
-
import type { ModuleState, State } from '../
|
|
3
|
-
export type Thunk<S extends State> = (set: set<S>, get:
|
|
4
|
+
import type { ModuleState, State } from '../states';
|
|
5
|
+
export type Thunk<S extends State> = (set: set<S>, get: get<S>, getOrNull: getOrNull<S>, dispatch: dispatch<S>, getModuleState: () => ModuleState<S>) => void;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { INIT, type InitParams, init, reduceInit } from './init';
|
|
2
|
+
export { INIT, type InitParams, init, reduceInit };
|
|
3
|
+
import { reduceUpdate, UPDATE, update } from './update';
|
|
4
|
+
export { reduceUpdate, UPDATE, update };
|
|
5
|
+
import { REMOVE, reduceRemove, remove } from './remove';
|
|
6
|
+
export { REMOVE, reduceRemove, remove };
|
|
7
|
+
import { reduceUpsert, UPSERT, upsert } from './upsert';
|
|
8
|
+
export { UPSERT, upsert, reduceUpsert };
|
|
9
|
+
import { reduceSetDefaultID, SET_DEFAULT_ID, setDefaultID } from './setDefaultID';
|
|
10
|
+
export { SET_DEFAULT_ID, setDefaultID, reduceSetDefaultID };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Thunk } from '../../action';
|
|
2
|
+
import type { State } from '../../states';
|
|
3
|
+
import { INIT, reduceInit } from './initCore';
|
|
4
|
+
export { INIT, reduceInit };
|
|
5
|
+
export interface InitParams<S extends State> {
|
|
6
|
+
myID?: string;
|
|
7
|
+
state: S;
|
|
8
|
+
}
|
|
9
|
+
export declare const init: <S extends State>(params: InitParams<S>) => Thunk<S>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type BaseAction from '
|
|
2
|
-
import type { ModuleState, State } from '
|
|
1
|
+
import type { BaseAction } from '../../action';
|
|
2
|
+
import type { ModuleState, State } from '../../states';
|
|
3
3
|
export interface InitAction<S extends State> extends BaseAction {
|
|
4
4
|
state: S;
|
|
5
5
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type BaseAction from '
|
|
2
|
-
import type { ModuleState, State } from '
|
|
1
|
+
import type { BaseAction } from '../action';
|
|
2
|
+
import type { ModuleState, State } from '../states';
|
|
3
3
|
export declare const REMOVE = "@chhsiao1981/use-thunk/REMOVE";
|
|
4
4
|
export declare const remove: (myID: string) => BaseAction;
|
|
5
5
|
export declare const reduceRemove: <S extends State>(moduleState: ModuleState<S>, action: BaseAction) => ModuleState<S>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type BaseAction from '
|
|
2
|
-
import type { ModuleState, State } from '
|
|
1
|
+
import type { BaseAction } from '../action';
|
|
2
|
+
import type { ModuleState, State } from '../states';
|
|
3
3
|
export declare const SET_DEFAULT_ID = "@chhsiao1981/use-thunk/SET_DEFAULT_ID";
|
|
4
4
|
export declare const setDefaultID: (myID: string) => BaseAction;
|
|
5
5
|
export declare const reduceSetDefaultID: <S extends State>(moduleState: ModuleState<S>, action: BaseAction) => ModuleState<S>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type BaseAction from '
|
|
2
|
-
import type { ModuleState, State } from '
|
|
1
|
+
import type { BaseAction } from '../action';
|
|
2
|
+
import type { ModuleState, State } from '../states';
|
|
3
3
|
export declare const UPDATE = "@chhsiao1981/use-thunk/UPDATE";
|
|
4
4
|
export declare const update: <S extends State>(myID: string, data: Partial<S>) => BaseAction;
|
|
5
5
|
export declare const reduceUpdate: <S extends State>(moduleState: ModuleState<S>, action: BaseAction) => ModuleState<S>;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { BaseAction } from '../action';
|
|
2
|
+
import type { ModuleState, State } from '../states';
|
|
3
|
+
export declare const UPSERT = "@chhsiao1981/use-thunk/UPSERT";
|
|
4
|
+
export declare const upsert: <S extends State>(myID: string, data: Partial<S>) => BaseAction;
|
|
5
|
+
export declare const reduceUpsert: <S extends State>(moduleState: ModuleState<S>, action: BaseAction) => ModuleState<S>;
|
package/types/dispatch.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Dispatch
|
|
2
|
-
import type { ActionOrThunk } from './action
|
|
3
|
-
import type { State } from './
|
|
4
|
-
export type
|
|
1
|
+
import type { Dispatch } from 'react';
|
|
2
|
+
import type { ActionOrThunk } from './action';
|
|
3
|
+
import type { State } from './states';
|
|
4
|
+
export type dispatch<S extends State> = Dispatch<ActionOrThunk<S>>;
|
package/types/get.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import type { State } from './
|
|
2
|
-
export type get
|
|
1
|
+
import type { State } from './states';
|
|
2
|
+
export type get<S extends State> = (id?: string) => S;
|
|
3
|
+
export type getOrNull<S extends State> = (id?: string) => S | null | undefined;
|
package/types/index.d.ts
CHANGED
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import type { get } from './get';
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
import type
|
|
8
|
-
import {
|
|
9
|
-
import type {
|
|
10
|
-
import { getDefaultID, getNode, getState, getStateByModule, getStateOrNullByModule } from './states';
|
|
11
|
-
import type { ModuleState, State } from './stateTypes';
|
|
12
|
-
import ThunkContext from './ThunkContext';
|
|
13
|
-
import type { ThunkModule, ThunkModuleToFunc } from './thunkModule';
|
|
14
|
-
import { update } from './update';
|
|
1
|
+
import type { getModuleState, Thunk, ThunkFunc } from './action';
|
|
2
|
+
import { type InitParams, init, remove, setDefaultID, update, upsert } from './defaultThunks';
|
|
3
|
+
import type { dispatch } from './dispatch';
|
|
4
|
+
import type { get, getOrNull } from './get';
|
|
5
|
+
import registerThunk from './registerThunk';
|
|
6
|
+
import type { set, setMap } from './set';
|
|
7
|
+
import { getDefaultID, getNodeOrNull, getState, getStateByModule, getStateOrNullByModule, type ModuleState, type State } from './states';
|
|
8
|
+
import { ThunkContext } from './thunkContext';
|
|
9
|
+
import type { doModule, ThunkModule, toDoModule } from './thunkModule';
|
|
15
10
|
import useThunk, { type UseThunk } from './useThunk';
|
|
16
|
-
|
|
11
|
+
import { genID } from './utils';
|
|
12
|
+
export { type Thunk, type set, type get, type getOrNull, type dispatch, type getModuleState, registerThunk, useThunk, type UseThunk, ThunkContext, type State, getState, type ModuleState, type ThunkModule, type toDoModule, type doModule, type ThunkFunc, init, type InitParams, update, upsert, remove, genID, type setMap, setDefaultID, getNodeOrNull, getDefaultID, getStateOrNullByModule, getStateByModule, };
|