blend-r 1.1.6

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.
Files changed (30) hide show
  1. package/README.md +213 -0
  2. package/dist/helper/ApiHelper.js +766 -0
  3. package/dist/helper/BasicHelper.js +43 -0
  4. package/dist/helper/DataHelper.js +231 -0
  5. package/dist/helper/FrontEndHelper.js +201 -0
  6. package/dist/helper/fileHelper.js +127 -0
  7. package/dist/helper/grammarHelper/BlendApiGrammarHelper.js +90 -0
  8. package/dist/helper/grammarHelper/BlendBasicGrammarHelper.js +135 -0
  9. package/dist/helper/grammarHelper/BlendDataGrammarHelper.js +47 -0
  10. package/dist/helper/grammarHelper/GrammarErrorHelper.js +16 -0
  11. package/dist/index.js +87 -0
  12. package/dist/parser/blendApi/src/grammar/BlendApiLexer.js +207 -0
  13. package/dist/parser/blendApi/src/grammar/BlendApiListener.js +3 -0
  14. package/dist/parser/blendApi/src/grammar/BlendApiParser.js +978 -0
  15. package/dist/parser/blendData/src/grammar/BlendDataLexer.js +154 -0
  16. package/dist/parser/blendData/src/grammar/BlendDataListener.js +3 -0
  17. package/dist/parser/blendData/src/grammar/BlendDataParser.js +642 -0
  18. package/dist/parser/blendRBasic/src/grammar/BlendRBasicListener.js +3 -0
  19. package/dist/parser/blendRBasic/src/grammar/blendRBasicLexer.js +184 -0
  20. package/dist/parser/blendRBasic/src/grammar/blendRBasicParser.js +993 -0
  21. package/dist/parser/blendRnBasic/src/grammar/BlendRnBasicLexer.js +214 -0
  22. package/dist/parser/blendRnBasic/src/grammar/BlendRnBasicListener.js +3 -0
  23. package/dist/parser/blendRnBasic/src/grammar/BlendRnBasicParser.js +1224 -0
  24. package/dist/types/apiOperationTypes.js +20 -0
  25. package/dist/types/basicOperationTypes.js +3 -0
  26. package/dist/types/dataOperationTypes.js +2 -0
  27. package/dist/types/frontendOperationTypes.js +4 -0
  28. package/dist/types/generalTypes.js +0 -0
  29. package/dist/types/mongoOperationTypes.js +12 -0
  30. package/package.json +36 -0
