@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.
Files changed (85) hide show
  1. package/README.md +143 -80
  2. package/package.json +10 -16
  3. package/src/action/ActionOrThunk.ts +1 -1
  4. package/src/action/index.ts +3 -3
  5. package/src/action/thunk.ts +6 -2
  6. package/src/defaultThunks/index.ts +15 -0
  7. package/src/defaultThunks/init/index.ts +27 -0
  8. package/src/{init → defaultThunks/init}/initCore.ts +2 -2
  9. package/src/{remove.ts → defaultThunks/remove.ts} +2 -2
  10. package/src/{setDefaultID.ts → defaultThunks/setDefaultID.ts} +4 -3
  11. package/src/{update.ts → defaultThunks/update.ts} +2 -2
  12. package/src/defaultThunks/upsert.ts +27 -0
  13. package/src/dispatch.ts +7 -0
  14. package/src/get.ts +3 -2
  15. package/src/index.ts +43 -27
  16. package/src/reducer/createReducer.ts +18 -0
  17. package/src/reducer/defaultReduceMap.ts +26 -0
  18. package/src/{reducer.ts → reducer/index.ts} +5 -2
  19. package/src/reducer/reduceMap.ts +6 -0
  20. package/src/{createThunk.ts → registerThunk.ts} +9 -4
  21. package/src/set/index.ts +9 -0
  22. package/src/{setMap.ts → set/setMap.ts} +12 -18
  23. package/src/states/index.ts +84 -0
  24. package/src/{stateTypes.ts → states/types.ts} +6 -5
  25. package/src/thunkContext/index.ts +9 -0
  26. package/src/{thunkContextMap.ts → thunkContext/thunkContextMap.ts} +2 -2
  27. package/src/{thunkContextTypes.ts → thunkContext/types.ts} +1 -1
  28. package/src/thunkModule/defaultDoModule.ts +13 -0
  29. package/src/thunkModule/index.ts +11 -10
  30. package/src/{useThunk.ts → useThunk/index.ts} +6 -8
  31. package/src/{useThunkReducer.ts → useThunk/useThunkReducer.ts} +41 -11
  32. package/src/utils/deepCopy.ts +30 -0
  33. package/src/utils/genID.ts +6 -0
  34. package/src/utils/index.ts +3 -0
  35. package/types/action/ActionOrThunk.d.ts +1 -1
  36. package/types/action/index.d.ts +2 -2
  37. package/types/action/thunk.d.ts +4 -2
  38. package/types/defaultThunks/index.d.ts +10 -0
  39. package/types/defaultThunks/init/index.d.ts +9 -0
  40. package/types/{init → defaultThunks/init}/initCore.d.ts +2 -2
  41. package/types/{remove.d.ts → defaultThunks/remove.d.ts} +2 -2
  42. package/types/{setDefaultID.d.ts → defaultThunks/setDefaultID.d.ts} +2 -2
  43. package/types/{update.d.ts → defaultThunks/update.d.ts} +2 -2
  44. package/types/defaultThunks/upsert.d.ts +5 -0
  45. package/types/dispatch.d.ts +4 -4
  46. package/types/get.d.ts +3 -2
  47. package/types/index.d.ts +11 -15
  48. package/types/reducer/createReducer.d.ts +3 -0
  49. package/types/reducer/defaultReduceMap.d.ts +2 -0
  50. package/types/{reducer.d.ts → reducer/index.d.ts} +4 -2
  51. package/types/reducer/reduceMap.d.ts +5 -0
  52. package/types/{createThunk.d.ts → registerThunk.d.ts} +1 -1
  53. package/types/set/index.d.ts +5 -0
  54. package/types/set/setMap.d.ts +16 -0
  55. package/types/states/index.d.ts +10 -0
  56. package/types/{stateTypes.d.ts → states/types.d.ts} +5 -4
  57. package/types/thunkContext/index.d.ts +6 -0
  58. package/types/{thunkContextMap.d.ts → thunkContext/thunkContextMap.d.ts} +2 -2
  59. package/types/{thunkContextTypes.d.ts → thunkContext/types.d.ts} +1 -1
  60. package/types/thunkModule/defaultDoModule.d.ts +5 -0
  61. package/types/thunkModule/index.d.ts +7 -9
  62. package/types/useThunk/index.d.ts +9 -0
  63. package/types/{useThunkReducer.d.ts → useThunk/useThunkReducer.d.ts} +3 -3
  64. package/types/utils/deepCopy.d.ts +2 -0
  65. package/types/utils/genID.d.ts +1 -0
  66. package/types/utils/index.d.ts +3 -0
  67. package/src/createReducer.ts +0 -24
  68. package/src/genUUID.ts +0 -38
  69. package/src/init/index.ts +0 -26
  70. package/src/reduceMap.ts +0 -22
  71. package/src/set.ts +0 -7
  72. package/src/states.ts +0 -50
  73. package/src/thunkModule/defaultThunkModuleFuncMap.ts +0 -15
  74. package/types/createReducer.d.ts +0 -4
  75. package/types/dispatchFuncMap.d.ts +0 -17
  76. package/types/genUUID.d.ts +0 -1
  77. package/types/init/index.d.ts +0 -7
  78. package/types/reduceMap.d.ts +0 -6
  79. package/types/set.d.ts +0 -4
  80. package/types/setMap.d.ts +0 -17
  81. package/types/states.d.ts +0 -9
  82. package/types/thunkModule/defaultThunkModuleFuncMap.d.ts +0 -5
  83. package/types/useThunk.d.ts +0 -9
  84. /package/src/{ThunkContext.tsx → thunkContext/ThunkContext.tsx} +0 -0
  85. /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 './action/baseAction'
