quapp 1.0.0 → 1.0.2

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 (2) hide show
  1. package/package.json +1 -1
  2. package/server.js +72 -72
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quapp",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"
package/server.js CHANGED
@@ -1,11 +1,20 @@
1
+ #!/usr/bin/env node
2
+
1
3
  import { spawn } from "child_process";
2
4
  import os from "os";
3
5
  import qrcode from "qrcode-terminal";
4
- import fs from "fs";
6
+ import fs from "fs/promises";
7
+ import { existsSync } from "fs";
5
8
  import path from "path";
6
9
  import open from "open";
10
+ import { fileURLToPath } from "url";
11
+ import { spawnSync } from "child_process";
12
+
13
+ // __dirname replacement in ES modules
14
+ const __filename = fileURLToPath(import.meta.url);
15
+ const __dirname = path.dirname(__filename);
7
16
 
8
- // Load config
17
+ // Default config
9
18
  let config = {
10
19
  server: {
11
20
  qr: true,
@@ -15,30 +24,35 @@ let config = {
15
24
  https: false,
16
25
  openBrowser: false,
17
26
  autoRetry: true,
18
- strictPort: false
19
- }
27
+ strictPort: false,
28
+ },
20
29
  };
21
30
 
22
- try {
23
- const configPath = path.resolve("quapp.config.json");
24
- if (fs.existsSync(configPath)) {
25
- const userConfig = JSON.parse(fs.readFileSync(configPath, "utf-8"));
26
- config = {
27
- ...config,
28
- ...userConfig,
29
- server: { ...config.server, ...userConfig.server }
30
- };
31
+ // Load user config
32
+ const loadUserConfig = async () => {
33
+ try {
34
+ const configPath = path.resolve("quapp.config.json");
35
+ if (existsSync(configPath)) {
36
+ const data = await fs.readFile(configPath, "utf-8");
37
+ const userConfig = JSON.parse(data);
38
+ config = {
39
+ ...config,
40
+ ...userConfig,
41
+ server: { ...config.server, ...userConfig.server },
42
+ };
43
+ }
44
+ } catch (err) {
45
+ console.warn("⚠️ Failed to read quapp.config.json. Using default config.");
46
+ console.warn(err.message);
31
47
  }
32
- } catch (err) {
33
- console.warn("⚠️ Failed to read quapp.config.json. Using default config.");
34
- }
48
+ };
35
49
 
36
- // Get local or LAN IP
37
- function getIP(networkType = "local") {
50
+ // Get IP address
51
+ const getIP = (networkType = "local") => {
38
52
  if (networkType === "private") {
39
53
  const interfaces = os.networkInterfaces();
40
54
  for (const key in interfaces) {
41
- for (const iface of interfaces[key] || []) {
55
+ for (const iface of interfaces[key] ?? []) {
42
56
  if (!iface.internal && iface.family === "IPv4") {
43
57
  return iface.address;
44
58
  }
@@ -46,83 +60,69 @@ function getIP(networkType = "local") {
46
60
  }
47
61
  }
48
62
  return "localhost";
49
- }
63
+ };
50
64
 
51
- // Start Vite with fallback logic
52
- function startVite(port, attempt = 0) {
65
+ // Start Vite server
66
+ const startVite = (port, attempt = 0) => {
53
67
  const host = config.server.network === "private" ? getIP("private") : "localhost";
54
- const url = `${config.server.https ? "https" : "http"}://${host}:${port}`;
68
+ const protocol = config.server.https ? "https" : "http";
69
+ const url = `${protocol}://${host}:${port}`;
55
70
 
56
71
  const viteArgs = [
57
72
  "--host",
58
73
  host,
59
74
  "--port",
60
75
  port,
61
- // 🛠 Automatically enable strictPort if autoRetry is false
62
76
  ...(config.server.strictPort || !config.server.autoRetry ? ["--strictPort"] : []),
63
- ...(config.server.https ? ["--https"] : [])
77
+ ...(config.server.https ? ["--https"] : []),
64
78
  ];
65
79
 
66
- const viteProcess = spawn("vite", viteArgs, { shell: true });
67
-
68
- let shown = false;
80
+ const viteBinary = path.resolve(
81
+ "node_modules",
82
+ ".bin",
83
+ process.platform === "win32" ? "vite.cmd" : "vite"
84
+ );
69
85
 
70
- viteProcess.stdout.on("data", (data) => {
71
- const output = data.toString();
72
-
73
- const portMatch = output.match(/http[s]?:\/\/.*:(\d+)/);
74
- if (portMatch && !shown) {
75
- const usedPort = parseInt(portMatch[1]);
76
- const finalUrl = `${config.server.https ? "https" : "http"}://${host}:${usedPort}`;
86
+ if (!existsSync(viteBinary)) {
87
+ console.error("❌ vite binary not found. Try running `npm install vite`.");
88
+ process.exit(1);
89
+ }
77
90
 
78
- console.log(`\n\n🌍 Access your app from LAN at: ${finalUrl}`);
79
- if (config.server.qr) {
80
- console.log(`\n📱 Scan the QR code below to open on any device:\n`);
81
- qrcode.generate(finalUrl, { small: true });
82
- }
91
+ const vite = spawn(viteBinary, viteArgs, { shell: true });
83
92
 
84
- if (config.server.openBrowser) {
85
- open(finalUrl); // ✅ Uses external open package
86
- }
93
+ vite.stdout.on("data", (data) => process.stdout.write(data));
94
+ vite.stderr.on("data", (data) => process.stderr.write(data));
87
95
 
88
- shown = true;
96
+ setTimeout(() => {
97
+ console.log(`\n🌍 Access your app from LAN at: ${url}`);
98
+ if (config.server.qr) {
99
+ console.log(`\n📱 Scan the QR code below:\n`);
100
+ qrcode.generate(url, { small: true });
89
101
  }
102
+ if (config.server.openBrowser) {
103
+ open(url);
104
+ }
105
+ }, 1500);
90
106
 
91
- process.stdout.write(data);
92
- });
93
-
94
- viteProcess.stderr.on("data", (data) => {
95
- process.stderr.write(data);
96
- });
97
-
98
- viteProcess.on("exit", (code) => {
107
+ vite.on("exit", (code) => {
99
108
  if (
100
109
  code !== 0 &&
101
110
  config.server.fallbackPort &&
102
111
  config.server.autoRetry &&
103
112
  attempt < 10
104
113
  ) {
105
- console.log(`⚠️ Port ${port} might be in use. Retrying on port ${port + 1}...`);
114
+ console.log(`⚠️ Port ${port} in use. Trying port ${port + 1}...`);
106
115
  startVite(port + 1, attempt + 1);
107
- } else {
108
- console.log(`❌ Vite exited with code ${code}`);
116
+ } else if (code !== 0) {
117
+ console.error(`❌ Vite exited with code ${code}`);
109
118
  }
110
119
  });
111
- }
112
- // Check if Vite is installed
113
- function checkViteInstalled() {
114
- try {
115
- require.resolve("vite");
116
- return true;
117
- } catch (err) {
118
- return false;
119
- }
120
- }
121
- // Check if Vite is installed
122
- if (checkViteInstalled()) {
123
- console.error("❌ Vite is not installed. Please install it globally or in your project.");
124
- process.exit(1);
125
- }
120
+ };
121
+
122
+ // Main
123
+ const main = async () => {
124
+ await loadUserConfig();
125
+ startVite(config.server.port);
126
+ };
126
127
 
127
- // Kickoff
128
- startVite(config.server.port);
128
+ main();