roster-server 1.8.2 â 1.8.4
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/README.md +25 -0
- package/index.js +20 -19
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -162,6 +162,31 @@ When creating a new `RosterServer` instance, you can pass the following options:
|
|
|
162
162
|
- `wwwPath` (string): Path to your `www` directory containing your sites.
|
|
163
163
|
- `greenlockStorePath` (string): Directory for Greenlock configuration.
|
|
164
164
|
- `staging` (boolean): Set to `true` to use Let's Encrypt's staging environment (for testing).
|
|
165
|
+
- `local` (boolean): Set to `true` to run in local development mode.
|
|
166
|
+
|
|
167
|
+
## đ Local Development Mode
|
|
168
|
+
|
|
169
|
+
For local development and testing, you can run RosterServer in local mode by setting `local: true`. This mode is perfect for development environments where you don't need SSL certificates or production features.
|
|
170
|
+
|
|
171
|
+
When `{ local: true }` is enabled, RosterServer **Skips SSL/HTTPS**: Runs pure HTTP servers instead of HTTPS.
|
|
172
|
+
|
|
173
|
+
### Setting Up Local Mode
|
|
174
|
+
|
|
175
|
+
```javascript
|
|
176
|
+
const server = new Roster({
|
|
177
|
+
wwwPath: '/srv/www',
|
|
178
|
+
local: true // Enable local development mode
|
|
179
|
+
});
|
|
180
|
+
server.start();
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Port Assignment
|
|
184
|
+
|
|
185
|
+
In local mode, domains are automatically assigned ports starting from 3000:
|
|
186
|
+
|
|
187
|
+
- `example.com` â `http://localhost:3000`
|
|
188
|
+
- `api.example.com` â `http://localhost:3001`
|
|
189
|
+
- And so on...
|
|
165
190
|
|
|
166
191
|
## đ§ A Touch of Magic
|
|
167
192
|
|
package/index.js
CHANGED
|
@@ -5,6 +5,7 @@ const https = require('https');
|
|
|
5
5
|
const tls = require('tls');
|
|
6
6
|
const { EventEmitter } = require('events');
|
|
7
7
|
const Greenlock = require('greenlock-express');
|
|
8
|
+
const log = require('lemonlog')('roster');
|
|
8
9
|
|
|
9
10
|
// Virtual Server that completely isolates applications
|
|
10
11
|
class VirtualServer extends EventEmitter {
|
|
@@ -80,7 +81,7 @@ class Roster {
|
|
|
80
81
|
this.greenlockStorePath = options.greenlockStorePath || path.join(basePath, 'greenlock.d');
|
|
81
82
|
this.staging = options.staging || false;
|
|
82
83
|
this.cluster = options.cluster || false;
|
|
83
|
-
this.local = options.local || false;
|
|
84
|
+
this.local = options.local || false;
|
|
84
85
|
this.domains = [];
|
|
85
86
|
this.sites = {};
|
|
86
87
|
this.domainServers = {}; // Store separate servers for each domain
|
|
@@ -98,7 +99,7 @@ class Roster {
|
|
|
98
99
|
async loadSites() {
|
|
99
100
|
// Check if wwwPath exists
|
|
100
101
|
if (!fs.existsSync(this.wwwPath)) {
|
|
101
|
-
|
|
102
|
+
log.warn(`â ī¸ WWW path does not exist: ${this.wwwPath}`);
|
|
102
103
|
return;
|
|
103
104
|
}
|
|
104
105
|
|
|
@@ -125,7 +126,7 @@ class Roster {
|
|
|
125
126
|
siteApp = siteApp.default || siteApp;
|
|
126
127
|
break;
|
|
127
128
|
} catch (err) {
|
|
128
|
-
|
|
129
|
+
log.warn(`â ī¸ Error loading ${indexPath}:`, err);
|
|
129
130
|
}
|
|
130
131
|
}
|
|
131
132
|
}
|
|
@@ -137,9 +138,9 @@ class Roster {
|
|
|
137
138
|
this.sites[d] = siteApp;
|
|
138
139
|
});
|
|
139
140
|
|
|
140
|
-
|
|
141
|
+
log.info(`(â) Loaded site: ${domain}`);
|
|
141
142
|
} else {
|
|
142
|
-
|
|
143
|
+
log.warn(`â ī¸ No index file (js/mjs/cjs) found in ${domainPath}`);
|
|
143
144
|
}
|
|
144
145
|
}
|
|
145
146
|
}
|
|
@@ -217,16 +218,16 @@ class Roster {
|
|
|
217
218
|
const currentConfigContentFormatted = JSON.stringify(currentConfig, null, 2);
|
|
218
219
|
|
|
219
220
|
if (newConfigContent === currentConfigContentFormatted) {
|
|
220
|
-
|
|
221
|
+
log.info('âšī¸ Configuration has not changed. config.json will not be overwritten.');
|
|
221
222
|
return;
|
|
222
223
|
}
|
|
223
|
-
|
|
224
|
+
log.info('đ Configuration has changed. config.json will be updated.');
|
|
224
225
|
} else {
|
|
225
|
-
|
|
226
|
+
log.info('đ config.json does not exist. A new one will be created.');
|
|
226
227
|
}
|
|
227
228
|
|
|
228
229
|
fs.writeFileSync(configPath, JSON.stringify(newConfig, null, 2));
|
|
229
|
-
|
|
230
|
+
log.info(`đ config.json generated at ${configPath}`);
|
|
230
231
|
}
|
|
231
232
|
|
|
232
233
|
handleRequest(req, res) {
|
|
@@ -270,7 +271,7 @@ class Roster {
|
|
|
270
271
|
this.sites[domainKey] = requestHandler;
|
|
271
272
|
});
|
|
272
273
|
|
|
273
|
-
|
|
274
|
+
log.info(`(â) Registered site: ${domain}${port !== this.defaultPort ? ':' + port : ''}`);
|
|
274
275
|
return this;
|
|
275
276
|
}
|
|
276
277
|
|
|
@@ -349,17 +350,17 @@ class Roster {
|
|
|
349
350
|
this.portServers[port] = httpServer;
|
|
350
351
|
|
|
351
352
|
httpServer.listen(port, 'localhost', () => {
|
|
352
|
-
|
|
353
|
+
log.info(`đ ${domain} â http://localhost:${port}`);
|
|
353
354
|
});
|
|
354
355
|
|
|
355
356
|
httpServer.on('error', (error) => {
|
|
356
|
-
|
|
357
|
+
log.error(`â Error on port ${port} for ${domain}:`, error.message);
|
|
357
358
|
});
|
|
358
359
|
|
|
359
360
|
currentPort++;
|
|
360
361
|
}
|
|
361
362
|
|
|
362
|
-
|
|
363
|
+
log.info(`(â) Started ${currentPort - startPort} sites in local mode`);
|
|
363
364
|
return Promise.resolve();
|
|
364
365
|
}
|
|
365
366
|
|
|
@@ -444,7 +445,7 @@ class Roster {
|
|
|
444
445
|
};
|
|
445
446
|
|
|
446
447
|
httpServer.listen(80, this.hostname, () => {
|
|
447
|
-
|
|
448
|
+
log.info('HTTP server listening on port 80');
|
|
448
449
|
});
|
|
449
450
|
|
|
450
451
|
// Handle different port types
|
|
@@ -458,7 +459,7 @@ class Roster {
|
|
|
458
459
|
this.portServers[portNum] = httpsServer;
|
|
459
460
|
|
|
460
461
|
httpsServer.listen(portNum, this.hostname, () => {
|
|
461
|
-
|
|
462
|
+
log.info(`HTTPS server listening on port ${portNum}`);
|
|
462
463
|
});
|
|
463
464
|
} else {
|
|
464
465
|
// Create HTTPS server for custom ports using Greenlock certificates
|
|
@@ -492,13 +493,13 @@ class Roster {
|
|
|
492
493
|
const httpsServer = https.createServer(httpsOptions, dispatcher);
|
|
493
494
|
|
|
494
495
|
httpsServer.on('error', (error) => {
|
|
495
|
-
|
|
496
|
+
log.error(`HTTPS server error on port ${portNum}:`, error.message);
|
|
496
497
|
});
|
|
497
498
|
|
|
498
499
|
httpsServer.on('tlsClientError', (error) => {
|
|
499
500
|
// Suppress HTTP request errors to avoid log spam
|
|
500
501
|
if (!error.message.includes('http request')) {
|
|
501
|
-
|
|
502
|
+
log.error(`TLS error on port ${portNum}:`, error.message);
|
|
502
503
|
}
|
|
503
504
|
});
|
|
504
505
|
|
|
@@ -506,9 +507,9 @@ class Roster {
|
|
|
506
507
|
|
|
507
508
|
httpsServer.listen(portNum, this.hostname, (error) => {
|
|
508
509
|
if (error) {
|
|
509
|
-
|
|
510
|
+
log.error(`Failed to start HTTPS server on port ${portNum}:`, error.message);
|
|
510
511
|
} else {
|
|
511
|
-
|
|
512
|
+
log.info(`HTTPS server listening on port ${portNum}`);
|
|
512
513
|
}
|
|
513
514
|
});
|
|
514
515
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "roster-server",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.4",
|
|
4
4
|
"description": "đž RosterServer - A domain host router to host multiple HTTPS.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
},
|
|
35
35
|
"homepage": "https://github.com/clasen/RosterServer#readme",
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"greenlock-express": "^4.0.3"
|
|
37
|
+
"greenlock-express": "^4.0.3",
|
|
38
|
+
"lemonlog": "^1.2.0"
|
|
38
39
|
}
|
|
39
40
|
}
|