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' ;
41import { 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' ;
59import { emhttpLogger } from '@app/core/log' ;
6- import { parseConfig } from '@app/core/utils/misc/parse-config' ;
710import { type Devices } from '@app/core/types/states/devices' ;
811import { type Networks } from '@app/core/types/states/network' ;
12+ import { type NfsShares } from '@app/core/types/states/nfs' ;
913import { type Nginx } from '@app/core/types/states/nginx' ;
1014import { 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' ;
1315import { type SmbShares } from '@app/core/types/states/smb' ;
16+ import { type Users } from '@app/core/types/states/user' ;
1417import { 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' ;
1520import { parse as parseDevices } from '@app/store/state-parsers/devices' ;
1621import { parse as parseNetwork } from '@app/store/state-parsers/network' ;
17- import { parse as parseNginx } from '@app/store/state-parsers/nginx' ;
1822import { parse as parseNfsShares } from '@app/store/state-parsers/nfs' ;
23+ import { parse as parseNginx } from '@app/store/state-parsers/nginx' ;
1924import { parse as parseShares } from '@app/store/state-parsers/shares' ;
2025import { parse as parseSlots } from '@app/store/state-parsers/slots' ;
2126import { parse as parseSmbShares } from '@app/store/state-parsers/smb' ;
2227import { parse as parseUsers } from '@app/store/state-parsers/users' ;
2328import { 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
2732export 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-
5345export 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
163158export 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
197198export const { updateEmhttpState } = emhttp . actions ;
0 commit comments