4bnode 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/README.md +199 -0
- package/README_4bnode.md +197 -0
- package/README_final_4bnode.md +199 -0
- package/add-api.js +200 -0
- package/add-login.js +395 -0
- package/add-mongo-delete.js +153 -0
- package/add-mongo-insert.js +231 -0
- package/add-mongo-read.js +235 -0
- package/add-mongo-schema.js +231 -0
- package/add-mongo-update.js +229 -0
- package/add-mongo.js +257 -0
- package/add-serialport.js +124 -0
- package/add-socket.js +110 -0
- package/add-websocket.js +199 -0
- package/index.js +226 -0
- package/package.json +40 -0
- package/skeleton/.env.development +1 -0
- package/skeleton/.env.production +1 -0
- package/skeleton/index.js +45 -0
- package/skeleton/package.json +19 -0
- package/skeleton/public/index.html +90 -0
- package/src/auth/passport.js +21 -0
- package/src/db.js +13 -0
- package/test-server/.env.development +1 -0
- package/test-server/.env.production +1 -0
- package/test-server/index.js +82 -0
- package/test-server/package-lock.json +1267 -0
- package/test-server/package.json +20 -0
- package/test-server/public/index.html +90 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from "fs";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import readline from "readline";
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
|
|
8
|
+
const rl = readline.createInterface({
|
|
9
|
+
input: process.stdin,
|
|
10
|
+
output: process.stdout,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
function listRoutes() {
|
|
14
|
+
const projectRoot = process.cwd();
|
|
15
|
+
const routesDir = path.join(projectRoot, "src", "routes");
|
|
16
|
+
if (!fs.existsSync(routesDir)) {
|
|
17
|
+
console.error(chalk.red("No routes directory found in src/routes"));
|
|
18
|
+
return [];
|
|
19
|
+
}
|
|
20
|
+
const routeFiles = fs
|
|
21
|
+
.readdirSync(routesDir)
|
|
22
|
+
.filter((file) => file.endsWith(".js"));
|
|
23
|
+
if (routeFiles.length === 0) {
|
|
24
|
+
console.error(chalk.red("No route files found in src/routes"));
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
return routeFiles;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function listModels() {
|
|
31
|
+
const projectRoot = process.cwd();
|
|
32
|
+
const modelsDir = path.join(projectRoot, "src", "models");
|
|
33
|
+
if (!fs.existsSync(modelsDir)) {
|
|
34
|
+
console.error(chalk.red("No models directory found in src/models"));
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
const modelFiles = fs
|
|
38
|
+
.readdirSync(modelsDir)
|
|
39
|
+
.filter((file) => file.endsWith(".js"));
|
|
40
|
+
if (modelFiles.length === 0) {
|
|
41
|
+
console.error(chalk.red("No model files found in src/models"));
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
return modelFiles;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function addDeleteTemplateToRoute(routeFile, modelName) {
|
|
48
|
+
const projectRoot = process.cwd();
|
|
49
|
+
const routeFilePath = path.join(projectRoot, "src", "routes", routeFile);
|
|
50
|
+
const pascalModelName =
|
|
51
|
+
modelName.charAt(0).toUpperCase() + modelName.slice(1);
|
|
52
|
+
const deleteTemplateImport = `
|
|
53
|
+
import ${pascalModelName} from '../models/${modelName}.js';
|
|
54
|
+
`;
|
|
55
|
+
|
|
56
|
+
const deleteTemplateFunction = `
|
|
57
|
+
// Data deletion logic
|
|
58
|
+
try {
|
|
59
|
+
const deletedDocument = await ${pascalModelName}.findByIdAndDelete(req.params.id);
|
|
60
|
+
if (!deletedDocument) {
|
|
61
|
+
return res.status(404).json({ message: "Document not found" });
|
|
62
|
+
}
|
|
63
|
+
res.json({ message: "Data deleted successfully", data: deletedDocument });
|
|
64
|
+
} catch (err) {
|
|
65
|
+
console.error(err);
|
|
66
|
+
res.status(500).json({ message: "Server error" });
|
|
67
|
+
}
|
|
68
|
+
`;
|
|
69
|
+
|
|
70
|
+
if (!fs.existsSync(routeFilePath)) {
|
|
71
|
+
console.error(
|
|
72
|
+
chalk.red(`The specified route file does not exist: ${routeFilePath}`)
|
|
73
|
+
);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
let routeContent = fs.readFileSync(routeFilePath, "utf8");
|
|
78
|
+
|
|
79
|
+
if (!routeContent.includes(`import ${pascalModelName}`)) {
|
|
80
|
+
routeContent = deleteTemplateImport + routeContent;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const lastCloseIndex = routeContent.lastIndexOf("});");
|
|
84
|
+
if (lastCloseIndex !== -1) {
|
|
85
|
+
const updatedContent = [
|
|
86
|
+
routeContent.slice(0, lastCloseIndex),
|
|
87
|
+
deleteTemplateFunction,
|
|
88
|
+
routeContent.slice(lastCloseIndex),
|
|
89
|
+
].join("\n");
|
|
90
|
+
|
|
91
|
+
routeContent = updatedContent;
|
|
92
|
+
} else {
|
|
93
|
+
routeContent += `\n${deleteTemplateFunction}\n`;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
fs.writeFileSync(routeFilePath, routeContent, "utf8");
|
|
97
|
+
console.log(chalk.green(`Delete template added to ${routeFile}`));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const routeFiles = listRoutes();
|
|
101
|
+
if (routeFiles.length === 0) {
|
|
102
|
+
rl.close();
|
|
103
|
+
process.exit(0);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const modelFiles = listModels();
|
|
107
|
+
if (modelFiles.length === 0) {
|
|
108
|
+
rl.close();
|
|
109
|
+
process.exit(0);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
console.log(chalk.cyan("Select the route file to modify:"));
|
|
113
|
+
routeFiles.forEach((file, index) => {
|
|
114
|
+
console.log(chalk.cyan(`${index + 1}. ${file}`));
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
rl.question(
|
|
118
|
+
chalk.yellow("Enter the number of the route file: "),
|
|
119
|
+
(routeAnswer) => {
|
|
120
|
+
const routeIndex = parseInt(routeAnswer, 10) - 1;
|
|
121
|
+
if (routeIndex >= 0 && routeIndex < routeFiles.length) {
|
|
122
|
+
const selectedRoute = routeFiles[routeIndex];
|
|
123
|
+
|
|
124
|
+
console.log(chalk.cyan("Select the model file to use:"));
|
|
125
|
+
modelFiles.forEach((file, index) => {
|
|
126
|
+
console.log(chalk.cyan(`${index + 1}. ${file}`));
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
rl.question(
|
|
130
|
+
chalk.yellow("Enter the number of the model file: "),
|
|
131
|
+
(modelAnswer) => {
|
|
132
|
+
const modelIndex = parseInt(modelAnswer, 10) - 1;
|
|
133
|
+
if (modelIndex >= 0 && modelIndex < modelFiles.length) {
|
|
134
|
+
const selectedModel = path.basename(modelFiles[modelIndex], ".js");
|
|
135
|
+
|
|
136
|
+
addDeleteTemplateToRoute(selectedRoute, selectedModel);
|
|
137
|
+
rl.close();
|
|
138
|
+
} else {
|
|
139
|
+
console.error(
|
|
140
|
+
chalk.red("Invalid selection. Please choose a valid number.")
|
|
141
|
+
);
|
|
142
|
+
rl.close();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
);
|
|
146
|
+
} else {
|
|
147
|
+
console.error(
|
|
148
|
+
chalk.red("Invalid selection. Please choose a valid number.")
|
|
149
|
+
);
|
|
150
|
+
rl.close();
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
);
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from "fs";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import readline from "readline";
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
import { execSync } from "child_process";
|
|
8
|
+
|
|
9
|
+
const rl = readline.createInterface({
|
|
10
|
+
input: process.stdin,
|
|
11
|
+
output: process.stdout,
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
function listRoutes() {
|
|
15
|
+
const projectRoot = process.cwd();
|
|
16
|
+
const routesDir = path.join(projectRoot, "src", "routes");
|
|
17
|
+
if (!fs.existsSync(routesDir)) {
|
|
18
|
+
console.error(chalk.red("No routes directory found in src/routes"));
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
const routeFiles = fs
|
|
22
|
+
.readdirSync(routesDir)
|
|
23
|
+
.filter((file) => file.endsWith(".js"));
|
|
24
|
+
if (routeFiles.length === 0) {
|
|
25
|
+
console.error(chalk.red("No route files found in src/routes"));
|
|
26
|
+
return [];
|
|
27
|
+
}
|
|
28
|
+
return routeFiles;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function listModels() {
|
|
32
|
+
const projectRoot = process.cwd();
|
|
33
|
+
const modelsDir = path.join(projectRoot, "src", "models");
|
|
34
|
+
if (!fs.existsSync(modelsDir)) {
|
|
35
|
+
console.error(chalk.red("No models directory found in src/models"));
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
const modelFiles = fs
|
|
39
|
+
.readdirSync(modelsDir)
|
|
40
|
+
.filter((file) => file.endsWith(".js"));
|
|
41
|
+
if (modelFiles.length === 0) {
|
|
42
|
+
console.error(chalk.red("No model files found in src/models"));
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
return modelFiles;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function getModelSchema(modelName) {
|
|
49
|
+
const projectRoot = process.cwd();
|
|
50
|
+
const modelFilePath = path.join(
|
|
51
|
+
projectRoot,
|
|
52
|
+
"src",
|
|
53
|
+
"models",
|
|
54
|
+
modelName + ".js"
|
|
55
|
+
);
|
|
56
|
+
const modelFileContent = fs.readFileSync(modelFilePath, "utf8");
|
|
57
|
+
|
|
58
|
+
// Improved regex to handle beautified code
|
|
59
|
+
const schemaRegex = /new mongoose\.Schema\s*\(\s*\{([\s\S]*?)\}\s*\)/m;
|
|
60
|
+
const match = modelFileContent.match(schemaRegex);
|
|
61
|
+
|
|
62
|
+
if (match) {
|
|
63
|
+
try {
|
|
64
|
+
const schemaContent = match[1];
|
|
65
|
+
const fieldRegex = /(\w+):\s*\{[\s\S]*?\}/g;
|
|
66
|
+
const schemaKeys = [];
|
|
67
|
+
let fieldMatch;
|
|
68
|
+
while ((fieldMatch = fieldRegex.exec(schemaContent)) !== null) {
|
|
69
|
+
schemaKeys.push(fieldMatch[1]);
|
|
70
|
+
}
|
|
71
|
+
return schemaKeys;
|
|
72
|
+
} catch (error) {
|
|
73
|
+
console.error(chalk.red("Error parsing schema: "), error);
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
} else {
|
|
77
|
+
console.error(chalk.red("Schema not found in model file."));
|
|
78
|
+
return [];
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function addInsertTemplateToRoute(routeFile, fields, modelName) {
|
|
83
|
+
const projectRoot = process.cwd();
|
|
84
|
+
const routeFilePath = path.join(projectRoot, "src", "routes", routeFile);
|
|
85
|
+
const pascalModelName =
|
|
86
|
+
modelName.charAt(0).toUpperCase() + modelName.slice(1);
|
|
87
|
+
|
|
88
|
+
let insertTemplateImport = `import ${pascalModelName} from '../models/${modelName}.js';\n`;
|
|
89
|
+
|
|
90
|
+
let passwordHashingLogic = "";
|
|
91
|
+
if (fields.includes("password")) {
|
|
92
|
+
insertTemplateImport =
|
|
93
|
+
`import bcrypt from 'bcrypt';\n` + insertTemplateImport;
|
|
94
|
+
passwordHashingLogic = `
|
|
95
|
+
if (newData.password) {
|
|
96
|
+
const salt = await bcrypt.genSalt(10);
|
|
97
|
+
newData.password = await bcrypt.hash(newData.password, salt);
|
|
98
|
+
}
|
|
99
|
+
`;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (!fs.existsSync(routeFilePath)) {
|
|
103
|
+
console.error(
|
|
104
|
+
chalk.red(`The specified route file does not exist: ${routeFilePath}`)
|
|
105
|
+
);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
let routeContent = fs.readFileSync(routeFilePath, "utf8");
|
|
110
|
+
|
|
111
|
+
if (!routeContent.includes(`import ${pascalModelName}`)) {
|
|
112
|
+
routeContent = insertTemplateImport + routeContent;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Detect the request method type (GET, POST, PUT, DELETE)
|
|
116
|
+
const methodTypeRegex =
|
|
117
|
+
/router\.(get|post|put|delete)\((['"`])\/.*?\2,\s*async\s*\(req,\s*res/;
|
|
118
|
+
const methodMatch = routeContent.match(methodTypeRegex);
|
|
119
|
+
const methodType = methodMatch ? methodMatch[1].toLowerCase() : "post";
|
|
120
|
+
|
|
121
|
+
// Determine whether to use req.body or req.query based on method type
|
|
122
|
+
const requestDataSource =
|
|
123
|
+
methodType === "get" || methodType === "delete" ? "req.query" : "req.body";
|
|
124
|
+
|
|
125
|
+
// Generate data insertion logic
|
|
126
|
+
const insertTemplateFunction = `
|
|
127
|
+
// Data insertion logic
|
|
128
|
+
const newData = {
|
|
129
|
+
${fields
|
|
130
|
+
.map((field) => `${field}: ${requestDataSource}.${field}`)
|
|
131
|
+
.join(",\n ")}
|
|
132
|
+
};
|
|
133
|
+
${passwordHashingLogic}
|
|
134
|
+
try {
|
|
135
|
+
const newDocument = new ${pascalModelName}(newData);
|
|
136
|
+
await newDocument.save();
|
|
137
|
+
res.json({ message: "Data inserted successfully", data: newDocument });
|
|
138
|
+
} catch (err) {
|
|
139
|
+
console.error(err);
|
|
140
|
+
res.status(500).json({ message: "Server error" });
|
|
141
|
+
}
|
|
142
|
+
`;
|
|
143
|
+
|
|
144
|
+
// Insert the logic before the last closing `});`
|
|
145
|
+
const lastCloseIndex = routeContent.lastIndexOf("});");
|
|
146
|
+
if (lastCloseIndex !== -1) {
|
|
147
|
+
const updatedContent = [
|
|
148
|
+
routeContent.slice(0, lastCloseIndex),
|
|
149
|
+
insertTemplateFunction,
|
|
150
|
+
routeContent.slice(lastCloseIndex),
|
|
151
|
+
].join("\n");
|
|
152
|
+
|
|
153
|
+
routeContent = updatedContent;
|
|
154
|
+
} else {
|
|
155
|
+
routeContent += `\n${insertTemplateFunction}\n`;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
fs.writeFileSync(routeFilePath, routeContent, "utf8");
|
|
159
|
+
console.log(chalk.green(`Insert template added to ${routeFile}`));
|
|
160
|
+
|
|
161
|
+
// Install bcrypt if needed
|
|
162
|
+
if (fields.includes("password")) {
|
|
163
|
+
console.log(chalk.green("Installing bcrypt..."));
|
|
164
|
+
execSync("npm install bcrypt", { stdio: "inherit" });
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const routeFiles = listRoutes();
|
|
169
|
+
if (routeFiles.length === 0) {
|
|
170
|
+
rl.close();
|
|
171
|
+
process.exit(0);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const modelFiles = listModels();
|
|
175
|
+
if (modelFiles.length === 0) {
|
|
176
|
+
rl.close();
|
|
177
|
+
process.exit(0);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
console.log(chalk.cyan("Select the route file to modify:"));
|
|
181
|
+
routeFiles.forEach((file, index) => {
|
|
182
|
+
console.log(chalk.cyan(`${index + 1}. ${file}`));
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
rl.question(
|
|
186
|
+
chalk.yellow("Enter the number of the route file: "),
|
|
187
|
+
(routeAnswer) => {
|
|
188
|
+
const routeIndex = parseInt(routeAnswer, 10) - 1;
|
|
189
|
+
if (routeIndex >= 0 && routeIndex < routeFiles.length) {
|
|
190
|
+
const selectedRoute = routeFiles[routeIndex];
|
|
191
|
+
|
|
192
|
+
console.log(chalk.cyan("Select the model file to use:"));
|
|
193
|
+
modelFiles.forEach((file, index) => {
|
|
194
|
+
console.log(chalk.cyan(`${index + 1}. ${file}`));
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
rl.question(
|
|
198
|
+
chalk.yellow("Enter the number of the model file: "),
|
|
199
|
+
(modelAnswer) => {
|
|
200
|
+
const modelIndex = parseInt(modelAnswer, 10) - 1;
|
|
201
|
+
if (modelIndex >= 0 && modelIndex < modelFiles.length) {
|
|
202
|
+
const selectedModel = path.basename(modelFiles[modelIndex], ".js");
|
|
203
|
+
const schemaFields = getModelSchema(selectedModel);
|
|
204
|
+
|
|
205
|
+
if (schemaFields.length === 0) {
|
|
206
|
+
rl.close();
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
addInsertTemplateToRoute(
|
|
211
|
+
selectedRoute,
|
|
212
|
+
schemaFields,
|
|
213
|
+
selectedModel
|
|
214
|
+
);
|
|
215
|
+
rl.close();
|
|
216
|
+
} else {
|
|
217
|
+
console.error(
|
|
218
|
+
chalk.red("Invalid selection. Please choose a valid number.")
|
|
219
|
+
);
|
|
220
|
+
rl.close();
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
);
|
|
224
|
+
} else {
|
|
225
|
+
console.error(
|
|
226
|
+
chalk.red("Invalid selection. Please choose a valid number.")
|
|
227
|
+
);
|
|
228
|
+
rl.close();
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
);
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from "fs";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import readline from "readline";
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
|
|
8
|
+
const rl = readline.createInterface({
|
|
9
|
+
input: process.stdin,
|
|
10
|
+
output: process.stdout,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
function listRoutes() {
|
|
14
|
+
const projectRoot = process.cwd();
|
|
15
|
+
const routesDir = path.join(projectRoot, "src", "routes");
|
|
16
|
+
if (!fs.existsSync(routesDir)) {
|
|
17
|
+
console.error(chalk.red("No routes directory found in src/routes"));
|
|
18
|
+
return [];
|
|
19
|
+
}
|
|
20
|
+
return fs.readdirSync(routesDir).filter((file) => file.endsWith(".js"));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function listModels() {
|
|
24
|
+
const projectRoot = process.cwd();
|
|
25
|
+
const modelsDir = path.join(projectRoot, "src", "models");
|
|
26
|
+
if (!fs.existsSync(modelsDir)) {
|
|
27
|
+
console.error(chalk.red("No models directory found in src/models"));
|
|
28
|
+
return [];
|
|
29
|
+
}
|
|
30
|
+
return fs.readdirSync(modelsDir).filter((file) => file.endsWith(".js"));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function getModelSchema(modelName) {
|
|
34
|
+
const projectRoot = process.cwd();
|
|
35
|
+
const modelFilePath = path.join(
|
|
36
|
+
projectRoot,
|
|
37
|
+
"src",
|
|
38
|
+
"models",
|
|
39
|
+
modelName + ".js"
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
if (!fs.existsSync(modelFilePath)) {
|
|
43
|
+
console.error(chalk.red(`Model file not found: ${modelFilePath}`));
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const modelFileContent = fs.readFileSync(modelFilePath, "utf8");
|
|
48
|
+
const schemaRegex = /new mongoose\.Schema\s*\(\s*\{([\s\S]*?)\}\s*\)/m;
|
|
49
|
+
const match = modelFileContent.match(schemaRegex);
|
|
50
|
+
|
|
51
|
+
if (match) {
|
|
52
|
+
try {
|
|
53
|
+
const schemaContent = match[1];
|
|
54
|
+
const fieldRegex = /(\w+):\s*\{[\s\S]*?\}/g;
|
|
55
|
+
const schemaKeys = ["_id"]; // Always include `_id`
|
|
56
|
+
let fieldMatch;
|
|
57
|
+
while ((fieldMatch = fieldRegex.exec(schemaContent)) !== null) {
|
|
58
|
+
schemaKeys.push(fieldMatch[1]);
|
|
59
|
+
}
|
|
60
|
+
return schemaKeys;
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.error(chalk.red("Error parsing schema: "), error);
|
|
63
|
+
return ["_id"];
|
|
64
|
+
}
|
|
65
|
+
} else {
|
|
66
|
+
console.error(chalk.red("Schema not found in model file."));
|
|
67
|
+
return ["_id"];
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function addReadTemplateToRoute(routeFile, modelName, selectedField = null) {
|
|
72
|
+
const projectRoot = process.cwd();
|
|
73
|
+
const routeFilePath = path.join(projectRoot, "src", "routes", routeFile);
|
|
74
|
+
const pascalModelName =
|
|
75
|
+
modelName.charAt(0).toUpperCase() + modelName.slice(1);
|
|
76
|
+
const readTemplateImport = `import ${pascalModelName} from '../models/${modelName}.js';\n`;
|
|
77
|
+
|
|
78
|
+
let readTemplateFunction;
|
|
79
|
+
|
|
80
|
+
if (selectedField) {
|
|
81
|
+
readTemplateFunction = `
|
|
82
|
+
// Fetch data based on ${selectedField}
|
|
83
|
+
try {
|
|
84
|
+
const documents = await ${pascalModelName}.find({ ${selectedField}: req.query.${selectedField} });
|
|
85
|
+
if (documents.length === 0) {
|
|
86
|
+
return res.status(404).json({ message: "No matching documents found" });
|
|
87
|
+
}
|
|
88
|
+
res.json({ data: documents });
|
|
89
|
+
} catch (err) {
|
|
90
|
+
console.error(err);
|
|
91
|
+
res.status(500).json({ message: "Server error" });
|
|
92
|
+
}
|
|
93
|
+
`;
|
|
94
|
+
} else {
|
|
95
|
+
readTemplateFunction = `
|
|
96
|
+
// Fetch all data
|
|
97
|
+
try {
|
|
98
|
+
const documents = await ${pascalModelName}.find();
|
|
99
|
+
res.json({ data: documents });
|
|
100
|
+
} catch (err) {
|
|
101
|
+
console.error(err);
|
|
102
|
+
res.status(500).json({ message: "Server error" });
|
|
103
|
+
}
|
|
104
|
+
`;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (!fs.existsSync(routeFilePath)) {
|
|
108
|
+
console.error(
|
|
109
|
+
chalk.red(`The specified route file does not exist: ${routeFilePath}`)
|
|
110
|
+
);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
let routeContent = fs.readFileSync(routeFilePath, "utf8");
|
|
115
|
+
|
|
116
|
+
if (!routeContent.includes(`import ${pascalModelName}`)) {
|
|
117
|
+
routeContent = readTemplateImport + routeContent;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const lastCloseIndex = routeContent.lastIndexOf("});");
|
|
121
|
+
if (lastCloseIndex !== -1) {
|
|
122
|
+
const updatedContent = [
|
|
123
|
+
routeContent.slice(0, lastCloseIndex),
|
|
124
|
+
readTemplateFunction,
|
|
125
|
+
routeContent.slice(lastCloseIndex),
|
|
126
|
+
].join("\n");
|
|
127
|
+
|
|
128
|
+
routeContent = updatedContent;
|
|
129
|
+
} else {
|
|
130
|
+
routeContent += `\n${readTemplateFunction}\n`;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
fs.writeFileSync(routeFilePath, routeContent, "utf8");
|
|
134
|
+
console.log(chalk.green(`Read template added to ${routeFile}`));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Main Logic
|
|
138
|
+
const routeFiles = listRoutes();
|
|
139
|
+
const modelFiles = listModels();
|
|
140
|
+
|
|
141
|
+
if (routeFiles.length === 0 || modelFiles.length === 0) {
|
|
142
|
+
rl.close();
|
|
143
|
+
process.exit(0);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
console.log(chalk.blue("Select the route file to modify:"));
|
|
147
|
+
routeFiles.forEach((file, index) => {
|
|
148
|
+
console.log(chalk.yellow(`${index + 1}. ${file}`));
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
rl.question(
|
|
152
|
+
chalk.cyan("Enter the number of the route file: "),
|
|
153
|
+
(routeAnswer) => {
|
|
154
|
+
const routeIndex = parseInt(routeAnswer, 10) - 1;
|
|
155
|
+
if (routeIndex >= 0 && routeIndex < routeFiles.length) {
|
|
156
|
+
const selectedRoute = routeFiles[routeIndex];
|
|
157
|
+
|
|
158
|
+
console.log(chalk.blue("Select the model file to use:"));
|
|
159
|
+
modelFiles.forEach((file, index) => {
|
|
160
|
+
console.log(chalk.yellow(`${index + 1}. ${file}`));
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
rl.question(
|
|
164
|
+
chalk.cyan("Enter the number of the model file: "),
|
|
165
|
+
(modelAnswer) => {
|
|
166
|
+
const modelIndex = parseInt(modelAnswer, 10) - 1;
|
|
167
|
+
if (modelIndex >= 0 && modelIndex < modelFiles.length) {
|
|
168
|
+
const selectedModel = path.basename(modelFiles[modelIndex], ".js");
|
|
169
|
+
const schemaFields = getModelSchema(selectedModel);
|
|
170
|
+
|
|
171
|
+
console.log(chalk.green("Do you want to:"));
|
|
172
|
+
console.log(chalk.green("1. Fetch all data"));
|
|
173
|
+
console.log(chalk.green("2. Fetch data based on a specific field"));
|
|
174
|
+
|
|
175
|
+
rl.question(
|
|
176
|
+
chalk.cyan("Enter your choice (1 or 2): "),
|
|
177
|
+
(choiceAnswer) => {
|
|
178
|
+
if (choiceAnswer === "1") {
|
|
179
|
+
addReadTemplateToRoute(selectedRoute, selectedModel);
|
|
180
|
+
rl.close();
|
|
181
|
+
} else if (choiceAnswer === "2" && schemaFields.length > 0) {
|
|
182
|
+
console.log(
|
|
183
|
+
chalk.green(
|
|
184
|
+
"Select a field to filter data by (_id is always available):"
|
|
185
|
+
)
|
|
186
|
+
);
|
|
187
|
+
schemaFields.forEach((field, index) => {
|
|
188
|
+
console.log(chalk.yellow(`${index + 1}. ${field}`));
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
rl.question(
|
|
192
|
+
chalk.cyan("Enter the number of the field: "),
|
|
193
|
+
(fieldAnswer) => {
|
|
194
|
+
const fieldIndex = parseInt(fieldAnswer, 10) - 1;
|
|
195
|
+
if (fieldIndex >= 0 && fieldIndex < schemaFields.length) {
|
|
196
|
+
const selectedField = schemaFields[fieldIndex];
|
|
197
|
+
addReadTemplateToRoute(
|
|
198
|
+
selectedRoute,
|
|
199
|
+
selectedModel,
|
|
200
|
+
selectedField
|
|
201
|
+
);
|
|
202
|
+
} else {
|
|
203
|
+
console.error(
|
|
204
|
+
chalk.red(
|
|
205
|
+
"Invalid selection. Please choose a valid field number."
|
|
206
|
+
)
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
rl.close();
|
|
210
|
+
}
|
|
211
|
+
);
|
|
212
|
+
} else {
|
|
213
|
+
console.error(
|
|
214
|
+
chalk.red("Invalid choice. Please enter 1 or 2.")
|
|
215
|
+
);
|
|
216
|
+
rl.close();
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
);
|
|
220
|
+
} else {
|
|
221
|
+
console.error(
|
|
222
|
+
chalk.red("Invalid selection. Please choose a valid number.")
|
|
223
|
+
);
|
|
224
|
+
rl.close();
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
);
|
|
228
|
+
} else {
|
|
229
|
+
console.error(
|
|
230
|
+
chalk.red("Invalid selection. Please choose a valid number.")
|
|
231
|
+
);
|
|
232
|
+
rl.close();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
);
|