procode-lowcode-core 1.0.15 → 1.0.17

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.
@@ -1,241 +1,221 @@
1
- import {
2
- createService,
3
- deleteService,
4
- fetchScreenDataService,
5
- fetchSupportiveDataService,
6
- patchService,
7
- updateService,
8
- } from "../Services/CRUDServices";
9
- import { EventService } from "../Services/EventService";
10
- import { ApiConfig } from "../UIElement/UIElementDefinations/ApiConfig";
11
- import { IViewModelHandler, QueryFilters } from "./IViewModelHandler";
12
- import {
13
- deserializedModel,
14
- deserializedSupportiveData,
15
- handleFetchRequest,
16
- handleRequest,
17
- serializedModel,
18
- serializedScreenDataQueryParams,
19
- serializedSupportiveQueryParams,
20
- } from "./SupportiveFunctions";
21
- import { ViewModel } from "./ViewModel";
22
-
23
- export class CoreViewModelHandler implements IViewModelHandler {
24
- private static instance: CoreViewModelHandler;
25
- private static createInstance() {
26
- CoreViewModelHandler.instance = new CoreViewModelHandler();
27
- }
28
-
29
- static getInstance() {
30
- if (!CoreViewModelHandler.instance) CoreViewModelHandler.createInstance();
31
- return CoreViewModelHandler.instance;
32
- }
33
-
34
- getViewModel = async (
35
- screenDataQueryParams: QueryFilters,
36
- supportiveQueryParams: string[],
37
- apiConfig: ApiConfig,
38
- eventService: EventService
39
- ): Promise<ViewModel> => {
40
- const viewModel: ViewModel = {
41
- screenData: null,
42
- supportiveData: null,
43
- };
44
-
45
- const [supportiveData, screenData] = await Promise.all([
46
- apiConfig?.loadSupportiveData?.endPoint &&
47
- supportiveQueryParams?.length > 0
48
- ? handleFetchRequest(
49
- serializedSupportiveQueryParams(
50
- eventService,
51
- supportiveQueryParams
52
- ),
53
- apiConfig,
54
- eventService,
55
- fetchSupportiveDataService,
56
- deserializedSupportiveData
57
- )
58
- : Promise.resolve(null),
59
- apiConfig?.get?.endPoint
60
- ? handleFetchRequest(
61
- serializedScreenDataQueryParams(
62
- eventService,
63
- screenDataQueryParams
64
- ),
65
- apiConfig,
66
- eventService,
67
- fetchScreenDataService,
68
- deserializedModel
69
- )
70
- : Promise.resolve(null),
71
- ]);
72
-
73
- viewModel.screenData = screenData;
74
- viewModel.supportiveData = supportiveData;
75
-
76
- return viewModel;
77
- };
78
-
79
- getModel = async (
80
- screenDataQueryParams: QueryFilters,
81
- apiConfig: ApiConfig,
82
- eventService: EventService
83
- ) => {
84
- const customAdapterBefore = eventService.emit(
85
- "GET_CUSTOM_ADAPTER_METHOD",
86
- apiConfig?.get?.beforeRequestMethodName
87
- );
88
- const customAdapterAfter = eventService.emit(
89
- "GET_CUSTOM_ADAPTER_METHOD",
90
- apiConfig?.get?.afterRequestMethodName
91
- );
92
-
93
- const applicableParams = apiConfig?.get?.disableBeforeRequest
94
- ? screenDataQueryParams
95
- : (customAdapterBefore ?? serializedScreenDataQueryParams)(
96
- eventService,
97
- screenDataQueryParams
98
- );
99
-
100
- const applicableResponse = apiConfig?.get?.disableAfterRequest
101
- ? null
102
- : customAdapterAfter ?? deserializedModel;
103
-
104
- return handleFetchRequest(
105
- applicableParams,
106
- apiConfig,
107
- eventService,
108
- fetchScreenDataService,
109
- applicableResponse
110
- );
111
- };
112
-
113
- getSupportiveData = async (
114
- supportiveQueryParams: string[],
115
- apiConfig: ApiConfig,
116
- eventService: EventService
117
- ) => {
118
- const customAdapterBefore = eventService.emit(
119
- "GET_CUSTOM_ADAPTER_METHOD",
120
- apiConfig?.loadSupportiveData?.beforeRequestMethodName
121
- );
122
- const customAdapterAfter = eventService.emit(
123
- "GET_CUSTOM_ADAPTER_METHOD",
124
- apiConfig?.loadSupportiveData?.afterRequestMethodName
125
- );
126
-
127
- const applicableParams = apiConfig?.loadSupportiveData?.disableBeforeRequest
128
- ? supportiveQueryParams
129
- : (customAdapterBefore ?? serializedSupportiveQueryParams)(
130
- eventService,
131
- supportiveQueryParams
132
- );
133
-
134
- const applicableResponse = apiConfig?.loadSupportiveData
135
- ?.disableAfterRequest
136
- ? null
137
- : customAdapterAfter ?? deserializedSupportiveData;
138
-
139
- return handleFetchRequest(
140
- applicableParams,
141
- apiConfig,
142
- eventService,
143
- fetchSupportiveDataService,
144
- applicableResponse
145
- );
146
- };
147
-
148
- createModel = async (
149
- model: any,
150
- apiConfig: ApiConfig,
151
- eventService: EventService
152
- ) => {
153
- const customAdapterBefore = eventService.emit(
154
- "GET_CUSTOM_ADAPTER_METHOD",
155
- apiConfig?.create?.beforeRequestMethodName
156
- );
157
- const customAdapterAfter = eventService.emit(
158
- "GET_CUSTOM_ADAPTER_METHOD",
159
- apiConfig?.create?.afterRequestMethodName
160
- );
161
-
162
- const applicableModel = apiConfig?.create?.disableBeforeRequest
163
- ? model
164
- : (customAdapterBefore ?? serializedModel)(eventService, model);
165
-
166
- return handleRequest(async () => {
167
- const servicesResponse = await createService(
168
- apiConfig,
169
- applicableModel,
170
- eventService
171
- );
172
-
173
- const applicableResponse = apiConfig?.create?.disableAfterRequest
174
- ? servicesResponse
175
- : (customAdapterAfter ?? deserializedModel)(
176
- eventService,
177
- servicesResponse
178
- );
179
-
180
- return applicableResponse;
181
- }, eventService);
182
- };
183
-
184
- updateModel = async (
185
- model: any,
186
- apiConfig: ApiConfig,
187
- eventService: EventService
188
- ) => {
189
- const customAdapterBefore = eventService.emit(
190
- "GET_CUSTOM_ADAPTER_METHOD",
191
- apiConfig?.update?.beforeRequestMethodName
192
- );
193
- const customAdapterAfter = eventService.emit(
194
- "GET_CUSTOM_ADAPTER_METHOD",
195
- apiConfig?.update?.afterRequestMethodName
196
- );
197
- return handleRequest(async () => {
198
- const serviceFc = apiConfig?.update?.isPatchUpdate
199
- ? patchService
200
- : updateService;
201
-
202
- const applicableModel = apiConfig?.update?.disableBeforeRequest
203
- ? model
204
- : (customAdapterBefore ?? serializedModel)(eventService, model);
205
-
206
- const servicesResponse = await serviceFc(
207
- apiConfig,
208
- applicableModel,
209
- eventService
210
- );
211
- const applicableResponse = apiConfig?.update?.disableAfterRequest
212
- ? servicesResponse
213
- : (customAdapterAfter ?? deserializedModel)(
214
- eventService,
215
- servicesResponse
216
- );
217
-
218
- return applicableResponse;
219
- }, eventService);
220
- };
221
-
222
- deleteModel = async (
223
- screenDataQueryParams: QueryFilters,
224
- apiConfig: ApiConfig,
225
- eventService: EventService
226
- ) => {
227
- const customAdapter = eventService.emit(
228
- "GET_CUSTOM_ADAPTER_METHOD",
229
- apiConfig?.delete?.beforeRequestMethodName
230
- );
231
- const params = apiConfig?.delete?.disableBeforeRequest
232
- ? screenDataQueryParams
233
- : (customAdapter ?? serializedScreenDataQueryParams)(
234
- eventService,
235
- screenDataQueryParams
236
- );
237
- return handleRequest(async () => {
238
- await deleteService(apiConfig, params, eventService);
239
- }, eventService);
240
- };
241
- }
1
+ import { AdapterType } from "../Adapter/IAdapterProvider";
2
+ import {
3
+ createService,
4
+ deleteService,
5
+ fetchScreenDataService,
6
+ fetchSupportiveDataService,
7
+ patchService,
8
+ updateService,
9
+ } from "../Services/CRUDServices";
10
+ import { EventService } from "../Services/EventService";
11
+ import { ApiConfig } from "../UIElement/UIElementDefinations/ApiConfig";
12
+ import { IViewModelHandler, QueryFilters } from "./IViewModelHandler";
13
+ import {
14
+ deserializedModel,
15
+ deserializedSupportiveData,
16
+ handleFetchRequest,
17
+ handleRequest,
18
+ serializedModel,
19
+ serializedScreenDataQueryParams,
20
+ serializedSupportiveQueryParams,
21
+ } from "./SupportiveFunctions";
22
+ import { ViewModel } from "./ViewModel";
23
+
24
+ type AdapterableOpConfig = {
25
+ beforeRequestMethodName?: string;
26
+ afterRequestMethodName?: string;
27
+ disableBeforeRequest?: boolean;
28
+ disableAfterRequest?: boolean;
29
+ };
30
+
31
+ type Adapter<TIn, TOut> = (eventService: EventService, input: TIn) => TOut;
32
+
33
+ export class CoreViewModelHandler implements IViewModelHandler {
34
+ private static instance: CoreViewModelHandler;
35
+ private static createInstance() {
36
+ CoreViewModelHandler.instance = new CoreViewModelHandler();
37
+ }
38
+
39
+ static getInstance() {
40
+ if (!CoreViewModelHandler.instance) CoreViewModelHandler.createInstance();
41
+ return CoreViewModelHandler.instance;
42
+ }
43
+
44
+ // Resolve & apply the configured "before request" adapter to the input.
45
+ // Order: disable flag wins, then a custom-named adapter from EventService,
46
+ // then the supplied default serializer.
47
+ private applyBefore = <TIn>(
48
+ eventService: EventService,
49
+ opConfig: AdapterableOpConfig | undefined,
50
+ input: TIn,
51
+ defaultSerializer: Adapter<TIn, any>,
52
+ ): any => {
53
+ if (opConfig?.disableBeforeRequest) return input;
54
+ const custom = eventService.emit(
55
+ AdapterType.GET_CUSTOM_ADAPTER_METHOD,
56
+ opConfig?.beforeRequestMethodName,
57
+ );
58
+ return (custom ?? defaultSerializer)(eventService, input);
59
+ };
60
+
61
+ // Build the "after request" adapter callable. Returns null when disabled,
62
+ // so it can be passed straight to handleFetchRequest (which treats null as
63
+ // "skip deserialization") and re-used directly for create/update flows.
64
+ private resolveAfter = (
65
+ eventService: EventService,
66
+ opConfig: AdapterableOpConfig | undefined,
67
+ defaultDeserializer: Adapter<any, any>,
68
+ ): Adapter<any, any> | null => {
69
+ if (opConfig?.disableAfterRequest) return null;
70
+ const custom = eventService.emit(
71
+ AdapterType.GET_CUSTOM_ADAPTER_METHOD,
72
+ opConfig?.afterRequestMethodName,
73
+ );
74
+ return custom ?? defaultDeserializer;
75
+ };
76
+
77
+ getViewModel = async (
78
+ screenDataQueryParams: QueryFilters,
79
+ supportiveQueryParams: string[],
80
+ apiConfig: ApiConfig,
81
+ eventService: EventService,
82
+ ): Promise<ViewModel> => {
83
+ const [supportiveData, screenData] = await Promise.all([
84
+ apiConfig?.loadSupportiveData?.endPoint &&
85
+ supportiveQueryParams?.length > 0
86
+ ? this.getSupportiveData(supportiveQueryParams, apiConfig, eventService)
87
+ : Promise.resolve(null),
88
+ apiConfig?.get?.endPoint
89
+ ? this.getModel(screenDataQueryParams, apiConfig, eventService)
90
+ : Promise.resolve(null),
91
+ ]);
92
+
93
+ return { screenData, supportiveData };
94
+ };
95
+
96
+ getModel = async (
97
+ screenDataQueryParams: QueryFilters,
98
+ apiConfig: ApiConfig,
99
+ eventService: EventService,
100
+ ) => {
101
+ const params = this.applyBefore(
102
+ eventService,
103
+ apiConfig?.get,
104
+ screenDataQueryParams,
105
+ serializedScreenDataQueryParams,
106
+ );
107
+ const after = this.resolveAfter(
108
+ eventService,
109
+ apiConfig?.get,
110
+ deserializedModel,
111
+ );
112
+
113
+ return handleFetchRequest(
114
+ params,
115
+ apiConfig,
116
+ eventService,
117
+ fetchScreenDataService,
118
+ after,
119
+ );
120
+ };
121
+
122
+ getSupportiveData = async (
123
+ supportiveQueryParams: string[],
124
+ apiConfig: ApiConfig,
125
+ eventService: EventService,
126
+ ) => {
127
+ const params = this.applyBefore(
128
+ eventService,
129
+ apiConfig?.loadSupportiveData,
130
+ supportiveQueryParams,
131
+ serializedSupportiveQueryParams,
132
+ );
133
+ const after = this.resolveAfter(
134
+ eventService,
135
+ apiConfig?.loadSupportiveData,
136
+ deserializedSupportiveData,
137
+ );
138
+
139
+ return handleFetchRequest(
140
+ params,
141
+ apiConfig,
142
+ eventService,
143
+ fetchSupportiveDataService,
144
+ after,
145
+ );
146
+ };
147
+
148
+ createModel = async (
149
+ model: any,
150
+ apiConfig: ApiConfig,
151
+ eventService: EventService,
152
+ ) => {
153
+ const payload = this.applyBefore(
154
+ eventService,
155
+ apiConfig?.create,
156
+ model,
157
+ serializedModel,
158
+ );
159
+ const after = this.resolveAfter(
160
+ eventService,
161
+ apiConfig?.create,
162
+ deserializedModel,
163
+ );
164
+
165
+ return handleRequest(async () => {
166
+ const servicesResponse = await createService(
167
+ apiConfig,
168
+ payload,
169
+ eventService,
170
+ );
171
+ return after ? after(eventService, servicesResponse) : servicesResponse;
172
+ }, eventService);
173
+ };
174
+
175
+ updateModel = async (
176
+ model: any,
177
+ apiConfig: ApiConfig,
178
+ eventService: EventService,
179
+ ) => {
180
+ const serviceFn = apiConfig?.update?.isPatchUpdate
181
+ ? patchService
182
+ : updateService;
183
+ const payload = this.applyBefore(
184
+ eventService,
185
+ apiConfig?.update,
186
+ model,
187
+ serializedModel,
188
+ );
189
+ const after = this.resolveAfter(
190
+ eventService,
191
+ apiConfig?.update,
192
+ deserializedModel,
193
+ );
194
+
195
+ return handleRequest(async () => {
196
+ const servicesResponse = await serviceFn(
197
+ apiConfig,
198
+ payload,
199
+ eventService,
200
+ );
201
+ return after ? after(eventService, servicesResponse) : servicesResponse;
202
+ }, eventService);
203
+ };
204
+
205
+ deleteModel = async (
206
+ screenDataQueryParams: QueryFilters,
207
+ apiConfig: ApiConfig,
208
+ eventService: EventService,
209
+ ) => {
210
+ const params = this.applyBefore(
211
+ eventService,
212
+ apiConfig?.delete,
213
+ screenDataQueryParams,
214
+ serializedScreenDataQueryParams,
215
+ );
216
+
217
+ return handleRequest(async () => {
218
+ await deleteService(apiConfig, params, eventService);
219
+ }, eventService);
220
+ };
221
+ }
@@ -47,10 +47,12 @@ export const fetchDataAndDeserialize = async (
47
47
  queryParam: string,
48
48
  eventService: EventService
49
49
  ) => Promise<ServicesResponse>,
