/genserve

Node Server generator

MIT LicenseMIT

Genserve (server generator) allows spawning servers in the background.

It is optimised to use with a CI system, in a development environment, etc.

Installation

npm install genserve -g

Note: Do not install from Github.

The repo version will be available after setting up the CI.


Usage

In a Terminal

$> genserve [command] [target] [--port number] [--dir path] [--silent] [--timeout number] [--apiport 
number] [--disableapi]

In a script

For CommonJs

// 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

For ESM

// ESM
import {startGenServer, stopGenServer, infoGenServer} from "genserve";

await startGenServer({...});
await stopGenServer({...});
const json = await infoGenServer({...})


Overview

Launch a server in the background and run some tests (using that server) in the same terminal
  • 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

tests-from-shell.gif



Commands

In the descriptions below, [servername] must be replaced by any name.


start

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

Restart a server

$> genserve restart [servername]

stop

Stop a server

$> genserve stop [servername]

remove

Remove a server from registered server list

$> genserve remove [servername]

lock

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

protect

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

log

Open log for a server

$> genserve log [servername]

list

Show list of created named servers.

$> genserve list

save

Save named servers current list

# Save server list into a ./testfile.json file
$> genserve save testfile

load

Load named servers from files

# Load server list from ./testfile.json file
$> genserve load testfile

scan

Show a list of servers and show which ones are running

$> genserve scan

flush

Remove all registered servers (must be stopped and unprotected).

$> genserve flush

edit

Edit session file in an editor

$> genserve edit servers          # Edit settings for registered servers

$> genserve edit settings         # Edit global settings

set

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 

Batch Operation


start all

Start all registered and unlocked servers

$> genserve start all

restart all

restart all registered and unlocked servers

$> genserve restart all

stop all

Stop all running and unlocked servers

$> genserve stop all

remove all

Remove all registered and unprotected servers

$> genserve remove all

status all

Display all registered servers statuses

$> genserve status all


Options

Access to server options

To obtain the path to the file that holds all of the servers configurations:
$> genserve path servers
To edit it
$> genserve edit servers


Options modifiable via CLI

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

SSL options

To enable SSL:

$> genserve --ssl --cert /path/to/cert --key /path/to/key


Enable CORS

To enable CORS:

$> genserve enable servername cors

To customise CORS edit servers file

$> genserve edit servers


Global Options modifiable Via Configuration file

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)



Examples


Start server serving multiple directories

$> genserve start --dir public --dir build

Stop default server

$> genserve stop

Start a named server on port 10040 serving the working directory

$> genserve start genesis --port 10040

Stop the named server

$> genserve stop genesis

Show list of registered servers

$> 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   │



Run server from a shell or in a CI system

# Start the server in the background
$> genserve start testserver --dir . --port 5000

# Run your tests
$> npm test

# Stop the server
$> genserve stop testserver


Run a server from within a script

(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});

}())


How to

Setup and configure a server

1. Set server properties
$> genserve set rserver --port 8080 --dir ./public
2. Edit server file properties for more advanced setup
$> genserve edit servers
Look for the rserver section in your editor and modify the options you want to change
{
  "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"
  }
}
Save and close the file

3. Start the server
$> genserve start rserver
4. Check that the server is up and running
$> genserve scan

💻↴

scan-genserve.gif



Serving static pages

1. Edit server properties you wish to setup
$> genserve edit servers
2. Update the staticDirs key
  ...
"staticDirs": [
"C:/path/to/public",
"C:/path/to/public2",
],
...
3. Start the server
$> genserve start myserver


Serving dynamic pages

1. Edit server properties you wish to setup
$> genserve edit servers
2. Update the dynamicDirs key
  ...
"dynamicDirs": [
"C:/path/to/dyn"
],
...
3. Start the server
$> genserve start myserver

Note: Script must have the extension .server.js, .server.cjs or .server.mjs and must export

a method/function named onRequest


Example

The code below uses .cjs, but ESM can be used as well.

In this case change the file extension to .server.mjs


index.server.cjs
// 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;


Run a script when the server starts

When a script is launched by the server at start via openApp,
It receives only two messages, "started" and "ended".

The user must exit the script when desired.

1. Stop the server
$> genserve stop myserver
2. Edit server properties you wish to setup
$> genserve edit servers
3. Update the openApp key
  ...
"openApp": "C:/path/to/start-app.cjs"
...
4. Start the server
$> genserve start myserver

Snippet example

start-app.cjs
/**
 * 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`);


Create plugins

1. Stop the server
$> genserve stop myserver
2. Edit server properties you wish to setup
$> genserve edit servers
3. Update the plugins key
  ...
"plugins": ["C:/path/to/my-plugin.cjs"]
...
4. Start the server
$> genserve start myserver

Snippet example

my-plugin.cjs
/**
 * 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`);
}());