@feardread/feature-factory 3.0.2 → 4.0.2
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.
- package/dist/bundle.min.js +2 -2
- package/dist/index.esm.js +3 -3
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/factory/api.js +521 -56
- package/src/factory/cache.js +479 -27
- package/src/factory/index.js +171 -100
- package/src/factory/service.js +412 -18
- package/src/factory/state.js +430 -5
- package/src/factory/thunk.js +264 -38
- package/src/factories/api.js +0 -72
- package/src/factories/api.ts +0 -72
- package/src/factories/cache.js +0 -71
- package/src/factories/cache.ts +0 -71
- package/src/factories/factory.js +0 -149
- package/src/factories/factory.ts +0 -158
- package/src/factories/service.js +0 -28
- package/src/factories/service.ts +0 -28
- package/src/factories/state.js +0 -10
- package/src/factories/state.ts +0 -10
- package/src/factories/thunk.js +0 -53
- package/src/factories/thunk.ts +0 -53
- package/src/index.ts +0 -7
- package/tsconfig.json +0 -11
package/src/factories/factory.js
DELETED
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
import { createSlice, createEntityAdapter, combineReducers } from '@reduxjs/toolkit';
|
|
2
|
-
import ThunkFactory from './thunk';
|
|
3
|
-
//import ApiFactory from './service';
|
|
4
|
-
|
|
5
|
-
export const StateFactory = (namespace) => ({
|
|
6
|
-
[namespace]: {},
|
|
7
|
-
data: [],
|
|
8
|
-
loading: false,
|
|
9
|
-
success: false,
|
|
10
|
-
error: null
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
export function FeatureFactory(entity, reducers = {}, endpoints = null) {
|
|
14
|
-
|
|
15
|
-
const factory = {
|
|
16
|
-
entity,
|
|
17
|
-
reducers,
|
|
18
|
-
//api: ApiFactory,
|
|
19
|
-
thunk: ThunkFactory,
|
|
20
|
-
state: StateFactory,
|
|
21
|
-
adapter: createEntityAdapter()
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
factory.manager = (initialReducers) => {
|
|
25
|
-
const reducers = { ...initialReducers };
|
|
26
|
-
let combinedReducer = combineReducers(reducers);
|
|
27
|
-
|
|
28
|
-
return {
|
|
29
|
-
reduce: (state, action) => combinedReducer(state, action),
|
|
30
|
-
add: (key, reducer) => {
|
|
31
|
-
if (!key || reducers[key]) return;
|
|
32
|
-
reducers[key] = reducer;
|
|
33
|
-
combinedReducer = combineReducers(reducers);
|
|
34
|
-
},
|
|
35
|
-
remove: (key) => {
|
|
36
|
-
if (!key || !reducers[key]) return;
|
|
37
|
-
delete reducers[key];
|
|
38
|
-
combinedReducer = combineReducers(reducers);
|
|
39
|
-
},
|
|
40
|
-
getReducerMap: () => reducers,
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
factory.inject = (source, dest) => {
|
|
45
|
-
for (var prop in source) {
|
|
46
|
-
if (source.hasOwnProperty(prop)) {
|
|
47
|
-
dest[prop] = source[prop];
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
return dest;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
factory.create = (options = { service: null, initialState: null }) => {
|
|
54
|
-
const { service, initialState } = options;
|
|
55
|
-
const sliceName = factory.entity;
|
|
56
|
-
const standard = {
|
|
57
|
-
fetch: factory.thunk.create(sliceName, 'all'),
|
|
58
|
-
fetchOne: factory.thunk.create(sliceName, 'one'),
|
|
59
|
-
search: factory.thunk.create(sliceName, 'search')
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const factorySlice = createSlice({
|
|
63
|
-
name: sliceName,
|
|
64
|
-
initialState: StateFactory(sliceName),
|
|
65
|
-
reducers: factory.reducers,
|
|
66
|
-
extraReducers: (builder) => {
|
|
67
|
-
Object.key(standard).forEach( key => {
|
|
68
|
-
builder
|
|
69
|
-
.addCase(standard[key].pending, (state) => {
|
|
70
|
-
state.loading = true;
|
|
71
|
-
state.error = null;
|
|
72
|
-
})
|
|
73
|
-
.addCase(standard[key].fulfilled, (state, action) => {
|
|
74
|
-
state.loading = false;
|
|
75
|
-
state.success = true;
|
|
76
|
-
state.data = action.payload;
|
|
77
|
-
state[sliceName] = action.payload[0];
|
|
78
|
-
if (act == 'fetchOne') {
|
|
79
|
-
state[sliceName] = action.payload[0];
|
|
80
|
-
}
|
|
81
|
-
})
|
|
82
|
-
.addCase(standard[key].rejected, (state, action) => {
|
|
83
|
-
state.loading = false;
|
|
84
|
-
state.success = false;
|
|
85
|
-
state.error = action.error;
|
|
86
|
-
});
|
|
87
|
-
})
|
|
88
|
-
/*
|
|
89
|
-
for (var act in standard) {
|
|
90
|
-
if (standard.hasOwnProperty(act)) {
|
|
91
|
-
builder
|
|
92
|
-
.addCase(standard[act].pending, (state) => {
|
|
93
|
-
state.loading = true;
|
|
94
|
-
state.error = null;
|
|
95
|
-
})
|
|
96
|
-
.addCase(standard[act].fulfilled, (state, action) => {
|
|
97
|
-
state.loading = false;
|
|
98
|
-
state.success = true;
|
|
99
|
-
state.data = action.payload;
|
|
100
|
-
state[sliceName] = action.payload[0];
|
|
101
|
-
if (act == 'fetchOne') {
|
|
102
|
-
state[sliceName] = action.payload[0];
|
|
103
|
-
}
|
|
104
|
-
})
|
|
105
|
-
.addCase(standard[act].rejected, (state, action) => {
|
|
106
|
-
state.loading = false;
|
|
107
|
-
state.success = false;
|
|
108
|
-
state.error = action.error;
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
*/
|
|
113
|
-
if (service) {
|
|
114
|
-
for (var key in service) {
|
|
115
|
-
if (service.hasOwnProperty(key) && !standard.hasOwnProperty(key)) {
|
|
116
|
-
builder
|
|
117
|
-
.addCase(service[key].pending, (state) => {
|
|
118
|
-
state.loading = true;
|
|
119
|
-
state.error = null;
|
|
120
|
-
})
|
|
121
|
-
.addCase(service[key].fulfilled, (state, action) => {
|
|
122
|
-
state.loading = false;
|
|
123
|
-
state.success = true;
|
|
124
|
-
state.data = action.payload;
|
|
125
|
-
console.log('action fulfilled :', state.data);
|
|
126
|
-
})
|
|
127
|
-
.addCase(service[key].rejected, (state, action) => {
|
|
128
|
-
state.loading = false;
|
|
129
|
-
state.success = false;
|
|
130
|
-
state.error = action.payload;
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
const asyncActions = factory.inject(standard, (service) ? service : {});
|
|
140
|
-
console.log('async = ', asyncActions);
|
|
141
|
-
return {
|
|
142
|
-
slice: factorySlice,
|
|
143
|
-
asyncActions
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
return factory;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
export default FeatureFactory;
|
package/src/factories/factory.ts
DELETED
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createSlice,
|
|
3
|
-
createEntityAdapter,
|
|
4
|
-
combineReducers,
|
|
5
|
-
EntityAdapter,
|
|
6
|
-
AsyncThunk,
|
|
7
|
-
Reducer,
|
|
8
|
-
AnyAction,
|
|
9
|
-
SliceCaseReducers,
|
|
10
|
-
PayloadAction,
|
|
11
|
-
} from '@reduxjs/toolkit';
|
|
12
|
-
import ThunkFactory from './thunk';
|
|
13
|
-
|
|
14
|
-
// Define the shape of your feature state
|
|
15
|
-
export interface FeatureState<T> {
|
|
16
|
-
loading: boolean;
|
|
17
|
-
success: boolean;
|
|
18
|
-
error: unknown | null;
|
|
19
|
-
data: T[];
|
|
20
|
-
[key: string]: any;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// A helper type for mapping service thunks
|
|
24
|
-
export type ServiceMap = Record<string, AsyncThunk<any, any, any>>;
|
|
25
|
-
|
|
26
|
-
// Manager API for dynamic reducer injection
|
|
27
|
-
export interface ReducerManager {
|
|
28
|
-
reduce: (state: any, action: AnyAction) => any;
|
|
29
|
-
add: (key: string, reducer: Reducer<any, AnyAction>) => void;
|
|
30
|
-
remove: (key: string) => void;
|
|
31
|
-
getReducerMap: () => Record<string, Reducer<any, AnyAction>>;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// Assume you have a StateFactory function somewhere:
|
|
35
|
-
function StateFactory<T>(name: string): FeatureState<T> {
|
|
36
|
-
return {
|
|
37
|
-
loading: false,
|
|
38
|
-
success: false,
|
|
39
|
-
error: null,
|
|
40
|
-
data: [],
|
|
41
|
-
[name]: null,
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// The main factory, now generic in T
|
|
46
|
-
export function FeatureFactory<T>(
|
|
47
|
-
entity: string,
|
|
48
|
-
reducers: SliceCaseReducers<FeatureState<T>> = {}, // → typed slices
|
|
49
|
-
endpoints: ServiceMap | null = null // → typed services
|
|
50
|
-
) {
|
|
51
|
-
const factory = {
|
|
52
|
-
entity,
|
|
53
|
-
reducers,
|
|
54
|
-
manager: ReducerManager ,
|
|
55
|
-
thunk: ThunkFactory,
|
|
56
|
-
state: StateFactory as (name: string) => FeatureState<T>,
|
|
57
|
-
adapter: createEntityAdapter<T>() as EntityAdapter<T>, // → typed adapter
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
factory.manager = (initialReducers: Record<string, Reducer<any, AnyAction>> = {}) => {
|
|
61
|
-
const reducersMap = { ...initialReducers };
|
|
62
|
-
let combined = combineReducers(reducersMap);
|
|
63
|
-
|
|
64
|
-
const manager: ReducerManager = {
|
|
65
|
-
reduce: (state, action) => combined(state, action),
|
|
66
|
-
add: (key, reducer) => {
|
|
67
|
-
if (!key || reducersMap[key]) return;
|
|
68
|
-
reducersMap[key] = reducer;
|
|
69
|
-
combined = combineReducers(reducersMap);
|
|
70
|
-
},
|
|
71
|
-
remove: (key) => {
|
|
72
|
-
if (!key || !reducersMap[key]) return;
|
|
73
|
-
delete reducersMap[key];
|
|
74
|
-
combined = combineReducers(reducersMap);
|
|
75
|
-
},
|
|
76
|
-
getReducerMap: () => reducersMap,
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
return manager;
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
factory.inject = <S extends object, D extends object>(source: S, dest: D): D & S => {
|
|
83
|
-
Object.keys(source).forEach((k) => {
|
|
84
|
-
// @ts-ignore
|
|
85
|
-
dest[k] = source[k];
|
|
86
|
-
});
|
|
87
|
-
return dest as D & S;
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
factory.create = (options: { service?: ServiceMap; initialState?: FeatureState<T> } = {}) => {
|
|
91
|
-
const { service, initialState } = options;
|
|
92
|
-
const sliceName = factory.entity;
|
|
93
|
-
|
|
94
|
-
const standard: ServiceMap = {
|
|
95
|
-
fetch: factory.thunk.create(sliceName, 'all'),
|
|
96
|
-
fetchOne: factory.thunk.create(sliceName, 'one'),
|
|
97
|
-
search: factory.thunk.create(sliceName, 'search'),
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
const slice = createSlice({
|
|
101
|
-
name: sliceName,
|
|
102
|
-
initialState: initialState ?? StateFactory<T>(sliceName),
|
|
103
|
-
reducers: factory.reducers,
|
|
104
|
-
extraReducers: (builder) => {
|
|
105
|
-
// handle standard thunks
|
|
106
|
-
Object.entries(standard).forEach(([act, thunk]) => {
|
|
107
|
-
builder
|
|
108
|
-
.addCase(thunk.pending, (state) => {
|
|
109
|
-
state.loading = true;
|
|
110
|
-
state.error = null;
|
|
111
|
-
})
|
|
112
|
-
.addCase(thunk.fulfilled, (state, action: PayloadAction<T[]>) => {
|
|
113
|
-
state.loading = false;
|
|
114
|
-
state.success = true;
|
|
115
|
-
state.data = action.payload;
|
|
116
|
-
state[sliceName] = action.payload[0];
|
|
117
|
-
})
|
|
118
|
-
.addCase(thunk.rejected, (state, action) => {
|
|
119
|
-
state.loading = false;
|
|
120
|
-
state.success = false;
|
|
121
|
-
state.error = action.error;
|
|
122
|
-
});
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
// handle extra service thunks
|
|
126
|
-
if (service) {
|
|
127
|
-
Object.entries(service).forEach(([key, thunk]) => {
|
|
128
|
-
if (!standard[key]) {
|
|
129
|
-
builder
|
|
130
|
-
.addCase(thunk.pending, (state) => {
|
|
131
|
-
state.loading = true;
|
|
132
|
-
state.error = null;
|
|
133
|
-
})
|
|
134
|
-
.addCase(thunk.fulfilled, (state, action: PayloadAction<any>) => {
|
|
135
|
-
state.loading = false;
|
|
136
|
-
state.success = true;
|
|
137
|
-
state.data = action.payload;
|
|
138
|
-
console.log('action fulfilled :', state.data);
|
|
139
|
-
})
|
|
140
|
-
.addCase(thunk.rejected, (state, action) => {
|
|
141
|
-
state.loading = false;
|
|
142
|
-
state.success = false;
|
|
143
|
-
state.error = action.payload;
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
},
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
const asyncActions = factory.inject(standard, service ?? {});
|
|
152
|
-
return { slice, asyncActions };
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
return factory;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
export default FeatureFactory;
|
package/src/factories/service.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
// src/services/myApi.js
|
|
2
|
-
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
|
|
3
|
-
const USERS_URL = "auth"
|
|
4
|
-
|
|
5
|
-
const ApiFactory = ( sliceName ) => {
|
|
6
|
-
const _this = {};
|
|
7
|
-
_this.API_BASE_URL = _this.base_url || "http://localhost:4000/fear/api/";
|
|
8
|
-
_this.baseQuery = { baseUrl: _this.API_BASE_URL };
|
|
9
|
-
|
|
10
|
-
_this.baseApi = createApi({
|
|
11
|
-
reducerPath: sliceName,
|
|
12
|
-
tagTypes: ["Product", "Order", "User", "Category"],
|
|
13
|
-
baseQuery: fetchBaseQuery(_this.baseQuery),
|
|
14
|
-
endpoints: () => ({})
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
_this.create = (routes) => {
|
|
18
|
-
const endpoints = (routes) ? routes : () => ({});
|
|
19
|
-
console.log('routes = ', routes);
|
|
20
|
-
const api = _this.baseApi.injectEndpoints((builder) => (routes));
|
|
21
|
-
|
|
22
|
-
return api;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return _this;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export default ApiFactory;
|
package/src/factories/service.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
// src/services/myApi.js
|
|
2
|
-
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
|
|
3
|
-
const USERS_URL = "auth"
|
|
4
|
-
|
|
5
|
-
const ApiFactory = ( sliceName ) => {
|
|
6
|
-
const _this = {};
|
|
7
|
-
_this.API_BASE_URL = _this.base_url || "http://localhost:4000/fear/api/";
|
|
8
|
-
_this.baseQuery = { baseUrl: _this.API_BASE_URL };
|
|
9
|
-
|
|
10
|
-
_this.baseApi = createApi({
|
|
11
|
-
reducerPath: sliceName,
|
|
12
|
-
tagTypes: ["Product", "Order", "User", "Category"],
|
|
13
|
-
baseQuery: fetchBaseQuery(_this.baseQuery),
|
|
14
|
-
endpoints: () => ({})
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
_this.create = (routes) => {
|
|
18
|
-
const endpoints = (routes) ? routes : () => ({});
|
|
19
|
-
console.log('routes = ', routes);
|
|
20
|
-
const api = _this.baseApi.injectEndpoints((builder) => (routes));
|
|
21
|
-
|
|
22
|
-
return api;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return _this;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export default ApiFactory;
|
package/src/factories/state.js
DELETED
package/src/factories/state.ts
DELETED
package/src/factories/thunk.js
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { createAsyncThunk } from "@reduxjs/toolkit"
|
|
2
|
-
import API from "./api"
|
|
3
|
-
|
|
4
|
-
// Async Thunk Factory Function
|
|
5
|
-
// This factory creates a specific createAsyncThunk for a given 'itemType'
|
|
6
|
-
export const ThunkFactory = {
|
|
7
|
-
|
|
8
|
-
create: (entity, prefix) => {
|
|
9
|
-
|
|
10
|
-
return (
|
|
11
|
-
createAsyncThunk(
|
|
12
|
-
|
|
13
|
-
`${entity}/${prefix}`,
|
|
14
|
-
|
|
15
|
-
async ( params, thunkApi ) => {
|
|
16
|
-
let url = `${entity}/${prefix}`;
|
|
17
|
-
console.log('params = ', params);
|
|
18
|
-
if ( prefix == 'one' ) url = `${entity}/${params.id}`
|
|
19
|
-
|
|
20
|
-
return API.get(url, (prefix == 'search') ? {params} : {})
|
|
21
|
-
|
|
22
|
-
.then((response) => response.data.result )
|
|
23
|
-
|
|
24
|
-
.catch((error) => thunkApi.rejectWithValue(error.message) )
|
|
25
|
-
}
|
|
26
|
-
)
|
|
27
|
-
)
|
|
28
|
-
},
|
|
29
|
-
|
|
30
|
-
post: (entity, prefix) => {
|
|
31
|
-
return (
|
|
32
|
-
createAsyncThunk(
|
|
33
|
-
|
|
34
|
-
`${entity}/${prefix}`,
|
|
35
|
-
|
|
36
|
-
async ( data, thunkApi ) => {
|
|
37
|
-
|
|
38
|
-
return API.post(`${entity}/${prefix}`, data)
|
|
39
|
-
|
|
40
|
-
.then((response) => {
|
|
41
|
-
|
|
42
|
-
return response.data.result;
|
|
43
|
-
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
.catch((error) => thunkApi.rejectWithValue(error.message) )
|
|
47
|
-
}
|
|
48
|
-
)
|
|
49
|
-
)
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export default ThunkFactory;
|
package/src/factories/thunk.ts
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { createAsyncThunk } from "@reduxjs/toolkit"
|
|
2
|
-
import API from "./api"
|
|
3
|
-
|
|
4
|
-
// Async Thunk Factory Function
|
|
5
|
-
// This factory creates a specific createAsyncThunk for a given 'itemType'
|
|
6
|
-
export const ThunkFactory = {
|
|
7
|
-
|
|
8
|
-
create: (entity, prefix) => {
|
|
9
|
-
|
|
10
|
-
return (
|
|
11
|
-
createAsyncThunk(
|
|
12
|
-
|
|
13
|
-
`${entity}/${prefix}`,
|
|
14
|
-
|
|
15
|
-
async ( params, thunkApi ) => {
|
|
16
|
-
let url = `${entity}/${prefix}`;
|
|
17
|
-
console.log('params = ', params);
|
|
18
|
-
if ( prefix == 'one' ) url = `${entity}/${params.id}`
|
|
19
|
-
|
|
20
|
-
return API.get(url, (prefix == 'search') ? {params} : {})
|
|
21
|
-
|
|
22
|
-
.then((response) => response.data.result )
|
|
23
|
-
|
|
24
|
-
.catch((error) => thunkApi.rejectWithValue(error.message) )
|
|
25
|
-
}
|
|
26
|
-
)
|
|
27
|
-
)
|
|
28
|
-
},
|
|
29
|
-
|
|
30
|
-
post: (entity, prefix) => {
|
|
31
|
-
return (
|
|
32
|
-
createAsyncThunk(
|
|
33
|
-
|
|
34
|
-
`${entity}/${prefix}`,
|
|
35
|
-
|
|
36
|
-
async ( data, thunkApi ) => {
|
|
37
|
-
|
|
38
|
-
return API.post(`${entity}/${prefix}`, data)
|
|
39
|
-
|
|
40
|
-
.then((response) => {
|
|
41
|
-
|
|
42
|
-
return response.data.result;
|
|
43
|
-
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
.catch((error) => thunkApi.rejectWithValue(error.message) )
|
|
47
|
-
}
|
|
48
|
-
)
|
|
49
|
-
)
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export default ThunkFactory;
|
package/src/index.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export { default as FeatureFactory } from "./factories/factory.js";
|
|
2
|
-
|
|
3
|
-
export { default as ThunkFactory } from "./factories/thunk.js";
|
|
4
|
-
|
|
5
|
-
export { default as ApiFactory } from "./factories/service.js";
|
|
6
|
-
|
|
7
|
-
export { default as StateFactory } from "./factories/state.js";
|