50
- deserializeFn: (
51
- eventService: EventService,
52
- servicesResponse: ServicesResponse
53
- ) => any
50
+ deserializeFn:
51
+ | ((
52
+ eventService: EventService,
53
+ servicesResponse: ServicesResponse
54
+ ) => any)
55
+ | null
54
56
  ): Promise<any> => {
55
57
  const servicesResponse = await fetchService(
56
58
  apiConfig,
@@ -86,10 +88,12 @@ export const handleFetchRequest = async (
86
88
  queryParam: string,
87
89
  eventService: EventService
88
90
  ) => Promise<ServicesResponse>,
89
- deserializeFn: (
90
- eventService: EventService,
91
- servicesResponse: ServicesResponse
92
- ) => any
91
+ deserializeFn:
92
+ | ((
93
+ eventService: EventService,
94
+ servicesResponse: ServicesResponse
95
+ ) => any)
96
+ | null
93
97
  ) => {
94
98
  return handleRequest(
95
99
  () =>
@@ -9,6 +9,7 @@ import {
9
9
  ResponseConfig,
10
10
  } from "../UIElement/UIElementDefinations/ApiConfig";
11
11
  import NotificationService from "../ApplicationStart/HOC/NotificationService";
12
+ import FieldValidationDispatcher from "../ApplicationStart/HOC/FieldValidationDispatcher";
12
13
  import { getStatusBaseNotifiType } from "./helpers/getStatusBaseNotifiType";
13
14
 
14
15
  export interface CustomAxiosRequestConfig extends AxiosRequestConfig {
@@ -18,7 +19,7 @@ export interface CustomAxiosRequestConfig extends AxiosRequestConfig {
18
19
 
19
20
  export class CentralService {
20
21
  private static instance: CentralService;
21
- private _axiosInstance: AxiosInstance | null = null;
22
+ private _axiosInstance: AxiosInstance;
22
23
 
23
24
  private constructor() {
24
25
  const axiosInstance = axios.create();
@@ -28,64 +29,74 @@ export class CentralService {
28
29
  this._axiosInstance = axiosInstance;
29
30
  }
30
31
 
31
- private setHeaders = (base: any, customHeaders: any) => {
32
+ private setHeaders = (base: any, customHeaders: any): void => {
32
33
  if (customHeaders) {
33
34
  Object.keys(customHeaders)?.forEach((key) => {
34
35
  base.headers[key] = customHeaders[key];
35
36
  });
36
37
  }
37
- return base;
38
38
  };
39
39
 
40
40
  private getMessage = (
41
41
  response: AxiosResponse<any, any>,
42
42
  responseConfig?: ResponseConfig,
43
43
  ) => {
44
- const statusRelatedConfig = (responseConfig ?? {})[response?.status];
45
- let errorMessage = "";
46
- if (statusRelatedConfig?.enableMessage) {
47
- errorMessage =
48
- statusRelatedConfig?.message ||
49
- response?.data?.message ||
50
- ErrorMessageProvider.get(
51
- response.config.method as RequestType,
52
- response?.status,
53
- );
54
- }
55
-
56
- return errorMessage;
44
+ const status = response?.data?.status;
45
+ const statusRelatedConfig = (responseConfig ?? {})[status];
46
+ if (!statusRelatedConfig?.enableMessage) return "";
47
+
48
+ const payloadMessage = response?.data?.message;
49
+ return (
50
+ statusRelatedConfig?.message ||
51
+ (typeof payloadMessage === "string" ? payloadMessage : "") ||
52
+ ErrorMessageProvider.get(
53
+ response.config.method as RequestType,
54
+ status,
55
+ )
56
+ );
57
57
  };
58
58
 
59
59
  private handleResponseStatus = (response: AxiosResponse<any, any>) => {
60
- if (response?.data?.status === 401) {
61
- window.location.href = env.baseLogoutUrl || "/";
62
- } else if (response?.data?.status >= 200 && response?.data?.status < 500) {
63
- const customAxiosRequestConfig =
64
- response.config as CustomAxiosRequestConfig;
60
+ const status = response?.data?.status;
65
61
 
66
- response.data.message = this.getMessage(
67
- response,
68
- customAxiosRequestConfig?.responseConfig,
69
- );
62
+ if (status === 401) {
63
+ window.location.href = env.baseLogoutUrl || "/";
64
+ return;
65
+ }
66
+ if (!(status >= 200 && status < 500)) {
67
+ throw new Error("Unhandled response status " + status);
68
+ }
70
69
 
71
- response.data.alertType =
72
- customAxiosRequestConfig?.responseConfig?.[response?.data?.status]
73
- ?.alertType || AlertType.TOAST;
70
+ const customAxiosRequestConfig =
71
+ response.config as CustomAxiosRequestConfig;
72
+ const responseConfig = customAxiosRequestConfig?.responseConfig;
73
+ const statusRelatedConfig = (responseConfig ?? {})[status];
74
+ const alertType = statusRelatedConfig?.alertType || AlertType.TOAST;
75
+ response.data.alertType = alertType;
76
+
77
+ if (alertType === AlertType.FIELDVALIDATION) {
78
+ // Structured payload (default convention {propertyName, message}, or
79
+ // whatever shape the registered fieldErrorMapper recognizes): route to
80
+ // the per-field validation slice. If the mapper finds nothing — e.g.
81
+ // the server returned a plain string — fall through to the toast path
82
+ // below, so the message still surfaces as a notification.
83
+ const fieldErrorMapper = AppDependenceyProvider.getInstance()
84
+ .getFieldErrorMapper();
85
+ const fieldErrors = fieldErrorMapper(response.data?.message);
86
+ if (Object.keys(fieldErrors).length > 0) {
87
+ response.data.fieldErrors = fieldErrors;
88
+ FieldValidationDispatcher.dispatch(fieldErrors);
89
+ return;
90
+ }
91
+ }
74
92
 
75
- const statusRelatedConfig = (customAxiosRequestConfig?.responseConfig ??
76
- {})[response?.data?.status];
93
+ response.data.message = this.getMessage(response, responseConfig);
77
94
 
78
- if (
79
- response.data.alertType === AlertType.TOAST &&
80
- statusRelatedConfig?.enableMessage
81
- ) {
82
- NotificationService.showNotification(
83
- response.data.message,
84
- getStatusBaseNotifiType(response?.data?.status),
85
- );
86
- }
87
- } else {
88
- throw new Error("Unhandled response status " + response?.data?.status);
95
+ if (statusRelatedConfig?.enableMessage) {
96
+ NotificationService.showNotification(
97
+ response.data.message,
98
+ getStatusBaseNotifiType(status),
99
+ );
89
100
  }
90
101
  };
91
102
 
@@ -113,21 +124,19 @@ export class CentralService {
113
124
  };
114
125
 
115
126
  private setInterceptorsRequest = (axiosInstance: AxiosInstance) => {
116
- if (axiosInstance) {
117
- axiosInstance.interceptors.request.use(
118
- (request) => {
119
- this.setHeaders(
120
- request,
121
- AppDependenceyProvider.getInstance().getRequestHeaders(),
122
- );
123
- return request;
124
- },
125
- (error) => {
126
- console.error("Request error:", error);
127
- throw error;
128
- },
129
- );
130
- }
127
+ axiosInstance.interceptors.request.use(
128
+ (request) => {
129
+ this.setHeaders(
130
+ request,
131
+ AppDependenceyProvider.getInstance().getRequestHeaders(),
132
+ );
133
+ return request;
134
+ },
135
+ (error) => {
136
+ console.error("Request error:", error);
137
+ throw error;
138
+ },
139
+ );
131
140
  };
132
141
 
133
142
  private static initInstance(): void {
@@ -141,5 +150,5 @@ export class CentralService {
141
150
  return CentralService.instance;
142
151
  }
143
152
 
144
- public getAxioInstance = (): AxiosInstance | null => this._axiosInstance;
153
+ public getAxioInstance = (): AxiosInstance => this._axiosInstance;
145
154
  }