Skip to content

Commit 9d09d0b

Browse files
committed
refactor(api): load emhttp state during init
so emhttp settings are always available, even at module load time.
1 parent 7ac731e commit 9d09d0b

File tree

1 file changed

+105
-104
lines changed

1 file changed

+105
-104
lines changed

api/src/store/modules/emhttp.ts

Lines changed: 105 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,33 @@
1-
import { FileLoadStatus, StateFileKey, type StateFileToIniParserMap } from '@app/store/types';
2-
import { createAsyncThunk, createSlice, type PayloadAction } from '@reduxjs/toolkit';
3-
import merge from 'lodash/merge';
41
import { join } from 'path';
2+
3+
import type { PayloadAction } from '@reduxjs/toolkit';
4+
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
5+
import merge from 'lodash/merge';
6+
7+
import type { RootState } from '@app/store';
8+
import type { StateFileToIniParserMap } from '@app/store/types';
59
import { emhttpLogger } from '@app/core/log';
6-
import { parseConfig } from '@app/core/utils/misc/parse-config';
710
import { type Devices } from '@app/core/types/states/devices';
811
import { type Networks } from '@app/core/types/states/network';
12+
import { type NfsShares } from '@app/core/types/states/nfs';
913
import { type Nginx } from '@app/core/types/states/nginx';
1014
import { type Shares } from '@app/core/types/states/share';
11-
import { type Users } from '@app/core/types/states/user';
12-
import { type NfsShares } from '@app/core/types/states/nfs';
1315
import { type SmbShares } from '@app/core/types/states/smb';
16+
import { type Users } from '@app/core/types/states/user';
1417
import { type Var } from '@app/core/types/states/var';
18+
import { parseConfig } from '@app/core/utils/misc/parse-config';
19+
import { type ArrayDisk } from '@app/graphql/generated/api/types';
1520
import { parse as parseDevices } from '@app/store/state-parsers/devices';
1621
import { parse as parseNetwork } from '@app/store/state-parsers/network';
17-
import { parse as parseNginx } from '@app/store/state-parsers/nginx';
1822
import { parse as parseNfsShares } from '@app/store/state-parsers/nfs';
23+
import { parse as parseNginx } from '@app/store/state-parsers/nginx';
1924
import { parse as parseShares } from '@app/store/state-parsers/shares';
2025
import { parse as parseSlots } from '@app/store/state-parsers/slots';
2126
import { parse as parseSmbShares } from '@app/store/state-parsers/smb';
2227
import { parse as parseUsers } from '@app/store/state-parsers/users';
2328
import { parse as parseVar } from '@app/store/state-parsers/var';
24-
import type { RootState } from '@app/store';
25-
import { type ArrayDisk } from '@app/graphql/generated/api/types';
29+
import { FileLoadStatus, StateFileKey } from '@app/store/types';
30+
import { paths } from './paths';
2631

