4bnode 3.5.2 → 4.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.
Files changed (43) hide show
  1. package/README.md +139 -114
  2. package/add-api.js +288 -156
  3. package/add-crud.js +226 -0
  4. package/add-login.js +152 -319
  5. package/add-mongo-delete.js +67 -138
  6. package/add-mongo-insert.js +87 -204
  7. package/add-mongo-read.js +100 -216
  8. package/add-mongo-schema.js +431 -199
  9. package/add-mongo-update.js +89 -202
  10. package/add-mongo.js +125 -218
  11. package/add-serialport.js +53 -98
  12. package/add-socket.js +43 -66
  13. package/add-websocket.js +68 -140
  14. package/index.js +288 -155
  15. package/lib/env.js +18 -0
  16. package/lib/indexFile.js +87 -0
  17. package/lib/names.js +21 -0
  18. package/lib/project.js +122 -0
  19. package/lib/routeFile.js +56 -0
  20. package/lib/ui.js +161 -0
  21. package/package.json +9 -16
  22. package/skeleton/dev-api.js +2785 -0
  23. package/skeleton/index.js +10 -3
  24. package/skeleton/package.json +9 -5
  25. package/skeleton/public/fonts/NotoSans-Bold.woff2 +0 -0
  26. package/skeleton/public/fonts/NotoSans-Light.woff2 +0 -0
  27. package/skeleton/public/fonts/NotoSans-Medium.woff2 +0 -0
  28. package/skeleton/public/fonts/NotoSans-Regular.woff2 +0 -0
  29. package/skeleton/public/fonts/NotoSans-SemiBold.woff2 +0 -0
  30. package/skeleton/public/images/mongo.png +0 -0
  31. package/skeleton/public/images/mysql.png +0 -0
  32. package/skeleton/public/images/postgresql.png +0 -0
  33. package/skeleton/public/images/sqlite.png +0 -0
  34. package/skeleton/public/index.html +7562 -64
  35. package/README_4bnode.md +0 -197
  36. package/src/auth/passport.js +0 -21
  37. package/src/db.js +0 -13
  38. package/test-server/.env.development +0 -1
  39. package/test-server/.env.production +0 -1
  40. package/test-server/index.js +0 -82
  41. package/test-server/package-lock.json +0 -1267
  42. package/test-server/package.json +0 -20
  43. package/test-server/public/index.html +0 -90