3
- import type { ModuleState, State } from './stateTypes'
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>
@@ -0,0 +1,6 @@
1
+ import type { State } from '../states'
2
+ import type { ReduceFunc } from './index'
3
+
4
+ export interface ReduceMap<S extends State> {
5
+ [type: string]: ReduceFunc<S>
6
+ }
@@ -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 './stateTypes'
3
- import { THUNK_CONTEXT_MAP } from './thunkContextMap'
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('createThunk: already init:', name)
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('createThunk: done:', name)
28
+ console.info('registerThunk: done:', name)
24
29
  }
@@ -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 './action'
2
- import type { set } from './set'
3
- import type { State } from './stateTypes'
4
- import type { ThunkModule, ThunkModuleFunc } from './thunkModule'
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 ThunkModuleFunc<S>> = {
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 DefaultThunkModuleFuncMap]: VoidReturnType<DefaultThunkModuleFuncMap[action]>
15
+ [action in keyof defaultDoModule]: VoidReturnType<defaultDoModule[action]>
19
16
  }
20
17
 
21
- export interface setMapByModuleMap<S extends State, T extends ThunkModuleFunc<S>> {
22
- [name: string]: setMap<S, T>
18
+ export interface setMapByModuleMap<S extends State, T extends doModule<S>> {
19
+ [moduleMap: string]: setMap<S, T>
23
20
  }
24
21
 
25
- // biome-ignore lint/suspicious/noExplicitAny: set map by module map can be any.
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(DEFAULT_THUNK_MODULE_FUNC_MAP).reduce((val, eachAction) => {
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 = DEFAULT_THUNK_MODULE_FUNC_MAP[eachAction]
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 './stateTypes'
3
- import type { Context } from './thunkContextTypes'
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 './stateTypes'
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
+ }
@@ -1,20 +1,21 @@
1
1
  import type { ThunkFunc } from '../action'
2
- import type { Reducer } from '../reducer'
3
- import type { State } from '../stateTypes'
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 ThunkModuleBase<S extends State> {
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
- export type ThunkModuleToFunc<T> = Omit<T, 'name' | 'default' | 'defaultState'>
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 './createReducer'
3
- import { constructSetMap, type setMap, type setMapByModuleMap } from './setMap'
4
- import type { ModuleState, State } from './stateTypes'
5
- import type { ThunkModule, ThunkModuleFunc } from './thunkModule'
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 ThunkModuleFunc<S>> = [ModuleState<S>, setMap<S, R>]
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 ThunkModuleFunc<S>>(
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 './action/baseAction'
6
- import type { Reducer } from './reducer'
7
- import type { set } from './set'
8
- import { getStateOrNullByModule } from './states'
9
- import type { ModuleState, State } from './stateTypes'
10
- import { THUNK_CONTEXT_MAP } from './thunkContextMap'
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 get = useCallback(
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
- // 5. reducer.
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
- // augmented setter.
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
@@ -0,0 +1,6 @@
1
+ let _GLOBAL_ID = 1
2
+
3
+ export const genID = (): string => {
4
+ _GLOBAL_ID += 1
5
+ return `${_GLOBAL_ID}`
6
+ }
@@ -0,0 +1,3 @@
1
+ import deepCopy from './deepCopy'
2
+ import { genID } from './genID'
3
+ export { deepCopy, genID }
@@ -1,4 +1,4 @@
1
- import type { State } from '../stateTypes';
1
+ import type { State } from '../states';
2
2
  import type BaseAction from './baseAction';
3
3
  import type { Thunk } from './thunk';
4
4
  export type ActionOrThunk<S extends State> = BaseAction | Thunk<S>;
@@ -1,8 +1,8 @@
1
- import type { ModuleState, State } from '../stateTypes';
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 GetModuleState<S extends State> = () => ModuleState<S>;
8
+ export type getModuleState<S extends State> = () => ModuleState<S>;
@@ -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 '../stateTypes';
3
- export type Thunk<S extends State> = (set: set<S>, get: (id?: string) => S | null, getModuleState: () => ModuleState<S>) => void;
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 '../action/baseAction';
2
- import type { ModuleState, State } from '../stateTypes';
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 './action/baseAction';
2
- import type { ModuleState, State } from './stateTypes';
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 './action/baseAction';
2
- import type { ModuleState, State } from './stateTypes';
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 './action/baseAction';
2
- import type { ModuleState, State } from './stateTypes';
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>;
@@ -1,4 +1,4 @@
1
- import type { Dispatch as rDispatch } from 'react';
2
- import type { ActionOrThunk } from './action/ActionOrThunk';
3
- import type { State } from './stateTypes';
4
- export type Dispatch<S extends State> = rDispatch<ActionOrThunk<S>>;
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 './stateTypes';
2
- export type get = <S extends State>(id: string) => S;
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 { GetModuleState, Thunk } from './action';
2
- import createThunk from './createThunk';
3
- import { genUUID } from './genUUID';
4
- import type { get } from './get';
5
- import { type InitParams, init } from './init';
6
- import { remove } from './remove';
7
- import type { set } from './set';
8
- import { setDefaultID } from './setDefaultID';
9
- import type { setMap } from './setMap';
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
- export { createThunk, useThunk, type UseThunk, ThunkContext, type State, type ModuleState, type GetModuleState, type Thunk, type ThunkModule, type ThunkModuleToFunc, type set, type setMap, type get, getNode, getDefaultID, getStateOrNullByModule, getStateByModule, getState, init, type InitParams, update, remove, setDefaultID, genUUID, };
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, };
@@ -0,0 +1,3 @@
1
+ import type { State } from '../states';
2
+ import type { Reducer } from './index';
3
+ export declare const createReducer: <S extends State>() => Reducer<S>;
@@ -0,0 +1,2 @@
1
+ import type { ReduceMap } from './reduceMap';
2
+ export declare const DEFAULT_REDUCE_MAP: ReduceMap<any>;