2732
export type SliceState = {
2833
status: FileLoadStatus;
@@ -37,19 +42,6 @@ export type SliceState = {
3742
nfsShares: NfsShares;
3843
};
3944

40-
const initialState: SliceState = {
41-
status: FileLoadStatus.UNLOADED,
42-
var: {} as unknown as Var,
43-
devices: [],
44-
networks: [],
45-
nginx: {} as unknown as Nginx,
46-
shares: [],
47-
disks: [],
48-
users: [],
49-
smbShares: [],
50-
nfsShares: [],
51-
};
52-
5345
export const parsers: StateFileToIniParserMap = {
5446
[StateFileKey.var]: parseVar,
5547
[StateFileKey.devs]: parseDevices,
@@ -62,14 +54,11 @@ export const parsers: StateFileToIniParserMap = {
6254
[StateFileKey.sec_nfs]: parseNfsShares,
6355
};
6456

65-
const getParserFunction = (
66-
parser: StateFileKey
67-
): StateFileToIniParserMap[StateFileKey] => parsers[parser];
6857

69-
const parseState = <
70-
T extends StateFileKey,
71-
Q = ReturnType<StateFileToIniParserMap[T]> | null
72-
>(
58+
const getParserFunction = (parser: StateFileKey): StateFileToIniParserMap[StateFileKey] =>
59+
parsers[parser];
60+
61+
const parseState = <T extends StateFileKey, Q = ReturnType<StateFileToIniParserMap[T]> | null>(
7362
statesDirectory: string,
7463
parser: T,
7564
defaultValue?: NonNullable<Q>
@@ -100,42 +89,60 @@ const parseState = <
10089
return null as Q;
10190
};
10291

103-
// @TODO Fix the type here Pick<SliceState, 'var' | 'devices' | 'networks' | 'nginx' | 'shares' | 'disks' | 'users' | 'smbShares' | 'nfsShares'> | null
104-
export const loadSingleStateFile = createAsyncThunk<
105-
any,
106-
StateFileKey,
107-
{ state: RootState }
108-
>('emhttp/load-single-state-file', async (stateFileKey, { getState }) => {
109-
const path = getState().paths.states;
92+
function loadState(path: string) {
93+
return {
94+
var: parseState(path, StateFileKey.var, {} as Var),
95+
devices: parseState(path, StateFileKey.devs, []),
96+
networks: parseState(path, StateFileKey.network, []),
97+
nginx: parseState(path, StateFileKey.nginx, {} as Nginx),
98+
shares: parseState(path, StateFileKey.shares, []),
99+
disks: parseState(path, StateFileKey.disks, []),
100+
users: parseState(path, StateFileKey.users, []),
101+
smbShares: parseState(path, StateFileKey.sec, []),
102+
nfsShares: parseState(path, StateFileKey.sec_nfs, []),
103+
} as Omit<SliceState, 'mode' | 'status'>;
104+
}
105+
106+
const initialState: SliceState = {
107+
status: FileLoadStatus.UNLOADED,
108+
...loadState(paths.getInitialState().states)
109+
};
110110

111-
const config = parseState(path, stateFileKey);
112-
if (config) {
113-
switch (stateFileKey) {
114-
case StateFileKey.var:
115-
return { var: config };
116-
case StateFileKey.devs:
117-
return { devices: config };
118-
case StateFileKey.network:
119-
return { networks: config };
120-
case StateFileKey.nginx:
121-
return { nginx: config };
122-
case StateFileKey.shares:
123-
return { shares: config };
124-
case StateFileKey.disks:
125-
return { disks: config };
126-
case StateFileKey.users:
127-
return { users: config };
128-
case StateFileKey.sec:
129-
return { smbShares: config };
130-
case StateFileKey.sec_nfs:
131-
return { nfsShares: config };
132-
default:
133-
return null;
111+
// @TODO Fix the type here Pick<SliceState, 'var' | 'devices' | 'networks' | 'nginx' | 'shares' | 'disks' | 'users' | 'smbShares' | 'nfsShares'> | null
112+
export const loadSingleStateFile = createAsyncThunk<any, StateFileKey, { state: RootState }>(
113+
'emhttp/load-single-state-file',
114+
async (stateFileKey, { getState }) => {
115+
const path = getState().paths.states;
116+
117+
const config = parseState(path, stateFileKey);
118+
if (config) {
119+
switch (stateFileKey) {
120+
case StateFileKey.var:
121+
return { var: config };
122+
case StateFileKey.devs:
123+
return { devices: config };
124+
case StateFileKey.network:
125+
return { networks: config };
126+
case StateFileKey.nginx:
127+
return { nginx: config };
128+
case StateFileKey.shares:
129+
return { shares: config };
130+
case StateFileKey.disks:
131+
return { disks: config };
132+
case StateFileKey.users:
133+
return { users: config };
134+
case StateFileKey.sec:
135+
return { smbShares: config };
136+
case StateFileKey.sec_nfs:
137+
return { nfsShares: config };
138+
default:
139+
return null;
140+
}
141+
} else {
142+
return null;
134143
}
135-
} else {
136-
return null;
137144
}
138-
});
145+
);
139146
/**
140147
* Load the emhttp states into the store.
141148
*/
@@ -145,53 +152,47 @@ export const loadStateFiles = createAsyncThunk<
145152
{ state: RootState }
146153
>('emhttp/load-state-file', async (_, { getState }) => {
147154
const path = getState().paths.states;
148-
const state: Omit<SliceState, 'mode' | 'status'> = {
149-
var: parseState(path, StateFileKey.var, {} as Var),
150-
devices: parseState(path, StateFileKey.devs, []),
151-
networks: parseState(path, StateFileKey.network, []),
152-
nginx: parseState(path, StateFileKey.nginx, {} as Nginx),
153-
shares: parseState(path, StateFileKey.shares, []),
154-
disks: parseState(path, StateFileKey.disks, []),
155-
users: parseState(path, StateFileKey.users, []),
156-
smbShares: parseState(path, StateFileKey.sec, []),
157-
nfsShares: parseState(path, StateFileKey.sec_nfs, []),
158-
};
159-
160-
return state;
155+
return loadState(path);
161156
});
162157

163158
export const emhttp = createSlice({
164-
name: 'emhttp',
165-
initialState,
166-
reducers: {
167-
updateEmhttpState(state, action: PayloadAction<{ field: StateFileKey; state: Partial<typeof initialState[keyof typeof initialState]> }>) {
168-
const { field } = action.payload;
169-
return merge(state, { [field]: action.payload.state });
170-
},
171-
},
172-
extraReducers(builder) {
173-
builder.addCase(loadStateFiles.pending, (state) => {
174-
state.status = FileLoadStatus.LOADING;
175-
});
176-
177-
builder.addCase(loadStateFiles.fulfilled, (state, action) => {
178-
merge(state, action.payload, { status: FileLoadStatus.LOADED });
179-
});
180-
181-
builder.addCase(loadStateFiles.rejected, (state, action) => {
182-
merge(state, action.payload, { status: FileLoadStatus.FAILED_LOADING });
183-
});
184-
185-
builder.addCase(loadSingleStateFile.fulfilled, (state, action) => {
186-
if (action.payload) {
159+
name: 'emhttp',
160+
initialState,
161+
reducers: {
162+
updateEmhttpState(
163+
state,
164+
action: PayloadAction<{
165+
field: StateFileKey;
166+
state: Partial<(typeof initialState)[keyof typeof initialState]>;
167+
}>
168+
) {
169+
const { field } = action.payload;
170+
return merge(state, { [field]: action.payload.state });
171+
},
172+
},
173+
extraReducers(builder) {
174+
builder.addCase(loadStateFiles.pending, (state) => {
175+
state.status = FileLoadStatus.LOADING;
176+
});
177+
178+
builder.addCase(loadStateFiles.fulfilled, (state, action) => {
179+
merge(state, action.payload, { status: FileLoadStatus.LOADED });
180+
});
181+
182+
builder.addCase(loadStateFiles.rejected, (state, action) => {
183+
merge(state, action.payload, { status: FileLoadStatus.FAILED_LOADING });
184+
});
185+
186+
builder.addCase(loadSingleStateFile.fulfilled, (state, action) => {
187+
if (action.payload) {
187188
// const changedKey = Object.keys(action.payload)[0]
188189
// emhttpLogger.debug('Key', changedKey, 'Difference in changes', getDiff(action.payload, { [changedKey]: state[changedKey] } ))
189-
merge(state, action.payload);
190-
} else {
191-
emhttpLogger.warn('Invalid payload returned from loadSingleStateFile()');
192-
}
193-
});
194-
},
190+
merge(state, action.payload);
191+
} else {
192+
emhttpLogger.warn('Invalid payload returned from loadSingleStateFile()');
193+
}
194+
});
195+
},
195196
});
196197

197198
export const { updateEmhttpState } = emhttp.actions;

0 commit comments

Comments
 (0)