@@ -0,0 +1,766 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const path_1 = __importDefault(require("path"));
7
+ const fileHelper_1 = require("./fileHelper");
8
+ const BlendApiGrammarHelper_1 = __importDefault(require("./grammarHelper/BlendApiGrammarHelper"));
9
+ class ApiHelper {
10
+ constructor() {
11
+ this.baseRoute = 'api';
12
+ this.folderPath = path_1.default.join(process.cwd());
13
+ this.folderName = path_1.default.basename(this.folderPath);
14
+ this.basicFilePath = path_1.default.join(this.folderPath, `${this.folderName}.basic`);
15
+ this.configPath = path_1.default.join(this.folderPath, '.basicConfig');
16
+ this.basicProjectContent = JSON.parse(fileHelper_1.FileHelper.readFile(`${this.configPath}/basicConfig.json`) || "{}");
17
+ }
18
+ parseSpec() {
19
+ let mainApiObjList = [];
20
+ this.basicProjectContent.apiModuleList.forEach(apiModule => {
21
+ const filePath = path_1.default.join(this.folderPath, `spec/api/${apiModule}.api`);
22
+ const specCode = fileHelper_1.FileHelper.readFile(filePath);
23
+ const json = new BlendApiGrammarHelper_1.default().parseBlendApi(specCode, this.basicProjectContent.dataModuleList || []);
24
+ if (!json.isValid) {
25
+ throw new Error("Error while parsing the syntax");
26
+ }
27
+ mainApiObjList.push(json.json);
28
+ });
29
+ fileHelper_1.FileHelper.writeFile(`${this.configPath}/apiConfig.json`, JSON.stringify(mainApiObjList));
30
+ }
31
+ doFrontEndApiGenerations() {
32
+ this.writeStoreFiles();
33
+ this.createRequiredFiles();
34
+ }
35
+ createRequiredFiles() {
36
+ const apiMainSectionList = JSON.parse(fileHelper_1.FileHelper.readFile(`${this.configPath}/apiConfig.json`));
37
+ // const rnSectionList: IReactSection[] = JSON.parse(FileHelper.readFile(`${this.configPath}/reactConfig.json`));
38
+ // rnSectionList.forEach(rnSection => {
39
+ // const rnFolderPath = path.join(this.folderPath, `module/${rnSection.name}/react`);
40
+ // rnSection.reactModuleList.forEach(rnModule => {
41
+ // let currentApiSection: IApiMainSection = apiMainSectionList.find(item => item.name === rnSection.name)
42
+ // const rnProjectPath = path.join(rnFolderPath, rnModule.name);
43
+ const rapcode = this.generateRmoteApiPointsCode();
44
+ fileHelper_1.FileHelper.createFile(`${this.folderPath}/src/remote-api-point.ts`, rapcode);
45
+ fileHelper_1.FileHelper.createFile(`${this.folderPath}/src-gen/data/common.ts`, commonApiDataCode);
46
+ fileHelper_1.FileHelper.createFile(`${this.folderPath}/src/redux/store/store.ts`, mainStoreCode);
47
+ // FileHelper.createFile(`${this.folderPath}/src/redux/store/saga.ts`, mainSagaCode);
48
+ fileHelper_1.FileHelper.createFile(`${this.folderPath}/src/redux/store/snackbar/snackbarSlice.ts`, snackbarSliceCode);
49
+ fileHelper_1.FileHelper.createFile(`${this.folderPath}/src/redux/hooks.ts`, hooksCode);
50
+ }
51
+ generateRmoteApiPointsCode() {
52
+ let code = `
53
+ import axios from 'axios';
54
+ const apiUrl = import.meta.env.VITE_API_URL;
55
+ ${this.basicProjectContent.apiModuleList.reduce((acc, curVal) => {
56
+ acc = acc + `export const ${curVal}Api = axios.create({
57
+ baseURL: apiUrl||'http://localhost:8000', // Replace with your API base URL
58
+ headers: {
59
+ Authorization: localStorage.getItem("authToken")||""
60
+ }
61
+ });
62
+ \n
63
+ `;
64
+ return acc;
65
+ }, "")}
66
+ `;
67
+ return code;
68
+ }
69
+ generateRoleSliceCode() {
70
+ const code = `
71
+ import { createSlice, type PayloadAction } from "@reduxjs/toolkit";
72
+ import type { Role } from "./type";
73
+
74
+ interface RolesState {
75
+ roles: Role[];
76
+ }
77
+
78
+
79
+ const initialState: RolesState = {
80
+ roles: []
81
+ };
82
+
83
+ // ---- Slice
84
+ const rolesSlice = createSlice({
85
+ name: "roles",
86
+ initialState,
87
+ reducers: {
88
+ setRoles(state, action: PayloadAction<Role[]>) {
89
+ state.roles = action.payload;
90
+ },
91
+ addRole(state, action: PayloadAction<Role>) {
92
+ if (!state.roles.includes(action.payload)) {
93
+ state.roles.push(action.payload);
94
+ }
95
+ },
96
+ removeRole(state, action: PayloadAction<Role>) {
97
+ state.roles = state.roles.filter(r => r !== action.payload);
98
+ },
99
+ clearRoles(state) {
100
+ state.roles = [];
101
+ }
102
+ }
103
+ });
104
+
105
+ // ---- Actions
106
+ export const { setRoles, addRole, removeRole, clearRoles } = rolesSlice.actions;
107
+
108
+ // ---- Reducer
109
+ export default rolesSlice.reducer;
110
+
111
+ `;
112
+ return code;
113
+ }
114
+ generateRolesGetterCode() {
115
+ const code = `
116
+ import type { RootState } from "@/redux/store/store";
117
+ import type { Role } from "./type";
118
+ export const selectRoles = (state: RootState) => state.roles.roles;
119
+
120
+ // Generic checker
121
+ export const hasRole = (role: Role) => (state: RootState) =>
122
+ state.roles.roles.includes(role);
123
+ export const hasAnyRole = (roles: Role[]) => (state: RootState) =>
124
+ roles.some(role => state.roles.roles.includes(role));
125
+
126
+ ${this.basicProjectContent.frontend.roleList.reduce((acc, role) => {
127
+ acc = acc + `
128
+ export const has${role}Role = (state: RootState) =>
129
+ state.roles.roles.includes("${role}");
130
+ `;
131
+ return acc;
132
+ }, '')}
133
+ `;
134
+ return code;
135
+ }
136
+ generateRolesTypeCode() {
137
+ const code = `
138
+ export type Role = ${this.basicProjectContent.frontend.roleList.map(role => `"${role}"`).join(' | ')};
139
+ `;
140
+ return this.basicProjectContent.frontend.roleList.length > 0 ? code : '';
141
+ }
142
+ generateRoleRelatedFiles() {
143
+ const roleSliceCode = this.generateRoleSliceCode();
144
+ const rolesGetterCode = this.generateRolesGetterCode();
145
+ const rolesTypeCode = this.generateRolesTypeCode();
146
+ const rolePath = path_1.default.join(this.folderPath, `src-gen/redux/roles`);
147
+ fileHelper_1.FileHelper.writeFile(`${rolePath}/rolesSlice.ts`, roleSliceCode);
148
+ fileHelper_1.FileHelper.writeFile(`${rolePath}/rolesGetter.ts`, rolesGetterCode);
149
+ fileHelper_1.FileHelper.writeFile(`${rolePath}/type.ts`, rolesTypeCode);
150
+ }
151
+ writeStoreFiles() {
152
+ const apiMainSectionList = JSON.parse(fileHelper_1.FileHelper.readFile(`${this.configPath}/apiConfig.json`));
153
+ const allApiSections = apiMainSectionList.flatMap((section) => section.apiSectionList.map((api) => (Object.assign(Object.assign({}, api), { sectionName: section.name }))));
154
+ const reducerCode = this.generateReducersCode(allApiSections);
155
+ this.generateRoleRelatedFiles();
156
+ apiMainSectionList.forEach(expressSection => {
157
+ const rnApiPath = path_1.default.join(this.folderPath, `src-gen/redux/${expressSection.name}`);
158
+ const rnSelectorPath = path_1.default.join(this.folderPath, `src/redux/selectors/${expressSection.name}`);
159
+ const rnReducerPath = path_1.default.join(this.folderPath, `src-gen/redux/gen-reducers.ts`);
160
+ // const rnSagaPath = path.join(this.folderPath, `src-gen/redux/gen-root-saga.ts`);
161
+ const rootSagaCode = this.generateRootSagaCode(expressSection.apiSectionList, expressSection.name);
162
+ fileHelper_1.FileHelper.writeFile(rnReducerPath, reducerCode);
163
+ // FileHelper.writeFile(rnSagaPath, rootSagaCode);
164
+ expressSection.apiSectionList.forEach(apiSection => {
165
+ const apiSectionSlicePath = path_1.default.join(rnApiPath, apiSection.name, `${apiSection.name}Slice.ts`);
166
+ const apiSectionSelectorPath = path_1.default.join(rnApiPath, apiSection.name, `selector.ts`);
167
+ const apiSectionDataPath = path_1.default.join(rnApiPath, apiSection.name, `data.ts`);
168
+ const apiSectionActionPath = path_1.default.join(rnApiPath, apiSection.name, `action.ts`);
169
+ const apiSelectorPath = path_1.default.join(rnSelectorPath, `${apiSection.name}.ts`);
170
+ // const apiSectionSagaPath = path.join(rnApiPath, apiSection.name, `${apiSection.name}Saga.ts`);
171
+ const sliceCode = this.generateSliceCode(apiSection);
172
+ const dataCode = this.generateApiDatacode(apiSection);
173
+ const actionCode = this.generateApiActioncode(apiSection, expressSection);
174
+ const selectorCode = this.generateApiSelectorCode(apiSection);
175
+ // const sagaCode = this.generateSagaCode(apiSection);
176
+ fileHelper_1.FileHelper.writeFile(apiSectionSlicePath, sliceCode);
177
+ fileHelper_1.FileHelper.writeFile(apiSectionSelectorPath, selectorCode);
178
+ fileHelper_1.FileHelper.createFile(apiSelectorPath, `
179
+ import { RootState } from "@/redux/store/store";
180
+ import * as ${apiSection.name}Selector from "src-gen/redux/${expressSection.name}/${apiSection.name}/selector";`);
181
+ if (!this.isEmptyOrWhitespace(dataCode)) {
182
+ fileHelper_1.FileHelper.writeFile(apiSectionDataPath, dataCode);
183
+ }
184
+ fileHelper_1.FileHelper.writeFile(apiSectionActionPath, actionCode);
185
+ // FileHelper.writeFile(apiSectionSagaPath, sagaCode);
186
+ });
187
+ });
188
+ }
189
+ isEmptyOrWhitespace(str) {
190
+ return str.trim().length === 0;
191
+ }
192
+ generateSliceCode(apiSection) {
193
+ const filteredApiListForData = apiSection.apiList.filter(api => {
194
+ const inputKeyList = Object.keys(api.input);
195
+ const outputKeyList = Object.keys(api.output);
196
+ return inputKeyList.length > 0 || outputKeyList.length > 0;
197
+ });
198
+ const code = `
199
+ import { createSlice, PayloadAction } from "@reduxjs/toolkit";
200
+ import {${apiSection.apiList.reduce((acc, curVal) => {
201
+ acc = acc + `${curVal.name}AsyncThunk,`;
202
+ return acc;
203
+ }, '')}} from './action';
204
+
205
+ ${filteredApiListForData.length > 0 ? `import { ${filteredApiListForData.reduce((acc, curVal) => {
206
+ const inputKeyList = Object.keys(curVal.input);
207
+ const outputKeyList = Object.keys(curVal.output);
208
+ // const inputDataTypeName: string = (`${apiSection.name}_${curVal.name}_Input`).toUpperCase();
209
+ const outputDataTypeName = (`${apiSection.name}_${curVal.name}_Output`).toUpperCase();
210
+ // acc = acc + `${inputKeyList.length > 0 ? inputDataTypeName + `,I_${inputDataTypeName}`+ ',' : ''}`;
211
+ acc = acc + `${outputKeyList.length > 0 ? outputDataTypeName + `,I_${outputDataTypeName}` + ',' : ''}`;
212
+ return acc;
213
+ }, '')} } from "./data";` : ''}
214
+
215
+ ${apiSection.apiList.reduce((acc, curVal) => {
216
+ var _a, _b, _c;
217
+ if ((_a = curVal === null || curVal === void 0 ? void 0 : curVal.directOutput) === null || _a === void 0 ? void 0 : _a.name) {
218
+ const [moduleName, dataName] = (_c = (_b = curVal === null || curVal === void 0 ? void 0 : curVal.directOutput) === null || _b === void 0 ? void 0 : _b.name) === null || _c === void 0 ? void 0 : _c.split("->");
219
+ console.log(dataName, moduleName, "DataName...........");
220
+ if (dataName) {
221
+ const dataTypeName = `${dataName === null || dataName === void 0 ? void 0 : dataName.replace("[]", "")}`;
222
+ acc = acc + `import {${dataTypeName},I_${dataTypeName}} from "../../../data/${moduleName}";`;
223
+ }
224
+ }
225
+ return acc;
226
+ }, '')}
227
+
228
+
229
+ import { ApiStatus } from "../../../data/common";
230
+ interface ${apiSection.name}State {
231
+ ${apiSection.apiList.reduce((acc, curVal) => {
232
+ var _a, _b;
233
+ const [moduleName, dataName] = ((_b = (_a = curVal === null || curVal === void 0 ? void 0 : curVal.directOutput) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.split("->")) || [];
234
+ acc = acc + `${curVal.name}: {
235
+ data: ${Object.keys(curVal.output).length > 0 ? `I_${apiSection.name.toUpperCase()}_${curVal.name.toUpperCase()}_OUTPUT` : dataName ? `I_${dataName}` : "any"},\n
236
+ status: ApiStatus,
237
+ error:string|null
238
+ }
239
+ `;
240
+ return acc;
241
+ }, "")}
242
+ }
243
+
244
+ const initialState: ${apiSection.name}State = {
245
+ ${apiSection.apiList.reduce((acc, curVal) => {
246
+ var _a, _b;
247
+ const [moduleName, dataName] = ((_b = (_a = curVal === null || curVal === void 0 ? void 0 : curVal.directOutput) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.split("->")) || [];
248
+ const isOutputDataArray = (dataName || "").includes("[]");
249
+ acc = acc + `${curVal.name}:{
250
+ data: ${Object.keys(curVal.output).length > 0 ? `new ${apiSection.name.toUpperCase()}_${curVal.name.toUpperCase()}_OUTPUT().toJSON()` : (dataName && !isOutputDataArray) ? `new ${dataName}().toJSON()` : (dataName && isOutputDataArray) ? '[]' : "null"},
251
+ status: ApiStatus.Idle,
252
+ error: null
253
+ },\n`;
254
+ return acc;
255
+ }, "")}
256
+ }
257
+
258
+ export const ${apiSection.name}Slice = createSlice({
259
+ name: "${apiSection.name}",
260
+ initialState,
261
+ reducers: {
262
+ reset${apiSection.name}Reducer: () => initialState
263
+ },
264
+ extraReducers: (builder) =>{
265
+ builder.
266
+ ${apiSection.apiList.reduce((acc, curVal, currentIndex) => {
267
+ acc = acc + `addCase(${curVal.name}AsyncThunk.pending, state => {
268
+ state.${curVal.name}.status= ApiStatus.Loading;
269
+ state.${curVal.name}.error= null;
270
+ })\n\t\t.addCase(${curVal.name}AsyncThunk.fulfilled,(state, action) => {
271
+ state.${curVal.name}.status = ApiStatus.Success;
272
+ state.${curVal.name}.data = action.payload;
273
+ state.${curVal.name}.error = null;
274
+ })\n\t\t.addCase(${curVal.name}AsyncThunk.rejected, (state, action) => {
275
+ state.${curVal.name}.status = ApiStatus.Failed;
276
+ state.${curVal.name}.error = action.payload as string;
277
+ })\n\t\t${currentIndex < apiSection.apiList.length - 1 ? '.' : ''}`;
278
+ return acc;
279
+ }, "")}
280
+ }
281
+ });
282
+
283
+ export const {reset${apiSection.name}Reducer} = ${apiSection.name}Slice.actions;
284
+ export default ${apiSection.name}Slice.reducer;
285
+ `;
286
+ return code;
287
+ }
288
+ generateSagaCode(apiSection) {
289
+ const code = `
290
+ import { put, takeLatest } from "redux-saga/effects";
291
+ import { PayloadAction } from "@reduxjs/toolkit";
292
+
293
+
294
+ import { ${apiSection.apiList.reduce((acc, curVal) => {
295
+ acc = acc + `${curVal.name}Api,`;
296
+ return acc;
297
+ }, '')} }from './action';
298
+
299
+ import { ${apiSection.apiList.reduce((acc, curVal) => {
300
+ acc = acc + `${curVal.name}SuccessAction,${curVal.name}ErrorAction,`;
301
+ return acc;
302
+ }, '')} } from "./${apiSection.name}Slice";
303
+
304
+ ${apiSection.apiList.reduce((acc, curVal) => {
305
+ const inputKeyList = Object.keys(curVal.input);
306
+ acc = acc + `
307
+ function* ${curVal.name}Saga(action: PayloadAction<any>): any {
308
+ try {
309
+ const response: any = yield ${curVal.name}Api(${inputKeyList.length > 0 ? `action.payload` : ``})
310
+ yield put(${curVal.name}SuccessAction(response.data))
311
+ } catch(e: any) {
312
+ yield put(${curVal.name}ErrorAction(e));
313
+ }
314
+ }
315
+
316
+ export function* watch${apiSection.name}${curVal.name}() {
317
+ yield takeLatest("${apiSection.name}/${curVal.name}Action", ${curVal.name}Saga);
318
+ }
319
+ `;
320
+ return acc;
321
+ }, '')}
322
+
323
+ `;
324
+ return code;
325
+ }
326
+ generateReducersCode(apiSectionList) {
327
+ const code = `
328
+ ${apiSectionList.reduce((acc, curVal) => {
329
+ console.log(curVal.name, "APINAME!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
330
+ acc = acc + `
331
+ import ${curVal.name}Reducer from './${curVal.sectionName}/${curVal.name}/${curVal.name}Slice';\n`;
332
+ return acc;
333
+ }, '')}
334
+
335
+ export const GeneratedReducers = {
336
+ ${apiSectionList.reduce((acc, curVal) => {
337
+ acc = acc + `${curVal.name.toLowerCase()}: ${curVal.name}Reducer,`;
338
+ return acc;
339
+ }, '')}
340
+ }
341
+ `;
342
+ return code;
343
+ }
344
+ generateApiActioncode(apiSection, expressSection) {
345
+ const filteredApiListForData = apiSection.apiList.filter(api => {
346
+ const inputKeyList = Object.keys(api.input);
347
+ const outputKeyList = Object.keys(api.output);
348
+ return inputKeyList.length > 0 || outputKeyList.length > 0;
349
+ });
350
+ const code = `
351
+ import { createAsyncThunk } from "@reduxjs/toolkit";
352
+ import axios, { AxiosError } from 'axios';
353
+ import {${expressSection.name}Api} from "../../../../src/remote-api-point";
354
+ ${filteredApiListForData.length > 0 ? `import { ${filteredApiListForData.reduce((acc, curVal) => {
355
+ const inputKeyList = Object.keys(curVal.input);
356
+ const outputKeyList = Object.keys(curVal.output);
357
+ const inputDataTypeName = (`${apiSection.name}_${curVal.name}_Input`).toUpperCase();
358
+ const outputDataTypeName = (`${apiSection.name}_${curVal.name}_Output`).toUpperCase();
359
+ acc = acc + `${inputKeyList.length > 0 ? inputDataTypeName + ',' : ''}`;
360
+ acc = acc + `${outputKeyList.length > 0 ? outputDataTypeName + ',' : ''}`;
361
+ return acc;
362
+ }, '')} } from "./data";` : ''}
363
+
364
+ ${apiSection.apiList.reduce((acc, curVal) => {
365
+ var _a, _b, _c;
366
+ if ((_a = curVal === null || curVal === void 0 ? void 0 : curVal.directOutput) === null || _a === void 0 ? void 0 : _a.name) {
367
+ const [moduleName, dataName] = (_c = (_b = curVal === null || curVal === void 0 ? void 0 : curVal.directOutput) === null || _b === void 0 ? void 0 : _b.name) === null || _c === void 0 ? void 0 : _c.split("->");
368
+ // console.log(dataName,moduleName,"DataName...........")
369
+ if (dataName) {
370
+ acc = acc + `import * as ${moduleName} from "../../../data/${moduleName}";`;
371
+ }
372
+ }
373
+ return acc;
374
+ }, '')}
375
+
376
+
377
+
378
+
379
+
380
+ const showError = (err: AxiosError) => {
381
+ const errorResponse: any = err.response?.data;
382
+ if (errorResponse) {
383
+ return {status: err.status,data: errorResponse}
384
+ }
385
+ else {
386
+ return {status: err.status||500, data: err.message||"Unknown Error"}
387
+ }
388
+ }
389
+
390
+
391
+
392
+
393
+
394
+ ${apiSection.apiList.reduce((acc, curVal) => {
395
+ var _a, _b;
396
+ const inputKeyList = Object.keys(curVal.input);
397
+ const outputKeyList = Object.keys(curVal.output);
398
+ const inputDataTypeName = (`${apiSection.name}_${curVal.name}_Input`).toUpperCase();
399
+ const outputDataTypeName = (`${apiSection.name}_${curVal.name}_Output`).toUpperCase();
400
+ const [moduleName, dataName] = ((_b = (_a = curVal === null || curVal === void 0 ? void 0 : curVal.directOutput) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.split("->")) || [];
401
+ acc = acc + `
402
+
403
+
404
+ export const ${curVal.name}Api = async (${inputKeyList.length > 0 ? `input: ${inputDataTypeName},` : ``} ) => {
405
+ return ${expressSection.name}Api.${curVal.type.toLowerCase()}('${curVal.url}',${inputKeyList.length > 0 ? `${curVal.type == 'POST' ? 'input' : '{params: input.toJSON()}'}` : ''});
406
+ }
407
+ export const ${curVal.name}AsyncThunk = createAsyncThunk<${outputKeyList.length > 0 ? outputDataTypeName : dataName ? `${moduleName}.${dataName}` : 'any'},${inputKeyList.length > 0 ? `${inputDataTypeName}` : `void`},any>('${apiSection.name}/${curVal.name}', async (${inputKeyList.length > 0 ? `input: ${inputDataTypeName}` : `_`}, { rejectWithValue }) => {
408
+ return call${this.capitalizeFirstLetter(curVal.name)}Api(${inputKeyList.length > 0 ? `input,` : ''} output => {
409
+ return output
410
+ },error=> {
411
+ return rejectWithValue(error)
412
+ })
413
+ })
414
+
415
+
416
+ export const call${this.capitalizeFirstLetter(curVal.name)}Api = async (${inputKeyList.length > 0 ? `input: ${inputDataTypeName},` : ``} output: (output: ${outputKeyList.length > 0 ? outputDataTypeName : dataName ? `${moduleName}.${dataName}` : 'any'}) => any,error?: (errMsg: any) => void) => {
417
+ try {
418
+ //const { data } = await ${expressSection.name}Api.${curVal.type.toLowerCase()}('${this.getApiName(apiSection.name)}/${this.getApiName(curVal.name)}',${inputKeyList.length > 0 ? `${curVal.type == 'POST' ? 'input' : '{params: input.toJSON()}'}` : ''});
419
+ const { data } = await ${curVal.name}Api(${inputKeyList.length > 0 ? `${curVal.type == 'POST' ? 'input' : 'input'}` : ''});
420
+ return output(data);
421
+ } catch (err: any) {
422
+ if(error) {
423
+ return error(showError(err));
424
+ }
425
+
426
+ }
427
+ }
428
+ `;
429
+ return acc;
430
+ }, '')}
431
+
432
+ `;
433
+ return code;
434
+ }
435
+ generateApiSelectorCode(apiSection) {
436
+ const code = `
437
+ import { RootState } from "@/redux/store/store";
438
+
439
+ ${apiSection.apiList.reduce((acc, curVal) => {
440
+ acc = acc +
441
+ `export const select${this.capitalizeFirstLetter(curVal.name)}Data = (state: RootState) => state.${apiSection.name.toLocaleLowerCase()}.${curVal.name}.data;\n`;
442
+ return acc;
443
+ }, '')}
444
+ `;
445
+ return code;
446
+ }
447
+ generateRootSagaCode(apiSectionList, expressSectionName) {
448
+ const code = `
449
+ import { all, fork } from "redux-saga/effects";
450
+ ${apiSectionList.reduce((acc, curVal) => {
451
+ acc = acc + `
452
+ import{
453
+ ${curVal.apiList.reduce((apiAcc, apiCurVal) => {
454
+ apiAcc = apiAcc + `
455
+ watch${curVal.name}${apiCurVal.name},
456
+ `;
457
+ return apiAcc;
458
+ }, '')}
459
+ } from './${expressSectionName}/${curVal.name}/${curVal.name}Saga';\n
460
+ `;
461
+ return acc;
462
+ }, '')}
463
+
464
+
465
+
466
+
467
+ const genRootSaga = [
468
+
469
+ ${apiSectionList.reduce((acc, curVal) => {
470
+ acc = acc + `
471
+
472
+ ${curVal.apiList.reduce((apiAcc, apiCurVal) => {
473
+ apiAcc = apiAcc + `
474
+ watch${curVal.name}${apiCurVal.name}()
475
+ ,
476
+ `;
477
+ return apiAcc;
478
+ }, '')}
479
+
480
+ `;
481
+ return acc;
482
+ }, '')}
483
+
484
+ ];
485
+
486
+ export default genRootSaga;
487
+ `;
488
+ return code;
489
+ }
490
+ getApiName(apiName) {
491
+ return apiName.replace(/[A-Z]/g, m => "-" + m.toLowerCase()).replace(/^-/, '');
492
+ }
493
+ capitalizeFirstLetter(val) {
494
+ return val.charAt(0).toUpperCase() + val.slice(1);
495
+ }
496
+ generateApiDatacode(apiSection) {
497
+ return this.generateSampleApiDataCode(apiSection, "react-native");
498
+ }
499
+ generateSampleApiDataCode(apiSection, type = "api") {
500
+ const imports = new Set(); // Collect unique imports
501
+ const code = `
502
+ ${apiSection.apiList.reduce((acc, api) => {
503
+ const inputKeyList = Object.keys(api.input);
504
+ const outputKeyList = api.output ? Object.keys(api.output) : [];
505
+ const inputDataTypeName = (`${apiSection.name}_${api.name}_Input`).toUpperCase();
506
+ const outputDataTypeName = (`${apiSection.name}_${api.name}_Output`).toUpperCase();
507
+ inputKeyList.forEach(inputKey => {
508
+ const typeParts = api.input[inputKey].type.split("->");
509
+ if (typeParts.length === 2) {
510
+ const [module, typeName] = typeParts;
511
+ const baseTypeName = typeName.endsWith("[]") ? typeName.slice(0, -2) : typeName;
512
+ if (type === "api") {
513
+ imports.add(`import { ${baseTypeName} } from '../data/${module}';`);
514
+ }
515
+ else {
516
+ imports.add(`import { ${baseTypeName} } from 'src-gen/data/${module}';`);
517
+ }
518
+ }
519
+ });
520
+ outputKeyList.forEach(outputKey => {
521
+ const typeParts = api.output[outputKey].type.split("->");
522
+ if (typeParts.length === 2) {
523
+ const [module, typeName] = typeParts;
524
+ const baseTypeName = typeName.endsWith("[]") ? typeName.slice(0, -2) : typeName;
525
+ if (type === "api") {
526
+ imports.add(`import { ${baseTypeName} } from '../data/${module}';`);
527
+ }
528
+ else {
529
+ imports.add(`import { ${baseTypeName} } from 'src-gen/data/${module}';`);
530
+ }
531
+ }
532
+ });
533
+ acc = acc + `
534
+
535
+ ${inputKeyList.length > 0 ? `
536
+ export class ${inputDataTypeName} {
537
+
538
+
539
+ constructor(
540
+ ${inputKeyList
541
+ .map((inputKey) => ` public ${inputKey}: ${this.resolveType(api.input[inputKey].type)}${!api.input[inputKey].required ? '|undefined' : ''} = ${this.getDefaultValue(api.input[inputKey])},`)
542
+ .join('\n')}
543
+ ) {}
544
+
545
+ static fromJSON(jsonObj: any):${inputDataTypeName} {
546
+ return new ${inputDataTypeName}(
547
+ ${inputKeyList
548
+ .map((inputKey) => this.generateFromJSONField(Object.assign(Object.assign({}, api.input[inputKey]), { name: inputKey })))
549
+ .join(',\n')}
550
+ );
551
+ }
552
+
553
+ toJSON():any {
554
+ return {
555
+ ${inputKeyList
556
+ .map((inputKey) => this.generateToJSONField(Object.assign(Object.assign({}, api.input[inputKey]), { name: inputKey })))
557
+ .join('\n')}
558
+ };
559
+ }
560
+
561
+
562
+ }\n
563
+
564
+ export interface I_${inputDataTypeName} {
565
+ ${inputKeyList
566
+ .map((inputKey) => ` ${inputKey}: ${this.resolveType(api.input[inputKey].type)}${!api.input[inputKey].required ? '|undefined' : ''},`)
567
+ .join('\n')}
568
+ }
569
+ ` : ''}
570
+
571
+ ${outputKeyList.length > 0 ? `export class ${outputDataTypeName} {
572
+
573
+ constructor(
574
+ ${outputKeyList
575
+ .map((outputKey) => ` public ${outputKey}: ${this.resolveType(api.output[outputKey].type)}${!api.output[outputKey].required ? '|undefined' : ''} = ${this.getDefaultValue(api.output[outputKey])},`)
576
+ .join('\n')}
577
+ ) {}
578
+
579
+ static fromJSON(jsonObj: any):${outputDataTypeName} {
580
+ return new ${outputDataTypeName}(
581
+ ${outputKeyList
582
+ .map((outputKey) => this.generateFromJSONField(Object.assign(Object.assign({}, api.output[outputKey]), { name: outputKey })))
583
+ .join(',\n')}
584
+ );
585
+ }
586
+
587
+
588
+ toJSON():any {
589
+ return {
590
+ ${outputKeyList
591
+ .map((outputKey) => this.generateToJSONField(Object.assign(Object.assign({}, api.output[outputKey]), { name: outputKey })))
592
+ .join('\n')}
593
+ };
594
+ }
595
+ }
596
+ export interface I_${outputDataTypeName} {
597
+ ${outputKeyList
598
+ .map((outputKey) => ` ${outputKey}: ${this.resolveType(api.output[outputKey].type)}${!api.output[outputKey].required ? '|undefined' : ''},`)
599
+ .join('\n')}
600
+ }
601
+ ` : ''}
602
+
603
+ `;
604
+ return acc;
605
+ }, "")}
606
+ `;
607
+ return Array.from(imports).join('\n') + code;
608
+ }
609
+ resolveType(type) {
610
+ const typeParts = type.split("->");
611
+ const baseType = typeParts.length === 2 ? typeParts[1] : type;
612
+ return baseType.endsWith("[]") ? `${baseType.slice(0, -2)}[]` : baseType; // Handle array types
613
+ }
614
+ getDefaultValue(field) {
615
+ const typeParts = field.type.split("->");
616
+ const baseType = typeParts.length === 2 ? typeParts[1] : field.type;
617
+ if (baseType.endsWith("[]")) {
618
+ return "[]"; // Default value for arrays
619
+ }
620
+ if (typeParts.length === 2) {
621
+ const [, typeName] = typeParts;
622
+ const baseTypeName = typeName.endsWith("[]") ? typeName.slice(0, -2) : typeName;
623
+ return field.required ? `new ${baseTypeName}()` : "undefined"; // Instantiate the imported class
624
+ }
625
+ switch (field.type) {
626
+ case "string":
627
+ return field.required ? "''" : "undefined";
628
+ case "object":
629
+ return field.required ? "{}" : "undefined";
630
+ case "boolean":
631
+ return field.required ? "false" : "undefined";
632
+ case "number":
633
+ return field.required ? "0" : "undefined";
634
+ default:
635
+ return "null";
636
+ }
637
+ }
638
+ generateFromJSONField(field) {
639
+ console.log(field, "field");
640
+ const typeParts = field.type.split("->");
641
+ const baseType = typeParts.length === 2 ? typeParts[1] : field.type;
642
+ if (baseType.endsWith("[]")) {
643
+ const elementType = baseType.slice(0, -2);
644
+ if (["string", "number", "boolean"].includes(elementType)) {
645
+ return ` jsonObj.${field.name} ?? []`;
646
+ }
647
+ return ` (jsonObj.${field.name} != null) ? jsonObj.${field.name}.map((item: any) => ${elementType}.fromJSON(item)) : []`;
648
+ }
649
+ if (typeParts.length === 2) {
650
+ const [, typeName] = typeParts;
651
+ const baseTypeName = typeName.endsWith("[]") ? typeName.slice(0, -2) : typeName;
652
+ return ` (jsonObj.${field.name} != null) ? ${baseTypeName}.fromJSON(jsonObj.${field.name}) : new ${baseTypeName}()`;
653
+ }
654
+ return ` (jsonObj.${field.name} !== null) ? jsonObj?.${field.name} : undefined`;
655
+ }
656
+ generateToJSONField(field) {
657
+ // const typeParts = field.type.split("->");
658
+ // const baseType = typeParts.length === 2 ? typeParts[1] : field.type;
659
+ // if (baseType.endsWith("[]")) {
660
+ // const elementType = baseType.slice(0, -2);
661
+ // if (["string", "number", "boolean"].includes(elementType)) {
662
+ // return ` ${field.name}: this.${field.name} ?? [],`;
663
+ // }
664
+ // return ` ${field.name}: (this.${field.name} != null) ? this.${field.name}.map((x) => x.toJson()) : [],`;
665
+ // }
666
+ // return ` ${field.name}: this.${field.name} != null ? this.${field.name} : undefined,`;
667
+ const typeParts = field.type.split("->");
668
+ const baseType = typeParts.length === 2 ? typeParts[1] : field.type;
669
+ if (baseType.endsWith("[]")) {
670
+ const elementType = baseType.slice(0, -2);
671
+ if (["string", "number", "boolean", "object", "any"].includes(elementType)) {
672
+ return ` ${field.name}: this.${field.name} ?? [],`;
673
+ }
674
+ return ` ${field.name}: (this.${field.name} != null) ? this.${field.name}.map((x) => x.toJSON()) : [],`;
675
+ }
676
+ else {
677
+ if (["string", "number", "boolean", "object", "any"].includes(baseType)) {
678
+ return `${field.name}: this.${field.name} != null ? this.${field.name} : ${this.getDefaultValue(field)},`;
679
+ }
680
+ else {
681
+ return ` ${field.name}: this.${field.name} != null ? this.${field.name}.toJSON() : ${field.required ? `${this.getDefaultValue(field)}.toJSON()` : 'undefined'},`;
682
+ }
683
+ }
684
+ }
685
+ }
686
+ exports.default = ApiHelper;
687
+ const commonApiDataCode = `
688
+ export enum ApiStatus {
689
+ Success="Success",
690
+ Loading="Loading",
691
+ Failed="Failed",
692
+ Idle="Idle"
693
+ }
694
+ `;
695
+ const snackbarSliceCode = `
696
+ import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
697
+
698
+
699
+ export interface SnackbarRequest {
700
+ type: SnackbarType,
701
+ message: string,
702
+ timing: number
703
+ }
704
+
705
+ export enum SnackbarType {
706
+ Success="success",
707
+ Error="error",
708
+ }
709
+
710
+
711
+ interface SnackbarState {
712
+ snackbarRequestList: SnackbarRequest[]
713
+ }
714
+
715
+ const initialState:SnackbarState = {
716
+ snackbarRequestList: []
717
+ }
718
+
719
+
720
+ export const snackbarSlice= createSlice({
721
+ name: "Snackbar",
722
+ initialState: initialState,
723
+ reducers: {
724
+ addSnackbar: (state, action: {type:String,payload: SnackbarRequest}) => {
725
+ state.snackbarRequestList.push(action.payload);
726
+ },
727
+ removeLastSnackbar: (state) => {
728
+ state.snackbarRequestList.pop();
729
+ },
730
+ }
731
+ });
732
+
733
+
734
+ export const {addSnackbar,removeLastSnackbar} = snackbarSlice.actions;
735
+
736
+ export default snackbarSlice.reducer;
737
+ `;
738
+ const mainStoreCode = `
739
+
740
+
741
+ import { configureStore } from '@reduxjs/toolkit'
742
+ import { GeneratedReducers } from 'src-gen/redux/gen-reducers';
743
+ const store = configureStore({
744
+ reducer: {
745
+ ...GeneratedReducers,
746
+ },
747
+
748
+ })
749
+
750
+
751
+
752
+ export type RootState = ReturnType<typeof store.getState>
753
+
754
+ export type AppDispatch = typeof store.dispatch;
755
+
756
+ export default store;
757
+ `;
758
+ const hooksCode = `
759
+ import { useDispatch, useSelector } from 'react-redux'
760
+ import type { TypedUseSelectorHook } from 'react-redux'
761
+ import type { RootState, AppDispatch } from './store/store'
762
+
763
+ // Use throughout your app instead of plain useDispatch and useSelector
764
+ export const useAppDispatch: () => AppDispatch = useDispatch
765
+ export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
766
+ `;