General update, removed short-hand argument options, used newer smaller depencies, turned into ecmamodule script and generally made smaller
This commit is contained in:
parent
628718d9be
commit
0d175c5600
13 changed files with 269 additions and 296 deletions
1
.npmrc
Normal file
1
.npmrc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
package-lock=false
|
24
README.md
24
README.md
|
@ -32,7 +32,7 @@ How to use
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm install [-g] spserver
|
npm install [-g] spserver
|
||||||
spserver -f ./myfile.html -s ./public -p 3000
|
spserver --file ./myfile.html --serve ./public -p 3000
|
||||||
```
|
```
|
||||||
|
|
||||||
Options
|
Options
|
||||||
|
@ -42,23 +42,23 @@ Options
|
||||||
|
|
||||||
By default, spserver will use the settings located in `config.json`. You can also override them or run it directly using only the commands below.
|
By default, spserver will use the settings located in `config.json`. You can also override them or run it directly using only the commands below.
|
||||||
|
|
||||||
`--config, -c` Location of the config file for the server [default: config.json]
|
`--config` Location of the config file for the server [default: config.json]
|
||||||
|
|
||||||
`--port, -p` The port server should bind to [default: 3001 or 80 in production mode]
|
`--port` The port server should bind to [default: 3001 or 80 in production mode]
|
||||||
|
|
||||||
`--file, -f` Single static file the server should serve on all unknown requests
|
`--file` Single static file the server should serve on all unknown requests
|
||||||
|
|
||||||
`--bunyan, -b` Use bunyan instead of console to log to [default: true in production mode]
|
`--bunyan` Use bunyan instead of console to log to [default: true in production mode]
|
||||||
|
|
||||||
`--template, -t` Parse the static file as lodash template with all options/settings being passed to it
|
`--template` Parse the static file as lodash template with all options/settings being passed to it
|
||||||
|
|
||||||
`--name, -n` The name for this server for logging [default: spserver]
|
`--name` The name for this server for logging [default: spserver]
|
||||||
|
|
||||||
`--serve, -s` Folder path to serve static files from [default: public]
|
`--serve` Folder path to serve static files from [default: public]
|
||||||
|
|
||||||
`--prod, -P` Force run the server in production mode
|
`--prod` Force run the server in production mode
|
||||||
|
|
||||||
`--debug, -d` Force run the server in development mode
|
`--debug` Force run the server in development mode
|
||||||
|
|
||||||
Config
|
Config
|
||||||
======
|
======
|
||||||
|
@ -91,7 +91,7 @@ Any of the settings in the `config.json` file can be overridden using the CLI op
|
||||||
Template
|
Template
|
||||||
========
|
========
|
||||||
|
|
||||||
spserver can also help provide any additional info to your single file thanks to lodash.template. If template mode is specified, it will parse the single file first through lodash.template with the whole config file. This can allow you to specify configuration in your config file and expose them in your single file.
|
spserver can also help provide any additional info to your single file thanks to lodash: `template`. If template mode is specified, it will parse the single file first through `lodash.template` with the whole config file. This can allow you to specify configuration in your config file and expose them in your single file.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
@ -115,4 +115,4 @@ Example:
|
||||||
```
|
```
|
||||||
|
|
||||||
Then you can run it like this:
|
Then you can run it like this:
|
||||||
`spserver -c ./config.json -t -f ./base.html -s ./public`
|
`spserver --config ./config.json --template --file ./base.html --serve ./public`
|
||||||
|
|
39
bin.js
39
bin.js
|
@ -1,39 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var config = require('./lib/config');
|
|
||||||
var server = require('./lib/spserver');
|
|
||||||
|
|
||||||
var env = config.get('NODE_ENV');
|
|
||||||
|
|
||||||
//Check if we any
|
|
||||||
var displayHelp = config.get('help');
|
|
||||||
if (!config.get('file') && !config.get(env + ':file') &&
|
|
||||||
!config.get('serve') && !config.get(env + ':serve')) {
|
|
||||||
displayHelp = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (displayHelp) {
|
|
||||||
console.log('Run static server for static files, simple servers or pure MVVM projects.');
|
|
||||||
console.log('Specifying either file or folder serving is required.');
|
|
||||||
console.log('');
|
|
||||||
console.log('Usage:');
|
|
||||||
console.log(' spserver [options]');
|
|
||||||
console.log('');
|
|
||||||
console.log(config.stores.argv.help());
|
|
||||||
console.log('Examples:');
|
|
||||||
console.log(' spserver -p 2000 -f base.html -s ./dist');
|
|
||||||
console.log('');
|
|
||||||
console.log(' Will run the server on port 2000 serving static files from the ./dist folder');
|
|
||||||
console.log(' with any unknown file being served the contents of base.html.');
|
|
||||||
console.log('');
|
|
||||||
console.log(' spserver -f base.html -t --custom test');
|
|
||||||
console.log('');
|
|
||||||
console.log(' Will run the server with the base.html as a template as well as');
|
|
||||||
console.log(' passing the contents of "test" argument into the template.');
|
|
||||||
|
|
||||||
process.exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Run our server \o/
|
|
||||||
server();
|
|
56
bin.mjs
Normal file
56
bin.mjs
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
import config from './lib/config.mjs'
|
||||||
|
import SPServer from './lib/spserver.mjs'
|
||||||
|
|
||||||
|
var env = config.get('NODE_ENV');
|
||||||
|
|
||||||
|
//Check if we any
|
||||||
|
var displayHelp = config.get('help');
|
||||||
|
if (!config.get('file') && !config.get(env + ':file') &&
|
||||||
|
!config.get('serve') && !config.get(env + ':serve')) {
|
||||||
|
displayHelp = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (displayHelp) {
|
||||||
|
console.log(`Run static server for static files, simple servers or pure MVVM projects.
|
||||||
|
Specifying either file or folder serving is required.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
spserver [options]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--config Location of the config file for the server [default:
|
||||||
|
config.json]
|
||||||
|
--port The port server should bind to [default: 3001 or 80 in
|
||||||
|
production mode]
|
||||||
|
--file Single static file the server should serve on all unknown
|
||||||
|
requests
|
||||||
|
--bunyan Use bunyan instead of console to log to [default: true in
|
||||||
|
production mode]
|
||||||
|
--template Parse the static file as lodash template with all
|
||||||
|
options/settings being passed to it
|
||||||
|
--name The name for this server for logging [default: spserver]
|
||||||
|
--serve Folder path to serve static files from [default: public]
|
||||||
|
--prod Force run the server in production mode
|
||||||
|
--debug Force run the server in development mode
|
||||||
|
--ip IP server runs on [default: 0.0.0.0]
|
||||||
|
--rooturlpath Root URL path server is deployed on; will be removed from
|
||||||
|
URL when resolving to files [default: /]
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
spserver -p 2000 -f base.html -s ./dist
|
||||||
|
|
||||||
|
Will run the server on port 2000 serving static files from the ./dist folder
|
||||||
|
with any unknown file being served the contents of base.html.
|
||||||
|
|
||||||
|
spserver -f base.html -t --custom test
|
||||||
|
|
||||||
|
Will run the server with the base.html as a template as well as
|
||||||
|
passing the contents of "test" argument into the template.`);
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Run our server \o/
|
||||||
|
|
||||||
|
let server = new SPServer()
|
|
@ -1,48 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
config: {
|
|
||||||
alias: 'c',
|
|
||||||
describe: 'Location of the config file for the server [default: config.json]'
|
|
||||||
},
|
|
||||||
port: {
|
|
||||||
alias: 'p',
|
|
||||||
describe: 'The port server should bind to [default: 3001 or 80 in production mode]'
|
|
||||||
},
|
|
||||||
file: {
|
|
||||||
alias: 'f',
|
|
||||||
describe: 'Single static file the server should serve on all unknown requests'
|
|
||||||
},
|
|
||||||
bunyan: {
|
|
||||||
alias: 'b',
|
|
||||||
describe: 'Use bunyan instead of console to log to [default: true in production mode]'
|
|
||||||
},
|
|
||||||
template: {
|
|
||||||
alias: 't',
|
|
||||||
describe: 'Parse the static file as lodash template with all options/settings being passed to it'
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
alias: 'n',
|
|
||||||
describe: 'The name for this server for logging [default: spserver]'
|
|
||||||
},
|
|
||||||
serve: {
|
|
||||||
alias: 's',
|
|
||||||
describe: 'Folder path to serve static files from [default: public]'
|
|
||||||
},
|
|
||||||
prod: {
|
|
||||||
alias: 'P',
|
|
||||||
describe: 'Force run the server in production mode'
|
|
||||||
},
|
|
||||||
debug: {
|
|
||||||
alias: 'd',
|
|
||||||
describe: 'Force run the server in development mode'
|
|
||||||
},
|
|
||||||
ip: {
|
|
||||||
alias: 'i',
|
|
||||||
describe: 'IP server runs on [default: 0.0.0.0]'
|
|
||||||
},
|
|
||||||
rooturlpath: {
|
|
||||||
alias: 'r',
|
|
||||||
describe: 'Root URL path server is deployed on; will be removed from URL when resolving to files [default: /]'
|
|
||||||
},
|
|
||||||
};
|
|
|
@ -1,9 +1,10 @@
|
||||||
'use strict';
|
import fs from 'fs'
|
||||||
|
import Nconf from 'nconf-lite'
|
||||||
|
|
||||||
var nconf = require('nconf');
|
const nconf = new Nconf()
|
||||||
|
|
||||||
// Load arguments as highest priority
|
// Load arguments as highest priority
|
||||||
nconf.argv(require('./arguments'));
|
nconf.argv({ lowerCase: true, separator: '__', parseValues: true, useEqualsign: true });
|
||||||
|
|
||||||
// Overrides
|
// Overrides
|
||||||
var overrides = {};
|
var overrides = {};
|
||||||
|
@ -20,8 +21,11 @@ nconf.overrides(overrides);
|
||||||
// Load enviroment variables as third priority
|
// Load enviroment variables as third priority
|
||||||
nconf.env();
|
nconf.env();
|
||||||
|
|
||||||
// Load the config if it exists.
|
var filename = nconf.get('config') || '../config.json'
|
||||||
nconf.file(nconf.get('config') || './config.json');
|
if (fs.existsSync(filename)) {
|
||||||
|
// Load the config if it exists.
|
||||||
|
nconf.file('main', nconf.get('config') || '../config.json');
|
||||||
|
}
|
||||||
|
|
||||||
// Default variables
|
// Default variables
|
||||||
nconf.defaults({
|
nconf.defaults({
|
||||||
|
@ -46,4 +50,4 @@ nconf.defaults({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = nconf;
|
export default nconf
|
|
@ -1,10 +1,6 @@
|
||||||
'use strict';
|
import _ from 'lodash'
|
||||||
|
import bunyan from 'bunyan-lite'
|
||||||
var _ = require('lodash');
|
import config from './config.mjs'
|
||||||
var bunyan = require('bunyan-lite');
|
|
||||||
|
|
||||||
//Get the config
|
|
||||||
var config = require('./config');
|
|
||||||
|
|
||||||
//Create our variables
|
//Create our variables
|
||||||
var env = config.get('NODE_ENV');
|
var env = config.get('NODE_ENV');
|
||||||
|
@ -14,7 +10,7 @@ if (config.get('bunyan') || config.get(env + ':use_bunyan')) {
|
||||||
var settings = _.cloneDeep(config.get(env + ':bunyan'));
|
var settings = _.cloneDeep(config.get(env + ':bunyan'));
|
||||||
|
|
||||||
// Stream can be specified either in settings.streams[ix] or globally in settings.stream, but not
|
// Stream can be specified either in settings.streams[ix] or globally in settings.stream, but not
|
||||||
// both. Since the defaults specify stetings.stream, if the user specifies anything of vaulue
|
// both. Since the defaults specify settings.stream, if the user specifies anything of vaulue
|
||||||
// in settings.streams, we should delete the global defaults, because bunyan gets angry if there
|
// in settings.streams, we should delete the global defaults, because bunyan gets angry if there
|
||||||
// are multiple keys
|
// are multiple keys
|
||||||
if (_.has(settings, 'streams')) {
|
if (_.has(settings, 'streams')) {
|
||||||
|
@ -43,4 +39,4 @@ if (config.get('bunyan') || config.get(env + ':use_bunyan')) {
|
||||||
output.debug = console.log.bind(console);
|
output.debug = console.log.bind(console);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = output;
|
export default output;
|
137
lib/spserver.js
137
lib/spserver.js
|
@ -1,137 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var fs = require('fs');
|
|
||||||
var http = require('http');
|
|
||||||
var path = require('path');
|
|
||||||
var url = require('url');
|
|
||||||
|
|
||||||
var _ = require('lodash');
|
|
||||||
var nStatic = require('node-static');
|
|
||||||
|
|
||||||
var config = require('./config');
|
|
||||||
var logger = require('./logger');
|
|
||||||
|
|
||||||
|
|
||||||
// The different config sources sometimes manipulate different setting names.
|
|
||||||
// E.g. command line flags maniuplate root settings, but config files can
|
|
||||||
// manipulate settings at the prod/debug level. Resolve all of these into a
|
|
||||||
// final object of settings.
|
|
||||||
function _resolveFinalSettings(settings) {
|
|
||||||
var finalSettings = {};
|
|
||||||
var env = config.get('NODE_ENV');
|
|
||||||
|
|
||||||
if (!settings) {
|
|
||||||
settings = config.get();
|
|
||||||
}
|
|
||||||
if (!settings[env]) {
|
|
||||||
settings[env] = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
// For 'name', 'file', 'serve', 'ip', and 'port', default to the global setting rather than an
|
|
||||||
// individual environment's setting, because it might have been set via command-line flags
|
|
||||||
_(['name', 'file', 'serve', 'ip', 'port']).forEach(function (field) {
|
|
||||||
finalSettings[field] = settings[field] || settings[env][field];
|
|
||||||
});
|
|
||||||
|
|
||||||
finalSettings.rooturlpath = config.get('rooturlpath') || config.get('ROOT_URL_PATH') || '/';
|
|
||||||
|
|
||||||
// For 'staticOptions', there are no command-line flags, so individual configuration options
|
|
||||||
// override global defaults where set
|
|
||||||
finalSettings.staticOptions = _.defaultsDeep(settings.staticOptions, settings[env].staticOptions);
|
|
||||||
|
|
||||||
// Make a template function so we can just pass that in downstream
|
|
||||||
finalSettings.template = (settings.template || settings[env].template) ?
|
|
||||||
function (contents) {
|
|
||||||
// Note: template is run with _original_, non-resolved settings
|
|
||||||
return _.template(contents)(settings);
|
|
||||||
} : null;
|
|
||||||
|
|
||||||
return finalSettings;
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateBase(file, finalSettings) {
|
|
||||||
if (!file) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_.endsWith(file, 'js')) {
|
|
||||||
return require(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
var contents = fs.readFileSync(file);
|
|
||||||
if (finalSettings.template) {
|
|
||||||
contents = finalSettings.template(contents);
|
|
||||||
}
|
|
||||||
|
|
||||||
return function(req, res) {
|
|
||||||
res.writeHead(200, {'Content-Type': 'text/html'});
|
|
||||||
res.end(contents);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function _rerouteRootUrl(reqUrl, rootUrl) {
|
|
||||||
var parsedUrl = url.parse(reqUrl);
|
|
||||||
|
|
||||||
parsedUrl.pathname = path.normalize(
|
|
||||||
parsedUrl.pathname.replace(rootUrl, '/') || '/'
|
|
||||||
);
|
|
||||||
|
|
||||||
return url.format(parsedUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
var spserver = function (settings) {
|
|
||||||
var finalSettings = _resolveFinalSettings(settings);
|
|
||||||
|
|
||||||
var fileServer = new nStatic.Server(
|
|
||||||
path.resolve(finalSettings.serve),
|
|
||||||
finalSettings.staticOptions
|
|
||||||
);
|
|
||||||
|
|
||||||
var base = generateBase(path.resolve(finalSettings.file), finalSettings);
|
|
||||||
|
|
||||||
var server = http.createServer(function (req, res) {
|
|
||||||
logger.debug('[REQ]', req.method + ':', req.url);
|
|
||||||
var startTime = new Date().getTime();
|
|
||||||
|
|
||||||
var done = function () {
|
|
||||||
var requestTime = new Date().getTime() - startTime;
|
|
||||||
logger.debug('[RES]', req.method + ':', req.url,
|
|
||||||
'(' + res.statusCode + ')', 'took', requestTime, 'ms');
|
|
||||||
};
|
|
||||||
|
|
||||||
req.url = _rerouteRootUrl(req.url, finalSettings.rooturlpath);
|
|
||||||
|
|
||||||
res.addListener('finish', done);
|
|
||||||
res.addListener('close', done);
|
|
||||||
|
|
||||||
req.addListener('end', function () {
|
|
||||||
fileServer.serve(req, res, function (err) {
|
|
||||||
if (err) {
|
|
||||||
if (err.status === 404 && base) {
|
|
||||||
return base(req, res);
|
|
||||||
} else {
|
|
||||||
logger.error(err);
|
|
||||||
|
|
||||||
res.writeHead(err.status, err.headers);
|
|
||||||
res.end(err.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}).resume();
|
|
||||||
});
|
|
||||||
|
|
||||||
server.listen(finalSettings.port, finalSettings.ip);
|
|
||||||
|
|
||||||
logger.info(
|
|
||||||
'Started single-page server: ' + finalSettings.name +
|
|
||||||
', base file: ' + finalSettings.file +
|
|
||||||
', static folder: ' + finalSettings.serve +
|
|
||||||
', port: ' + finalSettings.port
|
|
||||||
);
|
|
||||||
|
|
||||||
return server;
|
|
||||||
};
|
|
||||||
|
|
||||||
spserver.generateBase = generateBase;
|
|
||||||
|
|
||||||
module.exports = spserver;
|
|
144
lib/spserver.mjs
Normal file
144
lib/spserver.mjs
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
import fs from 'fs'
|
||||||
|
import http from 'http'
|
||||||
|
import path from 'path'
|
||||||
|
import url from 'url'
|
||||||
|
import _ from 'lodash'
|
||||||
|
import nStatic from 'node-static'
|
||||||
|
|
||||||
|
import config from './config.mjs'
|
||||||
|
import logger from './logger.mjs'
|
||||||
|
|
||||||
|
|
||||||
|
// The different config sources sometimes manipulate different setting names.
|
||||||
|
// E.g. command line flags maniuplate root settings, but config files can
|
||||||
|
// manipulate settings at the prod/debug level. Resolve all of these into a
|
||||||
|
// final object of settings.
|
||||||
|
function _resolveFinalSettings(settings) {
|
||||||
|
var finalSettings = {};
|
||||||
|
var env = config.get('NODE_ENV');
|
||||||
|
|
||||||
|
if (!settings) {
|
||||||
|
settings = config.get();
|
||||||
|
}
|
||||||
|
if (!settings[env]) {
|
||||||
|
settings[env] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// For 'name', 'file', 'serve', 'ip', and 'port', default to the global setting rather than an
|
||||||
|
// individual environment's setting, because it might have been set via command-line flags
|
||||||
|
_(['name', 'file', 'serve', 'ip', 'port']).forEach(function (field) {
|
||||||
|
finalSettings[field] = settings[field] || settings[env][field];
|
||||||
|
});
|
||||||
|
|
||||||
|
finalSettings.rooturlpath = config.get('rooturlpath') || config.get('ROOT_URL_PATH') || '/';
|
||||||
|
|
||||||
|
// For 'staticOptions', there are no command-line flags, so individual configuration options
|
||||||
|
// override global defaults where set
|
||||||
|
finalSettings.staticOptions = _.defaultsDeep(settings.staticOptions, settings[env].staticOptions);
|
||||||
|
|
||||||
|
// Make a template function so we can just pass that in downstream
|
||||||
|
finalSettings.template = (settings.template || settings[env].template) ?
|
||||||
|
function (contents) {
|
||||||
|
// Note: template is run with _original_, non-resolved settings
|
||||||
|
return _.template(contents)(settings);
|
||||||
|
} : null;
|
||||||
|
|
||||||
|
return finalSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _rerouteRootUrl(reqUrl, rootUrl) {
|
||||||
|
var parsedUrl = url.parse(reqUrl);
|
||||||
|
|
||||||
|
parsedUrl.pathname = path.normalize(
|
||||||
|
parsedUrl.pathname.replace(rootUrl, '/') || '/'
|
||||||
|
);
|
||||||
|
|
||||||
|
return url.format(parsedUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
class SPServer {
|
||||||
|
constructor(settings, opts = {}) {
|
||||||
|
Object.assign(this, {
|
||||||
|
fs: opts.fs || fs,
|
||||||
|
})
|
||||||
|
|
||||||
|
var finalSettings = _resolveFinalSettings(settings);
|
||||||
|
|
||||||
|
var fileServer = new nStatic.Server(
|
||||||
|
path.resolve(finalSettings.serve),
|
||||||
|
finalSettings.staticOptions
|
||||||
|
);
|
||||||
|
|
||||||
|
var base = SPServer.generateBase(finalSettings.file ? path.resolve(finalSettings.file) : null, finalSettings);
|
||||||
|
|
||||||
|
var server = http.createServer(function (req, res) {
|
||||||
|
var startTime = new Date().getTime();
|
||||||
|
|
||||||
|
var isFinished = false
|
||||||
|
var done = function () {
|
||||||
|
if (isFinished) return
|
||||||
|
isFinished = true
|
||||||
|
var requestTime = new Date().getTime() - startTime;
|
||||||
|
logger.debug('[RES]', req.method + ':', '(' + res.statusCode + ')', req.url,
|
||||||
|
'took', requestTime, 'ms');
|
||||||
|
};
|
||||||
|
|
||||||
|
req.url = _rerouteRootUrl(req.url, finalSettings.rooturlpath);
|
||||||
|
|
||||||
|
res.addListener('finish', done);
|
||||||
|
res.addListener('close', done);
|
||||||
|
|
||||||
|
req.addListener('end', function () {
|
||||||
|
fileServer.serve(req, res, function (err) {
|
||||||
|
if (err) {
|
||||||
|
if (err.status === 404 && base) {
|
||||||
|
return base(req, res);
|
||||||
|
} else if (err.status === 404) {
|
||||||
|
res.writeHead(err.status, err.headers);
|
||||||
|
res.end(err.message);
|
||||||
|
} else {
|
||||||
|
logger.debug('[REQ]', req.method + ':', req.url);
|
||||||
|
logger.error(err);
|
||||||
|
|
||||||
|
res.writeHead(err.status, err.headers);
|
||||||
|
res.end(err.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).resume();
|
||||||
|
});
|
||||||
|
|
||||||
|
server.listen(finalSettings.port, finalSettings.ip);
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
'Started single-page server: ' + finalSettings.name +
|
||||||
|
', base file: ' + (finalSettings.file || '<none>') +
|
||||||
|
', static folder: ' + finalSettings.serve +
|
||||||
|
', port: ' + finalSettings.port
|
||||||
|
);
|
||||||
|
|
||||||
|
this.server = server
|
||||||
|
}
|
||||||
|
|
||||||
|
static generateBase(file, finalSettings, useFs = fs) {
|
||||||
|
if (!file) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_.endsWith(file, 'js')) {
|
||||||
|
throw new Error('javascript file has been deprecated')
|
||||||
|
}
|
||||||
|
|
||||||
|
var contents = useFs.readFileSync(file, { encoding: 'utf-8' });
|
||||||
|
if (finalSettings.template) {
|
||||||
|
contents = finalSettings.template(contents)
|
||||||
|
}
|
||||||
|
|
||||||
|
return function(req, res) {
|
||||||
|
res.writeHead(200, {'Content-Type': 'text/html'});
|
||||||
|
res.end(contents);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SPServer;
|
14
package.json
14
package.json
|
@ -2,9 +2,10 @@
|
||||||
"name": "spserver",
|
"name": "spserver",
|
||||||
"version": "0.3.0",
|
"version": "0.3.0",
|
||||||
"description": "Node static page server for running quick MVVM file server",
|
"description": "Node static page server for running quick MVVM file server",
|
||||||
"main": "lib/spserver.js",
|
"main": "lib/spserver.mjs",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "mocha --reporter spec test/base.test.js"
|
"test": "set NODE_ENV=test&& eltro test/**/*.test.mjs -r dot",
|
||||||
|
"test:linux": "NODE_ENV=test eltro 'test/**/*.test.mjs' -r dot"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -21,14 +22,13 @@
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/TheThing/spserver",
|
"homepage": "https://github.com/TheThing/spserver",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bunyan-lite": "^1.0.0",
|
"bunyan-lite": "^1.1.1",
|
||||||
"lodash": "^4.17.2",
|
"lodash": "^4.17.2",
|
||||||
"nconf": "^0.8.4",
|
"nconf-lite": "^2.0.0",
|
||||||
"node-static": "^0.7.6"
|
"node-static": "^0.7.6"
|
||||||
},
|
},
|
||||||
"bin": "./bin.js",
|
"bin": "./bin.mjs",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"mocha": "^5.2.0",
|
"eltro": "^1.2.3"
|
||||||
"sinon": "^1.12.2"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var fs = require('fs');
|
|
||||||
var assert = require('assert');
|
|
||||||
var sinon = require('sinon');
|
|
||||||
|
|
||||||
describe('spserver', function () {
|
|
||||||
|
|
||||||
var spserver = require('../lib/spserver');
|
|
||||||
|
|
||||||
describe('#generateBase()', function () {
|
|
||||||
it('should return null when file is empty', function () {
|
|
||||||
assert.strictEqual(null, spserver.generateBase());
|
|
||||||
assert.strictEqual(null, spserver.generateBase(null, {}));
|
|
||||||
assert.strictEqual(null, spserver.generateBase(''));
|
|
||||||
assert.strictEqual(null, spserver.generateBase('', {}));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should read file contents if string', function () {
|
|
||||||
var stub = sinon.stub(fs, 'readFileSync').returns('bla');
|
|
||||||
|
|
||||||
spserver.generateBase('asdf', {});
|
|
||||||
assert(stub.called);
|
|
||||||
stub.restore();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return function if file is javascript', function () {
|
|
||||||
var path = require('path');
|
|
||||||
var nothing = require('./nothing');
|
|
||||||
var test = spserver.generateBase(path.resolve('test/nothing.js'), {});
|
|
||||||
|
|
||||||
assert.strictEqual(nothing.toString(), test.toString());
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
31
test/base.test.mjs
Normal file
31
test/base.test.mjs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
import { Eltro as t, assert, stub} from 'eltro'
|
||||||
|
|
||||||
|
import path from 'path'
|
||||||
|
import SPServer from '../lib/spserver.mjs'
|
||||||
|
|
||||||
|
|
||||||
|
t.describe('spserver', function () {
|
||||||
|
const fakeFs = { readFileSync: stub() }
|
||||||
|
|
||||||
|
t.describe('#generateBase()', function () {
|
||||||
|
t.test('should return null when file is empty', function () {
|
||||||
|
assert.strictEqual(null, SPServer.generateBase(undefined, undefined, fakeFs));
|
||||||
|
assert.strictEqual(null, SPServer.generateBase(null, {}, fakeFs));
|
||||||
|
assert.strictEqual(null, SPServer.generateBase('', undefined, fakeFs));
|
||||||
|
assert.strictEqual(null, SPServer.generateBase('', {}, fakeFs));
|
||||||
|
});
|
||||||
|
|
||||||
|
t.test('should read file contents if string', function () {
|
||||||
|
fakeFs.readFileSync.reset()
|
||||||
|
assert.notOk(fakeFs.readFileSync.called)
|
||||||
|
SPServer.generateBase('asdf', {}, fakeFs);
|
||||||
|
assert.ok(fakeFs.readFileSync.called)
|
||||||
|
});
|
||||||
|
|
||||||
|
t.test('should throw if file is javascript', async function () {
|
||||||
|
assert.throws(function() {
|
||||||
|
SPServer.generateBase(path.resolve('test/nothing.js'), {});
|
||||||
|
})
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,3 +1,3 @@
|
||||||
'use strict';
|
export default function(req, res) {
|
||||||
|
res.end('nothing')
|
||||||
module.exports = function() {};
|
}
|
||||||
|
|
Loading…
Reference in a new issue