create-nizam-app 1.0.0
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/LICENSE +21 -0
- package/README.md +153 -0
- package/dist/__main__.js +3196 -0
- package/dist/templates/NIZAM_DOC.template +10 -0
- package/dist/templates/env.template +1 -0
- package/dist/templates/react/css/bootstrap.template +127 -0
- package/dist/templates/react/css/index.template +1 -0
- package/dist/templates/react/css/tailwind.template +100 -0
- package/dist/templates/react/js/app.template +11 -0
- package/dist/templates/react/js/data_fetching/axios.template +11 -0
- package/dist/templates/react/js/data_fetching/fetcher.template +5 -0
- package/dist/templates/react/js/data_fetching/http.template +5 -0
- package/dist/templates/react/js/jsconfig.template +8 -0
- package/dist/templates/react/js/layout.template +17 -0
- package/dist/templates/react/js/main.template +41 -0
- package/dist/templates/react/js/react_router-router.template +17 -0
- package/dist/templates/react/js/state_management/context/theme_context.template +3 -0
- package/dist/templates/react/js/state_management/context/theme_provider.template +15 -0
- package/dist/templates/react/js/state_management/context/use_theme.template +14 -0
- package/dist/templates/react/js/state_management/store/counter_slice.template +19 -0
- package/dist/templates/react/js/state_management/store/index.template +1 -0
- package/dist/templates/react/js/state_management/store/store.template +8 -0
- package/dist/templates/react/js/state_management/zustand/index.template +1 -0
- package/dist/templates/react/js/state_management/zustand/use_counter_store.template +11 -0
- package/dist/templates/react/js/tanstack_router-router.template +24 -0
- package/dist/templates/react/js/vite.config.template +16 -0
- package/dist/templates/react/ts/app.template +11 -0
- package/dist/templates/react/ts/data_fetching/axios.template +13 -0
- package/dist/templates/react/ts/data_fetching/fetcher.template +7 -0
- package/dist/templates/react/ts/data_fetching/http.template +7 -0
- package/dist/templates/react/ts/layout.template +17 -0
- package/dist/templates/react/ts/main.template +41 -0
- package/dist/templates/react/ts/react_router-router.template +20 -0
- package/dist/templates/react/ts/state_management/context/theme_context.template +11 -0
- package/dist/templates/react/ts/state_management/context/theme_provider.template +15 -0
- package/dist/templates/react/ts/state_management/context/use_theme.template +14 -0
- package/dist/templates/react/ts/state_management/store/counter_slice.template +25 -0
- package/dist/templates/react/ts/state_management/store/index.template +1 -0
- package/dist/templates/react/ts/state_management/store/store.template +11 -0
- package/dist/templates/react/ts/state_management/zustand/index.template +1 -0
- package/dist/templates/react/ts/state_management/zustand/use_counter_store.template +17 -0
- package/dist/templates/react/ts/tanstack_router-router.template +26 -0
- package/dist/templates/react/ts/vite.config.template +16 -0
- package/dist/templates/vscode/settings.template +14 -0
- package/package.json +93 -0
package/dist/__main__.js
ADDED
|
@@ -0,0 +1,3196 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import ora from 'ora';
|
|
4
|
+
import blessed from 'blessed';
|
|
5
|
+
import dns from 'dns/promises';
|
|
6
|
+
import { exec, execSync } from 'child_process';
|
|
7
|
+
import util from 'util';
|
|
8
|
+
import { input, confirm, rawlist, checkbox, Separator, select } from '@inquirer/prompts';
|
|
9
|
+
import stripAnsi from 'strip-ansi';
|
|
10
|
+
import { execa } from 'execa';
|
|
11
|
+
import fs from 'fs-extra';
|
|
12
|
+
import path from 'path';
|
|
13
|
+
import checkboxPlus from 'inquirer-checkbox-plus-plus';
|
|
14
|
+
import { fileURLToPath } from 'url';
|
|
15
|
+
import stripJsonComments from 'strip-json-comments';
|
|
16
|
+
|
|
17
|
+
let runtimeContext = null;
|
|
18
|
+
let reset_data = null;
|
|
19
|
+
function startProject(ctx) {
|
|
20
|
+
runtimeContext = ctx;
|
|
21
|
+
reset_data = structuredClone(ctx);
|
|
22
|
+
}
|
|
23
|
+
function useContext() {
|
|
24
|
+
if (!runtimeContext) {
|
|
25
|
+
throw new Error("Runtime Context not initialized. Call startProject() first.");
|
|
26
|
+
}
|
|
27
|
+
return runtimeContext;
|
|
28
|
+
}
|
|
29
|
+
async function resetContext() {
|
|
30
|
+
if (!reset_data)
|
|
31
|
+
return;
|
|
32
|
+
runtimeContext.user_options = reset_data.user_options;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function operations(opration_fun, opration_name, opration_dis) {
|
|
36
|
+
const { operation_state } = useContext();
|
|
37
|
+
const spinner = ora(chalk.yellowBright(`${opration_dis}....`)).start();
|
|
38
|
+
await opration_fun();
|
|
39
|
+
const is_ok = operation_state[opration_name].status;
|
|
40
|
+
const error_message = operation_state[opration_name].error_message;
|
|
41
|
+
if (is_ok === "success")
|
|
42
|
+
spinner.stopAndPersist({
|
|
43
|
+
symbol: `${chalk.yellowBright("[")}${chalk.green("✔")}${chalk.yellowBright("]")}`,
|
|
44
|
+
text: `${chalk.greenBright(`${opration_dis} is done.`)}`,
|
|
45
|
+
});
|
|
46
|
+
else {
|
|
47
|
+
spinner.stopAndPersist({
|
|
48
|
+
symbol: `${chalk.yellowBright("[")}${chalk.red("X")}${chalk.yellowBright("]")}`,
|
|
49
|
+
text: `${chalk.redBright(`${opration_dis} is fail.`)}`,
|
|
50
|
+
});
|
|
51
|
+
console.log(`${chalk.bold.red("[x]==>")} ${chalk.redBright(error_message)}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function say(message) {
|
|
56
|
+
// Create the screen
|
|
57
|
+
const screen = blessed.screen({
|
|
58
|
+
smartCSR: true,
|
|
59
|
+
title: "Welcome CLI",
|
|
60
|
+
});
|
|
61
|
+
// Static top and bottom lines
|
|
62
|
+
const topLine = blessed.box({
|
|
63
|
+
top: 0,
|
|
64
|
+
left: "left",
|
|
65
|
+
width: "100%",
|
|
66
|
+
height: 1,
|
|
67
|
+
content: "nizam say:",
|
|
68
|
+
style: { fg: "yellow", bold: true },
|
|
69
|
+
});
|
|
70
|
+
// Box for the dynamic message
|
|
71
|
+
const messageBox = blessed.box({
|
|
72
|
+
top: 0,
|
|
73
|
+
left: 11,
|
|
74
|
+
width: "80%",
|
|
75
|
+
height: "shrink",
|
|
76
|
+
content: "",
|
|
77
|
+
style: { fg: "green" },
|
|
78
|
+
wrap: true,
|
|
79
|
+
scrollable: true,
|
|
80
|
+
});
|
|
81
|
+
screen.append(topLine);
|
|
82
|
+
screen.append(messageBox);
|
|
83
|
+
screen.render();
|
|
84
|
+
// Function for typing effect for just the message
|
|
85
|
+
const typeEffect = async (text, delay = 80) => {
|
|
86
|
+
messageBox.setContent("");
|
|
87
|
+
screen.render();
|
|
88
|
+
for (let i = 0; i < text.length; i++) {
|
|
89
|
+
messageBox.setContent(text.slice(0, i + 1));
|
|
90
|
+
screen.render();
|
|
91
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
// Run the effect
|
|
95
|
+
await typeEffect(message);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function sectionBox(section_name) {
|
|
99
|
+
const padding = 2;
|
|
100
|
+
const totalLength = Math.max(section_name.length + padding * 2, 20);
|
|
101
|
+
const sideHashes = "=".repeat(totalLength);
|
|
102
|
+
// calculate spaces to center the text
|
|
103
|
+
const spaceEachSide = Math.floor((totalLength - section_name.length) / 2);
|
|
104
|
+
const line = " ".repeat(spaceEachSide) +
|
|
105
|
+
section_name +
|
|
106
|
+
" ".repeat(totalLength - section_name.length - spaceEachSide - 2);
|
|
107
|
+
// const empty_line =
|
|
108
|
+
// " ".repeat(spaceEachSide) + " ".repeat(totalLength - spaceEachSide - 1);
|
|
109
|
+
console.log(chalk.yellowBright(`✦ `) + chalk.bold.green(`${sideHashes}╮`));
|
|
110
|
+
// console.log(chalk.green(`¦ ${empty_line} ¦`));
|
|
111
|
+
console.log(`${chalk.green(`¦ `)}${chalk.yellowBright.bold(line)}${chalk.green(` ¦`)}`);
|
|
112
|
+
// console.log(chalk.green(`¦ ${empty_line} ¦`));
|
|
113
|
+
console.log(chalk.bold.green(`╰${sideHashes}`) + chalk.yellowBright(` ✦`));
|
|
114
|
+
console.log(chalk.yellowBright.bold(`↓`));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async function getPkgInfo(pkg_name) {
|
|
118
|
+
const res = await fetch(`https://registry.npmjs.org/${encodeURIComponent(pkg_name)}/latest`, {
|
|
119
|
+
signal: AbortSignal.timeout(60000),
|
|
120
|
+
});
|
|
121
|
+
if (!res.ok) {
|
|
122
|
+
throw `Failed to fetch version for ${pkg_name}`;
|
|
123
|
+
}
|
|
124
|
+
const npm_json = await res.json();
|
|
125
|
+
return [npm_json.name, npm_json.version];
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
var app_info = {
|
|
129
|
+
version: "1.0.0"
|
|
130
|
+
};
|
|
131
|
+
var core_documentation = {
|
|
132
|
+
aliases: {
|
|
133
|
+
des: "geeksforgeeks - aliases",
|
|
134
|
+
link: "https://www.geeksforgeeks.org/reactjs/how-to-setup-path-aliases-in-vite-react/"
|
|
135
|
+
},
|
|
136
|
+
app_structure: {
|
|
137
|
+
react: {
|
|
138
|
+
des: "github - React-Project-Structure",
|
|
139
|
+
link: "https://github.com/ahmed-abd-alalim/React-Project-Structure"
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
var appData = {
|
|
144
|
+
app_info: app_info,
|
|
145
|
+
core_documentation: core_documentation
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
const execAsync = util.promisify(exec);
|
|
149
|
+
async function intro() {
|
|
150
|
+
const { pkg_is_installed } = useContext();
|
|
151
|
+
const cols = process.stdout.columns;
|
|
152
|
+
const pkg_list = ["npm", "bun", "pnpm", "yarn"];
|
|
153
|
+
const [, get_nizam_new_v] = await getPkgInfo("create-nizam-app");
|
|
154
|
+
const get_nizam_current_v = appData.app_info.version;
|
|
155
|
+
const is_new_v = String(get_nizam_new_v) !== String(get_nizam_current_v);
|
|
156
|
+
const lg_logo = chalk.yellowBright(`
|
|
157
|
+
░▒▒▒
|
|
158
|
+
▒▓▓▓ ${chalk.redBright.bold("ahmed abd alalim - 3A")}
|
|
159
|
+
░░░
|
|
160
|
+
▓▓▓▒▒▓▓▓▓▓ ▒▓▓▓ ▒▓▓▓▓▓▓▓▓▒ ░▓▓▓▓▓▓▓▓▓▒ ▒▓▓▓▒▓▓▓▓▓░▓▓▓▓▒
|
|
161
|
+
▓▓▓▒ ▒▓▓▒ ▒▓▓▓ ░▓▓▓▒ ▒░░▓▓▓▓ ▒▓▓▓ ▒▓▓▓ ▒▓▓▓
|
|
162
|
+
▓▓▓▒ ▒▓▓▒ ▒▓▓▓ ░▓▓▓▒ ▓▓▒ ▓▓▓▓ ▒▓▓▓ ▒▓▓▓ ▒▓▓▓
|
|
163
|
+
▓▓▓▒ ▒▓▓▒ ▒▓▓▓ ░▓▓▓░ ▓▓▓░ ▓▓▓▓ ▒▓▓▓ ▒▓▓▓ ▒▓▓▓
|
|
164
|
+
▓▓▓▒ ▒▓▓▒ ▒▓▓▓ ▒▓▓▓▓▓▓▓▓▓ ▒▓▓▓▓▓▓▓▓▓▓ ▒▓▓▓ ▒▓▓▓ ▒▓▓▓
|
|
165
|
+
▒▒▒░ ▒▒▒▒ ░▒▒▒ ░▒▒▒▒▒▒▒▒▒▒ ░▒ ▒▒▒▒ ░▒▒▒ ░▒▒▒ ░▒▒▒ ${chalk.redBright.bold(`v${appData.app_info.version}`)}
|
|
166
|
+
|
|
167
|
+
${is_new_v ? chalk.red("[!] There is a new version with more features. used (npm install -g create-nizam-app) for make update.") : " "}
|
|
168
|
+
`);
|
|
169
|
+
const md_logo = chalk.yellowBright(`
|
|
170
|
+
|
|
171
|
+
░░ ${chalk.redBright.bold("ahmed abd alalim - 3A")}
|
|
172
|
+
░▓▓▒
|
|
173
|
+
░░░ ░░ ░░░░ ░░░░░░░░░ ░░░░░░░ ░░░ ░░ ░░
|
|
174
|
+
░▓▓▓▒▒▓▓▓▒ ░▓▓▒░▓▓▓▓▓▓▓▒ ░▓▓▓▓▓▓▓▓░ ▒▓▓▒▒▓▓▓▒▒▓▓▓░
|
|
175
|
+
░▓▓▓ ░▓▓▒ ░▓▓▒ ▒▓▓▒ ░▒ ▒▓▓▒ ▒▓▓ ▒▓▓░ ▒▓▓░
|
|
176
|
+
░▓▓▓ ░▓▓▒ ░▓▓▒ ▒▓▓▒ ▒▓▓ ▒▓▓▒ ▒▓▓ ▒▓▓░ ▒▓▓░
|
|
177
|
+
░▓▓▓ ░▓▓▒ ░▓▓▒ ▒▓▓▓▓▓▓▓ ▒▓▓▒ ▒▓▓▓▒ ▒▓▓ ▒▓▓░ ▒▓▓░
|
|
178
|
+
░▒▒▒ ░▒▒▒ ░▒▒▒ ▒▒▒▒▒▒▒▒▒ ▒▒▒▒ ▒▒▒░ ▒▒▒ ▒▒▒░ ▒▒▒░ ${chalk.redBright.bold(`v${appData.app_info.version}`)}
|
|
179
|
+
|
|
180
|
+
${is_new_v ? chalk.red("[!] There is a new version with more features. used (npm install -g create-nizam-app) for make update.") : " "}
|
|
181
|
+
`);
|
|
182
|
+
const sm_logo = chalk.yellowBright(`
|
|
183
|
+
░▒▒ ${chalk.redBright.bold("ahmed abd alalim - 3A")}
|
|
184
|
+
░▓▓░
|
|
185
|
+
▓▓▓ ▓▓▓▒ ░▓▓░▓▓▓▓▓▓▓▓ ▒▓▓▓▓▓▓▒ ▓▓▓░▓▓▓ ▒▓▓▒
|
|
186
|
+
▓▓▓ ▒▓▓░░▓▓░ ▒▓▓▒ ▒░▓▓▓░▓▓▓ ░▓▓▒ ▓▓▓
|
|
187
|
+
▓▓▓ ▒▓▓░░▓▓░ ▒▓▓░ ▒▓▒ ▓▓▓░▓▓▓ ░▓▓▒ ▓▓▓
|
|
188
|
+
▓▓▓ ▒▓▓░░▓▓░ ▒▓▓▓▓▓▓ ▓▓▓▒▒▓▓▓░▓▓▓ ░▓▓▒ ▓▓▓
|
|
189
|
+
▒▒▒ ░▒▒░░▒▒ ▒▒▒▒▒▒▒▒ ░▒ ▒▒▒ ▒▒▒ ░▒▒░ ▒▒▒ ${chalk.redBright.bold(`v${appData.app_info.version}`)}
|
|
190
|
+
|
|
191
|
+
${is_new_v ? chalk.red("[!] There is a new version with more features. used (npm install -g create-nizam-app) for make update.") : " "}
|
|
192
|
+
`);
|
|
193
|
+
console.clear();
|
|
194
|
+
try {
|
|
195
|
+
await dns.lookup("google.com");
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
console.error(chalk.redBright("\n❌ No internet connection"));
|
|
199
|
+
process.exit(1);
|
|
200
|
+
}
|
|
201
|
+
const view = cols && cols < 50 ? sm_logo : cols < 80 ? md_logo : lg_logo;
|
|
202
|
+
console.log(view);
|
|
203
|
+
// eslint-disable-next-line no-async-promise-executor
|
|
204
|
+
await new Promise(async (resolve) => {
|
|
205
|
+
const spinner = ora({
|
|
206
|
+
text: `${chalk.yellowBright("Loading")}`,
|
|
207
|
+
spinner: "dots",
|
|
208
|
+
}).start();
|
|
209
|
+
let i = 0;
|
|
210
|
+
const load = async () => {
|
|
211
|
+
spinner.text = `${chalk.yellowBright("Loading █")}${chalk
|
|
212
|
+
.yellowBright("█")
|
|
213
|
+
.repeat(i / 5)}${"░".repeat(20 - i / 5)} ${chalk.redBright(i)} ${chalk.yellowBright("%")}`;
|
|
214
|
+
if (i >= 100) {
|
|
215
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
216
|
+
spinner.stop();
|
|
217
|
+
resolve();
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
for (const pkg of pkg_list) {
|
|
222
|
+
try {
|
|
223
|
+
await execAsync(`${pkg} -v`);
|
|
224
|
+
pkg_is_installed.push(pkg);
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
/* empty */
|
|
228
|
+
}
|
|
229
|
+
i += Number((100 / pkg_list.length).toFixed(1));
|
|
230
|
+
load();
|
|
231
|
+
if (is_new_v) {
|
|
232
|
+
await new Promise((resolve) => setTimeout(resolve, 1500));
|
|
233
|
+
}
|
|
234
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
if (pkg_is_installed.length === 0) {
|
|
238
|
+
console.error(chalk.redBright("\n❌ Can't find any package manager for use it. install any one and try again."));
|
|
239
|
+
process.exit(1);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
async function printMenu() {
|
|
244
|
+
const title = "YOUR SELECTED OPTIONS";
|
|
245
|
+
const ctx = useContext();
|
|
246
|
+
const rows = Object.entries(ctx.user_options)
|
|
247
|
+
.filter(([, value]) => value !== null &&
|
|
248
|
+
value !== undefined &&
|
|
249
|
+
value !== "" &&
|
|
250
|
+
value.length !== 0)
|
|
251
|
+
.map(([key, value]) => {
|
|
252
|
+
let normalizedValue;
|
|
253
|
+
if (value === true)
|
|
254
|
+
normalizedValue = "yes";
|
|
255
|
+
else if (value === false)
|
|
256
|
+
normalizedValue = "no";
|
|
257
|
+
else
|
|
258
|
+
normalizedValue = String(value);
|
|
259
|
+
const cleanKey = key
|
|
260
|
+
.replace(/_/g, " ")
|
|
261
|
+
.split(" ")
|
|
262
|
+
.map((word) => {
|
|
263
|
+
if (word.length < 4) {
|
|
264
|
+
return word.toUpperCase();
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
|
|
268
|
+
}
|
|
269
|
+
})
|
|
270
|
+
.join(" ");
|
|
271
|
+
return {
|
|
272
|
+
raw: ` ${cleanKey} : ${normalizedValue}`,
|
|
273
|
+
colored: ` ${chalk.redBright(cleanKey)} : ${chalk.greenBright(normalizedValue)}`,
|
|
274
|
+
};
|
|
275
|
+
});
|
|
276
|
+
const allLines = [title, ...rows.map((r) => r.raw)];
|
|
277
|
+
const width = Math.max(...allLines.map((l) => l.length + (rows.length > 9 ? 9 : 8)));
|
|
278
|
+
const line = "═".repeat(width);
|
|
279
|
+
const line2 = "-".repeat(width);
|
|
280
|
+
console.log(chalk.yellowBright(`╔${line}╗`));
|
|
281
|
+
console.log(`${chalk.yellowBright("║")}${chalk.redBright(title.padStart((width + title.length) / 2).padEnd(width))}${chalk.yellowBright("║")}`);
|
|
282
|
+
console.log(chalk.yellowBright(`╠${line}╣`));
|
|
283
|
+
rows.forEach((row, i) => {
|
|
284
|
+
const padding = width - stripAnsi(row.raw).length;
|
|
285
|
+
console.log(`${chalk.yellowBright("║")}${chalk.yellowBright("[")}${chalk.redBright(i + 1)}${chalk.yellowBright("]")} ${row.colored + " ".repeat(padding - (i + 1 > 9 ? 5 : 4))}${chalk.yellowBright("║")}`);
|
|
286
|
+
if (rows.length - 1 === i)
|
|
287
|
+
return;
|
|
288
|
+
console.log(chalk.yellowBright(`╠${line2}╣`));
|
|
289
|
+
});
|
|
290
|
+
console.log(chalk.yellowBright(`╚${line}╝`));
|
|
291
|
+
await input({
|
|
292
|
+
message: `${chalk.yellowBright("\n[!] Press the Enter key to continue or (")}${chalk.redBright("q + Enter")}${chalk.yellowBright(") to go back to home.")}`,
|
|
293
|
+
theme: {
|
|
294
|
+
prefix: {
|
|
295
|
+
idle: ``,
|
|
296
|
+
done: ``,
|
|
297
|
+
},
|
|
298
|
+
},
|
|
299
|
+
validate: (inbut) => {
|
|
300
|
+
if (inbut.toLowerCase() === "q") {
|
|
301
|
+
ctx.reset_menu = true;
|
|
302
|
+
}
|
|
303
|
+
return true;
|
|
304
|
+
},
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function extractMainMessage(error) {
|
|
309
|
+
if (!error)
|
|
310
|
+
return "Unknown error";
|
|
311
|
+
if (typeof error.shortMessage === "string") {
|
|
312
|
+
return error.shortMessage;
|
|
313
|
+
}
|
|
314
|
+
if (typeof error.stderr === "string") {
|
|
315
|
+
return error.stderr.split("\n")[0];
|
|
316
|
+
}
|
|
317
|
+
if (error instanceof Error) {
|
|
318
|
+
return error.message.split("\n")[0];
|
|
319
|
+
}
|
|
320
|
+
if (typeof error === "string") {
|
|
321
|
+
return error;
|
|
322
|
+
}
|
|
323
|
+
return "Unexpected error occurred";
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
async function install() {
|
|
327
|
+
const { full_project_path, user_options, operation_state } = useContext();
|
|
328
|
+
try {
|
|
329
|
+
await execa(user_options.pkg_manager, ["install"], {
|
|
330
|
+
cwd: full_project_path,
|
|
331
|
+
timeout: 600000,
|
|
332
|
+
});
|
|
333
|
+
operation_state.install_all_packages.status = "success";
|
|
334
|
+
}
|
|
335
|
+
catch (e) {
|
|
336
|
+
if (e.timedOut) {
|
|
337
|
+
operation_state.install_all_packages.status = "fatal";
|
|
338
|
+
operation_state.install_all_packages.error_message = `⏱ Timeout, Check your internet connection and Take a look at the NIZAM_DOC.md file to learn how to continue the download.`;
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
operation_state.install_all_packages.status = "fatal";
|
|
342
|
+
operation_state.install_all_packages.error_message =
|
|
343
|
+
extractMainMessage(e);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
async function customInstall(npx_params, pkg_command_params) {
|
|
349
|
+
const { full_project_path } = useContext();
|
|
350
|
+
const pkj_installer = ["giget", "degit", "tiged"];
|
|
351
|
+
let success = false;
|
|
352
|
+
for (const pkj_ins of pkj_installer) {
|
|
353
|
+
try {
|
|
354
|
+
await execa(npx_params, [
|
|
355
|
+
"--yes",
|
|
356
|
+
pkj_ins,
|
|
357
|
+
pkj_ins === "giget" ? `gh:${pkg_command_params}` : pkg_command_params,
|
|
358
|
+
pkj_ins === "giget" ? `.` : "",
|
|
359
|
+
], {
|
|
360
|
+
cwd: full_project_path,
|
|
361
|
+
timeout: 600000,
|
|
362
|
+
});
|
|
363
|
+
success = true;
|
|
364
|
+
break;
|
|
365
|
+
}
|
|
366
|
+
catch (e) {
|
|
367
|
+
if (e.timedOut) {
|
|
368
|
+
throw "⏱ Timeout, Check your internet connection and try again";
|
|
369
|
+
}
|
|
370
|
+
if (e.exitCode === 1)
|
|
371
|
+
continue;
|
|
372
|
+
throw e;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
if (!success) {
|
|
376
|
+
throw "❌ All installers failed";
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
const rename = fs.rename;
|
|
381
|
+
const mkdir = fs.mkdir;
|
|
382
|
+
const lstat = fs.lstat;
|
|
383
|
+
const readdir = fs.readdir;
|
|
384
|
+
const ensureDir = fs.ensureDir;
|
|
385
|
+
const ensureFile = fs.ensureFile;
|
|
386
|
+
const readFile = fs.readFile;
|
|
387
|
+
const writeFile = fs.writeFile;
|
|
388
|
+
const appendFile = fs.appendFile;
|
|
389
|
+
const pathExists = fs.pathExists;
|
|
390
|
+
const remove = fs.remove;
|
|
391
|
+
const emptyDir = fs.emptyDir;
|
|
392
|
+
const readJson = fs.readJson;
|
|
393
|
+
const writeJson = fs.writeJson;
|
|
394
|
+
const outputJson = fs.outputJson;
|
|
395
|
+
|
|
396
|
+
function pathBox() {
|
|
397
|
+
const { full_project_path, nizam_templates_path, user_options } = useContext();
|
|
398
|
+
const js_or_ts = user_options.js_framework.includes("js") ? "js" : "ts";
|
|
399
|
+
return {
|
|
400
|
+
// nizam-app
|
|
401
|
+
src_path: path.resolve(full_project_path, "src"),
|
|
402
|
+
tsconfig_app_path: path.resolve(full_project_path, "tsconfig.app.json"),
|
|
403
|
+
jsconfig_app_path: path.resolve(full_project_path, "jsconfig.json"),
|
|
404
|
+
vite_config_path: path.resolve(full_project_path, `vite.config.${js_or_ts}`),
|
|
405
|
+
vsc_path: path.resolve(full_project_path, ".vscode"),
|
|
406
|
+
vsc_setting_path: path.resolve(full_project_path, ".vscode", "settings.json"),
|
|
407
|
+
index_css_path: path.resolve(full_project_path, "src", "index.css"),
|
|
408
|
+
main_react_path: path.resolve(full_project_path, "src", `main.${js_or_ts}x`),
|
|
409
|
+
old_gitignore_path: path.resolve(full_project_path, "_gitignore"),
|
|
410
|
+
new_gitignore_path: path.resolve(full_project_path, ".gitignore"),
|
|
411
|
+
nizam_Instructions_path: path.resolve(full_project_path, "NIZAM_DOC.md"),
|
|
412
|
+
README_path: path.resolve(full_project_path, "README.md"),
|
|
413
|
+
index_html_path: path.resolve(full_project_path, "index.html"),
|
|
414
|
+
public_path: path.resolve(full_project_path, "public"),
|
|
415
|
+
app_css_path: path.resolve(full_project_path, "src", "app.css"),
|
|
416
|
+
assets_folder_path: path.resolve(full_project_path, "src", "assets"),
|
|
417
|
+
app_react_path: path.resolve(full_project_path, "src", `App.${js_or_ts}x`),
|
|
418
|
+
package_json_path: path.resolve(full_project_path, "package.json"),
|
|
419
|
+
layout_path: path.resolve(full_project_path, "src", `layout.${js_or_ts}x`),
|
|
420
|
+
reactrouter_router_path: path.resolve(full_project_path, "src", `router.${js_or_ts}x`),
|
|
421
|
+
tanstackrouter_router_path: path.resolve(full_project_path, "src", `router.${js_or_ts}`),
|
|
422
|
+
context_path: path.resolve(full_project_path, "src", `context`),
|
|
423
|
+
context_theme_path: path.resolve(full_project_path, "src", `context`, "theme"),
|
|
424
|
+
theme_context_file_path: path.resolve(full_project_path, "src", `context`, "theme", `ThemeContext.${js_or_ts}`),
|
|
425
|
+
theme_provider_file_path: path.resolve(full_project_path, "src", `context`, "theme", `ThemeProvider.${js_or_ts}x`),
|
|
426
|
+
use_theme_file_path: path.resolve(full_project_path, "src", `context`, "theme", `useTheme.${js_or_ts}`),
|
|
427
|
+
store_path: path.resolve(full_project_path, "src", `store`),
|
|
428
|
+
store_file_path: path.resolve(full_project_path, "src", `store`, `store.${js_or_ts}`),
|
|
429
|
+
store_slices_path: path.resolve(full_project_path, "src", `store`, "slices"),
|
|
430
|
+
slices_index_file_path: path.resolve(full_project_path, "src", `store`, "slices", `index.${js_or_ts}`),
|
|
431
|
+
slices_counter_file_path: path.resolve(full_project_path, "src", `store`, "slices", `counterSlice.${js_or_ts}`),
|
|
432
|
+
zustand_use_counter_file_path: path.resolve(full_project_path, "src", `store`, `useCounterStore.${js_or_ts}`),
|
|
433
|
+
zustand_index_file_path: path.resolve(full_project_path, "src", `store`, `index.${js_or_ts}`),
|
|
434
|
+
env_path: path.resolve(full_project_path, ".env"),
|
|
435
|
+
api_path: path.resolve(full_project_path, "src", `api`),
|
|
436
|
+
api_http_file_path: path.resolve(full_project_path, "src", `api`, `http.${js_or_ts}`),
|
|
437
|
+
api_fetcher_file_path: path.resolve(full_project_path, "src", `api`, `fetcher.${js_or_ts}`),
|
|
438
|
+
api_axios_fle_path: path.resolve(full_project_path, "src", `api`, `axios.${js_or_ts}`),
|
|
439
|
+
// nizam-main
|
|
440
|
+
jsconfig_app_template: path.resolve(nizam_templates_path, "react", js_or_ts, "jsconfig.template"),
|
|
441
|
+
vsc_settings_templates: path.resolve(nizam_templates_path, "vscode", "settings.template"),
|
|
442
|
+
bootstrap_templates: path.resolve(nizam_templates_path, "react", "css", "bootstrap.template"),
|
|
443
|
+
tailwind_templates: path.resolve(nizam_templates_path, "react", "css", "tailwind.template"),
|
|
444
|
+
nizam_Instructions_templates: path.resolve(nizam_templates_path, "NIZAM_DOC.template"),
|
|
445
|
+
index_css_templates: path.resolve(nizam_templates_path, "react", "css", "index.template"),
|
|
446
|
+
app_react_templates: path.resolve(nizam_templates_path, "react", js_or_ts, "app.template"),
|
|
447
|
+
vite_config_templates: path.resolve(nizam_templates_path, "react", js_or_ts, "vite.config.template"),
|
|
448
|
+
main_react_templates: path.resolve(nizam_templates_path, "react", js_or_ts, "main.template"),
|
|
449
|
+
layout_templates: path.resolve(nizam_templates_path, "react", js_or_ts, "layout.template"),
|
|
450
|
+
reactrouter_router_templates: path.resolve(nizam_templates_path, "react", js_or_ts, "react_router-router.template"),
|
|
451
|
+
tanstackrouter_router_templates: path.resolve(nizam_templates_path, "react", js_or_ts, "tanstack_router-router.template"),
|
|
452
|
+
theme_context_file_template: path.resolve(nizam_templates_path, "react", js_or_ts, "state_management", "context", "theme_context.template"),
|
|
453
|
+
theme_provider_file_template: path.resolve(nizam_templates_path, "react", js_or_ts, "state_management", "context", "theme_provider.template"),
|
|
454
|
+
use_theme_file_template: path.resolve(nizam_templates_path, "react", js_or_ts, "state_management", "context", "use_theme.template"),
|
|
455
|
+
store_file_template: path.resolve(nizam_templates_path, "react", js_or_ts, "state_management", "store", "store.template"),
|
|
456
|
+
slices_index_file_template: path.resolve(nizam_templates_path, "react", js_or_ts, "state_management", "store", "index.template"),
|
|
457
|
+
slices_counter_file_template: path.resolve(nizam_templates_path, "react", js_or_ts, "state_management", "store", "counter_slice.template"),
|
|
458
|
+
zustand_use_counter_file_template: path.resolve(nizam_templates_path, "react", js_or_ts, "state_management", "zustand", `use_counter_store.template`),
|
|
459
|
+
zustand_index_file_template: path.resolve(nizam_templates_path, "react", js_or_ts, "state_management", "zustand", `index.template`),
|
|
460
|
+
env_template: path.resolve(nizam_templates_path, "env.template"),
|
|
461
|
+
api_http_file_template: path.resolve(nizam_templates_path, "react", js_or_ts, "data_fetching", `http.template`),
|
|
462
|
+
api_fetcher_file_template: path.resolve(nizam_templates_path, "react", js_or_ts, "data_fetching", `fetcher.template`),
|
|
463
|
+
api_axios_file_template: path.resolve(nizam_templates_path, "react", js_or_ts, "data_fetching", `axios.template`),
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
async function appendInPkgFile(pkg_name, pkg_v) {
|
|
468
|
+
const path_box = pathBox();
|
|
469
|
+
const package_json = await readJson(path_box.package_json_path, "utf8");
|
|
470
|
+
package_json.dependencies ??= {};
|
|
471
|
+
package_json.dependencies[pkg_name] = `^${pkg_v}`;
|
|
472
|
+
await writeJson(path_box.package_json_path, package_json, { spaces: 2 });
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
async function installDependencies({ user_option_library, lib_list, }) {
|
|
476
|
+
const package_identification = async (pkg_name) => {
|
|
477
|
+
const pkg_info = await getPkgInfo(pkg_name);
|
|
478
|
+
await appendInPkgFile(pkg_info[0], pkg_info[1]);
|
|
479
|
+
};
|
|
480
|
+
if (typeof user_option_library === "string") {
|
|
481
|
+
const lib_info = lib_list.find((i) => i.name.includes(user_option_library.toLowerCase()));
|
|
482
|
+
const fil_dependencies = lib_info?.dependencies.filter((x) => Boolean(x));
|
|
483
|
+
if (fil_dependencies?.length !== 0) {
|
|
484
|
+
for (const dependencie_name of fil_dependencies) {
|
|
485
|
+
await package_identification(dependencie_name);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
const lib_fun = lib_info?.fun;
|
|
489
|
+
await lib_fun();
|
|
490
|
+
}
|
|
491
|
+
else if (Array.isArray(user_option_library)) {
|
|
492
|
+
for (const lib_name of user_option_library) {
|
|
493
|
+
const lib_info = lib_list.find((i) => i.name.includes(lib_name.toLowerCase()));
|
|
494
|
+
const fil_dependencies = lib_info?.dependencies.filter((x) => Boolean(x));
|
|
495
|
+
if (fil_dependencies?.length !== 0) {
|
|
496
|
+
for (const dependencie_name of fil_dependencies) {
|
|
497
|
+
await package_identification(dependencie_name);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
const lib_fun = lib_info?.fun;
|
|
501
|
+
await lib_fun();
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
async function askAboutInstall() {
|
|
507
|
+
const { user_options, operation_state } = useContext();
|
|
508
|
+
const path_box = pathBox();
|
|
509
|
+
const question_theme = {
|
|
510
|
+
prefix: {
|
|
511
|
+
idle: `${chalk.yellowBright("[")}${chalk.blueBright("?")}${chalk.yellowBright("]")}`,
|
|
512
|
+
done: `${chalk.yellowBright("[")}${chalk.greenBright("✔")}${chalk.yellowBright("]")}`,
|
|
513
|
+
},
|
|
514
|
+
style: {
|
|
515
|
+
message: (text) => chalk.blueBright(text),
|
|
516
|
+
answer: (text) => chalk.greenBright(text),
|
|
517
|
+
},
|
|
518
|
+
};
|
|
519
|
+
const install_instructions = `
|
|
520
|
+
### install all package
|
|
521
|
+
|
|
522
|
+
#### Here’s the way, to install all packages
|
|
523
|
+
|
|
524
|
+
Run (Development mode)
|
|
525
|
+
\`\`\`bash
|
|
526
|
+
${user_options.pkg_manager} install
|
|
527
|
+
\`\`\`
|
|
528
|
+
---
|
|
529
|
+
`;
|
|
530
|
+
if (user_options.pkg_manager.length !== 0) {
|
|
531
|
+
const is_ok = await confirm({
|
|
532
|
+
message: `Do you want install all packages now?`,
|
|
533
|
+
default: false,
|
|
534
|
+
theme: question_theme,
|
|
535
|
+
});
|
|
536
|
+
if (is_ok) {
|
|
537
|
+
process.stdout.write("\x1b[1A\x1b[2K");
|
|
538
|
+
await operations(install, "install_all_packages", "Install all packages");
|
|
539
|
+
}
|
|
540
|
+
else {
|
|
541
|
+
const content = await readFile(path_box.nizam_Instructions_path, "utf8");
|
|
542
|
+
const lines = content.split("\n");
|
|
543
|
+
lines.splice(11, 0, install_instructions);
|
|
544
|
+
await writeFile(path_box.nizam_Instructions_path, lines.join("\n"), "utf8");
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
if (operation_state.install_all_packages.status === "fatal")
|
|
548
|
+
return;
|
|
549
|
+
await new Promise((r) => setTimeout(r, 1500));
|
|
550
|
+
await say(`Don't forget to take a look at the attached file ${chalk.bold("NIZAM_DOC.md")} within the new project to learn how to work with the downloaded packages.`);
|
|
551
|
+
await new Promise((r) => setTimeout(r, 4000));
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
const question_theme = {
|
|
555
|
+
prefix: {
|
|
556
|
+
idle: `${chalk.yellowBright("[")}${chalk.blueBright("?")}${chalk.yellowBright("]")}`,
|
|
557
|
+
done: `${chalk.yellowBright("[")}${chalk.greenBright("✔")}${chalk.yellowBright("]")}`,
|
|
558
|
+
},
|
|
559
|
+
style: {
|
|
560
|
+
message: (text) => chalk.blue(text),
|
|
561
|
+
answer: (text) => chalk.greenBright(text),
|
|
562
|
+
},
|
|
563
|
+
};
|
|
564
|
+
const checkbox_theme = {
|
|
565
|
+
icon: {
|
|
566
|
+
checked: ` ${chalk.greenBright("✔")} `,
|
|
567
|
+
unchecked: ` ${chalk.redBright("✖")} `,
|
|
568
|
+
cursor: `${chalk.yellowBright("➤")} `,
|
|
569
|
+
},
|
|
570
|
+
style: {
|
|
571
|
+
message: (text) => chalk.blue(text),
|
|
572
|
+
answer: (text) => chalk.greenBright(text),
|
|
573
|
+
description: (text) => chalk.yellowBright(`[!] ${text}`),
|
|
574
|
+
highlight: (text) => chalk.cyanBright(text),
|
|
575
|
+
},
|
|
576
|
+
prefix: {
|
|
577
|
+
idle: `${chalk.yellowBright("[")}${chalk.blueBright("?")}${chalk.yellowBright("]")}`,
|
|
578
|
+
done: `${chalk.yellowBright("[")}${chalk.greenBright("✔")}${chalk.yellowBright("]")}`,
|
|
579
|
+
},
|
|
580
|
+
};
|
|
581
|
+
async function fun_input(message, default_inbut, validate) {
|
|
582
|
+
return await input({
|
|
583
|
+
message: message,
|
|
584
|
+
default: default_inbut,
|
|
585
|
+
validate: validate,
|
|
586
|
+
theme: question_theme,
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
async function rawlist_fun(message, choices) {
|
|
590
|
+
return await rawlist({
|
|
591
|
+
message: message,
|
|
592
|
+
choices: choices,
|
|
593
|
+
theme: question_theme,
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
async function confirm_fun(message, default_value) {
|
|
597
|
+
return await confirm({
|
|
598
|
+
message: message,
|
|
599
|
+
default: default_value,
|
|
600
|
+
theme: question_theme,
|
|
601
|
+
});
|
|
602
|
+
}
|
|
603
|
+
async function checkbox_fun(message, choices, validate) {
|
|
604
|
+
return await checkbox({
|
|
605
|
+
message,
|
|
606
|
+
choices: choices,
|
|
607
|
+
validate: (value) => validate(value) ?? (() => true),
|
|
608
|
+
theme: checkbox_theme,
|
|
609
|
+
});
|
|
610
|
+
}
|
|
611
|
+
async function check_is_Ok(qu_title) {
|
|
612
|
+
return await confirm_fun(`Do you want use ${chalk.blueBright(qu_title)}?`, false);
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
async function Core() {
|
|
616
|
+
const ctx = useContext();
|
|
617
|
+
const user_options = [];
|
|
618
|
+
const nizam_choices = {
|
|
619
|
+
pkg_manager: [
|
|
620
|
+
new Separator(chalk.gray("--- Available to you ---")),
|
|
621
|
+
...ctx.pkg_is_installed,
|
|
622
|
+
],
|
|
623
|
+
structure_method: [
|
|
624
|
+
new Separator(chalk.gray("--- Available methods ---")),
|
|
625
|
+
"nizam method",
|
|
626
|
+
"custom method",
|
|
627
|
+
],
|
|
628
|
+
// if i add hear nams for (file or folder) should add it in structure_react.ts file
|
|
629
|
+
folders: [
|
|
630
|
+
new Separator(chalk.gray("--- Select the folders you need ---")),
|
|
631
|
+
{ name: "pages", value: "pages", description: "app screens & routes" },
|
|
632
|
+
{
|
|
633
|
+
name: "layouts",
|
|
634
|
+
value: "layouts",
|
|
635
|
+
description: "page structure wrappers (header, footer, sidebar)",
|
|
636
|
+
},
|
|
637
|
+
{
|
|
638
|
+
name: "components",
|
|
639
|
+
value: "components",
|
|
640
|
+
description: "reusable UI elements",
|
|
641
|
+
},
|
|
642
|
+
{
|
|
643
|
+
name: "utils",
|
|
644
|
+
value: "utils",
|
|
645
|
+
description: "helper functions used everywhere",
|
|
646
|
+
},
|
|
647
|
+
{
|
|
648
|
+
name: "storage",
|
|
649
|
+
value: "storage",
|
|
650
|
+
description: "saves & manages app data",
|
|
651
|
+
},
|
|
652
|
+
{
|
|
653
|
+
name: "sections",
|
|
654
|
+
value: "sections",
|
|
655
|
+
description: "contains reusable page sections",
|
|
656
|
+
},
|
|
657
|
+
],
|
|
658
|
+
files: [
|
|
659
|
+
new Separator(chalk.gray("--- Select the files you need ---")),
|
|
660
|
+
{
|
|
661
|
+
name: "config.json",
|
|
662
|
+
value: "config.json",
|
|
663
|
+
description: "global app settings & constants.",
|
|
664
|
+
},
|
|
665
|
+
{
|
|
666
|
+
name: "api.json",
|
|
667
|
+
value: "api.json",
|
|
668
|
+
description: "API endpoints & base URLs.",
|
|
669
|
+
},
|
|
670
|
+
{
|
|
671
|
+
name: "routing.json",
|
|
672
|
+
value: "routing.json",
|
|
673
|
+
description: "routes definitions & paths.",
|
|
674
|
+
},
|
|
675
|
+
{
|
|
676
|
+
name: "icons.j/ts",
|
|
677
|
+
value: "icons.j/ts",
|
|
678
|
+
description: "centralized icons exports for easy reuse.",
|
|
679
|
+
},
|
|
680
|
+
],
|
|
681
|
+
};
|
|
682
|
+
const core_options = async () => {
|
|
683
|
+
user_options.push([
|
|
684
|
+
"project_path",
|
|
685
|
+
await fun_input("Project path (full path or . for current folder):", ".", async (value) => {
|
|
686
|
+
if (!(await pathExists(value)))
|
|
687
|
+
return "Can't see your input path";
|
|
688
|
+
return true;
|
|
689
|
+
}),
|
|
690
|
+
]);
|
|
691
|
+
user_options.push([
|
|
692
|
+
"project_name",
|
|
693
|
+
await fun_input("Enter your project name:", "nizam-app", async (value) => {
|
|
694
|
+
const regex = /^[a-z_-]+$/;
|
|
695
|
+
if (!regex.test(value))
|
|
696
|
+
return "Only lowercase letters, _ and - are allowed!";
|
|
697
|
+
if (await pathExists(`${ctx.full_project_path}${value}`))
|
|
698
|
+
return "This name has been used before in the same path that was previously chosen.";
|
|
699
|
+
return true;
|
|
700
|
+
}),
|
|
701
|
+
]);
|
|
702
|
+
if (ctx.pkg_is_installed.length > 1) {
|
|
703
|
+
user_options.push([
|
|
704
|
+
"pkg_manager",
|
|
705
|
+
await rawlist_fun("Choose a package manager:", nizam_choices.pkg_manager),
|
|
706
|
+
]);
|
|
707
|
+
}
|
|
708
|
+
else
|
|
709
|
+
ctx.user_options.pkg_manager = ctx.pkg_is_installed[0];
|
|
710
|
+
user_options.push([
|
|
711
|
+
"add_aliase",
|
|
712
|
+
await confirm_fun("Do you want add @ aliase?", false),
|
|
713
|
+
]);
|
|
714
|
+
if (await check_is_Ok("Ready made app structure")) {
|
|
715
|
+
user_options.push([
|
|
716
|
+
"app_structure",
|
|
717
|
+
await rawlist_fun("Choose app structure method:", nizam_choices.structure_method),
|
|
718
|
+
]);
|
|
719
|
+
if (user_options.find((n) => n[1] === "custom method")) {
|
|
720
|
+
user_options.push([
|
|
721
|
+
"folder_structure_names",
|
|
722
|
+
await checkbox_fun("Select folders:", nizam_choices.folders, async (value) => {
|
|
723
|
+
if (value.length === 0)
|
|
724
|
+
return "At least one should be chosen";
|
|
725
|
+
return true;
|
|
726
|
+
}),
|
|
727
|
+
]);
|
|
728
|
+
user_options.push([
|
|
729
|
+
"files_structure_names",
|
|
730
|
+
await checkbox_fun("Select files:", nizam_choices.files, async (value) => {
|
|
731
|
+
if (value.length === 0)
|
|
732
|
+
return "At least one should be chosen";
|
|
733
|
+
return true;
|
|
734
|
+
}),
|
|
735
|
+
]);
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
};
|
|
739
|
+
await core_options();
|
|
740
|
+
const user_options_conv = Object.fromEntries(user_options);
|
|
741
|
+
ctx.user_options = { ...ctx.user_options, ...user_options_conv };
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
var js_framework = {
|
|
745
|
+
name: "JS Framework",
|
|
746
|
+
type: "fixed",
|
|
747
|
+
options: [
|
|
748
|
+
{
|
|
749
|
+
name: "React + vite + js",
|
|
750
|
+
value: "React + vite + js"
|
|
751
|
+
},
|
|
752
|
+
{
|
|
753
|
+
name: "React + vite + ts",
|
|
754
|
+
value: "React + vite + ts"
|
|
755
|
+
}
|
|
756
|
+
],
|
|
757
|
+
documentation: {
|
|
758
|
+
react: {
|
|
759
|
+
des: "react - learn",
|
|
760
|
+
link: "https://react.dev/learn"
|
|
761
|
+
}
|
|
762
|
+
},
|
|
763
|
+
terminal_command: {
|
|
764
|
+
react: {
|
|
765
|
+
js: "vitejs/vite/packages/create-vite/template-react",
|
|
766
|
+
ts: "vitejs/vite/packages/create-vite/template-react-ts"
|
|
767
|
+
}
|
|
768
|
+
},
|
|
769
|
+
description: "This section is for selecting the JavaScript framework and build setup for the project."
|
|
770
|
+
};
|
|
771
|
+
var css_framework = {
|
|
772
|
+
name: "CSS Framework",
|
|
773
|
+
type: "single",
|
|
774
|
+
options: [
|
|
775
|
+
{
|
|
776
|
+
name: "Bootstrap",
|
|
777
|
+
value: "Bootstrap"
|
|
778
|
+
},
|
|
779
|
+
{
|
|
780
|
+
name: "Tailwindcss",
|
|
781
|
+
value: "Tailwindcss"
|
|
782
|
+
},
|
|
783
|
+
{
|
|
784
|
+
name: "Bulma",
|
|
785
|
+
value: "Bulma"
|
|
786
|
+
},
|
|
787
|
+
{
|
|
788
|
+
name: "Foundation",
|
|
789
|
+
value: "Foundation"
|
|
790
|
+
},
|
|
791
|
+
{
|
|
792
|
+
name: "Materialize",
|
|
793
|
+
value: "Materialize"
|
|
794
|
+
}
|
|
795
|
+
],
|
|
796
|
+
documentation: {
|
|
797
|
+
bootstrap: {
|
|
798
|
+
des: "bootstrap - docs",
|
|
799
|
+
link: "https://getbootstrap.com/docs"
|
|
800
|
+
},
|
|
801
|
+
tailwindcss: {
|
|
802
|
+
des: "tailwindcss - docs",
|
|
803
|
+
link: "https://tailwindcss.com/docs"
|
|
804
|
+
},
|
|
805
|
+
bulma: {
|
|
806
|
+
des: "bulma - docs",
|
|
807
|
+
link: "https://bulma.io/documentation"
|
|
808
|
+
},
|
|
809
|
+
foundation: {
|
|
810
|
+
des: "foundation - docs",
|
|
811
|
+
link: "https://get.foundation/sites/docs"
|
|
812
|
+
},
|
|
813
|
+
materialize: {
|
|
814
|
+
des: "materialize - docs",
|
|
815
|
+
link: "https://materializecss.com/getting-started.html"
|
|
816
|
+
}
|
|
817
|
+
},
|
|
818
|
+
description: "This section is for selecting the CSS framework or styling library to use in the project."
|
|
819
|
+
};
|
|
820
|
+
var ui_library = {
|
|
821
|
+
name: "UI Component Library",
|
|
822
|
+
type: "multi",
|
|
823
|
+
options: [
|
|
824
|
+
{
|
|
825
|
+
name: "Material UI",
|
|
826
|
+
value: "Material UI",
|
|
827
|
+
description: "A popular React UI library based on Google’s Material Design, with ready made components and strong theming support."
|
|
828
|
+
},
|
|
829
|
+
{
|
|
830
|
+
name: "Ant Design",
|
|
831
|
+
value: "Ant Design",
|
|
832
|
+
description: "A powerful enterprise focused React UI framework with rich components and clean, professional design."
|
|
833
|
+
},
|
|
834
|
+
{
|
|
835
|
+
name: "Headless UI",
|
|
836
|
+
value: "Headless UI",
|
|
837
|
+
description: "Headless UI has no CSS at all. you must style it yourself (usually with Tailwind CSS)"
|
|
838
|
+
}
|
|
839
|
+
],
|
|
840
|
+
documentation: {
|
|
841
|
+
mui: {
|
|
842
|
+
des: "material ui - docs",
|
|
843
|
+
link: "https://mui.com/material-ui/getting-started"
|
|
844
|
+
},
|
|
845
|
+
ant: {
|
|
846
|
+
des: "ant design - docs",
|
|
847
|
+
link: "https://5x.ant.design/docs/react/introduce"
|
|
848
|
+
},
|
|
849
|
+
headless: {
|
|
850
|
+
des: "headless ui - docs",
|
|
851
|
+
link: "https://headlessui.com/react/disclosure"
|
|
852
|
+
}
|
|
853
|
+
},
|
|
854
|
+
description: "This section is for choosing a library of prebuilt UI components to speed up interface development."
|
|
855
|
+
};
|
|
856
|
+
var routing_library = {
|
|
857
|
+
name: "Routing Library",
|
|
858
|
+
type: "single",
|
|
859
|
+
options: [
|
|
860
|
+
{
|
|
861
|
+
name: "React Router",
|
|
862
|
+
value: "React Router"
|
|
863
|
+
},
|
|
864
|
+
{
|
|
865
|
+
name: "TanStack Router",
|
|
866
|
+
value: "TanStack Router"
|
|
867
|
+
},
|
|
868
|
+
{
|
|
869
|
+
name: "Wouter",
|
|
870
|
+
value: "Wouter"
|
|
871
|
+
}
|
|
872
|
+
],
|
|
873
|
+
documentation: {
|
|
874
|
+
react_router: {
|
|
875
|
+
des: "react router - docs",
|
|
876
|
+
link: "https://reactrouter.com/home"
|
|
877
|
+
},
|
|
878
|
+
tanStack_router: {
|
|
879
|
+
des: "tanStack router - docs",
|
|
880
|
+
link: "https://tanstack.com/router/latest"
|
|
881
|
+
},
|
|
882
|
+
wouter: {
|
|
883
|
+
des: "github-wouter - docs",
|
|
884
|
+
link: "https://github.com/molefrog/wouter"
|
|
885
|
+
}
|
|
886
|
+
},
|
|
887
|
+
description: "This section is for selecting the library that manages navigation and page routing in the project."
|
|
888
|
+
};
|
|
889
|
+
var react_router_rout = {
|
|
890
|
+
name: "React Router Rout Ways",
|
|
891
|
+
type: "single",
|
|
892
|
+
depended_on: "React Router",
|
|
893
|
+
options: [
|
|
894
|
+
{
|
|
895
|
+
name: "Classic Router",
|
|
896
|
+
value: "Classic Router"
|
|
897
|
+
},
|
|
898
|
+
{
|
|
899
|
+
name: "Data Router",
|
|
900
|
+
value: "Data Router"
|
|
901
|
+
}
|
|
902
|
+
],
|
|
903
|
+
description: "This section is for choosing the routing approach in React Router: Classic Router for traditional route setup, or Data Router for route-based data loading."
|
|
904
|
+
};
|
|
905
|
+
var state_management = {
|
|
906
|
+
name: "State Management",
|
|
907
|
+
type: "single",
|
|
908
|
+
options: [
|
|
909
|
+
{
|
|
910
|
+
name: "React Context API",
|
|
911
|
+
value: "React Context API"
|
|
912
|
+
},
|
|
913
|
+
{
|
|
914
|
+
name: "Redux Toolkit",
|
|
915
|
+
value: "Redux Toolkit"
|
|
916
|
+
},
|
|
917
|
+
{
|
|
918
|
+
name: "Zustand",
|
|
919
|
+
value: "Zustand"
|
|
920
|
+
}
|
|
921
|
+
],
|
|
922
|
+
documentation: {
|
|
923
|
+
react_context_api: {
|
|
924
|
+
des: "react - docs",
|
|
925
|
+
link: "https://react.dev/reference/react/createContext"
|
|
926
|
+
},
|
|
927
|
+
redux_toolkit: {
|
|
928
|
+
des: "redux toolkit - docs",
|
|
929
|
+
link: "https://redux-toolkit.js.org/introduction/getting-started"
|
|
930
|
+
},
|
|
931
|
+
zustand: {
|
|
932
|
+
des: "zustand - docs",
|
|
933
|
+
link: "https://zustand.docs.pmnd.rs/getting-started/introduction"
|
|
934
|
+
}
|
|
935
|
+
},
|
|
936
|
+
description: "This section is for selecting the method or library to manage and share application state across components."
|
|
937
|
+
};
|
|
938
|
+
var icon_library = {
|
|
939
|
+
name: "Icons Library",
|
|
940
|
+
type: "multi",
|
|
941
|
+
options: [
|
|
942
|
+
{
|
|
943
|
+
name: "React Icons",
|
|
944
|
+
value: "React Icons",
|
|
945
|
+
description: "A popular library that provides thousands of icons from multiple icon packs (like FontAwesome, Material, and more) as easy-to-use React components."
|
|
946
|
+
},
|
|
947
|
+
{
|
|
948
|
+
name: "Lucide React",
|
|
949
|
+
value: "Lucide React",
|
|
950
|
+
description: "A modern, lightweight icon library that offers clean and customizable SVG icons as React components."
|
|
951
|
+
},
|
|
952
|
+
{
|
|
953
|
+
name: "Lord Icon",
|
|
954
|
+
value: "Lord Icon",
|
|
955
|
+
description: "Animated SVG icons with a React wrapper."
|
|
956
|
+
},
|
|
957
|
+
{
|
|
958
|
+
name: "Material Icons",
|
|
959
|
+
value: "Material Icons",
|
|
960
|
+
description: "Google's official icon set for Material Design Provides a wide range of icons with consistent style, mainly used in Material-UI projects."
|
|
961
|
+
}
|
|
962
|
+
],
|
|
963
|
+
documentation: {
|
|
964
|
+
react_icons: {
|
|
965
|
+
des: "react icons - docs",
|
|
966
|
+
link: "https://react-icons.github.io/react-icons"
|
|
967
|
+
},
|
|
968
|
+
lucide_react: {
|
|
969
|
+
des: "lucide react - guide",
|
|
970
|
+
link: "https://lucide.dev/guide"
|
|
971
|
+
},
|
|
972
|
+
material_icons: {
|
|
973
|
+
des: "material icons - docs",
|
|
974
|
+
link: "https://mui.com/material-ui/material-icons/"
|
|
975
|
+
},
|
|
976
|
+
lord_icon: {
|
|
977
|
+
des: "lord icon - docs",
|
|
978
|
+
link: "https://lordicon.com/docs"
|
|
979
|
+
}
|
|
980
|
+
},
|
|
981
|
+
description: "This section is for choosing a library of icons to use throughout the project’s UI."
|
|
982
|
+
};
|
|
983
|
+
var head_management = {
|
|
984
|
+
name: "SEO / Meta Tag Management Libraries",
|
|
985
|
+
type: "single",
|
|
986
|
+
options: [
|
|
987
|
+
{
|
|
988
|
+
name: "React Helmet Async",
|
|
989
|
+
value: "React Helmet Async"
|
|
990
|
+
},
|
|
991
|
+
{
|
|
992
|
+
name: "Dr. Pogodin React Helmet",
|
|
993
|
+
value: "Dr. Pogodin React Helmet"
|
|
994
|
+
},
|
|
995
|
+
{
|
|
996
|
+
name: "Unhead",
|
|
997
|
+
value: "Unhead"
|
|
998
|
+
}
|
|
999
|
+
],
|
|
1000
|
+
documentation: {
|
|
1001
|
+
react_helmet_async: {
|
|
1002
|
+
des: "react-helmet-async - docs",
|
|
1003
|
+
link: "https://www.npmjs.com/package/react-helmet-async"
|
|
1004
|
+
},
|
|
1005
|
+
"@dr.pogodin/react-helmet": {
|
|
1006
|
+
des: "@dr.pogodin/react-helmet - docs",
|
|
1007
|
+
link: "https://www.npmjs.com/package/@dr.pogodin/react-helmet"
|
|
1008
|
+
},
|
|
1009
|
+
unhead: {
|
|
1010
|
+
des: "unhead - docs",
|
|
1011
|
+
link: "https://unhead.unjs.io/docs/react/head/guides/get-started/installation"
|
|
1012
|
+
}
|
|
1013
|
+
},
|
|
1014
|
+
description: "This section is for selecting libraries that help manage SEO and meta tags in the project."
|
|
1015
|
+
};
|
|
1016
|
+
var data_fetching = {
|
|
1017
|
+
name: "Data Fetching Libraries",
|
|
1018
|
+
type: "single",
|
|
1019
|
+
options: [
|
|
1020
|
+
{
|
|
1021
|
+
name: "Axios",
|
|
1022
|
+
value: "Axios"
|
|
1023
|
+
},
|
|
1024
|
+
{
|
|
1025
|
+
name: "TanStack Query",
|
|
1026
|
+
value: "TanStack Query"
|
|
1027
|
+
},
|
|
1028
|
+
{
|
|
1029
|
+
name: "SWR",
|
|
1030
|
+
value: "SWR"
|
|
1031
|
+
}
|
|
1032
|
+
],
|
|
1033
|
+
documentation: {
|
|
1034
|
+
axios: {
|
|
1035
|
+
des: "axios - docs",
|
|
1036
|
+
link: "https://axios-http.com/docs/intro"
|
|
1037
|
+
},
|
|
1038
|
+
tanstack_query: {
|
|
1039
|
+
des: "tanstack query - docs",
|
|
1040
|
+
link: "https://tanstack.com/query/latest/docs/framework/react/overview"
|
|
1041
|
+
},
|
|
1042
|
+
swr: {
|
|
1043
|
+
des: "swr - docs",
|
|
1044
|
+
link: "https://swr.vercel.app/docs/getting-started"
|
|
1045
|
+
}
|
|
1046
|
+
},
|
|
1047
|
+
description: "This section is for choosing libraries to handle API calls and data fetching in the project."
|
|
1048
|
+
};
|
|
1049
|
+
var resources_json = {
|
|
1050
|
+
js_framework: js_framework,
|
|
1051
|
+
css_framework: css_framework,
|
|
1052
|
+
ui_library: ui_library,
|
|
1053
|
+
routing_library: routing_library,
|
|
1054
|
+
react_router_rout: react_router_rout,
|
|
1055
|
+
state_management: state_management,
|
|
1056
|
+
icon_library: icon_library,
|
|
1057
|
+
head_management: head_management,
|
|
1058
|
+
data_fetching: data_fetching
|
|
1059
|
+
};
|
|
1060
|
+
|
|
1061
|
+
async function Custom() {
|
|
1062
|
+
const app_data = resources_json;
|
|
1063
|
+
const ctx = useContext();
|
|
1064
|
+
const user_options = [];
|
|
1065
|
+
const is_react_app = () => {
|
|
1066
|
+
return user_options.some((item) => item[1]?.startsWith("React + vite"));
|
|
1067
|
+
};
|
|
1068
|
+
const append_hint_fun = (name_, hint_message) => {
|
|
1069
|
+
for (const group of Object.values(app_data)) {
|
|
1070
|
+
group.options.forEach((i) => {
|
|
1071
|
+
if (i.name === name_) {
|
|
1072
|
+
i.name += chalk.gray(`\t(${hint_message.toLocaleLowerCase()})`);
|
|
1073
|
+
}
|
|
1074
|
+
});
|
|
1075
|
+
}
|
|
1076
|
+
};
|
|
1077
|
+
const custom_options = async () => {
|
|
1078
|
+
append_hint_fun("Classic Router", "old way");
|
|
1079
|
+
append_hint_fun("Data Router", "new way");
|
|
1080
|
+
append_hint_fun("React Icons", "most used");
|
|
1081
|
+
append_hint_fun("Lord Icon", "animated icons");
|
|
1082
|
+
append_hint_fun("React Helmet Async", "react 18");
|
|
1083
|
+
append_hint_fun("Dr. Pogodin React Helmet", "fork for react 19+");
|
|
1084
|
+
append_hint_fun("Unhead", "powerful, SSR/SEO friendly");
|
|
1085
|
+
user_options.push([
|
|
1086
|
+
"js_framework",
|
|
1087
|
+
await rawlist_fun("Select a js framework:", [
|
|
1088
|
+
new Separator(chalk.gray("--- Popular Options ---")),
|
|
1089
|
+
...app_data.js_framework.options,
|
|
1090
|
+
]),
|
|
1091
|
+
]);
|
|
1092
|
+
if (await check_is_Ok("CSS Framework")) {
|
|
1093
|
+
user_options.push([
|
|
1094
|
+
"css_framework",
|
|
1095
|
+
await rawlist_fun("Select a CSS framework:", [
|
|
1096
|
+
new Separator(chalk.gray("--- Popular Options ---")),
|
|
1097
|
+
...app_data.css_framework.options,
|
|
1098
|
+
]),
|
|
1099
|
+
]);
|
|
1100
|
+
}
|
|
1101
|
+
if (await check_is_Ok("UI Component Library")) {
|
|
1102
|
+
user_options.push([
|
|
1103
|
+
"ui_library",
|
|
1104
|
+
await checkbox_fun("Select Library:", [
|
|
1105
|
+
new Separator(chalk.gray("--- Popular Options ---")),
|
|
1106
|
+
...app_data.ui_library.options,
|
|
1107
|
+
], (value) => {
|
|
1108
|
+
if (value.length === 0)
|
|
1109
|
+
return "At least one should be chosen";
|
|
1110
|
+
return true;
|
|
1111
|
+
}),
|
|
1112
|
+
]);
|
|
1113
|
+
}
|
|
1114
|
+
if (is_react_app())
|
|
1115
|
+
if (await check_is_Ok("Routing Library")) {
|
|
1116
|
+
user_options.push([
|
|
1117
|
+
"routing_library",
|
|
1118
|
+
await rawlist_fun("Select Library:", [
|
|
1119
|
+
new Separator(chalk.gray("--- Popular Options ---")),
|
|
1120
|
+
...app_data.routing_library.options,
|
|
1121
|
+
]),
|
|
1122
|
+
]);
|
|
1123
|
+
if (user_options.find((n) => n[1] === "React Router")) {
|
|
1124
|
+
user_options.push([
|
|
1125
|
+
"react_router_rout",
|
|
1126
|
+
await rawlist_fun("Select way:", [
|
|
1127
|
+
new Separator(chalk.gray("--- Popular Options ---")),
|
|
1128
|
+
...app_data.react_router_rout.options,
|
|
1129
|
+
]),
|
|
1130
|
+
]);
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
if (await check_is_Ok("State Management way")) {
|
|
1134
|
+
user_options.push([
|
|
1135
|
+
"state_management",
|
|
1136
|
+
await rawlist_fun("Select way:", [
|
|
1137
|
+
new Separator(chalk.gray("--- Popular Options ---")),
|
|
1138
|
+
...app_data.state_management.options,
|
|
1139
|
+
]),
|
|
1140
|
+
]);
|
|
1141
|
+
}
|
|
1142
|
+
if (await check_is_Ok("Icons Library")) {
|
|
1143
|
+
const found = user_options.find((i) => Array.isArray(i[1]) && i[1].includes("Material UI"));
|
|
1144
|
+
if (found) {
|
|
1145
|
+
append_hint_fun("Material Icons", "strong candidate because you use Material UI");
|
|
1146
|
+
}
|
|
1147
|
+
user_options.push([
|
|
1148
|
+
"icon_library",
|
|
1149
|
+
await checkbox_fun("Select Library:", [
|
|
1150
|
+
new Separator(chalk.gray("--- Popular Options ---")),
|
|
1151
|
+
...app_data.icon_library.options,
|
|
1152
|
+
], (value) => {
|
|
1153
|
+
if (value.length === 0)
|
|
1154
|
+
return "At least one should be chosen";
|
|
1155
|
+
return true;
|
|
1156
|
+
}),
|
|
1157
|
+
]);
|
|
1158
|
+
}
|
|
1159
|
+
if (await check_is_Ok("SEO / Meta Tag Management Libraries")) {
|
|
1160
|
+
user_options.push([
|
|
1161
|
+
"head_management",
|
|
1162
|
+
await rawlist_fun("Select Library:", [
|
|
1163
|
+
new Separator(chalk.gray("--- Popular Options ---")),
|
|
1164
|
+
...app_data.head_management.options,
|
|
1165
|
+
]),
|
|
1166
|
+
]);
|
|
1167
|
+
}
|
|
1168
|
+
if (await check_is_Ok("Data Fetching Libraries")) {
|
|
1169
|
+
user_options.push([
|
|
1170
|
+
"data_fetching",
|
|
1171
|
+
await rawlist_fun("Select Library:", [
|
|
1172
|
+
new Separator(chalk.gray("--- Popular Options ---")),
|
|
1173
|
+
...app_data.data_fetching.options,
|
|
1174
|
+
]),
|
|
1175
|
+
]);
|
|
1176
|
+
}
|
|
1177
|
+
};
|
|
1178
|
+
await custom_options();
|
|
1179
|
+
const user_options_conv = Object.fromEntries(user_options);
|
|
1180
|
+
ctx.user_options = { ...ctx.user_options, ...user_options_conv };
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
async function help() {
|
|
1184
|
+
const resource = resources_json;
|
|
1185
|
+
const app_data_value = Object.values(resource);
|
|
1186
|
+
let back = false;
|
|
1187
|
+
console.log(`${chalk.yellowBright("[")}${chalk.redBright("#")}${chalk.yellowBright("]== Explanation of all questions and their options in OneShot Mode:")}`);
|
|
1188
|
+
console.log(chalk.yellowBright("|"));
|
|
1189
|
+
for (const [i, section] of app_data_value.entries()) {
|
|
1190
|
+
console.log(chalk.yellowBright(`[${chalk.redBright(i)}]==========[ ${chalk.redBright(section.name)} ]==========`));
|
|
1191
|
+
console.log(chalk.yellowBright("|"));
|
|
1192
|
+
console.log(`${chalk.yellowBright(`|=(${chalk.gray("options")})=>`)} ${chalk.greenBright(section.options
|
|
1193
|
+
.map((opt, i) => `${opt.name}${i + 1 === section.options.length ? "" : chalk.yellowBright(",")}`)
|
|
1194
|
+
.join(" "))}`);
|
|
1195
|
+
console.log(chalk.yellowBright("|"));
|
|
1196
|
+
console.log(`${chalk.yellowBright(`|=(${chalk.gray("description")})=>`)} ${chalk.yellowBright(section.description)}\n`);
|
|
1197
|
+
}
|
|
1198
|
+
while (!back) {
|
|
1199
|
+
await input({
|
|
1200
|
+
message: `\n[${chalk.redBright("!")}] Press the ${chalk.bgRedBright("Enter key")} to return to the home menu.`,
|
|
1201
|
+
theme: {
|
|
1202
|
+
prefix: {
|
|
1203
|
+
idle: ``,
|
|
1204
|
+
done: ``,
|
|
1205
|
+
},
|
|
1206
|
+
},
|
|
1207
|
+
});
|
|
1208
|
+
back = true;
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
async function HomeMenu() {
|
|
1213
|
+
const ctx = useContext();
|
|
1214
|
+
const question_theme = {
|
|
1215
|
+
icon: {
|
|
1216
|
+
cursor: `${chalk.yellowBright("➤")} `,
|
|
1217
|
+
},
|
|
1218
|
+
prefix: {
|
|
1219
|
+
idle: "",
|
|
1220
|
+
done: "",
|
|
1221
|
+
},
|
|
1222
|
+
style: {
|
|
1223
|
+
message: (text) => chalk.blueBright(text),
|
|
1224
|
+
answer: () => "",
|
|
1225
|
+
description: (text) => chalk.yellowBright(`[!] ${text}`),
|
|
1226
|
+
},
|
|
1227
|
+
};
|
|
1228
|
+
const run = await select({
|
|
1229
|
+
message: "",
|
|
1230
|
+
loop: false,
|
|
1231
|
+
choices: [
|
|
1232
|
+
{
|
|
1233
|
+
name: `${chalk.green(`[🔍]`)} ${chalk.yellow(`Browse Mode`)}`,
|
|
1234
|
+
value: "Browse Mode",
|
|
1235
|
+
description: "Multiple options with the ability to search or browse through comprehensive lists. Useful if you know which tools you'll be using.",
|
|
1236
|
+
},
|
|
1237
|
+
{
|
|
1238
|
+
name: `${chalk.green(`[❓]`)} ${chalk.yellow(`OneShot Mode`)}`,
|
|
1239
|
+
value: "OneShot Mode",
|
|
1240
|
+
description: `A series of questions that suggest suitable options when you are unsure which tools to use. ${chalk.redBright("If this is your first time, we recommend checking out the")} ${chalk.redBright.bold("Help menu")} ${chalk.redBright("to understand the questions and suggestions contained therein.")}`,
|
|
1241
|
+
},
|
|
1242
|
+
{
|
|
1243
|
+
name: `${chalk.green(`[🚨]`)} ${chalk.yellowBright(`Help`)}`,
|
|
1244
|
+
value: "Help",
|
|
1245
|
+
description: "It provides you with support and guidance, with an explanation of each question and the options that will be displayed, to make it easier to understand and use the tool.",
|
|
1246
|
+
},
|
|
1247
|
+
{
|
|
1248
|
+
name: `${chalk.green(`[📤]`)} ${chalk.redBright(`Exit`)}`,
|
|
1249
|
+
value: "Exit",
|
|
1250
|
+
description: "",
|
|
1251
|
+
},
|
|
1252
|
+
],
|
|
1253
|
+
theme: question_theme,
|
|
1254
|
+
});
|
|
1255
|
+
ctx.start_menu_options = run;
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
async function Search() {
|
|
1259
|
+
const ctx = useContext();
|
|
1260
|
+
const resources = resources_json;
|
|
1261
|
+
const groupedChoices = [];
|
|
1262
|
+
const resources_refruns_data = [];
|
|
1263
|
+
const fixed_options = [];
|
|
1264
|
+
const single_options = [];
|
|
1265
|
+
const multi_options = [];
|
|
1266
|
+
const depended_on_options = [];
|
|
1267
|
+
Object.values(resources).forEach((section) => {
|
|
1268
|
+
if (section.type === "fixed") {
|
|
1269
|
+
fixed_options.push([
|
|
1270
|
+
section.name,
|
|
1271
|
+
section.options.map((i) => i.name),
|
|
1272
|
+
]);
|
|
1273
|
+
}
|
|
1274
|
+
});
|
|
1275
|
+
Object.values(resources).forEach((section) => {
|
|
1276
|
+
if (section.type === "single") {
|
|
1277
|
+
single_options.push([
|
|
1278
|
+
section.name,
|
|
1279
|
+
section.options.map((i) => i.name),
|
|
1280
|
+
]);
|
|
1281
|
+
}
|
|
1282
|
+
});
|
|
1283
|
+
Object.values(resources).forEach((section) => {
|
|
1284
|
+
if (section.type === "multi") {
|
|
1285
|
+
multi_options.push(Object.keys(resources).find((k) => resources[k] === section));
|
|
1286
|
+
}
|
|
1287
|
+
});
|
|
1288
|
+
Object.values(resources).forEach((section) => {
|
|
1289
|
+
if (section.depended_on) {
|
|
1290
|
+
depended_on_options.push([
|
|
1291
|
+
section.depended_on,
|
|
1292
|
+
section.name,
|
|
1293
|
+
section.options.map((n) => n.name),
|
|
1294
|
+
]);
|
|
1295
|
+
}
|
|
1296
|
+
});
|
|
1297
|
+
Object.values(resources).forEach((section) => {
|
|
1298
|
+
if (section.options) {
|
|
1299
|
+
resources_refruns_data.push({
|
|
1300
|
+
name: section.name,
|
|
1301
|
+
key: Object.keys(resources).find((k) => resources[k] === section),
|
|
1302
|
+
options: section.options,
|
|
1303
|
+
});
|
|
1304
|
+
}
|
|
1305
|
+
});
|
|
1306
|
+
resources_refruns_data.forEach((section) => {
|
|
1307
|
+
if (section.options) {
|
|
1308
|
+
groupedChoices.push({
|
|
1309
|
+
name: ``,
|
|
1310
|
+
value: "citrus-header",
|
|
1311
|
+
disabled: true,
|
|
1312
|
+
});
|
|
1313
|
+
groupedChoices.push({
|
|
1314
|
+
name: `=== ${section.name} ===`,
|
|
1315
|
+
value: "citrus-header",
|
|
1316
|
+
disabled: true,
|
|
1317
|
+
});
|
|
1318
|
+
section.options.forEach((el) => {
|
|
1319
|
+
groupedChoices.push(el);
|
|
1320
|
+
});
|
|
1321
|
+
}
|
|
1322
|
+
});
|
|
1323
|
+
const answers = await checkboxPlus({
|
|
1324
|
+
message: chalk.blueBright(" Enter in the search and select:"),
|
|
1325
|
+
pageSize: 10,
|
|
1326
|
+
highlight: true,
|
|
1327
|
+
searchable: true,
|
|
1328
|
+
loop: false,
|
|
1329
|
+
validate: function (answer) {
|
|
1330
|
+
// not empty
|
|
1331
|
+
if (answer.length === 0) {
|
|
1332
|
+
return "You must choose at least one.";
|
|
1333
|
+
}
|
|
1334
|
+
// search about fixed options
|
|
1335
|
+
const unselect_fixed_value = fixed_options.find(([, values]) => !values.some((v) => answer.includes(v)))?.[0];
|
|
1336
|
+
if (unselect_fixed_value) {
|
|
1337
|
+
return `just select at least one from ${unselect_fixed_value}`;
|
|
1338
|
+
}
|
|
1339
|
+
// search about single options
|
|
1340
|
+
const more_one_single_value = [...single_options, ...fixed_options].find(([, h]) => {
|
|
1341
|
+
const selectedCount = h.filter((v) => answer.includes(v)).length;
|
|
1342
|
+
return selectedCount > 1;
|
|
1343
|
+
})?.[0];
|
|
1344
|
+
if (more_one_single_value) {
|
|
1345
|
+
return `just select only one from ${more_one_single_value}`;
|
|
1346
|
+
}
|
|
1347
|
+
//search about options depends on anouther
|
|
1348
|
+
const depended_on_value = depended_on_options.find(([n, , o]) => {
|
|
1349
|
+
return answer.includes(n) && !o.some((v) => answer.includes(v));
|
|
1350
|
+
});
|
|
1351
|
+
if (depended_on_value) {
|
|
1352
|
+
return `one of the (${depended_on_value?.[1].toLowerCase()}) options must be used because ${depended_on_value?.[0].toLowerCase()} depends on it`;
|
|
1353
|
+
}
|
|
1354
|
+
return true;
|
|
1355
|
+
},
|
|
1356
|
+
source: (_answersSoFar, input = "") => {
|
|
1357
|
+
return Promise.resolve(groupedChoices.filter((choice) => {
|
|
1358
|
+
if (input === "")
|
|
1359
|
+
return true;
|
|
1360
|
+
return (!choice.disabled &&
|
|
1361
|
+
choice.name.toLowerCase().includes(input.toLowerCase()));
|
|
1362
|
+
}));
|
|
1363
|
+
},
|
|
1364
|
+
theme: {
|
|
1365
|
+
icon: {
|
|
1366
|
+
checked: ` ${chalk.greenBright("✔")} `,
|
|
1367
|
+
unchecked: ` ${chalk.redBright("✖")} `,
|
|
1368
|
+
cursor: `${chalk.yellowBright("➤")} `,
|
|
1369
|
+
disabled: "",
|
|
1370
|
+
},
|
|
1371
|
+
style: {
|
|
1372
|
+
disabledChoice: (text) => chalk.gray(text.replace("(disabled)", "")),
|
|
1373
|
+
description: (text) => chalk.yellowBright(`[!] ${text}`),
|
|
1374
|
+
highlight: (text) => chalk.cyanBright(text),
|
|
1375
|
+
searching: (text) => chalk.cyanBright(text),
|
|
1376
|
+
noResults: (text) => chalk.red(text),
|
|
1377
|
+
error: (text) => chalk.bgRed.white(text),
|
|
1378
|
+
searchHint: (text) => chalk.dim.italic(text),
|
|
1379
|
+
renderSelectedChoices: (selected) => chalk.greenBright(selected.map((c) => c.name).join(", ")),
|
|
1380
|
+
},
|
|
1381
|
+
},
|
|
1382
|
+
});
|
|
1383
|
+
const result = Object.entries(answers.reduce((acc, answer) => {
|
|
1384
|
+
const resource = resources_refruns_data.find((r) => r.options.some((o) => o.name === answer));
|
|
1385
|
+
if (!resource)
|
|
1386
|
+
return acc;
|
|
1387
|
+
acc[resource.key] ??= [];
|
|
1388
|
+
acc[resource.key].push(answer);
|
|
1389
|
+
return acc;
|
|
1390
|
+
}, {}));
|
|
1391
|
+
const result_filter = result.map((s) => {
|
|
1392
|
+
if (!multi_options.includes(s[0])) {
|
|
1393
|
+
return [s[0], s[1].toString()];
|
|
1394
|
+
}
|
|
1395
|
+
else {
|
|
1396
|
+
return s;
|
|
1397
|
+
}
|
|
1398
|
+
});
|
|
1399
|
+
const user_options_conv = Object.fromEntries(result_filter);
|
|
1400
|
+
ctx.user_options = { ...ctx.user_options, ...user_options_conv };
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1403
|
+
function CorePaths() {
|
|
1404
|
+
const ctx = useContext();
|
|
1405
|
+
// get full project path
|
|
1406
|
+
const project_Path = path.resolve(process.cwd(), ctx.user_options.project_path);
|
|
1407
|
+
ctx.full_project_path = path.resolve(project_Path, ctx.user_options.project_name);
|
|
1408
|
+
// get templates dir
|
|
1409
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
1410
|
+
const __dirname = path.dirname(__filename);
|
|
1411
|
+
const TEMPLATES_DIR = path.resolve(__dirname, "templates");
|
|
1412
|
+
ctx.nizam_templates_path = TEMPLATES_DIR;
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
async function CreatFolder() {
|
|
1416
|
+
const { operation_state, full_project_path } = useContext();
|
|
1417
|
+
try {
|
|
1418
|
+
await ensureDir(full_project_path);
|
|
1419
|
+
operation_state.creat_project_folder.status = "success";
|
|
1420
|
+
}
|
|
1421
|
+
catch (err) {
|
|
1422
|
+
operation_state.creat_project_folder.status = "fatal";
|
|
1423
|
+
operation_state.creat_project_folder.error_message =
|
|
1424
|
+
extractMainMessage(err);
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
|
|
1428
|
+
async function CreatVSCFolder() {
|
|
1429
|
+
const { user_options, operation_state } = useContext();
|
|
1430
|
+
const path_box = pathBox();
|
|
1431
|
+
try {
|
|
1432
|
+
await ensureDir(path_box.vsc_path);
|
|
1433
|
+
let vsc_settings_json = await readJson(path_box.vsc_settings_templates);
|
|
1434
|
+
if (user_options.js_framework.includes("ts")) {
|
|
1435
|
+
vsc_settings_json = {
|
|
1436
|
+
...vsc_settings_json,
|
|
1437
|
+
"[typescript]": {
|
|
1438
|
+
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
|
1439
|
+
},
|
|
1440
|
+
};
|
|
1441
|
+
}
|
|
1442
|
+
if (user_options.css_framework === "Tailwind") {
|
|
1443
|
+
vsc_settings_json = {
|
|
1444
|
+
...vsc_settings_json,
|
|
1445
|
+
"files.associations": {
|
|
1446
|
+
"*.css": "tailwindcss",
|
|
1447
|
+
},
|
|
1448
|
+
};
|
|
1449
|
+
}
|
|
1450
|
+
await outputJson(path_box.vsc_setting_path, vsc_settings_json, {
|
|
1451
|
+
spaces: 2,
|
|
1452
|
+
});
|
|
1453
|
+
operation_state.creat_vsc_folder.status = "success";
|
|
1454
|
+
}
|
|
1455
|
+
catch (err) {
|
|
1456
|
+
operation_state.creat_vsc_folder.status = "fatal";
|
|
1457
|
+
operation_state.creat_vsc_folder.error_message = extractMainMessage(err);
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
async function nizamDocEditor(nizam_doc_contant) {
|
|
1462
|
+
const path_box = pathBox();
|
|
1463
|
+
const new_instructions = `
|
|
1464
|
+
${!nizam_doc_contant.title_params ? "" : `## ${nizam_doc_contant.title_params}`}
|
|
1465
|
+
|
|
1466
|
+
${!nizam_doc_contant.dec_params ? "" : `### ${nizam_doc_contant.dec_params}`}
|
|
1467
|
+
|
|
1468
|
+
${!nizam_doc_contant.expla_params ? "" : nizam_doc_contant.expla_params}
|
|
1469
|
+
|
|
1470
|
+
---
|
|
1471
|
+
`;
|
|
1472
|
+
await appendFile(path_box.nizam_Instructions_path, new_instructions);
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
async function UsingMark(file_path, data_array) {
|
|
1476
|
+
let file_content = await readFile(file_path, "utf8");
|
|
1477
|
+
data_array.forEach((_) => {
|
|
1478
|
+
file_content = file_content.replace(`##-nizam@mark-##:${_.tage_name}`, _.content);
|
|
1479
|
+
});
|
|
1480
|
+
await writeFile(file_path, file_content, "utf8");
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1483
|
+
async function AliaseReact() {
|
|
1484
|
+
const { user_options } = useContext();
|
|
1485
|
+
const path_box = pathBox();
|
|
1486
|
+
const vite_config_file_data = [
|
|
1487
|
+
{
|
|
1488
|
+
tage_name: "import_fileURLToPath",
|
|
1489
|
+
content: `import { fileURLToPath } from "url";`,
|
|
1490
|
+
},
|
|
1491
|
+
{
|
|
1492
|
+
tage_name: "import_dirname_resolve",
|
|
1493
|
+
content: `import { dirname, resolve } from "path";`,
|
|
1494
|
+
},
|
|
1495
|
+
{
|
|
1496
|
+
tage_name: "make__filename",
|
|
1497
|
+
content: `const __filename = fileURLToPath(import.meta.url);`,
|
|
1498
|
+
},
|
|
1499
|
+
{
|
|
1500
|
+
tage_name: "make__dirname",
|
|
1501
|
+
content: `const __dirname = dirname(__filename);`,
|
|
1502
|
+
},
|
|
1503
|
+
{
|
|
1504
|
+
tage_name: "add_resolve",
|
|
1505
|
+
content: `resolve: {
|
|
1506
|
+
alias: {
|
|
1507
|
+
"@": resolve(__dirname, "src"),
|
|
1508
|
+
},
|
|
1509
|
+
},`,
|
|
1510
|
+
},
|
|
1511
|
+
];
|
|
1512
|
+
await UsingMark(path_box.vite_config_path, vite_config_file_data);
|
|
1513
|
+
if (user_options.js_framework.includes("js")) {
|
|
1514
|
+
// make jsconfig file
|
|
1515
|
+
const jsconfig_app_contant = await readJson(path_box.jsconfig_app_template, "utf8");
|
|
1516
|
+
await outputJson(path_box.jsconfig_app_path, jsconfig_app_contant, {
|
|
1517
|
+
spaces: 2,
|
|
1518
|
+
});
|
|
1519
|
+
}
|
|
1520
|
+
else {
|
|
1521
|
+
// edit tsconfig.app.json for @ alise apped to json
|
|
1522
|
+
const tsconfig_app_cotant = await readFile(path_box.tsconfig_app_path, "utf8");
|
|
1523
|
+
const tsconfig_app_cotant_parse = JSON.parse(stripJsonComments(tsconfig_app_cotant));
|
|
1524
|
+
const new_tsconfig_app_cotant = {
|
|
1525
|
+
...tsconfig_app_cotant_parse,
|
|
1526
|
+
compilerOptions: {
|
|
1527
|
+
...tsconfig_app_cotant_parse.compilerOptions,
|
|
1528
|
+
baseUrl: "src",
|
|
1529
|
+
paths: {
|
|
1530
|
+
"@/*": ["*"],
|
|
1531
|
+
},
|
|
1532
|
+
},
|
|
1533
|
+
};
|
|
1534
|
+
await outputJson(path_box.tsconfig_app_path, new_tsconfig_app_cotant, {
|
|
1535
|
+
spaces: 2,
|
|
1536
|
+
});
|
|
1537
|
+
}
|
|
1538
|
+
await nizamDocEditor({
|
|
1539
|
+
title_params: "aliase (@)",
|
|
1540
|
+
dec_params: "you can use it inside code to move between folder fast",
|
|
1541
|
+
expla_params: `
|
|
1542
|
+
\`\`\`bash
|
|
1543
|
+
import { } from '@/';
|
|
1544
|
+
\`\`\`
|
|
1545
|
+
|
|
1546
|
+
> [!TIP]
|
|
1547
|
+
> Aliase Documentation: [${appData.core_documentation.aliases.des}](${appData.core_documentation.aliases.link})`,
|
|
1548
|
+
});
|
|
1549
|
+
}
|
|
1550
|
+
|
|
1551
|
+
async function Aliase() {
|
|
1552
|
+
const { user_options, operation_state } = useContext();
|
|
1553
|
+
try {
|
|
1554
|
+
if (user_options.js_framework.includes("React")) {
|
|
1555
|
+
await AliaseReact();
|
|
1556
|
+
}
|
|
1557
|
+
operation_state.add_aliase.status = "success";
|
|
1558
|
+
}
|
|
1559
|
+
catch (err) {
|
|
1560
|
+
operation_state.add_aliase.status = "fatal";
|
|
1561
|
+
operation_state.add_aliase.error_message = extractMainMessage(err);
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
async function structureReact() {
|
|
1566
|
+
const { user_options } = useContext();
|
|
1567
|
+
const path_box = pathBox();
|
|
1568
|
+
const app_structure = user_options.app_structure;
|
|
1569
|
+
const folder_structure_array = user_options.folder_structure_names;
|
|
1570
|
+
const files_structure_array = user_options.files_structure_names;
|
|
1571
|
+
const files_structure_array_with_some_from_user_options = [
|
|
1572
|
+
...files_structure_array,
|
|
1573
|
+
user_options.js_framework.includes("ts") ? "type.ts" : null,
|
|
1574
|
+
];
|
|
1575
|
+
const all_folder_structure_names = [
|
|
1576
|
+
"pages",
|
|
1577
|
+
"layouts",
|
|
1578
|
+
"components",
|
|
1579
|
+
"utils",
|
|
1580
|
+
"storage",
|
|
1581
|
+
"sections",
|
|
1582
|
+
];
|
|
1583
|
+
const all_file_structure_names = [
|
|
1584
|
+
user_options.js_framework.includes("ts") ? "type.ts" : null,
|
|
1585
|
+
"config.json",
|
|
1586
|
+
"api.json",
|
|
1587
|
+
!user_options.routing_library ? null : "routing.json",
|
|
1588
|
+
!user_options.icon_library.length ? null : "icons.j/ts",
|
|
1589
|
+
];
|
|
1590
|
+
const creat_folder_fun = async (folder_name) => {
|
|
1591
|
+
const new_folder_path = path.resolve(path_box.src_path, folder_name);
|
|
1592
|
+
const index_file_Path = path.join(new_folder_path, `index.${user_options.js_framework.includes("js") ? "js" : "ts"}`);
|
|
1593
|
+
await mkdir(new_folder_path, { recursive: true });
|
|
1594
|
+
await writeFile(index_file_Path, "", "utf8");
|
|
1595
|
+
};
|
|
1596
|
+
const creat_file_fun = async ({ file_name, index_folder = "assets", }) => {
|
|
1597
|
+
const index_folder_path = path.resolve(path_box.src_path, index_folder);
|
|
1598
|
+
const [f_name, f_type] = file_name.split(".");
|
|
1599
|
+
const file_Path = path.join(index_folder_path, `${f_name}.${f_type.includes("j/ts")
|
|
1600
|
+
? user_options.js_framework.includes("js")
|
|
1601
|
+
? "js"
|
|
1602
|
+
: "ts"
|
|
1603
|
+
: f_type}`);
|
|
1604
|
+
await writeFile(file_Path, `${f_type.includes("json") ? JSON.stringify({}) : ""}`, "utf8");
|
|
1605
|
+
};
|
|
1606
|
+
if (app_structure.includes("nizam method")) {
|
|
1607
|
+
// make folders
|
|
1608
|
+
for (let folder_name of all_folder_structure_names.filter(Boolean)) {
|
|
1609
|
+
await creat_folder_fun(folder_name);
|
|
1610
|
+
}
|
|
1611
|
+
// make files
|
|
1612
|
+
for (let file_name of all_file_structure_names.filter(Boolean)) {
|
|
1613
|
+
await creat_file_fun({ file_name });
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
else if (app_structure.includes("custom method")) {
|
|
1617
|
+
// make folders
|
|
1618
|
+
for (let folder_name of folder_structure_array.filter(Boolean)) {
|
|
1619
|
+
await creat_folder_fun(folder_name);
|
|
1620
|
+
}
|
|
1621
|
+
// make files
|
|
1622
|
+
for (let file_name of files_structure_array_with_some_from_user_options.filter(Boolean)) {
|
|
1623
|
+
await creat_file_fun({ file_name });
|
|
1624
|
+
}
|
|
1625
|
+
}
|
|
1626
|
+
await nizamDocEditor({
|
|
1627
|
+
title_params: "React App Structure",
|
|
1628
|
+
dec_params: `Creating a barrel file \`index.${user_options.js_framework.includes("js") ? "js" : "ts"}\` inside a folder allows you to re-export everything in that folder, and then when importing out, you only need to import from the same folder.`,
|
|
1629
|
+
expla_params: `
|
|
1630
|
+
Example of a folder structure
|
|
1631
|
+
\`\`\`
|
|
1632
|
+
components/
|
|
1633
|
+
├─ Button.${user_options.js_framework.includes("js") ? "js" : "ts"}x
|
|
1634
|
+
├─ Card.${user_options.js_framework.includes("js") ? "js" : "ts"}x
|
|
1635
|
+
├─ Modal.${user_options.js_framework.includes("js") ? "js" : "ts"}x
|
|
1636
|
+
└─ index.${user_options.js_framework.includes("js") ? "js" : "ts"}
|
|
1637
|
+
\`\`\`
|
|
1638
|
+
|
|
1639
|
+
Inside the \`index.${user_options.js_framework.includes("js") ? "js" : "ts"}\`
|
|
1640
|
+
\`\`\`
|
|
1641
|
+
// re-export all components
|
|
1642
|
+
export { default as Button } from "./Button";
|
|
1643
|
+
export { default as Card } from "./Card";
|
|
1644
|
+
export { default as Modal } from "./Modal";
|
|
1645
|
+
\`\`\`
|
|
1646
|
+
|
|
1647
|
+
When use it
|
|
1648
|
+
\`\`\`
|
|
1649
|
+
import { Button, Card, Modal } from "./components";
|
|
1650
|
+
|
|
1651
|
+
Button(); // use Button
|
|
1652
|
+
Card(); // use Card
|
|
1653
|
+
Modal(); // use Modal
|
|
1654
|
+
\`\`\`
|
|
1655
|
+
\`from "./components"\` We only write the folder name.
|
|
1656
|
+
|
|
1657
|
+
> [!TIP]
|
|
1658
|
+
> React App Structure Documentation: [${appData.core_documentation.app_structure.react.des}](${appData.core_documentation.app_structure.react.link})`,
|
|
1659
|
+
});
|
|
1660
|
+
}
|
|
1661
|
+
|
|
1662
|
+
async function Structure() {
|
|
1663
|
+
const { user_options, operation_state } = useContext();
|
|
1664
|
+
try {
|
|
1665
|
+
if (user_options.js_framework.includes("React")) {
|
|
1666
|
+
await structureReact();
|
|
1667
|
+
}
|
|
1668
|
+
operation_state.app_structure.status = "success";
|
|
1669
|
+
}
|
|
1670
|
+
catch (err) {
|
|
1671
|
+
operation_state.app_structure.status = "fatal";
|
|
1672
|
+
operation_state.app_structure.error_message = extractMainMessage(err);
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1675
|
+
|
|
1676
|
+
async function ReactFiles() {
|
|
1677
|
+
const { user_options } = useContext();
|
|
1678
|
+
const { js_framework } = resources_json;
|
|
1679
|
+
const path_box = pathBox();
|
|
1680
|
+
const index_title = `<title>nizam - add your website name (${user_options.project_name}) here</title>`;
|
|
1681
|
+
// add app name in package json file
|
|
1682
|
+
const package_json = await readJson(path_box.package_json_path, "utf8");
|
|
1683
|
+
package_json.name ??= "";
|
|
1684
|
+
package_json.name = user_options.project_name;
|
|
1685
|
+
await writeJson(path_box.package_json_path, package_json, { spaces: 2 });
|
|
1686
|
+
// fixed _gitignore file name
|
|
1687
|
+
if (await pathExists(path_box.old_gitignore_path))
|
|
1688
|
+
await rename(path_box.old_gitignore_path, path_box.new_gitignore_path);
|
|
1689
|
+
// make nizam Instructions file
|
|
1690
|
+
const nizam_Instructions_text = await readFile(path_box.nizam_Instructions_templates, "utf8");
|
|
1691
|
+
await ensureFile(path_box.nizam_Instructions_path);
|
|
1692
|
+
await writeFile(path_box.nizam_Instructions_path, nizam_Instructions_text, "utf8");
|
|
1693
|
+
// clean README.md file
|
|
1694
|
+
await ensureFile(path_box.README_path);
|
|
1695
|
+
await writeFile(path_box.README_path, `# ${user_options.project_name}`, "utf8");
|
|
1696
|
+
// clean index.css
|
|
1697
|
+
const index_css_text = await readFile(path_box.index_css_templates, "utf8");
|
|
1698
|
+
await ensureFile(path_box.index_css_path);
|
|
1699
|
+
await writeFile(path_box.index_css_path, index_css_text, "utf8");
|
|
1700
|
+
// clean public folder
|
|
1701
|
+
await ensureDir(path_box.public_path);
|
|
1702
|
+
await emptyDir(path_box.public_path);
|
|
1703
|
+
// edit title in index.html
|
|
1704
|
+
const html = await readFile(path_box.index_html_path, "utf8");
|
|
1705
|
+
const updatedHtml = html.replace(/<title>(.*?)<\/title>/i, index_title);
|
|
1706
|
+
await writeFile(path_box.index_html_path, updatedHtml, "utf8");
|
|
1707
|
+
// remove app.css
|
|
1708
|
+
await remove(path_box.app_css_path);
|
|
1709
|
+
// remove src/assets folder
|
|
1710
|
+
await ensureDir(path_box.assets_folder_path);
|
|
1711
|
+
await emptyDir(path_box.assets_folder_path);
|
|
1712
|
+
if ((user_options.routing_library.includes("React Router") &&
|
|
1713
|
+
user_options.react_router_rout.includes("Data Router")) ||
|
|
1714
|
+
user_options.routing_library.includes("TanStack Router")) {
|
|
1715
|
+
// remove app.jsx file for data routing and add layout file
|
|
1716
|
+
await remove(path_box.app_react_path);
|
|
1717
|
+
const main_react_text = await readFile(path_box.layout_templates, "utf8");
|
|
1718
|
+
await ensureFile(path_box.layout_path);
|
|
1719
|
+
await writeFile(path_box.layout_path, main_react_text, "utf8");
|
|
1720
|
+
}
|
|
1721
|
+
else {
|
|
1722
|
+
// new app file
|
|
1723
|
+
const app_react_text = await readFile(path_box.app_react_templates, "utf8");
|
|
1724
|
+
await ensureFile(path_box.app_react_path);
|
|
1725
|
+
await writeFile(path_box.app_react_path, app_react_text, "utf8");
|
|
1726
|
+
}
|
|
1727
|
+
// new vite.config
|
|
1728
|
+
const vite_config_text = await readFile(path_box.vite_config_templates, "utf8");
|
|
1729
|
+
await ensureFile(path_box.vite_config_path);
|
|
1730
|
+
await writeFile(path_box.vite_config_path, vite_config_text, "utf8");
|
|
1731
|
+
// make .env file
|
|
1732
|
+
const env_text = await readFile(path_box.env_template, "utf8");
|
|
1733
|
+
await ensureFile(path_box.env_path);
|
|
1734
|
+
await writeFile(path_box.env_path, env_text, "utf8");
|
|
1735
|
+
// new main
|
|
1736
|
+
const main_react_text = await readFile(path_box.main_react_templates, "utf8");
|
|
1737
|
+
await ensureFile(path_box.main_react_path);
|
|
1738
|
+
await writeFile(path_box.main_react_path, main_react_text, "utf8");
|
|
1739
|
+
await nizamDocEditor({
|
|
1740
|
+
title_params: user_options.js_framework,
|
|
1741
|
+
dec_params: "Here’s the clear, correct way to run & build a React app using Vite",
|
|
1742
|
+
expla_params: `
|
|
1743
|
+
Run (Development mode)
|
|
1744
|
+
\`\`\`bash
|
|
1745
|
+
npm run dev
|
|
1746
|
+
\`\`\`
|
|
1747
|
+
|
|
1748
|
+
You’ll see something like:
|
|
1749
|
+
\`\`\`bash
|
|
1750
|
+
Local: http://localhost:5173/
|
|
1751
|
+
\`\`\`
|
|
1752
|
+
|
|
1753
|
+
Build (Production)
|
|
1754
|
+
\`\`\`bash
|
|
1755
|
+
npm run build
|
|
1756
|
+
\`\`\`
|
|
1757
|
+
|
|
1758
|
+
> [!TIP]
|
|
1759
|
+
> React Documentation: [${js_framework.documentation.react.des}](${js_framework.documentation.react.link})`,
|
|
1760
|
+
});
|
|
1761
|
+
}
|
|
1762
|
+
|
|
1763
|
+
async function React() {
|
|
1764
|
+
const { user_options } = useContext();
|
|
1765
|
+
const { js_framework } = resources_json;
|
|
1766
|
+
let pkg = "npx";
|
|
1767
|
+
if (user_options.js_framework.includes("js")) {
|
|
1768
|
+
await customInstall(pkg, js_framework.terminal_command.react.js);
|
|
1769
|
+
}
|
|
1770
|
+
else if (user_options.js_framework.includes("ts")) {
|
|
1771
|
+
await customInstall(pkg, js_framework.terminal_command.react.ts);
|
|
1772
|
+
}
|
|
1773
|
+
await ReactFiles();
|
|
1774
|
+
}
|
|
1775
|
+
|
|
1776
|
+
async function JSFramework() {
|
|
1777
|
+
const { user_options, operation_state } = useContext();
|
|
1778
|
+
try {
|
|
1779
|
+
if (user_options.js_framework.includes("React")) {
|
|
1780
|
+
await React();
|
|
1781
|
+
}
|
|
1782
|
+
operation_state.js_framework.status = "success";
|
|
1783
|
+
}
|
|
1784
|
+
catch (err) {
|
|
1785
|
+
operation_state.js_framework.status = "fatal";
|
|
1786
|
+
operation_state.js_framework.error_message = extractMainMessage(err);
|
|
1787
|
+
}
|
|
1788
|
+
}
|
|
1789
|
+
|
|
1790
|
+
async function Bootstrap() {
|
|
1791
|
+
const { user_options } = useContext();
|
|
1792
|
+
const path_box = pathBox();
|
|
1793
|
+
const { css_framework } = resources_json;
|
|
1794
|
+
const main_file_data = [
|
|
1795
|
+
{
|
|
1796
|
+
tage_name: "bootstrap_min",
|
|
1797
|
+
content: `import 'bootstrap/dist/css/bootstrap.min.css';`,
|
|
1798
|
+
},
|
|
1799
|
+
{
|
|
1800
|
+
tage_name: "bootstrap_bundle",
|
|
1801
|
+
content: `import 'bootstrap/dist/js/bootstrap.bundle.min.js';`,
|
|
1802
|
+
},
|
|
1803
|
+
];
|
|
1804
|
+
await UsingMark(path_box.main_react_path, main_file_data);
|
|
1805
|
+
// edit index.css
|
|
1806
|
+
const bootstrap_text = await readFile(path_box.bootstrap_templates, "utf8");
|
|
1807
|
+
await appendFile(path_box.index_css_path, bootstrap_text);
|
|
1808
|
+
await nizamDocEditor({
|
|
1809
|
+
title_params: user_options.css_framework,
|
|
1810
|
+
expla_params: `
|
|
1811
|
+
We have created a clear and ready made structure that you can use. you will find it inside \`index.css\` file.
|
|
1812
|
+
|
|
1813
|
+
> [!TIP]
|
|
1814
|
+
> Bootstrap Documentation: [${css_framework.documentation.bootstrap.des}](${css_framework.documentation.bootstrap.link})`,
|
|
1815
|
+
});
|
|
1816
|
+
}
|
|
1817
|
+
|
|
1818
|
+
async function Tailwind() {
|
|
1819
|
+
const { user_options } = useContext();
|
|
1820
|
+
const path_box = pathBox();
|
|
1821
|
+
const { css_framework } = resources_json;
|
|
1822
|
+
const vite_config_data = [
|
|
1823
|
+
{
|
|
1824
|
+
tage_name: "import_tailwindcss",
|
|
1825
|
+
content: `import tailwindcss from '@tailwindcss/vite'`,
|
|
1826
|
+
},
|
|
1827
|
+
{
|
|
1828
|
+
tage_name: "append_tailwindcss_plugins",
|
|
1829
|
+
content: `tailwindcss(),`,
|
|
1830
|
+
},
|
|
1831
|
+
];
|
|
1832
|
+
const index_css_data = [
|
|
1833
|
+
{
|
|
1834
|
+
tage_name: "import_tailwindcss",
|
|
1835
|
+
content: `@import "tailwindcss";`,
|
|
1836
|
+
},
|
|
1837
|
+
];
|
|
1838
|
+
await UsingMark(path_box.vite_config_path, vite_config_data);
|
|
1839
|
+
await UsingMark(path_box.index_css_path, index_css_data);
|
|
1840
|
+
// edit index.css
|
|
1841
|
+
const tailwind_text = await readFile(path_box.tailwind_templates, "utf8");
|
|
1842
|
+
await appendFile(path_box.index_css_path, tailwind_text);
|
|
1843
|
+
await nizamDocEditor({
|
|
1844
|
+
title_params: user_options.css_framework,
|
|
1845
|
+
expla_params: `
|
|
1846
|
+
We have created a clear and ready made structure that you can use. you will find it inside \`index.css\` file.
|
|
1847
|
+
|
|
1848
|
+
> [!TIP]
|
|
1849
|
+
> Tailwindcss Documentation: [${css_framework.documentation.tailwindcss.des}](${css_framework.documentation.tailwindcss.link})`,
|
|
1850
|
+
});
|
|
1851
|
+
}
|
|
1852
|
+
|
|
1853
|
+
async function Bulma() {
|
|
1854
|
+
const { user_options } = useContext();
|
|
1855
|
+
const path_box = pathBox();
|
|
1856
|
+
const { css_framework } = resources_json;
|
|
1857
|
+
const main_file_data = [
|
|
1858
|
+
{
|
|
1859
|
+
tage_name: "bulma_min",
|
|
1860
|
+
content: `import 'bulma/css/bulma.min.css';`,
|
|
1861
|
+
},
|
|
1862
|
+
];
|
|
1863
|
+
await UsingMark(path_box.main_react_path, main_file_data);
|
|
1864
|
+
// edit index.css
|
|
1865
|
+
const css_text = await readFile(path_box.bootstrap_templates, "utf8");
|
|
1866
|
+
await appendFile(path_box.index_css_path, css_text);
|
|
1867
|
+
await nizamDocEditor({
|
|
1868
|
+
title_params: user_options.css_framework,
|
|
1869
|
+
expla_params: `
|
|
1870
|
+
We have created a clear and ready made structure that you can use. you will find it inside \`index.css\` file.
|
|
1871
|
+
|
|
1872
|
+
> [!TIP]
|
|
1873
|
+
> Bulma Documentation: [${css_framework.documentation.bulma.des}](${css_framework.documentation.bulma.link})`,
|
|
1874
|
+
});
|
|
1875
|
+
}
|
|
1876
|
+
|
|
1877
|
+
async function Foundation() {
|
|
1878
|
+
const { user_options } = useContext();
|
|
1879
|
+
const path_box = pathBox();
|
|
1880
|
+
const { css_framework } = resources_json;
|
|
1881
|
+
const main_file_data = [
|
|
1882
|
+
{
|
|
1883
|
+
tage_name: "foundation_min",
|
|
1884
|
+
content: `import 'foundation-sites/dist/css/foundation.min.css';`,
|
|
1885
|
+
},
|
|
1886
|
+
];
|
|
1887
|
+
await UsingMark(path_box.main_react_path, main_file_data);
|
|
1888
|
+
// edit index.css
|
|
1889
|
+
const css_text = await readFile(path_box.bootstrap_templates, "utf8");
|
|
1890
|
+
await appendFile(path_box.index_css_path, css_text);
|
|
1891
|
+
await nizamDocEditor({
|
|
1892
|
+
title_params: user_options.css_framework,
|
|
1893
|
+
expla_params: `
|
|
1894
|
+
We have created a clear and ready made structure that you can use. you will find it inside \`index.css\` file.
|
|
1895
|
+
|
|
1896
|
+
> [!TIP]
|
|
1897
|
+
> Foundation Documentation: [${css_framework.documentation.foundation.des}](${css_framework.documentation.foundation.link})`,
|
|
1898
|
+
});
|
|
1899
|
+
}
|
|
1900
|
+
|
|
1901
|
+
async function Materialize() {
|
|
1902
|
+
const { user_options } = useContext();
|
|
1903
|
+
const path_box = pathBox();
|
|
1904
|
+
const { css_framework } = resources_json;
|
|
1905
|
+
const main_file_data = [
|
|
1906
|
+
{
|
|
1907
|
+
tage_name: "materialize_min",
|
|
1908
|
+
content: `import 'materialize-css/dist/css/materialize.min.css';`,
|
|
1909
|
+
},
|
|
1910
|
+
];
|
|
1911
|
+
await UsingMark(path_box.main_react_path, main_file_data);
|
|
1912
|
+
// edit index.css
|
|
1913
|
+
const css_text = await readFile(path_box.bootstrap_templates, "utf8");
|
|
1914
|
+
await appendFile(path_box.index_css_path, css_text);
|
|
1915
|
+
await nizamDocEditor({
|
|
1916
|
+
title_params: user_options.css_framework,
|
|
1917
|
+
expla_params: `
|
|
1918
|
+
We have created a clear and ready made structure that you can use. you will find it inside \`index.css\` file.
|
|
1919
|
+
|
|
1920
|
+
> [!TIP]
|
|
1921
|
+
> Materialize Documentation: [${css_framework.documentation.materialize.des}](${css_framework.documentation.materialize.link})`,
|
|
1922
|
+
});
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1925
|
+
async function CSSFrameworkReact() {
|
|
1926
|
+
const { user_options } = useContext();
|
|
1927
|
+
const lib_list = [
|
|
1928
|
+
{
|
|
1929
|
+
name: "bootstrap",
|
|
1930
|
+
fun: Bootstrap,
|
|
1931
|
+
dependencies: ["bootstrap"],
|
|
1932
|
+
},
|
|
1933
|
+
{
|
|
1934
|
+
name: "tailwindcss",
|
|
1935
|
+
fun: Tailwind,
|
|
1936
|
+
dependencies: ["tailwindcss", "@tailwindcss/vite"],
|
|
1937
|
+
},
|
|
1938
|
+
{
|
|
1939
|
+
name: "bulma",
|
|
1940
|
+
fun: Bulma,
|
|
1941
|
+
dependencies: ["bulma"],
|
|
1942
|
+
},
|
|
1943
|
+
{
|
|
1944
|
+
name: "foundation",
|
|
1945
|
+
fun: Foundation,
|
|
1946
|
+
dependencies: ["foundation-sites"],
|
|
1947
|
+
},
|
|
1948
|
+
{
|
|
1949
|
+
name: "materialize",
|
|
1950
|
+
fun: Materialize,
|
|
1951
|
+
dependencies: ["materialize-css"],
|
|
1952
|
+
},
|
|
1953
|
+
];
|
|
1954
|
+
await installDependencies({
|
|
1955
|
+
lib_list: lib_list,
|
|
1956
|
+
user_option_library: user_options.css_framework,
|
|
1957
|
+
});
|
|
1958
|
+
}
|
|
1959
|
+
|
|
1960
|
+
async function CSSFramework() {
|
|
1961
|
+
const { user_options, operation_state } = useContext();
|
|
1962
|
+
try {
|
|
1963
|
+
if (user_options.js_framework.includes("React")) {
|
|
1964
|
+
await CSSFrameworkReact();
|
|
1965
|
+
}
|
|
1966
|
+
operation_state.css_framework.status = "success";
|
|
1967
|
+
}
|
|
1968
|
+
catch (err) {
|
|
1969
|
+
operation_state.css_framework.status = "fatal";
|
|
1970
|
+
operation_state.css_framework.error_message = extractMainMessage(err);
|
|
1971
|
+
}
|
|
1972
|
+
}
|
|
1973
|
+
|
|
1974
|
+
async function MUI() {
|
|
1975
|
+
const { ui_library } = resources_json;
|
|
1976
|
+
await nizamDocEditor({
|
|
1977
|
+
title_params: "Material UI",
|
|
1978
|
+
expla_params: `
|
|
1979
|
+
> [!TIP]
|
|
1980
|
+
> MUI Documentation: [${ui_library.documentation.mui.des}](${ui_library.documentation.mui.link})`,
|
|
1981
|
+
});
|
|
1982
|
+
}
|
|
1983
|
+
|
|
1984
|
+
async function Ant() {
|
|
1985
|
+
const path_box = pathBox();
|
|
1986
|
+
const { ui_library } = resources_json;
|
|
1987
|
+
const main_data = [
|
|
1988
|
+
{
|
|
1989
|
+
tage_name: "ant_reset_css",
|
|
1990
|
+
content: `import 'antd/dist/reset.css';`,
|
|
1991
|
+
},
|
|
1992
|
+
];
|
|
1993
|
+
await UsingMark(path_box.main_react_path, main_data);
|
|
1994
|
+
await nizamDocEditor({
|
|
1995
|
+
title_params: "Ant Design",
|
|
1996
|
+
expla_params: `
|
|
1997
|
+
> [!TIP]
|
|
1998
|
+
> Ant Design Documentation: [${ui_library.documentation.ant.des}](${ui_library.documentation.ant.link})`,
|
|
1999
|
+
});
|
|
2000
|
+
}
|
|
2001
|
+
|
|
2002
|
+
async function Headless() {
|
|
2003
|
+
const { ui_library } = resources_json;
|
|
2004
|
+
await nizamDocEditor({
|
|
2005
|
+
title_params: "Headless UI",
|
|
2006
|
+
expla_params: `
|
|
2007
|
+
> [!TIP]
|
|
2008
|
+
> Headless UI Documentation: [${ui_library.documentation.headless.des}](${ui_library.documentation.headless.link})`,
|
|
2009
|
+
});
|
|
2010
|
+
}
|
|
2011
|
+
|
|
2012
|
+
async function UILibraryReact() {
|
|
2013
|
+
const { user_options } = useContext();
|
|
2014
|
+
const lib_list = [
|
|
2015
|
+
{
|
|
2016
|
+
name: "material ui",
|
|
2017
|
+
fun: MUI,
|
|
2018
|
+
dependencies: ["@mui/material", "@emotion/react", "@emotion/styled"],
|
|
2019
|
+
},
|
|
2020
|
+
{
|
|
2021
|
+
name: "ant design",
|
|
2022
|
+
fun: Ant,
|
|
2023
|
+
dependencies: ["antd"],
|
|
2024
|
+
},
|
|
2025
|
+
{
|
|
2026
|
+
name: "headless ui",
|
|
2027
|
+
fun: Headless,
|
|
2028
|
+
dependencies: ["@headlessui/react"],
|
|
2029
|
+
},
|
|
2030
|
+
];
|
|
2031
|
+
await installDependencies({
|
|
2032
|
+
lib_list: lib_list,
|
|
2033
|
+
user_option_library: user_options.ui_library,
|
|
2034
|
+
});
|
|
2035
|
+
}
|
|
2036
|
+
|
|
2037
|
+
async function UILibrary() {
|
|
2038
|
+
const { user_options, operation_state } = useContext();
|
|
2039
|
+
try {
|
|
2040
|
+
if (user_options.js_framework.includes("React")) {
|
|
2041
|
+
await UILibraryReact();
|
|
2042
|
+
}
|
|
2043
|
+
operation_state.ui_library.status = "success";
|
|
2044
|
+
}
|
|
2045
|
+
catch (err) {
|
|
2046
|
+
operation_state.ui_library.status = "fatal";
|
|
2047
|
+
operation_state.ui_library.error_message = extractMainMessage(err);
|
|
2048
|
+
}
|
|
2049
|
+
}
|
|
2050
|
+
|
|
2051
|
+
async function ReactIcons() {
|
|
2052
|
+
const { user_options } = useContext();
|
|
2053
|
+
const { icon_library } = resources_json;
|
|
2054
|
+
await nizamDocEditor({
|
|
2055
|
+
title_params: "React Icons",
|
|
2056
|
+
dec_params: `React Icons is a library that gives you icons as React components.`,
|
|
2057
|
+
expla_params: `
|
|
2058
|
+
You don’t use images or SVG files manually you just import the icon and use it like a component.
|
|
2059
|
+
|
|
2060
|
+
#### Explanation of some of the shortcuts found within the library:
|
|
2061
|
+
| Prefix | Library |
|
|
2062
|
+
|------|---------|
|
|
2063
|
+
| \`fa\` | Font Awesome |
|
|
2064
|
+
| \`md\` | Material Design |
|
|
2065
|
+
| \`ai\` | Ant Design |
|
|
2066
|
+
| \`bs\` | Bootstrap Icons |
|
|
2067
|
+
| \`hi\` | Heroicons |
|
|
2068
|
+
|
|
2069
|
+
${user_options.files_structure_names.includes("icons") ||
|
|
2070
|
+
user_options.icon_library.length !== 0
|
|
2071
|
+
? `
|
|
2072
|
+
> [!NOTE]
|
|
2073
|
+
> Import all icons from one file (clean way).
|
|
2074
|
+
> We have created a \`icon.${user_options.js_framework.includes("js") ? "js" : "ts"}\` file to use it which you will find in \`src/assets/icon.${user_options.js_framework.includes("js") ? "js" : "ts"}\``
|
|
2075
|
+
: ""}
|
|
2076
|
+
|
|
2077
|
+
> [!TIP]
|
|
2078
|
+
> React Icons Documentation: [${icon_library.documentation.react_icons.des}](${icon_library.documentation.react_icons.link})`,
|
|
2079
|
+
});
|
|
2080
|
+
}
|
|
2081
|
+
|
|
2082
|
+
async function LucideReact() {
|
|
2083
|
+
const { user_options } = useContext();
|
|
2084
|
+
const { icon_library } = resources_json;
|
|
2085
|
+
await nizamDocEditor({
|
|
2086
|
+
title_params: "Lucide React",
|
|
2087
|
+
dec_params: `Lucide React is based on SVG and does not require any additional CSS files.`,
|
|
2088
|
+
expla_params: `
|
|
2089
|
+
${user_options.files_structure_names.includes("icons") ||
|
|
2090
|
+
user_options.icon_library.length !== 0
|
|
2091
|
+
? `
|
|
2092
|
+
> [!NOTE]
|
|
2093
|
+
> Import all icons from one file (clean way).
|
|
2094
|
+
> We have created a \`icon.${user_options.js_framework.includes("js") ? "js" : "ts"}\` file to use it which you will find in \`src/assets/icon.${user_options.js_framework.includes("js") ? "js" : "ts"}\``
|
|
2095
|
+
: ""}
|
|
2096
|
+
|
|
2097
|
+
> [!TIP]
|
|
2098
|
+
> Lucide React Documentation: [${icon_library.documentation.lucide_react.des}](${icon_library.documentation.lucide_react.link})`,
|
|
2099
|
+
});
|
|
2100
|
+
}
|
|
2101
|
+
|
|
2102
|
+
async function MaterialIcons() {
|
|
2103
|
+
const { icon_library } = resources_json;
|
|
2104
|
+
await nizamDocEditor({
|
|
2105
|
+
title_params: "Material Icons",
|
|
2106
|
+
expla_params: `
|
|
2107
|
+
> [!TIP]
|
|
2108
|
+
> Material Icons Documentation: [${icon_library.documentation.material_icons.des}](${icon_library.documentation.material_icons.link})`,
|
|
2109
|
+
});
|
|
2110
|
+
}
|
|
2111
|
+
|
|
2112
|
+
async function LordIcon() {
|
|
2113
|
+
const { user_options } = useContext();
|
|
2114
|
+
const { icon_library } = resources_json;
|
|
2115
|
+
await nizamDocEditor({
|
|
2116
|
+
title_params: "Lord Icon",
|
|
2117
|
+
dec_params: `Lord Icon is animated SVG icons with a React wrapper.`,
|
|
2118
|
+
expla_params: `
|
|
2119
|
+
${user_options.files_structure_names.includes("icons") ||
|
|
2120
|
+
user_options.icon_library.length !== 0
|
|
2121
|
+
? `
|
|
2122
|
+
> [!NOTE]
|
|
2123
|
+
> Import all icons from one file (clean way).
|
|
2124
|
+
> We have created a \`icon.${user_options.js_framework.includes("js") ? "js" : "ts"}\` file to use it which you will find in \`src/assets/icon.${user_options.js_framework.includes("js") ? "js" : "ts"}\``
|
|
2125
|
+
: ""}
|
|
2126
|
+
|
|
2127
|
+
> [!TIP]
|
|
2128
|
+
> Lord Icon Documentation: [${icon_library.documentation.lord_icon.des}](${icon_library.documentation.lord_icon.link})`,
|
|
2129
|
+
});
|
|
2130
|
+
}
|
|
2131
|
+
|
|
2132
|
+
async function IconLibraryReact() {
|
|
2133
|
+
const { user_options } = useContext();
|
|
2134
|
+
const check_mui_pkg = user_options.ui_library.find((i) => i.includes("Material UI"));
|
|
2135
|
+
const lib_list = [
|
|
2136
|
+
{
|
|
2137
|
+
name: "react icons",
|
|
2138
|
+
fun: ReactIcons,
|
|
2139
|
+
dependencies: ["react-icons"],
|
|
2140
|
+
},
|
|
2141
|
+
{
|
|
2142
|
+
name: "lucide react",
|
|
2143
|
+
fun: LucideReact,
|
|
2144
|
+
dependencies: ["lucide-react"],
|
|
2145
|
+
},
|
|
2146
|
+
{
|
|
2147
|
+
name: "material icons",
|
|
2148
|
+
fun: MaterialIcons,
|
|
2149
|
+
dependencies: [
|
|
2150
|
+
"@mui/icons-material",
|
|
2151
|
+
!check_mui_pkg ? "@mui/material" : null,
|
|
2152
|
+
!check_mui_pkg ? "@emotion/react" : null,
|
|
2153
|
+
!check_mui_pkg ? "@emotion/styled" : null,
|
|
2154
|
+
],
|
|
2155
|
+
},
|
|
2156
|
+
{
|
|
2157
|
+
name: "lord icon",
|
|
2158
|
+
fun: LordIcon,
|
|
2159
|
+
dependencies: ["@lordicon/react"],
|
|
2160
|
+
},
|
|
2161
|
+
];
|
|
2162
|
+
await installDependencies({
|
|
2163
|
+
lib_list: lib_list,
|
|
2164
|
+
user_option_library: user_options.icon_library,
|
|
2165
|
+
});
|
|
2166
|
+
}
|
|
2167
|
+
|
|
2168
|
+
async function IconLibrary() {
|
|
2169
|
+
const { user_options, operation_state } = useContext();
|
|
2170
|
+
try {
|
|
2171
|
+
if (user_options.js_framework.includes("React")) {
|
|
2172
|
+
await IconLibraryReact();
|
|
2173
|
+
}
|
|
2174
|
+
operation_state.icon_library.status = "success";
|
|
2175
|
+
}
|
|
2176
|
+
catch (err) {
|
|
2177
|
+
operation_state.icon_library.status = "fatal";
|
|
2178
|
+
operation_state.icon_library.error_message = extractMainMessage(err);
|
|
2179
|
+
}
|
|
2180
|
+
}
|
|
2181
|
+
|
|
2182
|
+
async function ReactRouter() {
|
|
2183
|
+
const { user_options } = useContext();
|
|
2184
|
+
const path_box = pathBox();
|
|
2185
|
+
const { routing_library } = resources_json;
|
|
2186
|
+
const read_wride_maker = async (template_file, write_file) => {
|
|
2187
|
+
const main_react_text = await readFile(template_file, "utf8");
|
|
2188
|
+
await ensureFile(write_file);
|
|
2189
|
+
await writeFile(write_file, main_react_text, "utf8");
|
|
2190
|
+
};
|
|
2191
|
+
const app_file_data = [
|
|
2192
|
+
{
|
|
2193
|
+
tage_name: "rr_class_import",
|
|
2194
|
+
content: `import {BrowserRouter as Router, Route, Routes, Navigate} from "react-router-dom";`,
|
|
2195
|
+
},
|
|
2196
|
+
{
|
|
2197
|
+
tage_name: "rr_class_start_rout",
|
|
2198
|
+
content: `
|
|
2199
|
+
<Router>
|
|
2200
|
+
<Routes>
|
|
2201
|
+
<Route path="/" element={<Navigate to="/home" replace />} />
|
|
2202
|
+
<Route path="/home" element={"#name of component#"} />
|
|
2203
|
+
|
|
2204
|
+
<Route path="*" element={<Navigate to="/" replace />} />
|
|
2205
|
+
</Routes>
|
|
2206
|
+
</Router>`,
|
|
2207
|
+
},
|
|
2208
|
+
];
|
|
2209
|
+
const main_file_data = [
|
|
2210
|
+
{
|
|
2211
|
+
tage_name: "rr_data_import",
|
|
2212
|
+
content: `import { RouterProvider } from "react-router-dom";`,
|
|
2213
|
+
},
|
|
2214
|
+
];
|
|
2215
|
+
const layout_file_data = [
|
|
2216
|
+
{
|
|
2217
|
+
tage_name: "rr_Outlet_import",
|
|
2218
|
+
content: `import { Outlet } from "react-router-dom";`,
|
|
2219
|
+
},
|
|
2220
|
+
];
|
|
2221
|
+
if (user_options.react_router_rout.includes("Classic Router")) {
|
|
2222
|
+
await UsingMark(path_box.app_react_path, app_file_data);
|
|
2223
|
+
}
|
|
2224
|
+
else if (user_options.react_router_rout.includes("Data Router")) {
|
|
2225
|
+
let file_content = await readFile(path_box.main_react_path, "utf8");
|
|
2226
|
+
file_content = file_content.replace(`import App from './App.${user_options.js_framework.includes("js") ? "js" : "ts"}x'`, `import router from "./router";`);
|
|
2227
|
+
file_content = file_content.replace(`<App />`, `<RouterProvider router={router} />`);
|
|
2228
|
+
await writeFile(path_box.main_react_path, file_content, "utf8");
|
|
2229
|
+
await UsingMark(path_box.main_react_path, main_file_data);
|
|
2230
|
+
await UsingMark(path_box.layout_path, layout_file_data);
|
|
2231
|
+
await read_wride_maker(path_box.reactrouter_router_templates, path_box.reactrouter_router_path);
|
|
2232
|
+
}
|
|
2233
|
+
await nizamDocEditor({
|
|
2234
|
+
title_params: "React Router",
|
|
2235
|
+
dec_params: `React Router is the most popular routing library for React.`,
|
|
2236
|
+
expla_params: `
|
|
2237
|
+
It lets you handle client-side routing in single-page applications (SPAs) with dynamic URLs, nested routes, and more.
|
|
2238
|
+
|
|
2239
|
+
${user_options.files_structure_names.includes("routing.json") ||
|
|
2240
|
+
!user_options.routing_library
|
|
2241
|
+
? ""
|
|
2242
|
+
: `
|
|
2243
|
+
> [!NOTE]
|
|
2244
|
+
> add all routing paths from one file (clean way).
|
|
2245
|
+
> We have created a \`routing.json\` file to use it which you will find in \`src/assets/routing.json\`
|
|
2246
|
+
`}
|
|
2247
|
+
|
|
2248
|
+
> [!TIP]
|
|
2249
|
+
> React Icons Documentation: [${routing_library.documentation.react_router.des}](${routing_library.documentation.react_router.link})`,
|
|
2250
|
+
});
|
|
2251
|
+
}
|
|
2252
|
+
|
|
2253
|
+
async function TanStackRouter() {
|
|
2254
|
+
const { user_options } = useContext();
|
|
2255
|
+
const path_box = pathBox();
|
|
2256
|
+
const { routing_library } = resources_json;
|
|
2257
|
+
const main_file_data = [
|
|
2258
|
+
{
|
|
2259
|
+
tage_name: "tr_data_import",
|
|
2260
|
+
content: `import { RouterProvider } from '@tanstack/react-router';`,
|
|
2261
|
+
},
|
|
2262
|
+
];
|
|
2263
|
+
const layout_file_data = [
|
|
2264
|
+
{
|
|
2265
|
+
tage_name: "tr_Outlet_import",
|
|
2266
|
+
content: `import { Outlet } from '@tanstack/react-router';`,
|
|
2267
|
+
},
|
|
2268
|
+
];
|
|
2269
|
+
const read_wride_maker = async (template_file, write_file) => {
|
|
2270
|
+
const main_react_text = await readFile(template_file, "utf8");
|
|
2271
|
+
await ensureFile(write_file);
|
|
2272
|
+
await writeFile(write_file, main_react_text, "utf8");
|
|
2273
|
+
};
|
|
2274
|
+
let file_content = await readFile(path_box.main_react_path, "utf8");
|
|
2275
|
+
file_content = file_content.replace(`import App from './App.${user_options.js_framework.includes("js") ? "js" : "ts"}x'`, `import { router } from './router';`);
|
|
2276
|
+
file_content = file_content.replace(`<App />`, `<RouterProvider router={router} />`);
|
|
2277
|
+
await writeFile(path_box.main_react_path, file_content, "utf8");
|
|
2278
|
+
await UsingMark(path_box.main_react_path, main_file_data);
|
|
2279
|
+
await UsingMark(path_box.layout_path, layout_file_data);
|
|
2280
|
+
await read_wride_maker(path_box.tanstackrouter_router_templates, path_box.tanstackrouter_router_path);
|
|
2281
|
+
await nizamDocEditor({
|
|
2282
|
+
title_params: "TanStack Route",
|
|
2283
|
+
dec_params: `TanStack Router is a modern, flexible, fully-featured routing library for React.`,
|
|
2284
|
+
expla_params: `
|
|
2285
|
+
It’s designed to handle complex routing needs in large-scale applications, while still offering strong developer ergonomics.
|
|
2286
|
+
|
|
2287
|
+
> [!TIP]
|
|
2288
|
+
> React Icons Documentation: [${routing_library.documentation.tanStack_router.des}](${routing_library.documentation.tanStack_router.link})`,
|
|
2289
|
+
});
|
|
2290
|
+
}
|
|
2291
|
+
|
|
2292
|
+
async function Wouter() {
|
|
2293
|
+
const path_box = pathBox();
|
|
2294
|
+
const { routing_library } = resources_json;
|
|
2295
|
+
const app_file_data = [
|
|
2296
|
+
{
|
|
2297
|
+
tage_name: "wouter_import",
|
|
2298
|
+
content: `import { Route } from "wouter";`,
|
|
2299
|
+
},
|
|
2300
|
+
{
|
|
2301
|
+
tage_name: "wouter_example",
|
|
2302
|
+
content: `{/*<Route path="/" component={ex:Home} />*/}`,
|
|
2303
|
+
},
|
|
2304
|
+
];
|
|
2305
|
+
UsingMark(path_box.app_react_path, app_file_data);
|
|
2306
|
+
await nizamDocEditor({
|
|
2307
|
+
title_params: "Wouter",
|
|
2308
|
+
dec_params: `Wouter is a minimalistic React router \`(~1KB gzipped!)\`.`,
|
|
2309
|
+
expla_params: `
|
|
2310
|
+
It provides the essential routing features: <Router>, \`<Route>\`, \`useLocation()\`, and \`useRoute()\`.
|
|
2311
|
+
It does not include nested routes, transitions, or complicated features—just simple client side routing.
|
|
2312
|
+
|
|
2313
|
+
> [!TIP]
|
|
2314
|
+
> React Icons Documentation: [${routing_library.documentation.wouter.des}](${routing_library.documentation.wouter.link})`,
|
|
2315
|
+
});
|
|
2316
|
+
}
|
|
2317
|
+
|
|
2318
|
+
async function RoutingLibrary() {
|
|
2319
|
+
const { user_options, operation_state } = useContext();
|
|
2320
|
+
const lib_list = [
|
|
2321
|
+
{
|
|
2322
|
+
name: "react router",
|
|
2323
|
+
fun: ReactRouter,
|
|
2324
|
+
dependencies: ["react-router-dom"],
|
|
2325
|
+
},
|
|
2326
|
+
{
|
|
2327
|
+
name: "tanstack router",
|
|
2328
|
+
fun: TanStackRouter,
|
|
2329
|
+
dependencies: ["@tanstack/react-router"],
|
|
2330
|
+
},
|
|
2331
|
+
{
|
|
2332
|
+
name: "wouter",
|
|
2333
|
+
fun: Wouter,
|
|
2334
|
+
dependencies: ["wouter"],
|
|
2335
|
+
},
|
|
2336
|
+
];
|
|
2337
|
+
try {
|
|
2338
|
+
await installDependencies({
|
|
2339
|
+
lib_list: lib_list,
|
|
2340
|
+
user_option_library: user_options.routing_library,
|
|
2341
|
+
});
|
|
2342
|
+
operation_state.routing_library.status = "success";
|
|
2343
|
+
}
|
|
2344
|
+
catch (err) {
|
|
2345
|
+
operation_state.routing_library.status = "fatal";
|
|
2346
|
+
operation_state.routing_library.error_message = extractMainMessage(err);
|
|
2347
|
+
}
|
|
2348
|
+
}
|
|
2349
|
+
|
|
2350
|
+
async function ReactContextAPI() {
|
|
2351
|
+
const { user_options } = useContext();
|
|
2352
|
+
const { state_management } = resources_json;
|
|
2353
|
+
const path_box = pathBox();
|
|
2354
|
+
const main_file_data = [
|
|
2355
|
+
{
|
|
2356
|
+
tage_name: "context_import_theme_provider",
|
|
2357
|
+
content: `import { ThemeProvider } from "${user_options.add_aliase ? "@" : "."}/context/theme/ThemeProvider";`,
|
|
2358
|
+
},
|
|
2359
|
+
{
|
|
2360
|
+
tage_name: "open_tage_theme_provider",
|
|
2361
|
+
content: `<ThemeProvider>`,
|
|
2362
|
+
},
|
|
2363
|
+
{
|
|
2364
|
+
tage_name: "close_tage_theme_provider",
|
|
2365
|
+
content: `</ThemeProvider>`,
|
|
2366
|
+
},
|
|
2367
|
+
];
|
|
2368
|
+
const ensure_read_write = async (file_path, temp_path) => {
|
|
2369
|
+
const file_contant = await readFile(temp_path);
|
|
2370
|
+
await ensureFile(file_path);
|
|
2371
|
+
await writeFile(file_path, file_contant, "utf8");
|
|
2372
|
+
};
|
|
2373
|
+
await mkdir(path_box.context_path, { recursive: true });
|
|
2374
|
+
await mkdir(path_box.context_theme_path, { recursive: true });
|
|
2375
|
+
await ensure_read_write(path_box.theme_context_file_path, path_box.theme_context_file_template);
|
|
2376
|
+
await ensure_read_write(path_box.theme_provider_file_path, path_box.theme_provider_file_template);
|
|
2377
|
+
await ensure_read_write(path_box.use_theme_file_path, path_box.use_theme_file_template);
|
|
2378
|
+
await UsingMark(path_box.main_react_path, main_file_data);
|
|
2379
|
+
await nizamDocEditor({
|
|
2380
|
+
title_params: user_options.state_management,
|
|
2381
|
+
expla_params: `
|
|
2382
|
+
#### We've created a template that you can use or modify. You'll find it inside. \`src/context/theme\`.
|
|
2383
|
+
|
|
2384
|
+
Its structure:
|
|
2385
|
+
\`\`\`
|
|
2386
|
+
src/
|
|
2387
|
+
├─ context/
|
|
2388
|
+
│ ├─ theme/
|
|
2389
|
+
│ │ ├─ ThemeContext.${user_options.js_framework.includes("js") ? "js" : "ts"}
|
|
2390
|
+
│ │ ├─ ThemeProvider.${user_options.js_framework.includes("js") ? "js" : "ts"}x
|
|
2391
|
+
│ │ └─ useTheme.${user_options.js_framework.includes("js") ? "js" : "ts"}
|
|
2392
|
+
\`\`\`
|
|
2393
|
+
|
|
2394
|
+
> [!TIP]
|
|
2395
|
+
> React Context API Documentation: [${state_management.documentation.react_context_api.des}](${state_management.documentation.react_context_api.link})`,
|
|
2396
|
+
});
|
|
2397
|
+
}
|
|
2398
|
+
|
|
2399
|
+
async function ReduxToolkit() {
|
|
2400
|
+
const { user_options } = useContext();
|
|
2401
|
+
const { state_management } = resources_json;
|
|
2402
|
+
const path_box = pathBox();
|
|
2403
|
+
const main_file_data = [
|
|
2404
|
+
{
|
|
2405
|
+
tage_name: "import_react_toolkit_provider",
|
|
2406
|
+
content: `import { Provider } from "react-redux";`,
|
|
2407
|
+
},
|
|
2408
|
+
{
|
|
2409
|
+
tage_name: "import_react_toolkit_store",
|
|
2410
|
+
content: `import { store } from "${user_options.add_aliase ? "@" : "."}/store/store";`,
|
|
2411
|
+
},
|
|
2412
|
+
{
|
|
2413
|
+
tage_name: "open_tage_react_toolkit_provider",
|
|
2414
|
+
content: `<Provider store={store}>`,
|
|
2415
|
+
},
|
|
2416
|
+
{
|
|
2417
|
+
tage_name: "close_tage_react_toolkit_provider",
|
|
2418
|
+
content: `</Provider>`,
|
|
2419
|
+
},
|
|
2420
|
+
];
|
|
2421
|
+
const ensure_read_write = async (file_path, temp_path) => {
|
|
2422
|
+
const file_contant = await readFile(temp_path);
|
|
2423
|
+
await ensureFile(file_path);
|
|
2424
|
+
await writeFile(file_path, file_contant, "utf8");
|
|
2425
|
+
};
|
|
2426
|
+
await mkdir(path_box.store_path, { recursive: true });
|
|
2427
|
+
await mkdir(path_box.store_slices_path, { recursive: true });
|
|
2428
|
+
await ensure_read_write(path_box.store_file_path, path_box.store_file_template);
|
|
2429
|
+
await ensure_read_write(path_box.slices_counter_file_path, path_box.slices_counter_file_template);
|
|
2430
|
+
await ensure_read_write(path_box.slices_index_file_path, path_box.slices_index_file_template);
|
|
2431
|
+
await UsingMark(path_box.main_react_path, main_file_data);
|
|
2432
|
+
await nizamDocEditor({
|
|
2433
|
+
title_params: user_options.state_management,
|
|
2434
|
+
expla_params: `
|
|
2435
|
+
#### We've created a template that you can use or modify. You'll find it inside. \`src/store\`.
|
|
2436
|
+
|
|
2437
|
+
Its structure:
|
|
2438
|
+
\`\`\`
|
|
2439
|
+
src/
|
|
2440
|
+
├─ store/
|
|
2441
|
+
│ ├─ slices/
|
|
2442
|
+
│ │ ├─ index.${user_options.js_framework.includes("js") ? "js" : "ts"}
|
|
2443
|
+
│ │ └─ counterSlice.${user_options.js_framework.includes("js") ? "js" : "ts"}
|
|
2444
|
+
│ └─ store.${user_options.js_framework.includes("js") ? "js" : "ts"}
|
|
2445
|
+
\`\`\`
|
|
2446
|
+
|
|
2447
|
+
> [!TIP]
|
|
2448
|
+
> Redux Toolkit Documentation: [${state_management.documentation.redux_toolkit.des}](${state_management.documentation.redux_toolkit.link})`,
|
|
2449
|
+
});
|
|
2450
|
+
}
|
|
2451
|
+
|
|
2452
|
+
async function Zustand() {
|
|
2453
|
+
const { user_options } = useContext();
|
|
2454
|
+
const { state_management } = resources_json;
|
|
2455
|
+
const path_box = pathBox();
|
|
2456
|
+
const ensure_read_write = async (file_path, temp_path) => {
|
|
2457
|
+
const file_contant = await readFile(temp_path);
|
|
2458
|
+
await ensureFile(file_path);
|
|
2459
|
+
await writeFile(file_path, file_contant, "utf8");
|
|
2460
|
+
};
|
|
2461
|
+
await mkdir(path_box.store_path, { recursive: true });
|
|
2462
|
+
await ensure_read_write(path_box.zustand_use_counter_file_path, path_box.zustand_use_counter_file_template);
|
|
2463
|
+
await ensure_read_write(path_box.zustand_index_file_path, path_box.zustand_index_file_template);
|
|
2464
|
+
await nizamDocEditor({
|
|
2465
|
+
title_params: user_options.state_management,
|
|
2466
|
+
expla_params: `
|
|
2467
|
+
#### We've created a template that you can use or modify. You'll find it inside. \`src/store\`.
|
|
2468
|
+
|
|
2469
|
+
Its structure:
|
|
2470
|
+
\`\`\`
|
|
2471
|
+
src/
|
|
2472
|
+
├─ store/
|
|
2473
|
+
│ ├─ useCounterStore.${user_options.js_framework.includes("js") ? "js" : "ts"}
|
|
2474
|
+
│ │
|
|
2475
|
+
\`\`\`
|
|
2476
|
+
|
|
2477
|
+
> [!TIP]
|
|
2478
|
+
> Zustand Documentation: [${state_management.documentation.zustand.des}](${state_management.documentation.zustand.link})`,
|
|
2479
|
+
});
|
|
2480
|
+
}
|
|
2481
|
+
|
|
2482
|
+
async function StateManagementReact() {
|
|
2483
|
+
const { user_options } = useContext();
|
|
2484
|
+
const lib_list = [
|
|
2485
|
+
{
|
|
2486
|
+
name: "react context api",
|
|
2487
|
+
fun: ReactContextAPI,
|
|
2488
|
+
dependencies: [],
|
|
2489
|
+
},
|
|
2490
|
+
{
|
|
2491
|
+
name: "redux toolkit",
|
|
2492
|
+
fun: ReduxToolkit,
|
|
2493
|
+
dependencies: ["@reduxjs/toolkit", "react-redux"],
|
|
2494
|
+
},
|
|
2495
|
+
{
|
|
2496
|
+
name: "zustand",
|
|
2497
|
+
fun: Zustand,
|
|
2498
|
+
dependencies: ["zustand"],
|
|
2499
|
+
},
|
|
2500
|
+
];
|
|
2501
|
+
await installDependencies({
|
|
2502
|
+
lib_list: lib_list,
|
|
2503
|
+
user_option_library: user_options.state_management,
|
|
2504
|
+
});
|
|
2505
|
+
}
|
|
2506
|
+
|
|
2507
|
+
async function StateManagement() {
|
|
2508
|
+
const { user_options, operation_state } = useContext();
|
|
2509
|
+
try {
|
|
2510
|
+
if (user_options.js_framework.includes("React")) {
|
|
2511
|
+
await StateManagementReact();
|
|
2512
|
+
}
|
|
2513
|
+
operation_state.state_management.status = "success";
|
|
2514
|
+
}
|
|
2515
|
+
catch (err) {
|
|
2516
|
+
operation_state.state_management.status = "fatal";
|
|
2517
|
+
operation_state.state_management.error_message = extractMainMessage(err);
|
|
2518
|
+
}
|
|
2519
|
+
}
|
|
2520
|
+
|
|
2521
|
+
async function ReactHelmetAsync() {
|
|
2522
|
+
const { user_options } = useContext();
|
|
2523
|
+
const path_box = pathBox();
|
|
2524
|
+
const { head_management } = resources_json;
|
|
2525
|
+
const main_file_data = [
|
|
2526
|
+
{
|
|
2527
|
+
tage_name: "import_react_helmet_async_provider",
|
|
2528
|
+
content: `import { HelmetProvider } from 'react-helmet-async';`,
|
|
2529
|
+
},
|
|
2530
|
+
{
|
|
2531
|
+
tage_name: "open_react_helmet_async_provider_tage",
|
|
2532
|
+
content: `<HelmetProvider>`,
|
|
2533
|
+
},
|
|
2534
|
+
{
|
|
2535
|
+
tage_name: "close_react_helmet_async_provider_tage",
|
|
2536
|
+
content: `</HelmetProvider>`,
|
|
2537
|
+
},
|
|
2538
|
+
];
|
|
2539
|
+
await UsingMark(path_box.main_react_path, main_file_data);
|
|
2540
|
+
await nizamDocEditor({
|
|
2541
|
+
title_params: user_options.head_management,
|
|
2542
|
+
expla_params: `
|
|
2543
|
+
example on how to use:
|
|
2544
|
+
\`\`\`
|
|
2545
|
+
import { Helmet } from 'react-helmet-async';
|
|
2546
|
+
|
|
2547
|
+
const home = (
|
|
2548
|
+
<>
|
|
2549
|
+
<Helmet>
|
|
2550
|
+
<title></title>
|
|
2551
|
+
<meta name="description" content="" />
|
|
2552
|
+
<meta name="keywords" content="" />
|
|
2553
|
+
|
|
2554
|
+
{/* Open Graph / Facebook / LinkedIn / WhatsApp */}
|
|
2555
|
+
<meta property="og:url" content="" />
|
|
2556
|
+
<meta property="og:title" content="" />
|
|
2557
|
+
<meta property="og:description" content="" />
|
|
2558
|
+
<meta property="og:image" content="" />
|
|
2559
|
+
|
|
2560
|
+
{/* Twitter */}
|
|
2561
|
+
<meta name="twitter:url" content="" />
|
|
2562
|
+
<meta name="twitter:title" content="" />
|
|
2563
|
+
<meta name="twitter:description" content="" />
|
|
2564
|
+
<meta name="twitter:image" content="" />
|
|
2565
|
+
</Helmet>
|
|
2566
|
+
<h1>Hello World</h1>
|
|
2567
|
+
</>
|
|
2568
|
+
);
|
|
2569
|
+
\`\`\`
|
|
2570
|
+
|
|
2571
|
+
> [!TIP]
|
|
2572
|
+
> React Helmet Async Documentation: [${head_management.documentation.react_helmet_async.des}](${head_management.documentation.react_helmet_async.link})`,
|
|
2573
|
+
});
|
|
2574
|
+
}
|
|
2575
|
+
|
|
2576
|
+
async function Drpogodin() {
|
|
2577
|
+
const { user_options } = useContext();
|
|
2578
|
+
const path_box = pathBox();
|
|
2579
|
+
const { head_management } = resources_json;
|
|
2580
|
+
const main_file_data = [
|
|
2581
|
+
{
|
|
2582
|
+
tage_name: "import_dr_pogodin_react_helmet_async_provider",
|
|
2583
|
+
content: `import { HelmetProvider } from '@dr.pogodin/react-helmet';`,
|
|
2584
|
+
},
|
|
2585
|
+
{
|
|
2586
|
+
tage_name: "open_dr_pogodin_react_helmet_async_provider_tage",
|
|
2587
|
+
content: `<HelmetProvider>`,
|
|
2588
|
+
},
|
|
2589
|
+
{
|
|
2590
|
+
tage_name: "close_dr_pogodin_react_helmet_async_provider_tage",
|
|
2591
|
+
content: `</HelmetProvider>`,
|
|
2592
|
+
},
|
|
2593
|
+
];
|
|
2594
|
+
await UsingMark(path_box.main_react_path, main_file_data);
|
|
2595
|
+
await nizamDocEditor({
|
|
2596
|
+
title_params: user_options.head_management,
|
|
2597
|
+
expla_params: `
|
|
2598
|
+
example on how to use:
|
|
2599
|
+
\`\`\`
|
|
2600
|
+
import { Helmet } from '@dr.pogodin/react-helmet';
|
|
2601
|
+
|
|
2602
|
+
const home = (
|
|
2603
|
+
<>
|
|
2604
|
+
<Helmet>
|
|
2605
|
+
<title></title>
|
|
2606
|
+
<meta name="description" content="" />
|
|
2607
|
+
<meta name="keywords" content="" />
|
|
2608
|
+
|
|
2609
|
+
{/* Open Graph / Facebook / LinkedIn / WhatsApp */}
|
|
2610
|
+
<meta property="og:url" content="" />
|
|
2611
|
+
<meta property="og:title" content="" />
|
|
2612
|
+
<meta property="og:description" content="" />
|
|
2613
|
+
<meta property="og:image" content="" />
|
|
2614
|
+
|
|
2615
|
+
{/* Twitter */}
|
|
2616
|
+
<meta name="twitter:url" content="" />
|
|
2617
|
+
<meta name="twitter:title" content="" />
|
|
2618
|
+
<meta name="twitter:description" content="" />
|
|
2619
|
+
<meta name="twitter:image" content="" />
|
|
2620
|
+
</Helmet>
|
|
2621
|
+
<h1>Hello World</h1>
|
|
2622
|
+
</>
|
|
2623
|
+
);
|
|
2624
|
+
\`\`\`
|
|
2625
|
+
|
|
2626
|
+
> [!TIP]
|
|
2627
|
+
> Dr. Pogodin React Helmet Documentation: [${head_management.documentation["@dr.pogodin/react-helmet"].des}](${head_management.documentation["@dr.pogodin/react-helmet"].link})`,
|
|
2628
|
+
});
|
|
2629
|
+
}
|
|
2630
|
+
|
|
2631
|
+
async function Unhead() {
|
|
2632
|
+
const { user_options } = useContext();
|
|
2633
|
+
const path_box = pathBox();
|
|
2634
|
+
const { head_management } = resources_json;
|
|
2635
|
+
const main_file_data = [
|
|
2636
|
+
{
|
|
2637
|
+
tage_name: "import_unhead_provider",
|
|
2638
|
+
content: `import { createHead, UnheadProvider } from '@unhead/react';`,
|
|
2639
|
+
},
|
|
2640
|
+
{
|
|
2641
|
+
tage_name: "import_unhead_createhead",
|
|
2642
|
+
content: `const head = createHead();`,
|
|
2643
|
+
},
|
|
2644
|
+
{
|
|
2645
|
+
tage_name: "open_unhead_provider_tage",
|
|
2646
|
+
content: `<UnheadProvider head={head}>`,
|
|
2647
|
+
},
|
|
2648
|
+
{
|
|
2649
|
+
tage_name: "close_unhead_provider_tage",
|
|
2650
|
+
content: `</UnheadProvider>`,
|
|
2651
|
+
},
|
|
2652
|
+
];
|
|
2653
|
+
await UsingMark(path_box.main_react_path, main_file_data);
|
|
2654
|
+
await nizamDocEditor({
|
|
2655
|
+
title_params: user_options.head_management,
|
|
2656
|
+
expla_params: `
|
|
2657
|
+
example on how to use:
|
|
2658
|
+
\`\`\`
|
|
2659
|
+
import { useHead } from '@unhead/react';
|
|
2660
|
+
|
|
2661
|
+
useHead({
|
|
2662
|
+
title: "Home",
|
|
2663
|
+
meta: [
|
|
2664
|
+
{ name: "description", content: "" },
|
|
2665
|
+
{ name: "keywords", content: "" }
|
|
2666
|
+
],
|
|
2667
|
+
link: [
|
|
2668
|
+
{ rel: "", href: "https://example.com/" }
|
|
2669
|
+
]
|
|
2670
|
+
});
|
|
2671
|
+
\`\`\`
|
|
2672
|
+
|
|
2673
|
+
> [!TIP]
|
|
2674
|
+
> Unhead Documentation: [${head_management.documentation.unhead.des}](${head_management.documentation.unhead.link})`,
|
|
2675
|
+
});
|
|
2676
|
+
}
|
|
2677
|
+
|
|
2678
|
+
async function HeadManagement() {
|
|
2679
|
+
const { user_options, operation_state } = useContext();
|
|
2680
|
+
const lib_list = [
|
|
2681
|
+
{
|
|
2682
|
+
name: "react helmet async",
|
|
2683
|
+
fun: ReactHelmetAsync,
|
|
2684
|
+
dependencies: ["react-helmet-async"],
|
|
2685
|
+
},
|
|
2686
|
+
{
|
|
2687
|
+
name: "dr. pogodin react helmet",
|
|
2688
|
+
fun: Drpogodin,
|
|
2689
|
+
dependencies: ["@dr.pogodin/react-helmet"],
|
|
2690
|
+
},
|
|
2691
|
+
{
|
|
2692
|
+
name: "unhead",
|
|
2693
|
+
fun: Unhead,
|
|
2694
|
+
dependencies: ["@unhead/react"],
|
|
2695
|
+
},
|
|
2696
|
+
];
|
|
2697
|
+
try {
|
|
2698
|
+
await installDependencies({
|
|
2699
|
+
lib_list: lib_list,
|
|
2700
|
+
user_option_library: user_options.head_management,
|
|
2701
|
+
});
|
|
2702
|
+
operation_state.head_management.status = "success";
|
|
2703
|
+
}
|
|
2704
|
+
catch (err) {
|
|
2705
|
+
operation_state.head_management.status = "fatal";
|
|
2706
|
+
operation_state.head_management.error_message = extractMainMessage(err);
|
|
2707
|
+
}
|
|
2708
|
+
}
|
|
2709
|
+
|
|
2710
|
+
async function Axios() {
|
|
2711
|
+
const { user_options } = useContext();
|
|
2712
|
+
const path_box = pathBox();
|
|
2713
|
+
const { data_fetching } = resources_json;
|
|
2714
|
+
const env_file_data = [
|
|
2715
|
+
{
|
|
2716
|
+
tage_name: "VITE_API_URL",
|
|
2717
|
+
content: `VITE_API_URL=https://example.com`,
|
|
2718
|
+
},
|
|
2719
|
+
];
|
|
2720
|
+
await mkdir(path_box.api_path, { recursive: true });
|
|
2721
|
+
const file_contant = await readFile(path_box.api_axios_file_template);
|
|
2722
|
+
await ensureFile(path_box.api_axios_fle_path);
|
|
2723
|
+
await writeFile(path_box.api_axios_fle_path, file_contant, "utf8");
|
|
2724
|
+
UsingMark(path_box.env_path, env_file_data);
|
|
2725
|
+
await nizamDocEditor({
|
|
2726
|
+
title_params: user_options.data_fetching,
|
|
2727
|
+
expla_params: `
|
|
2728
|
+
example on how to use:
|
|
2729
|
+
|
|
2730
|
+
\`\`\`
|
|
2731
|
+
import api from "${user_options.add_aliase ? "@" : "."}/api/axios";
|
|
2732
|
+
|
|
2733
|
+
function Home() {
|
|
2734
|
+
useEffect(() => {
|
|
2735
|
+
api.get<Post[]>("/posts").then(res => setPosts(res.data));
|
|
2736
|
+
}, []);
|
|
2737
|
+
|
|
2738
|
+
return (
|
|
2739
|
+
<div>
|
|
2740
|
+
{posts.map(post => <p key={post.id}>{post.title}</p>)}
|
|
2741
|
+
</div>
|
|
2742
|
+
);
|
|
2743
|
+
}
|
|
2744
|
+
|
|
2745
|
+
export default Home;
|
|
2746
|
+
\`\`\`
|
|
2747
|
+
|
|
2748
|
+
> [!TIP]
|
|
2749
|
+
> Axios Documentation: [${data_fetching.documentation.axios.des}](${data_fetching.documentation.axios.link})`,
|
|
2750
|
+
});
|
|
2751
|
+
}
|
|
2752
|
+
|
|
2753
|
+
async function TanStackQuery() {
|
|
2754
|
+
const { user_options } = useContext();
|
|
2755
|
+
const path_box = pathBox();
|
|
2756
|
+
const { data_fetching } = resources_json;
|
|
2757
|
+
const main_file_data = [
|
|
2758
|
+
{
|
|
2759
|
+
tage_name: "import_query_client_provider",
|
|
2760
|
+
content: `import { QueryClient, QueryClientProvider } from "@tanstack/react-query";`,
|
|
2761
|
+
},
|
|
2762
|
+
{
|
|
2763
|
+
tage_name: "using_query_client",
|
|
2764
|
+
content: `const queryClient = new QueryClient();`,
|
|
2765
|
+
},
|
|
2766
|
+
{
|
|
2767
|
+
tage_name: "open_tage_query_client_provider",
|
|
2768
|
+
content: `<QueryClientProvider client={queryClient}>`,
|
|
2769
|
+
},
|
|
2770
|
+
{
|
|
2771
|
+
tage_name: "close_tage_query_client_provider",
|
|
2772
|
+
content: `</QueryClientProvider>`,
|
|
2773
|
+
},
|
|
2774
|
+
];
|
|
2775
|
+
const env_file_data = [
|
|
2776
|
+
{
|
|
2777
|
+
tage_name: "VITE_API_URL",
|
|
2778
|
+
content: `VITE_API_URL=https://example.com`,
|
|
2779
|
+
},
|
|
2780
|
+
];
|
|
2781
|
+
await mkdir(path_box.api_path, { recursive: true });
|
|
2782
|
+
const file_contant = await readFile(path_box.api_http_file_template);
|
|
2783
|
+
await ensureFile(path_box.api_http_file_path);
|
|
2784
|
+
await writeFile(path_box.api_http_file_path, file_contant, "utf8");
|
|
2785
|
+
UsingMark(path_box.env_path, env_file_data);
|
|
2786
|
+
UsingMark(path_box.main_react_path, main_file_data);
|
|
2787
|
+
await nizamDocEditor({
|
|
2788
|
+
title_params: user_options.data_fetching,
|
|
2789
|
+
expla_params: `
|
|
2790
|
+
example on how to use:
|
|
2791
|
+
|
|
2792
|
+
\`\`\`
|
|
2793
|
+
import { useQuery } from "@tanstack/react-query";
|
|
2794
|
+
import { http, Post } from "${user_options.add_aliase ? "@" : "."}/api/http";
|
|
2795
|
+
|
|
2796
|
+
function Home() {
|
|
2797
|
+
const { data, isLoading, error } = useQuery({
|
|
2798
|
+
queryKey: ["posts"],
|
|
2799
|
+
queryFn: () => http("/posts"),
|
|
2800
|
+
});
|
|
2801
|
+
|
|
2802
|
+
if (isLoading) return <p>Loading...</p>;
|
|
2803
|
+
if (error instanceof Error) return <p>Error: {error.message}</p>;
|
|
2804
|
+
|
|
2805
|
+
return <div>{data?.map(post => <p key={post.id}>{post.title}</p>)}</div>;
|
|
2806
|
+
}
|
|
2807
|
+
|
|
2808
|
+
export default Home;
|
|
2809
|
+
\`\`\`
|
|
2810
|
+
|
|
2811
|
+
> [!TIP]
|
|
2812
|
+
> TanStack Query Documentation: [${data_fetching.documentation.tanstack_query.des}](${data_fetching.documentation.tanstack_query.link})`,
|
|
2813
|
+
});
|
|
2814
|
+
}
|
|
2815
|
+
|
|
2816
|
+
async function SWR() {
|
|
2817
|
+
const { user_options } = useContext();
|
|
2818
|
+
const path_box = pathBox();
|
|
2819
|
+
const { data_fetching } = resources_json;
|
|
2820
|
+
const env_file_data = [
|
|
2821
|
+
{
|
|
2822
|
+
tage_name: "VITE_API_URL",
|
|
2823
|
+
content: `VITE_API_URL=https://example.com`,
|
|
2824
|
+
},
|
|
2825
|
+
];
|
|
2826
|
+
await mkdir(path_box.api_path, { recursive: true });
|
|
2827
|
+
const file_contant = await readFile(path_box.api_fetcher_file_template);
|
|
2828
|
+
await ensureFile(path_box.api_fetcher_file_path);
|
|
2829
|
+
await writeFile(path_box.api_fetcher_file_path, file_contant, "utf8");
|
|
2830
|
+
UsingMark(path_box.env_path, env_file_data);
|
|
2831
|
+
await nizamDocEditor({
|
|
2832
|
+
title_params: user_options.data_fetching,
|
|
2833
|
+
expla_params: `
|
|
2834
|
+
example on how to use:
|
|
2835
|
+
|
|
2836
|
+
\`\`\`
|
|
2837
|
+
import useSWR from "swr";
|
|
2838
|
+
import { fetcher } from "${user_options.add_aliase ? "@" : "."}/api/fetcher";
|
|
2839
|
+
|
|
2840
|
+
function Home() {
|
|
2841
|
+
const { data, error } = useSWR("/posts", fetcher);
|
|
2842
|
+
|
|
2843
|
+
if (error) return <p>Error: {error.message}</p>;
|
|
2844
|
+
if (!data) return <p>Loading...</p>;
|
|
2845
|
+
|
|
2846
|
+
return <div>{data.map(post => <p key={post.id}>{post.title}</p>)}</div>;
|
|
2847
|
+
}
|
|
2848
|
+
|
|
2849
|
+
export default Home;
|
|
2850
|
+
\`\`\`
|
|
2851
|
+
|
|
2852
|
+
> [!TIP]
|
|
2853
|
+
> SWR Documentation: [${data_fetching.documentation.swr.des}](${data_fetching.documentation.swr.link})`,
|
|
2854
|
+
});
|
|
2855
|
+
}
|
|
2856
|
+
|
|
2857
|
+
async function DataFetchingReact() {
|
|
2858
|
+
const { user_options } = useContext();
|
|
2859
|
+
const lib_list = [
|
|
2860
|
+
{
|
|
2861
|
+
name: "axios",
|
|
2862
|
+
fun: Axios,
|
|
2863
|
+
dependencies: ["axios"],
|
|
2864
|
+
},
|
|
2865
|
+
{
|
|
2866
|
+
name: "tanstack query",
|
|
2867
|
+
fun: TanStackQuery,
|
|
2868
|
+
dependencies: ["@tanstack/react-query"],
|
|
2869
|
+
},
|
|
2870
|
+
{
|
|
2871
|
+
name: "swr",
|
|
2872
|
+
fun: SWR,
|
|
2873
|
+
dependencies: ["swr"],
|
|
2874
|
+
},
|
|
2875
|
+
];
|
|
2876
|
+
await installDependencies({
|
|
2877
|
+
lib_list: lib_list,
|
|
2878
|
+
user_option_library: user_options.data_fetching,
|
|
2879
|
+
});
|
|
2880
|
+
}
|
|
2881
|
+
|
|
2882
|
+
async function DataFetching() {
|
|
2883
|
+
const { user_options, operation_state } = useContext();
|
|
2884
|
+
try {
|
|
2885
|
+
if (user_options.js_framework.includes("React")) {
|
|
2886
|
+
await DataFetchingReact();
|
|
2887
|
+
}
|
|
2888
|
+
operation_state.data_fetching.status = "success";
|
|
2889
|
+
}
|
|
2890
|
+
catch (err) {
|
|
2891
|
+
operation_state.data_fetching.status = "fatal";
|
|
2892
|
+
operation_state.data_fetching.error_message = extractMainMessage(err);
|
|
2893
|
+
}
|
|
2894
|
+
}
|
|
2895
|
+
|
|
2896
|
+
async function cleanFolder() {
|
|
2897
|
+
const { full_project_path, operation_state } = useContext();
|
|
2898
|
+
const MARK = "##-nizam@mark-##:";
|
|
2899
|
+
const remove_mark = async (dir) => {
|
|
2900
|
+
const items = await readdir(dir);
|
|
2901
|
+
const IGNORE_FILES = new Set([
|
|
2902
|
+
"NIZAM_DOC.md",
|
|
2903
|
+
"package.json",
|
|
2904
|
+
".gitignore",
|
|
2905
|
+
"README.md",
|
|
2906
|
+
"tsconfig.app.json",
|
|
2907
|
+
"tsconfig.json",
|
|
2908
|
+
"tsconfig.node.json",
|
|
2909
|
+
"index.html",
|
|
2910
|
+
"eslint.config.js",
|
|
2911
|
+
"public",
|
|
2912
|
+
]);
|
|
2913
|
+
for (const item of items) {
|
|
2914
|
+
if (IGNORE_FILES.has(item))
|
|
2915
|
+
continue;
|
|
2916
|
+
const fullPath = path.join(dir, item);
|
|
2917
|
+
const stat = await lstat(fullPath);
|
|
2918
|
+
if (stat.isDirectory()) {
|
|
2919
|
+
await remove_mark(fullPath);
|
|
2920
|
+
}
|
|
2921
|
+
else if (stat.isFile()) {
|
|
2922
|
+
let content = await readFile(fullPath, "utf8");
|
|
2923
|
+
const lines = content.split(/\r?\n/);
|
|
2924
|
+
const cleanedLines = lines
|
|
2925
|
+
.map((line) => {
|
|
2926
|
+
if (line.includes(MARK)) {
|
|
2927
|
+
const newLine = line.replace(new RegExp(`${MARK}\\S+`, "g"), "");
|
|
2928
|
+
return newLine.trim() === "" ? null : newLine;
|
|
2929
|
+
}
|
|
2930
|
+
return line;
|
|
2931
|
+
})
|
|
2932
|
+
.filter(Boolean);
|
|
2933
|
+
const cleanedContent = cleanedLines.join("\n");
|
|
2934
|
+
await writeFile(fullPath, cleanedContent, "utf8");
|
|
2935
|
+
}
|
|
2936
|
+
}
|
|
2937
|
+
};
|
|
2938
|
+
try {
|
|
2939
|
+
await remove_mark(full_project_path);
|
|
2940
|
+
operation_state.clean_folder_mark.status = "success";
|
|
2941
|
+
}
|
|
2942
|
+
catch (err) {
|
|
2943
|
+
operation_state.clean_folder_mark.status = "fatal";
|
|
2944
|
+
operation_state.clean_folder_mark.error_message = extractMainMessage(err);
|
|
2945
|
+
}
|
|
2946
|
+
}
|
|
2947
|
+
|
|
2948
|
+
async function Setup() {
|
|
2949
|
+
const { operation_state, user_options } = useContext();
|
|
2950
|
+
const operation_data = [
|
|
2951
|
+
{
|
|
2952
|
+
operation_name: "creat_project_folder",
|
|
2953
|
+
operation_fun: CreatFolder,
|
|
2954
|
+
operation_des: "creat project folder",
|
|
2955
|
+
operation_is_need: true,
|
|
2956
|
+
operation_targit: true,
|
|
2957
|
+
},
|
|
2958
|
+
{
|
|
2959
|
+
operation_name: "js_framework",
|
|
2960
|
+
operation_fun: JSFramework,
|
|
2961
|
+
operation_des: `install ${user_options.js_framework}`,
|
|
2962
|
+
operation_is_need: true,
|
|
2963
|
+
operation_targit: user_options.js_framework,
|
|
2964
|
+
},
|
|
2965
|
+
{
|
|
2966
|
+
operation_name: "creat_vsc_folder",
|
|
2967
|
+
operation_fun: CreatVSCFolder,
|
|
2968
|
+
operation_des: "creat (.vscode) folder",
|
|
2969
|
+
operation_is_need: false,
|
|
2970
|
+
operation_targit: true,
|
|
2971
|
+
},
|
|
2972
|
+
{
|
|
2973
|
+
operation_name: "add_aliase",
|
|
2974
|
+
operation_fun: Aliase,
|
|
2975
|
+
operation_des: "make path alias (@) configuration",
|
|
2976
|
+
operation_is_need: false,
|
|
2977
|
+
operation_targit: user_options.add_aliase,
|
|
2978
|
+
},
|
|
2979
|
+
{
|
|
2980
|
+
operation_name: "app_structure",
|
|
2981
|
+
operation_fun: Structure,
|
|
2982
|
+
operation_des: "build app structure",
|
|
2983
|
+
operation_is_need: false,
|
|
2984
|
+
operation_targit: user_options.app_structure,
|
|
2985
|
+
},
|
|
2986
|
+
{
|
|
2987
|
+
operation_name: "css_framework",
|
|
2988
|
+
operation_fun: CSSFramework,
|
|
2989
|
+
operation_des: `install and integrate ${user_options.css_framework}`,
|
|
2990
|
+
operation_is_need: false,
|
|
2991
|
+
operation_targit: user_options.css_framework,
|
|
2992
|
+
},
|
|
2993
|
+
{
|
|
2994
|
+
operation_name: "ui_library",
|
|
2995
|
+
operation_fun: UILibrary,
|
|
2996
|
+
operation_des: `install and integrate UI component library`,
|
|
2997
|
+
operation_is_need: false,
|
|
2998
|
+
operation_targit: user_options.ui_library,
|
|
2999
|
+
},
|
|
3000
|
+
{
|
|
3001
|
+
operation_name: "routing_library",
|
|
3002
|
+
operation_fun: RoutingLibrary,
|
|
3003
|
+
operation_des: `install and integrate ${user_options.routing_library}`,
|
|
3004
|
+
operation_is_need: false,
|
|
3005
|
+
operation_targit: user_options.routing_library,
|
|
3006
|
+
},
|
|
3007
|
+
{
|
|
3008
|
+
operation_name: "state_management",
|
|
3009
|
+
operation_fun: StateManagement,
|
|
3010
|
+
operation_des: `install and integrate ${user_options.state_management}`,
|
|
3011
|
+
operation_is_need: false,
|
|
3012
|
+
operation_targit: user_options.state_management,
|
|
3013
|
+
},
|
|
3014
|
+
{
|
|
3015
|
+
operation_name: "icon_library",
|
|
3016
|
+
operation_fun: IconLibrary,
|
|
3017
|
+
operation_des: `install icons Library`,
|
|
3018
|
+
operation_is_need: false,
|
|
3019
|
+
operation_targit: user_options.icon_library,
|
|
3020
|
+
},
|
|
3021
|
+
{
|
|
3022
|
+
operation_name: "head_management",
|
|
3023
|
+
operation_fun: HeadManagement,
|
|
3024
|
+
operation_des: `install and integrate ${user_options.head_management}`,
|
|
3025
|
+
operation_is_need: false,
|
|
3026
|
+
operation_targit: user_options.head_management,
|
|
3027
|
+
},
|
|
3028
|
+
{
|
|
3029
|
+
operation_name: "data_fetching",
|
|
3030
|
+
operation_fun: DataFetching,
|
|
3031
|
+
operation_des: `install and integrate ${user_options.data_fetching}`,
|
|
3032
|
+
operation_is_need: false,
|
|
3033
|
+
operation_targit: user_options.data_fetching,
|
|
3034
|
+
},
|
|
3035
|
+
{
|
|
3036
|
+
operation_name: "clean_folder_mark",
|
|
3037
|
+
operation_fun: cleanFolder,
|
|
3038
|
+
operation_des: `preparing the file for use`,
|
|
3039
|
+
operation_is_need: true,
|
|
3040
|
+
operation_targit: true,
|
|
3041
|
+
},
|
|
3042
|
+
];
|
|
3043
|
+
// get all path that's i will use
|
|
3044
|
+
CorePaths();
|
|
3045
|
+
for (const _ of operation_data) {
|
|
3046
|
+
if (!_.operation_targit ||
|
|
3047
|
+
(Array.isArray(_.operation_targit) && _.operation_targit.length === 0))
|
|
3048
|
+
continue;
|
|
3049
|
+
await operations(_.operation_fun, _.operation_name, _.operation_des);
|
|
3050
|
+
if (!_.operation_is_need)
|
|
3051
|
+
continue;
|
|
3052
|
+
if (operation_state[_.operation_name].status ===
|
|
3053
|
+
"fatal") {
|
|
3054
|
+
process.exit(0);
|
|
3055
|
+
}
|
|
3056
|
+
}
|
|
3057
|
+
}
|
|
3058
|
+
|
|
3059
|
+
function createContext() {
|
|
3060
|
+
const one_operation_state = { status: "", error_message: "" };
|
|
3061
|
+
return {
|
|
3062
|
+
internet_conection: false,
|
|
3063
|
+
start_menu_options: "",
|
|
3064
|
+
full_project_path: "",
|
|
3065
|
+
nizam_templates_path: "",
|
|
3066
|
+
pkg_is_installed: [],
|
|
3067
|
+
reset_menu: false,
|
|
3068
|
+
user_options: {
|
|
3069
|
+
project_path: "",
|
|
3070
|
+
project_name: "",
|
|
3071
|
+
pkg_manager: "",
|
|
3072
|
+
js_framework: "",
|
|
3073
|
+
add_aliase: false,
|
|
3074
|
+
css_framework: "",
|
|
3075
|
+
app_structure: "",
|
|
3076
|
+
folder_structure_names: [],
|
|
3077
|
+
files_structure_names: [],
|
|
3078
|
+
ui_library: [],
|
|
3079
|
+
icon_library: [],
|
|
3080
|
+
routing_library: "",
|
|
3081
|
+
react_router_rout: "",
|
|
3082
|
+
state_management: "",
|
|
3083
|
+
head_management: "",
|
|
3084
|
+
data_fetching: "",
|
|
3085
|
+
},
|
|
3086
|
+
operation_state: {
|
|
3087
|
+
creat_project_folder: one_operation_state,
|
|
3088
|
+
js_framework: one_operation_state,
|
|
3089
|
+
creat_vsc_folder: one_operation_state,
|
|
3090
|
+
add_aliase: one_operation_state,
|
|
3091
|
+
css_framework: one_operation_state,
|
|
3092
|
+
app_structure: one_operation_state,
|
|
3093
|
+
ui_library: one_operation_state,
|
|
3094
|
+
routing_library: one_operation_state,
|
|
3095
|
+
icon_library: one_operation_state,
|
|
3096
|
+
state_management: one_operation_state,
|
|
3097
|
+
head_management: one_operation_state,
|
|
3098
|
+
data_fetching: one_operation_state,
|
|
3099
|
+
install_all_packages: one_operation_state,
|
|
3100
|
+
clean_folder_mark: one_operation_state,
|
|
3101
|
+
},
|
|
3102
|
+
};
|
|
3103
|
+
}
|
|
3104
|
+
|
|
3105
|
+
async function main() {
|
|
3106
|
+
const ctx = createContext();
|
|
3107
|
+
startProject(ctx);
|
|
3108
|
+
const clearConsole = () => {
|
|
3109
|
+
if (process.platform === "win32") {
|
|
3110
|
+
execSync("cls", { stdio: "inherit" });
|
|
3111
|
+
}
|
|
3112
|
+
else {
|
|
3113
|
+
execSync("clear", { stdio: "inherit" });
|
|
3114
|
+
}
|
|
3115
|
+
};
|
|
3116
|
+
const search_mode_colle = async () => {
|
|
3117
|
+
clearConsole();
|
|
3118
|
+
sectionBox("Browse Mode".toUpperCase());
|
|
3119
|
+
await Search();
|
|
3120
|
+
await Core();
|
|
3121
|
+
clearConsole();
|
|
3122
|
+
await printMenu();
|
|
3123
|
+
if (ctx.reset_menu) {
|
|
3124
|
+
await resetContext();
|
|
3125
|
+
ctx.reset_menu = false;
|
|
3126
|
+
return;
|
|
3127
|
+
}
|
|
3128
|
+
clearConsole();
|
|
3129
|
+
sectionBox("Installation".toUpperCase());
|
|
3130
|
+
await Setup();
|
|
3131
|
+
await askAboutInstall();
|
|
3132
|
+
clearConsole();
|
|
3133
|
+
process.exit(0);
|
|
3134
|
+
};
|
|
3135
|
+
const custom_mode_colle = async () => {
|
|
3136
|
+
clearConsole();
|
|
3137
|
+
sectionBox("OneShot Mode".toUpperCase());
|
|
3138
|
+
await Core();
|
|
3139
|
+
await Custom();
|
|
3140
|
+
clearConsole();
|
|
3141
|
+
await printMenu();
|
|
3142
|
+
if (ctx.reset_menu) {
|
|
3143
|
+
await resetContext();
|
|
3144
|
+
ctx.reset_menu = false;
|
|
3145
|
+
return;
|
|
3146
|
+
}
|
|
3147
|
+
clearConsole();
|
|
3148
|
+
sectionBox("Installation".toUpperCase());
|
|
3149
|
+
await Setup();
|
|
3150
|
+
await askAboutInstall();
|
|
3151
|
+
clearConsole();
|
|
3152
|
+
process.exit(0);
|
|
3153
|
+
};
|
|
3154
|
+
const help_colle = async () => {
|
|
3155
|
+
clearConsole();
|
|
3156
|
+
sectionBox("Help".toUpperCase());
|
|
3157
|
+
await help();
|
|
3158
|
+
};
|
|
3159
|
+
const exit_colle = async () => {
|
|
3160
|
+
clearConsole();
|
|
3161
|
+
await say(`See you soon... `);
|
|
3162
|
+
await new Promise((r) => setTimeout(r, 1500));
|
|
3163
|
+
};
|
|
3164
|
+
try {
|
|
3165
|
+
await intro();
|
|
3166
|
+
while (true) {
|
|
3167
|
+
clearConsole();
|
|
3168
|
+
sectionBox("Home".toUpperCase());
|
|
3169
|
+
await HomeMenu();
|
|
3170
|
+
switch (ctx.start_menu_options) {
|
|
3171
|
+
case "Browse Mode":
|
|
3172
|
+
await search_mode_colle();
|
|
3173
|
+
break;
|
|
3174
|
+
case "OneShot Mode":
|
|
3175
|
+
await custom_mode_colle();
|
|
3176
|
+
break;
|
|
3177
|
+
case "Help":
|
|
3178
|
+
await help_colle();
|
|
3179
|
+
break;
|
|
3180
|
+
case "Exit":
|
|
3181
|
+
await exit_colle();
|
|
3182
|
+
return;
|
|
3183
|
+
}
|
|
3184
|
+
}
|
|
3185
|
+
}
|
|
3186
|
+
catch (err) {
|
|
3187
|
+
if (err.name === "ExitPromptError") {
|
|
3188
|
+
await say(`Good Bay...`);
|
|
3189
|
+
await new Promise((r) => setTimeout(r, 1500));
|
|
3190
|
+
process.exit(0);
|
|
3191
|
+
}
|
|
3192
|
+
console.error(chalk.red(err));
|
|
3193
|
+
process.exit(1);
|
|
3194
|
+
}
|
|
3195
|
+
}
|
|
3196
|
+
main();
|