Genserve (server generator) allows spawning servers in the background.
It is optimised to use with a CI system, in a development environment, etc.
npm install genserve -g
The repo version will be available after setting up the CI.
$> genserve [command] [target] [--port number] [--dir path] [--silent] [--timeout number] [--apiport
number] [--disableapi]
// CommonJs
const {startGenServer, stopGenServer, runCommand} = require("genserve");
await startGenServer({...}); // Start a server
await stopGenServer({...}); // Stop a server
const json = await infoGenServer({...}); // Get server info in a JSON formatted string
// ESM
import {startGenServer, stopGenServer, infoGenServer} from "genserve";
await startGenServer({...});
await stopGenServer({...});
const json = await infoGenServer({...})
- Step 1: Spawn a non-blocking server
$> genserve start server
- Step 2: Run tests (from the same terminal)
$> npm test
- Step 3: Stop the server
$> genserve stop server
In the descriptions below, [servername] must be replaced by any name.
Start a server named [servername] on any available port.
When [servername] is missing, it uses "default" as a name.
# [servername] must be replaced by any name you wish to set
$> genserve start [servername]
Restart a server
$> genserve restart [servername]
Stop a server
$> genserve stop [servername]
Remove a server from registered server list
$> genserve remove [servername]
Prevent a server to be stopped from the registered server list. The commands stop [all], start [all], restart [all], set [all] will have no effect on this server.
$> genserve lock [servername]
or
$> genserve start [servername] --lock
Prevent a server to be removed from the registered server list. The commands flush, remove [all] will have no effect on this server.
$> genserve protect [servername]
or
$> genserve start [servername] --protect
Open log for a server
$> genserve log [servername]
Show list of created named servers.
$> genserve list
Save named servers current list
# Save server list into a ./testfile.json file
$> genserve save testfile
Load named servers from files
# Load server list from ./testfile.json file
$> genserve load testfile
Show a list of servers and show which ones are running
$> genserve scan
Remove all registered servers (must be stopped and unprotected).
$> genserve flush
Edit session file in an editor
$> genserve edit servers # Edit settings for registered servers
$> genserve edit settings # Edit global settings
Modify server property without starting it.
Note: Users must stop the server before being able to change properties.
$> genserve set tom --port 6000 --dir public
Start all registered and unlocked servers
$> genserve start all
restart all registered and unlocked servers
$> genserve restart all
Stop all running and unlocked servers
$> genserve stop all
Remove all registered and unprotected servers
$> genserve remove all
Display all registered servers statuses
$> genserve status all
$> genserve path servers
$> genserve edit servers
The options below can be used with the start, restart, set commands
Options | default | Expect | Description |
---|---|---|---|
--help | false | boolean | Display help |
--version | false | boolean | Display version |
--dir | . | path | Directory to serve |
--port | random | integer | Port to run the server on |
--protocol | http:// | string | Protocol used by server |
--apiport | random | integer | Port to control server |
--defaultPage | index.html | string | Default page to serve |
--silent | false | boolean | Whether to display messages |
--disableapi | false | boolean | Disable server API |
--open | "" | string | Open browser on specified path |
--ssl | false | boolean | Enable https |
--cert | "" | string | Path to ssl cert file |
--key | "" | string | Path to ssl key file |
To enable SSL:
$> genserve --ssl --cert /path/to/cert --key /path/to/key
To enable CORS:
$> genserve enable servername cors
To customise CORS edit servers file
$> genserve edit servers
To obtain the path to the file that holds some default settings:
$> genserve path settings
To edit
$> genserve edit settings
📝 .genserve.cjs ↴
module.exports = {
"protocol": "http://",
"host" : "desktop-amd",
API : {
"GREETINGS" : "Hello!",
"SERVER_STATUS": {
"SERVER_STARTED" : "SERVER_STARTED",
"SERVER_RUNNING" : "SERVER_RUNNING",
"GET_SERVER_INFO": "GET_SERVER_INFO"
}
}
};
staticDirs: Directories to serve (The first directory specified has precedence over the other and so on)
$> genserve start --dir public --dir build
$> genserve stop
$> genserve start genesis --port 10040
$> genserve stop genesis
$> genserve scan
💻↴
active │ serverName │ serverUrl │ port │ apiPort │ staticDirs │ defaultPage │
────── │ ────────── │ ───────────────────────── │ ───── │ ─────── │ ────────────────────────────────── │ ──────────── │
false │ default │ http://localhost:60287/ │ 60287 │ 60287 │ C:\projects\genserve\public │ index.html │
false │ genesis │ http://localhost:10040/ │ 10040 │ 10040 │ C:\projects\genserve │ index.html │
# Start the server in the background
$> genserve start testserver --dir . --port 5000
# Run your tests
$> npm test
# Stop the server
$> genserve stop testserver
(async function ()
{
const {startGenServer, stopGenServer, infoGenServer} = require("genserve");
// Server name
const SERVER_NAME = "my-test-server";
// Start the server which name will be "my-test-server"
const serverStarted = await startGenServer({name: SERVER_NAME, port: 9880});
if (!serverStarted)
{
console.error("Failed to start server");
process.exit(1);
}
// Display info server (Optional)
const data = await infoGenServer({name: SERVER_NAME});
console.log(data);
// Stop the server "my-test-server"
await stopGenServer({name: SERVER_NAME});
}())
$> genserve set rserver --port 8080 --dir ./public
$> genserve edit servers
{
"rserver": {
"serverName": "rserver",
"defaultPage": "index.html",
"protocol": "http://",
"host": "localhost",
"port": 8080,
"staticDirs": [
"C:/projects/genserve/public"
],
"serverUrl": "http://localhost:5050/index.html",
"enableapi": true,
"webSocketStarted": false,
"active": false,
"timeout": 5000,
"perMessageDeflate": false,
"strictApiPort": false,
"strictServerPort": true,
"apiPort": 8080,
"dynamicDirs": [],
"dynamicExts": ".server.[cm]?js"
}
}
$> genserve start rserver
$> genserve scan
💻↴
$> genserve edit servers
...
"staticDirs": [
"C:/path/to/public",
"C:/path/to/public2",
],
...
$> genserve start myserver
$> genserve edit servers
...
"dynamicDirs": [
"C:/path/to/dyn"
],
...
$> genserve start myserver
a method/function named onRequest
The code below uses .cjs, but ESM can be used as well.
In this case change the file extension to .server.mjs
// Intercept all requests made to the server
const onRequest = (req, res, {session}) =>
{
// Send the response to the client
res.end("Awesome");
};
// Export the onRequest function.
module.exports.onRequest = onRequest;
The user must exit the script when desired.
$> genserve stop myserver
$> genserve edit servers
...
"openApp": "C:/path/to/start-app.cjs"
...
$> genserve start myserver
/**
* This script is launched by the server at start.
* It receives only two messages, started and ended.
* The user must exit the script when done.
*/
const argv = require("minimist")(process.argv);
process.on("message",
({action} = {}) =>
{
if (action === "started")
{
console.log(`[${argv.server}] child started`);
}
else if (action === "ended")
{
console.log(`[${argv.server}] Child Exited`);
process.exit(0);
}
});
console.log(`[${argv.server}] child stated`);
$> genserve stop myserver
$> genserve edit servers
...
"plugins": ["C:/path/to/my-plugin.cjs"]
...
$> genserve start myserver
/**
* This plugin is launched by the server at start.
* It receives one message, "request".
* Values change in here will be taken into account by the server.
* The plugin dies along with the server.
*/
const argv = require("minimist")(process.argv);
process.on("message",
({action, req, res, data = {}} = {}) =>
{
if (action === "request")
{
console.log(`[${argv.server}] Child acknowledged request`);
data = data || {};
data.message = "cool";
const message = {req, res, data};
process.send(message);
}
});
(async function ()
{
console.log(`[${argv.server}] child waited`);
}());