package/add-socket.js CHANGED
@@ -1,33 +1,42 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import fs from "fs";
4
- import path from "path";
5
- import readline from "readline";
6
- import { execSync } from "child_process";
7
- import chalk from "chalk";
8
-
9
- const rl = readline.createInterface({
10
- input: process.stdin,
11
- output: process.stdout,
12
- });
13
-
14
- function addSocketIo(ipAddresses) {
15
- const projectRoot = process.cwd();
16
- const indexPath = path.join(projectRoot, "index.js");
3
+ import { input } from "@inquirer/prompts";
4
+ import {
5
+ addImport,
6
+ insertBeforeRoutes,
7
+ replaceAppListen,
8
+ } from "./lib/indexFile.js";
9
+ import {
10
+ showHeader,
11
+ showTaskDone,
12
+ showError,
13
+ showFileAction,
14
+ installDeps,
15
+ } from "./lib/ui.js";
16
+
17
+ async function main() {
18
+ showHeader("add-socket", "Add Socket.IO real-time support");
19
+
20
+ const ipAddresses = await input({
21
+ message: "CORS origins (comma-separated, or * for all):",
22
+ default: "*",
23
+ });
17
24
 
18
- const socketIoImport = `import { Server } from "socket.io";\n`;
19
- const httpImport = `import http from "http";\n`;
25
+ console.log();
20
26
 
21
27
  let corsOrigins;
22
-
23
28
  if (ipAddresses.trim() === "*") {
24
- corsOrigins = `["*"]`; // Allow all origins
29
+ corsOrigins = '["*"]';
25
30
  } else {
26
31
  const ipArray = ipAddresses.split(",").map((ip) => ip.trim());
27
32
  corsOrigins = `[${ipArray.map((ip) => `"http://${ip}"`).join(", ")}]`;
28
33
  }
29
34
 
30
- const socketIoSetup = `
35
+ addImport('import { Server } from "socket.io";');
36
+ addImport('import http from "http";');
37
+ showFileAction("updated", "index.js");
38
+
39
+ const socketSetup = `
31
40
  const server = http.createServer(app);
32
41
  const io = new Server(server, {
33
42
  cors: {
@@ -44,40 +53,14 @@ io.on("connection", (socket) => {
44
53
  });
45
54
  });
46
55
 
47
- // Middleware to pass io instance to routes
48
56
  app.use((req, res, next) => {
49
57
  req.io = io;
50
58
  next();
51
- });
52
- `;
53
-
54
- let indexContent = fs.readFileSync(indexPath, "utf8");
59
+ });`;
55
60
 
56
- // Add imports if they don't already exist
57
- if (!indexContent.includes(socketIoImport)) {
58
- indexContent = socketIoImport + indexContent;
59
- }
60
- if (!indexContent.includes(httpImport)) {
61
- indexContent = httpImport + indexContent;
62
- }
61
+ insertBeforeRoutes(socketSetup);
63
62
 
64
- // Ensure Socket.io setup is placed before routes
65
- const routesStart = indexContent.indexOf("app.use(");
66
- if (routesStart !== -1) {
67
- indexContent =
68
- indexContent.slice(0, routesStart) +
69
- socketIoSetup +
70
- indexContent.slice(routesStart);
71
- } else {
72
- indexContent += socketIoSetup;
73
- }
74
-
75
- // Replace existing app.listen if it exists
76
- indexContent = indexContent.replace(/app\.listen\(port,.*\);/s, "");
77
-
78
- // Append server.listen at the end if not already present
79
- if (!indexContent.includes("server.listen(port")) {
80
- indexContent += `
63
+ replaceAppListen(`
81
64
  server.listen(port, () => {
82
65
  const localIp = getLocalNetworkIp();
83
66
  console.log(\`App is running on http://localhost:\${port}\`);
@@ -86,25 +69,19 @@ server.listen(port, () => {
86
69
  \`App is also accessible on your local network at http://\${localIp}:\${port}\`
87
70
  );
88
71
  }
89
- });
90
- `;
91
- }
92
-
93
- fs.writeFileSync(indexPath, indexContent, "utf8");
72
+ });`);
94
73
 
95
- // Install socket.io
96
- console.log(chalk.green("Installing socket.io..."));
97
- execSync("npm install socket.io", { stdio: "inherit" });
74
+ await installDeps("socket.io");
98
75
 
99
- console.log(chalk.green("Socket.io integration added successfully."));
76
+ showTaskDone("Socket.IO integration complete", [
77
+ `CORS: ${ipAddresses.trim()}`,
78
+ "Access via req.io in routes",
79
+ "Events: connection, disconnect",
80
+ ]);
100
81
  }
101
82
 
102
- rl.question(
103
- chalk.yellow(
104
- "Enter the IP addresses for socket.io (comma-separated or '*' to allow all): "
105
- ),
106
- (ipAddresses) => {
107
- addSocketIo(ipAddresses);
108
- rl.close();
109
- }
110
- );
83
+ main().catch((err) => {
84
+ if (err.name === "ExitPromptError") process.exit(0);
85
+ showError(err.message);
86
+ process.exit(1);
87
+ });
package/add-websocket.js CHANGED
@@ -1,54 +1,63 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import fs from "fs";
4
3
  import path from "path";
5
- import readline from "readline";
6
- import { execSync } from "child_process";
7
- import chalk from "chalk";
8
-
9
- const rl = readline.createInterface({
10
- input: process.stdin,
11
- output: process.stdout,
12
- });
13
-
14
- function updateEnvFile(filePath, wsPort) {
15
- if (!wsPort) return; // Don't update .env if using the same port as the server
16
-
17
- const wsPortLine = `WS_PORT=${wsPort}\n`;
4
+ import { confirm, input } from "@inquirer/prompts";
5
+ import { getProjectRoot } from "./lib/project.js";
6
+ import { updateEnvFile } from "./lib/env.js";
7
+ import {
8
+ addImport,
9
+ insertBeforeRoutes,
10
+ replaceAppListen,
11
+ } from "./lib/indexFile.js";
12
+ import {
13
+ showHeader,
14
+ showTaskDone,
15
+ showError,
16
+ showFileAction,
17
+ installDeps,
18
+ } from "./lib/ui.js";
19
+
20
+ async function main() {
21
+ showHeader("add-websocket", "Add native WebSocket support");
22
+
23
+ const samePort = await confirm({
24
+ message: "Use the server port for WebSocket?",
25
+ default: true,
26
+ });
18
27
 
19
- if (fs.existsSync(filePath)) {
20
- let envContent = fs.readFileSync(filePath, "utf8");
21
- if (envContent.includes("WS_PORT=")) {
22
- envContent = envContent.replace(/WS_PORT=.*/, wsPortLine.trim());
23
- } else {
24
- envContent = envContent.trim() + "\n" + wsPortLine;
25
- }
26
- fs.writeFileSync(filePath, envContent, "utf8");
27
- } else {
28
- fs.writeFileSync(filePath, wsPortLine, "utf8");
28
+ let wsPort = null;
29
+ if (!samePort) {
30
+ const serverPort = process.env.PORT || 3000;
31
+ wsPort = await input({
32
+ message: "Enter WebSocket port:",
33
+ default: "3001",
34
+ validate: (v) => {
35
+ const num = parseInt(v, 10);
36
+ if (isNaN(num) || num < 1 || num > 65535) return "Enter a valid port.";
37
+ if (num === Number(serverPort))
38
+ return "Cannot be the same as the server port.";
39
+ return true;
40
+ },
41
+ });
29
42
  }
30
- }
31
43
 
32
- function addWebSocket(samePort, wsPort = null) {
33
- const projectRoot = process.cwd();
34
- const indexPath = path.join(projectRoot, "index.js");
44
+ console.log();
35
45
 
36
- let indexContent = fs.readFileSync(indexPath, "utf8");
37
-
38
- const wsImport = `import { WebSocketServer } from 'ws';\nimport http from 'http';\n`;
46
+ addImport("import { WebSocketServer } from 'ws';");
47
+ if (samePort) {
48
+ addImport("import http from 'http';");
49
+ }
50
+ showFileAction("updated", "index.js");
39
51
 
40
- // Define WebSocket setup based on `samePort`
41
52
  const websocketSetup = samePort
42
53
  ? `
43
54
  const server = http.createServer(app);
44
55
  const wsServer = new WebSocketServer({ server });
45
- console.log(\`WebSocket server is running on the same port as the server (\${port})\`);
46
- `
56
+ console.log(\`WebSocket server is running on the same port as the server (\${port})\`);`
47
57
  : `
48
58
  const wsPort = process.env.WS_PORT || ${wsPort};
49
59
  const wsServer = new WebSocketServer({ port: wsPort });
50
- console.log(\`WebSocket server is running on WebSocket port \${wsPort}\`);
51
- `;
60
+ console.log(\`WebSocket server is running on WebSocket port \${wsPort}\`);`;
52
61
 
53
62
  const wsLogic = `
54
63
  wsServer.on('connection', (ws) => {
@@ -58,8 +67,7 @@ wsServer.on('connection', (ws) => {
58
67
  try {
59
68
  const parsedMessage = JSON.parse(message);
60
69
  console.log('Received:', parsedMessage);
61
-
62
- // Broadcast to all clients except sender
70
+
63
71
  wsServer.clients.forEach((client) => {
64
72
  if (client !== ws && client.readyState === ws.OPEN) {
65
73
  client.send(JSON.stringify(parsedMessage));
@@ -78,12 +86,12 @@ wsServer.on('connection', (ws) => {
78
86
  app.use((req, res, next) => {
79
87
  req.wss = wsServer;
80
88
  next();
81
- });
82
- `;
89
+ });`;
83
90
 
84
- // Select correct `listen()` method
85
- const listenSetup = samePort
86
- ? `
91
+ insertBeforeRoutes(websocketSetup + "\n" + wsLogic);
92
+
93
+ if (samePort) {
94
+ replaceAppListen(`
87
95
  server.listen(port, () => {
88
96
  const localIp = getLocalNetworkIp();
89
97
  console.log(\`App is running on http://localhost:\${port}\`);
@@ -92,108 +100,28 @@ server.listen(port, () => {
92
100
  \`App is also accessible on your local network at http://\${localIp}:\${port}\`
93
101
  );
94
102
  }
95
- });
96
- `
97
- : `
98
- app.listen(port, () => {
99
- const localIp = getLocalNetworkIp();
100
- console.log(\`App is running on http://localhost:\${port}\`);
101
- if (localIp) {
102
- console.log(
103
- \`App is also accessible on your local network at http://\${localIp}:\${port}\`
104
- );
105
- }
106
- });
107
- `;
108
-
109
- // Add imports if they don't already exist
110
- if (!indexContent.includes(wsImport)) {
111
- indexContent = wsImport + indexContent;
112
- }
113
-
114
- // Remove existing `app.listen()` or `server.listen()`
115
- indexContent = indexContent.replace(/server\.listen\(port.*\);/s, "");
116
- indexContent = indexContent.replace(/app\.listen\(port.*\);/s, "");
117
-
118
- // Ensure WebSocket setup is placed before routes
119
- if (!indexContent.includes("const wsServer = new WebSocketServer({")) {
120
- const routesStart = indexContent.indexOf("app.use(");
121
- if (routesStart !== -1) {
122
- indexContent =
123
- indexContent.slice(0, routesStart) +
124
- websocketSetup +
125
- wsLogic +
126
- indexContent.slice(routesStart);
127
- } else {
128
- indexContent += websocketSetup + wsLogic;
129
- }
103
+ });`);
130
104
  }
131
105
 
132
- // Append the correct `listen()` function
133
- if (
134
- !indexContent.includes("app.listen(port)") &&
135
- !indexContent.includes("server.listen(port)")
136
- ) {
137
- indexContent += listenSetup;
138
- }
139
-
140
- fs.writeFileSync(indexPath, indexContent, "utf8");
141
-
142
- // Update `.env` files only if using a separate WebSocket port
143
106
  if (!samePort) {
144
- updateEnvFile(path.join(projectRoot, ".env.development"), wsPort);
145
- updateEnvFile(path.join(projectRoot, ".env.production"), wsPort);
107
+ const projectRoot = getProjectRoot();
108
+ updateEnvFile(path.join(projectRoot, ".env.development"), "WS_PORT", wsPort);
109
+ updateEnvFile(path.join(projectRoot, ".env.production"), "WS_PORT", wsPort);
110
+ showFileAction("updated", ".env.development");
111
+ showFileAction("updated", ".env.production");
146
112
  }
147
113
 
148
- // Install ws library
149
- console.log(chalk.green("Installing ws..."));
150
- execSync("npm install ws", { stdio: "inherit" });
114
+ await installDeps("ws");
151
115
 
152
- console.log(chalk.green("WebSocket integration added successfully."));
153
- }
154
-
155
- // Get the server port from environment variables, default to 3000 if undefined
156
- const serverPort = process.env.PORT || 3000;
157
-
158
- function askWebSocketPort() {
159
- rl.question(
160
- chalk.yellow("Enter a different WebSocket port (default: 3001): "),
161
- (wsPortInput) => {
162
- let wsPort = parseInt(wsPortInput.trim()) || 3001;
163
-
164
- if (wsPort === serverPort) {
165
- console.log(
166
- chalk.red("WebSocket port cannot be the same as the server port.")
167
- );
168
- askWebSocketPort(); // Re-prompt if user enters the same port
169
- } else {
170
- addWebSocket(false, wsPort); // samePort = false, pass wsPort
171
- rl.close();
172
- }
173
- }
174
- );
116
+ showTaskDone("WebSocket integration complete", [
117
+ samePort ? "Sharing server port" : `WebSocket port: ${wsPort}`,
118
+ "Access via req.wss in routes",
119
+ "Auto-broadcasts to all clients",
120
+ ]);
175
121
  }
176
122
 
177
- function askUseSamePort() {
178
- rl.question(
179
- chalk.yellow(
180
- "Do you want to use the server port for WebSocket? (Yes/No): "
181
- ),
182
- (useSamePort) => {
183
- const answer = useSamePort.trim().toLowerCase();
184
-
185
- if (answer === "y" || answer === "yes") {
186
- addWebSocket(true); // samePort = true, no wsPort needed
187
- rl.close();
188
- } else if (answer === "n" || answer === "no") {
189
- askWebSocketPort(); // Ask for a different WebSocket port
190
- } else {
191
- console.log(chalk.red("Invalid input. Please enter Yes or No."));
192
- askUseSamePort(); // Re-prompt if invalid input
193
- }
194
- }
195
- );
196
- }
197
-
198
- // Start asking user input
199
- askUseSamePort();
123
+ main().catch((err) => {
124
+ if (err.name === "ExitPromptError") process.exit(0);
125
+ showError(err.message);
126
+ process.exit(1);
127
+ });