/
index.ts
83 lines (68 loc) · 2.2 KB
/
index.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
import { createStore, combineReducers, Store } from "redux"
import { reducer } from "./reducer"
import { ActionsUnion, ISetLogs, IGatsbyCLIState } from "./types"
import { isInternalAction } from "./utils"
import { createStructuredLoggingDiagnosticsMiddleware } from "./diagnostics"
import { Actions } from "../constants"
let store: Store<{ logs: IGatsbyCLIState }> = createStore(
combineReducers({
logs: reducer,
}),
{}
)
const diagnosticsMiddleware =
createStructuredLoggingDiagnosticsMiddleware(store)
export type GatsbyCLIStore = typeof store
type StoreListener = (store: GatsbyCLIStore) => void
type ActionLogListener = (action: ActionsUnion) => any
type Thunk = (...args: Array<any>) => ActionsUnion
const storeSwapListeners: Array<StoreListener> = []
const onLogActionListeners = new Set<ActionLogListener>()
export const getStore = (): typeof store => store
export const dispatch = (action: ActionsUnion | Thunk): void => {
if (!action) {
return
}
if (Array.isArray(action)) {
action.forEach(item => dispatch(item))
return
} else if (typeof action === `function`) {
action(dispatch)
return
}
action = {
...action,
// @ts-ignore this is a typescript no-no..
// And i'm pretty sure this timestamp isn't used anywhere.
// but for now, the structured logs integration tests expect it
// so it's easier to leave it and then explore as a follow up
timestamp: new Date().toJSON(),
} as ActionsUnion
store.dispatch(action)
diagnosticsMiddleware(action)
if (isInternalAction(action)) {
// consumers (ipc, yurnalist, json logger) shouldn't have to
// deal with actions needed just for internal tracking of status
return
}
for (const fn of onLogActionListeners) {
fn(action)
}
}
export const onStoreSwap = (fn: StoreListener): void => {
storeSwapListeners.push(fn)
}
export const onLogAction = (fn: ActionLogListener): (() => void) => {
onLogActionListeners.add(fn)
return (): void => {
onLogActionListeners.delete(fn)
}
}
export const setStore = (s: GatsbyCLIStore): void => {
s.dispatch({
type: Actions.SetLogs,
payload: store.getState().logs,
} as ISetLogs)
store = s
storeSwapListeners.forEach(fn => fn(store))
}