generated from garronej/ts-ci
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathcreateCore.ts
110 lines (94 loc) · 3.41 KB
/
createCore.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import { Evt } from "evt";
import type { ReturnType } from "tsafe";
import { assert } from "tsafe/assert";
import { createStore, type GenericStore, type UsecaseLike as UsecaseLike_store } from "./createStore";
import {
usecasesToEvts,
type CoreEvts,
type GenericCreateEvt,
type UsecaseLike as UsecaseLike_evts
} from "./usecasesToEvts";
import {
usecasesToStates,
type CoreStates,
type UsecaseLike as UsecaseLike_selectors
} from "./usecasesToStates";
import {
usecasesToFunctions,
CoreFunctions,
type UsecaseLike as UsecaseLike_functions
} from "./usecasesToFunctions";
import type { ThunkAction, Action } from "@reduxjs/toolkit";
type UsecaseLike = UsecaseLike_store & UsecaseLike_evts & UsecaseLike_selectors & UsecaseLike_functions;
export type GenericCore<
Usecases extends Record<string, UsecaseLike>,
Context extends Record<string, unknown>
> = {
states: CoreStates<Usecases[keyof Usecases]>;
subscribe: (listener: () => void) => { unsubscribe: () => void };
evts: CoreEvts<Usecases[keyof Usecases]>;
functions: CoreFunctions<Usecases[keyof Usecases]>;
types: {
State: ReturnType<GenericStore<Context, Usecases[keyof Usecases]>["getState"]>;
CreateEvt: GenericCreateEvt<GenericStore<Context, Usecases[keyof Usecases]>>;
Thunks: Record<
string,
(params: any) => ThunkAction<
any,
ReturnType<GenericStore<Context, Usecases[keyof Usecases]>["getState"]>,
Context & {
evtAction: GenericStore<Context, Usecases[keyof Usecases]>["evtAction"];
},
Action<string>
>
>;
};
};
export function createCore<
Usecases extends Record<string, UsecaseLike>,
Context extends Record<string, unknown>
>(params: {
context: Context;
usecases: Usecases;
}): {
core: GenericCore<Usecases, Context>;
dispatch: GenericStore<Context, Usecases[keyof Usecases]>["dispatch"];
getState: GenericStore<Context, Usecases[keyof Usecases]>["getState"];
evtAction: GenericStore<Context, Usecases[keyof Usecases]>["evtAction"];
} {
const { context, usecases } = params;
Object.entries(usecases).forEach(([key, usecase]) => {
assert(
key === usecase.name,
`You should reconcile the name of the usecase (${usecase.name}) and the key it's assigned to in the usecases object (${key})`
);
});
const usecasesArr = Object.values(usecases) as Usecases[keyof Usecases][];
const store = createStore({ context, usecasesArr });
const { states } = usecasesToStates({ usecasesArr, store });
const { evts } = usecasesToEvts({ usecasesArr, store });
const { functions } = usecasesToFunctions({ usecasesArr, store });
const evtStateUpdated = store.evtAction.pipe(() => [undefined]);
evtStateUpdated.setMaxHandlers(Infinity);
const core: GenericCore<Usecases, Context> = {
"subscribe": listener => {
const ctx = Evt.newCtx();
evtStateUpdated.attach(ctx, () => listener());
return {
"unsubscribe": () => ctx.done()
};
},
states,
evts,
functions,
types: null as any
};
//@ts-expect-error
delete core.types;
return {
core,
"dispatch": store.dispatch,
"getState": store.getState,
"evtAction": store.evtAction
};
}