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/add-mongo.js ADDED
@@ -0,0 +1,257 @@
1
+ #!/usr/bin/env node
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 isDatabaseConfigured() {
15
+ const projectRoot = process.cwd();
16
+
17
+ const devEnvPath = path.join(projectRoot, ".env.development");
18
+ const prodEnvPath = path.join(projectRoot, ".env.production");
19
+
20
+ const isDevConfigured =
21
+ fs.existsSync(devEnvPath) &&
22
+ fs.readFileSync(devEnvPath, "utf8").includes("MONGO_URI=");
23
+ const isProdConfigured =
24
+ fs.existsSync(prodEnvPath) &&
25
+ fs.readFileSync(prodEnvPath, "utf8").includes("MONGO_URI=");
26
+
27
+ return isDevConfigured || isProdConfigured;
28
+ }
29
+
30
+ function updateEnvFile(filePath, uri) {
31
+ const mongoUriLine = `MONGO_URI=${uri}\n`;
32
+
33
+ if (fs.existsSync(filePath)) {
34
+ let envContent = fs.readFileSync(filePath, "utf8");
35
+ if (envContent.includes("MONGO_URI=")) {
36
+ envContent = envContent.replace(/MONGO_URI=.*/, mongoUriLine.trim());
37
+ } else {
38
+ envContent = envContent.trim() + "\n" + mongoUriLine;
39
+ }
40
+ fs.writeFileSync(filePath, envContent, "utf8");
41
+ } else {
42
+ fs.writeFileSync(filePath, mongoUriLine, "utf8");
43
+ }
44
+ }
45
+
46
+ function addMongoDB(devUri, prodUri) {
47
+ const projectRoot = process.cwd();
48
+
49
+ // Add MongoDB connection file
50
+ const dbContent = `
51
+ import mongoose from 'mongoose';
52
+
53
+ const connectDB = async () => {
54
+ try {
55
+ const conn = await mongoose.connect(process.env.MONGO_URI);
56
+ console.log(\`MongoDB connected: \${conn.connection.host}\`);
57
+ } catch (err) {
58
+ console.error(err);
59
+ process.exit(1);
60
+ }
61
+ };
62
+
63
+ export default connectDB;
64
+ `;
65
+ if (!fs.existsSync(path.join(projectRoot, "src"))) {
66
+ fs.mkdirSync(path.join(projectRoot, "src"), { recursive: true });
67
+ }
68
+ fs.writeFileSync(
69
+ path.join(projectRoot, "src", "db.js"),
70
+ dbContent.trim(),
71
+ "utf8"
72
+ );
73
+
74
+ // Update index.js to import and use MongoDB connection
75
+ const indexPath = path.join(projectRoot, "index.js");
76
+ const dbImport = `import connectDB from './src/db.js';\n`;
77
+ const dbUse = `connectDB();\n`;
78
+
79
+ let indexContent = fs.readFileSync(indexPath, "utf8");
80
+ if (!indexContent.includes(dbImport)) {
81
+ indexContent = dbImport + indexContent;
82
+ }
83
+ if (!indexContent.includes(dbUse)) {
84
+ indexContent = indexContent.replace(
85
+ "const app = express();",
86
+ `${dbUse}const app = express();`
87
+ );
88
+ }
89
+ fs.writeFileSync(indexPath, indexContent, "utf8");
90
+
91
+ // Update .env files
92
+ updateEnvFile(path.join(projectRoot, ".env.development"), devUri);
93
+ updateEnvFile(path.join(projectRoot, ".env.production"), prodUri);
94
+
95
+ // Add mongoose to dependencies
96
+ execSync("npm install mongoose", { stdio: "inherit" });
97
+
98
+ console.log(
99
+ chalk.green(
100
+ `MongoDB integration added with development URI: ${devUri} and production URI: ${prodUri}`
101
+ )
102
+ );
103
+ }
104
+
105
+ if (isDatabaseConfigured()) {
106
+ console.log(
107
+ chalk.yellow(
108
+ "MongoDB is already configured in your environment files. Aborting operation."
109
+ )
110
+ );
111
+ rl.close();
112
+ process.exit(0);
113
+ } else {
114
+ function promptForDatabaseDetails(env, callback) {
115
+ console.log(chalk.cyan(`\nEnter details for the ${env} database:`));
116
+
117
+ function askDatabaseName() {
118
+ rl.question(
119
+ chalk.yellow("Enter the MongoDB database name: "),
120
+ (dbName) => {
121
+ if (!dbName.trim()) {
122
+ console.log(chalk.red("Database name is required."));
123
+ askDatabaseName();
124
+ } else {
125
+ callback(dbName);
126
+ }
127
+ }
128
+ );
129
+ }
130
+
131
+ askDatabaseName();
132
+ }
133
+
134
+ promptForDatabaseDetails("development", (devDbName) => {
135
+ rl.question(
136
+ chalk.yellow("Enter the MongoDB IP address (default: 127.0.0.1): "),
137
+ (devIpAddress) => {
138
+ const devIp = devIpAddress.trim() || "127.0.0.1";
139
+ rl.question(
140
+ chalk.yellow("Enter the MongoDB port (default: 27017): "),
141
+ (devPort) => {
142
+ const devDbPort = devPort.trim() || "27017";
143
+ rl.question(
144
+ chalk.yellow("Enter the MongoDB user ID (leave blank if none): "),
145
+ (devUserId) => {
146
+ rl.question(
147
+ chalk.yellow(
148
+ "Enter the MongoDB password (leave blank if none): "
149
+ ),
150
+ (devPassword) => {
151
+ let devUri = `mongodb://${devIp}:${devDbPort}/${devDbName}`;
152
+ if (devUserId && devPassword) {
153
+ devUri = `mongodb://${devUserId}:${devPassword}@${devIp}:${devDbPort}/${devDbName}`;
154
+ } else if (devUserId || devPassword) {
155
+ console.error(
156
+ chalk.red(
157
+ "Both user ID and password must be provided together."
158
+ )
159
+ );
160
+ process.exit(1);
161
+ }
162
+
163
+ // Ask if the same details should be used for production
164
+ function askSameForProduction() {
165
+ rl.question(
166
+ chalk.blueBright(
167
+ "\nUse the same database details for production? (Yes/No): "
168
+ ),
169
+ (answer) => {
170
+ const response = answer.trim().toLowerCase();
171
+
172
+ if (response === "y" || response === "yes") {
173
+ addMongoDB(devUri, devUri);
174
+ rl.close();
175
+ process.exit(0);
176
+ } else if (response === "n" || response === "no") {
177
+ promptForDatabaseDetails(
178
+ "production",
179
+ (prodDbName) => {
180
+ rl.question(
181
+ chalk.yellow(
182
+ "Enter the MongoDB IP address (default: 127.0.0.1): "
183
+ ),
184
+ (prodIpAddress) => {
185
+ const prodIp =
186
+ prodIpAddress.trim() || "127.0.0.1";
187
+ rl.question(
188
+ chalk.yellow(
189
+ "Enter the MongoDB port (default: 27017): "
190
+ ),
191
+ (prodPort) => {
192
+ const prodDbPort =
193
+ prodPort.trim() || "27017";
194
+ rl.question(
195
+ chalk.yellow(
196
+ "Enter the MongoDB user ID (leave blank if none): "
197
+ ),
198
+ (prodUserId) => {
199
+ rl.question(
200
+ chalk.yellow(
201
+ "Enter the MongoDB password (leave blank if none): "
202
+ ),
203
+ (prodPassword) => {
204
+ let prodUri = `mongodb://${prodIp}:${prodDbPort}/${prodDbName}`;
205
+ if (
206
+ prodUserId &&
207
+ prodPassword
208
+ ) {
209
+ prodUri = `mongodb://${prodUserId}:${prodPassword}@${prodIp}:${prodDbPort}/${prodDbName}`;
210
+ } else if (
211
+ prodUserId ||
212
+ prodPassword
213
+ ) {
214
+ console.error(
215
+ chalk.red(
216
+ "Both user ID and password must be provided together."
217
+ )
218
+ );
219
+ process.exit(1);
220
+ }
221
+
222
+ addMongoDB(devUri, prodUri);
223
+ rl.close();
224
+ process.exit(0);
225
+ }
226
+ );
227
+ }
228
+ );
229
+ }
230
+ );
231
+ }
232
+ );
233
+ }
234
+ );
235
+ } else {
236
+ console.log(
237
+ chalk.red(
238
+ "Invalid input. Please enter Yes or No."
239
+ )
240
+ );
241
+ askSameForProduction();
242
+ }
243
+ }
244
+ );
245
+ }
246
+
247
+ askSameForProduction();
248
+ }
249
+ );
250
+ }
251
+ );
252
+ }
253
+ );
254
+ }
255
+ );
256
+ });
257
+ }
@@ -0,0 +1,124 @@
1
+ #!/usr/bin/env node
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 updateEnvFile(filePath, serialPortPath, baudRate) {
15
+ const serialPortPathLine = `SERIALPORT_PATH=${serialPortPath}\n`;
16
+ const baudRateLine = `BAUDRATE=${baudRate}\n`;
17
+
18
+ if (fs.existsSync(filePath)) {
19
+ let envContent = fs.readFileSync(filePath, "utf8");
20
+ if (envContent.includes("SERIALPORT_PATH=")) {
21
+ envContent = envContent.replace(
22
+ /SERIALPORT_PATH=.*/,
23
+ serialPortPathLine.trim()
24
+ );
25
+ } else {
26
+ envContent = envContent.trim() + "\n" + serialPortPathLine;
27
+ }
28
+ if (envContent.includes("BAUDRATE=")) {
29
+ envContent = envContent.replace(/BAUDRATE=.*/, baudRateLine.trim());
30
+ } else {
31
+ envContent = envContent.trim() + "\n" + baudRateLine;
32
+ }
33
+ fs.writeFileSync(filePath, envContent, "utf8");
34
+ } else {
35
+ fs.writeFileSync(filePath, serialPortPathLine + baudRateLine, "utf8");
36
+ }
37
+ }
38
+
39
+ function addSerialPort(serialPortPath, baudRate) {
40
+ const projectRoot = process.cwd();
41
+ const indexPath = path.join(projectRoot, "index.js");
42
+
43
+ const serialportImport = `
44
+ import { SerialPort } from 'serialport';
45
+ import { ReadlineParser } from '@serialport/parser-readline';
46
+ `;
47
+
48
+ const serialportSetup = `
49
+ try {
50
+ const serialPort = new SerialPort({
51
+ baudRate: parseInt(process.env.BAUDRATE, 10) || ${baudRate},
52
+ path: process.env.SERIALPORT_PATH || '${serialPortPath}',
53
+ });
54
+
55
+ const parser = serialPort.pipe(new ReadlineParser({ delimiter: "\\r\\n" }));
56
+
57
+ parser.on("data", async (data) => {
58
+ console.log('Received data:', data);
59
+ });
60
+
61
+ serialPort.on("error", function (err) {
62
+ console.error("SerialPort Error: ", err.message);
63
+ });
64
+ } catch (error) {
65
+ console.error("Error initializing SerialPort or Parser:", error);
66
+ }
67
+ `;
68
+
69
+ let indexContent = fs.readFileSync(indexPath, "utf8");
70
+
71
+ // Add imports if they don't already exist
72
+ if (!indexContent.includes("import { SerialPort }")) {
73
+ indexContent = serialportImport + indexContent;
74
+ }
75
+
76
+ // Ensure SerialPort setup is added just before app.listen or server.listen
77
+ const listenMatch = indexContent.match(/(app|server)\.listen\(.*\);/);
78
+ if (listenMatch) {
79
+ indexContent = indexContent.replace(
80
+ listenMatch[0],
81
+ serialportSetup + "\n" + listenMatch[0]
82
+ );
83
+ } else {
84
+ indexContent += serialportSetup;
85
+ }
86
+
87
+ fs.writeFileSync(indexPath, indexContent, "utf8");
88
+
89
+ // Update .env files
90
+ updateEnvFile(
91
+ path.join(projectRoot, ".env.development"),
92
+ serialPortPath,
93
+ baudRate
94
+ );
95
+ updateEnvFile(
96
+ path.join(projectRoot, ".env.production"),
97
+ serialPortPath,
98
+ baudRate
99
+ );
100
+
101
+ // Install serialport and @serialport/parser-readline
102
+ execSync("npm install serialport @serialport/parser-readline", {
103
+ stdio: "inherit",
104
+ });
105
+
106
+ console.log(chalk.green("SerialPort integration added successfully."));
107
+ }
108
+
109
+ rl.question(
110
+ chalk.yellow(
111
+ "Enter the serial port path (e.g., /dev/tty-usbserial1) [default: /dev/tty-usbserial1]: "
112
+ ),
113
+ (serialPortPath) => {
114
+ serialPortPath = serialPortPath.trim() || "/dev/tty-usbserial1";
115
+ rl.question(
116
+ chalk.yellow("Enter the baud rate (e.g., 9600) [default: 9600]: "),
117
+ (baudRate) => {
118
+ baudRate = baudRate.trim() || "9600";
119
+ addSerialPort(serialPortPath, baudRate);
120
+ rl.close();
121
+ }
122
+ );
123
+ }
124
+ );
package/add-socket.js ADDED
@@ -0,0 +1,110 @@
1
+ #!/usr/bin/env node
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");
17
+
18
+ const socketIoImport = `import { Server } from "socket.io";\n`;
19
+ const httpImport = `import http from "http";\n`;
20
+
21
+ let corsOrigins;
22
+
23
+ if (ipAddresses.trim() === "*") {
24
+ corsOrigins = `["*"]`; // Allow all origins
25
+ } else {
26
+ const ipArray = ipAddresses.split(",").map((ip) => ip.trim());
27
+ corsOrigins = `[${ipArray.map((ip) => `"http://${ip}"`).join(", ")}]`;
28
+ }
29
+
30
+ const socketIoSetup = `
31
+ const server = http.createServer(app);
32
+ const io = new Server(server, {
33
+ cors: {
34
+ origin: ${corsOrigins},
35
+ methods: ["GET", "POST"]
36
+ }
37
+ });
38
+
39
+ io.on("connection", (socket) => {
40
+ console.log("A user connected");
41
+
42
+ socket.on("disconnect", () => {
43
+ console.log("User disconnected");
44
+ });
45
+ });
46
+
47
+ // Middleware to pass io instance to routes
48
+ app.use((req, res, next) => {
49
+ req.io = io;
50
+ next();
51
+ });
52
+ `;
53
+
54
+ let indexContent = fs.readFileSync(indexPath, "utf8");
55
+
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
+ }
63
+
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 += `
81
+ server.listen(port, () => {
82
+ const localIp = getLocalNetworkIp();
83
+ console.log(\`App is running on http://localhost:\${port}\`);
84
+ if (localIp) {
85
+ console.log(
86
+ \`App is also accessible on your local network at http://\${localIp}:\${port}\`
87
+ );
88
+ }
89
+ });
90
+ `;
91
+ }
92
+
93
+ fs.writeFileSync(indexPath, indexContent, "utf8");
94
+
95
+ // Install socket.io
96
+ console.log(chalk.green("Installing socket.io..."));
97
+ execSync("npm install socket.io", { stdio: "inherit" });
98
+
99
+ console.log(chalk.green("Socket.io integration added successfully."));
100
+ }
101
+
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
+ );
@@ -0,0 +1,199 @@
1
+ #!/usr/bin/env node
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 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`;
18
+
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");
29
+ }
30
+ }
31
+
32
+ function addWebSocket(samePort, wsPort = null) {
33
+ const projectRoot = process.cwd();
34
+ const indexPath = path.join(projectRoot, "index.js");
35
+
36
+ let indexContent = fs.readFileSync(indexPath, "utf8");
37
+
38
+ const wsImport = `import { WebSocketServer } from 'ws';\nimport http from 'http';\n`;
39
+
40
+ // Define WebSocket setup based on `samePort`
41
+ const websocketSetup = samePort
42
+ ? `
43
+ const server = http.createServer(app);
44
+ const wsServer = new WebSocketServer({ server });
45
+ console.log(\`WebSocket server is running on the same port as the server (\${port})\`);
46
+ `
47
+ : `
48
+ const wsPort = process.env.WS_PORT || ${wsPort};
49
+ const wsServer = new WebSocketServer({ port: wsPort });
50
+ console.log(\`WebSocket server is running on WebSocket port \${wsPort}\`);
51
+ `;
52
+
53
+ const wsLogic = `
54
+ wsServer.on('connection', (ws) => {
55
+ console.log('A client connected');
56
+
57
+ ws.on('message', (message) => {
58
+ try {
59
+ const parsedMessage = JSON.parse(message);
60
+ console.log('Received:', parsedMessage);
61
+
62
+ // Broadcast to all clients except sender
63
+ wsServer.clients.forEach((client) => {
64
+ if (client !== ws && client.readyState === ws.OPEN) {
65
+ client.send(JSON.stringify(parsedMessage));
66
+ }
67
+ });
68
+ } catch (error) {
69
+ console.error('Invalid message format:', error);
70
+ }
71
+ });
72
+
73
+ ws.on('close', () => {
74
+ console.log('Client disconnected');
75
+ });
76
+ });
77
+
78
+ app.use((req, res, next) => {
79
+ req.wss = wsServer;
80
+ next();
81
+ });
82
+ `;
83
+
84
+ // Select correct `listen()` method
85
+ const listenSetup = samePort
86
+ ? `
87
+ server.listen(port, () => {
88
+ const localIp = getLocalNetworkIp();
89
+ console.log(\`App is running on http://localhost:\${port}\`);
90
+ if (localIp) {
91
+ console.log(
92
+ \`App is also accessible on your local network at http://\${localIp}:\${port}\`
93
+ );
94
+ }
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
+ }
130
+ }
131
+
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
+ if (!samePort) {
144
+ updateEnvFile(path.join(projectRoot, ".env.development"), wsPort);
145
+ updateEnvFile(path.join(projectRoot, ".env.production"), wsPort);
146
+ }
147
+
148
+ // Install ws library
149
+ console.log(chalk.green("Installing ws..."));
150
+ execSync("npm install ws", { stdio: "inherit" });
151
+
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
+ );
175
+ }
176
+
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();