commit
eed5dadc01
26 changed files with 392 additions and 207 deletions
16
.eslintrc
16
.eslintrc
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"extends": "eslint-config-dabapps/base/.eslintrc",
|
||||
"env": {
|
||||
"node": true,
|
||||
"browser": false,
|
||||
"mocha": true,
|
||||
"es6": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"sourceType": "module",
|
||||
"ecmaVersion": 6
|
||||
},
|
||||
"rules": {
|
||||
"no-console": 0
|
||||
}
|
||||
}
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -31,3 +31,5 @@ node_modules
|
|||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
typings/
|
||||
dist/
|
||||
|
|
48
README.md
48
README.md
|
@ -2,29 +2,55 @@
|
|||
The only static-file server you'll ever need!
|
||||
|
||||
### Features:
|
||||
- Logging
|
||||
- Basic-Auth _(optional)_
|
||||
- Logging - [`winston`](https://www.npmjs.com/package/winston)
|
||||
- Basic-Auth - [`basic-auth`](https://www.npmjs.com/package/basic-auth)
|
||||
- Custom 404 page
|
||||
- Optimum Compression - [`compression`](https://www.npmjs.com/package/compression)
|
||||
- Security checks / headers - [`helmet`](https://www.npmjs.com/package/helmet)
|
||||
- Opbeat error-reporting - [docs](https://opbeat.com/docs/articles/get-started-with-express/)
|
||||
- Whitelist IP Addresses - [`express-ip-access-control`](https://www.npmjs.com/package/express-ip-access-control)
|
||||
- Directory Listing - [`serve-index`](https://www.npmjs.com/package/serve-index)
|
||||
|
||||
### Usage / Configuration
|
||||
### Usage
|
||||
```bash
|
||||
tstatic <directory>
|
||||
tstatic <dir> [options]
|
||||
|
||||
-h --help Show this screen.
|
||||
--version Show version.
|
||||
-p <port> --port=<port> Port to listen on.
|
||||
-b <auth> --basic-auth=<auth> Enable basic-auth.
|
||||
-i <ips> --ips=<ips> Allowed IP addresses.
|
||||
-l --list-dir List Directory.
|
||||
--opbeat Enable Opbeat.
|
||||
-o --open Open in browser after start.
|
||||
|
||||
```
|
||||
`directory` is where your static files are.
|
||||
`dir` is where your static files are.
|
||||
|
||||
404 errors will return with `<directory>/.404.html`, with status code 404. If this file doesnt exist, plain error page will be shown.
|
||||
404 errors will return with `<dir>/.404.html`, with status code 404. If this file doesnt exist, the default error page will be shown.
|
||||
|
||||
|
||||
#### Environment
|
||||
Make sure to set `NODE_ENV` to `production`!
|
||||
### Configuration
|
||||
|
||||
`PORT`: The port you want the server to listen on. Default: `5000`.
|
||||
##### `port`
|
||||
The port for the server to listen on. Currently supports plain HTTP only
|
||||
|
||||
`BASIC_AUTH_USERNAME` / `BASIC_AUTH_PASSWORD`: Credentials for built-in basic auth
|
||||
##### `basic-auth`
|
||||
Enable basic-auth for all paths. Currently only supports single credentals.
|
||||
|
||||
Opbeat middleware is configured using documented variables [here](https://opbeat.com/docs/articles/opbeat-for-nodejs-api/#appid). _Requires production `NODE_ENV`!_
|
||||
Format:`-b username:password`
|
||||
|
||||
##### `ips`
|
||||
IP addresses that are allowed to connect to the server.
|
||||
|
||||
Format: `-i 192.168.1.100,192.168.1.101`
|
||||
|
||||
##### `list-dir`
|
||||
Enables directory listing. Allow browseing
|
||||
|
||||
##### `opbeat`
|
||||
Enable opbeat error reporting. `--opbeat` only enables this, configuration is done using [environment varables](https://opbeat.com/docs/articles/get-started-with-express/#appId).
|
||||
|
||||
##### `open`
|
||||
Open the server in the browser one started. It will open in your default browser, and use url `http://0.0.0.0:<port>`.
|
||||
|
||||
|
|
38
package.json
38
package.json
|
@ -2,15 +2,17 @@
|
|||
"name": "tstatic",
|
||||
"version": "1.0.0",
|
||||
"description": "Container to host simple static applications using a node server, so files can be deployed using rsync",
|
||||
"main": "./src/server.js",
|
||||
"main": "node ./dist/index.js",
|
||||
"bin": {
|
||||
"tstatic": "./src/server.js"
|
||||
"tstatic": "node ./dist/index.js"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "npm run mocha && npm run lint && nsp check",
|
||||
"lint": "eslint src/ tests/",
|
||||
"start": "./src/server.js site/",
|
||||
"mocha": "NODE_ENV=test mocha tests/**.test.js"
|
||||
"start": "node ./dist/index.js",
|
||||
"postinstall": "typings install",
|
||||
"build": "tsc",
|
||||
"test": "npm run build && npm run mocha && nsp check",
|
||||
"mocha": "mocha --compilers ts:ts-node/register --require scripts/test-helper.js tests/**.test.ts",
|
||||
"lint": "tslint src/**/*.ts"
|
||||
},
|
||||
"engines": {
|
||||
"node": "6.9.4"
|
||||
|
@ -25,22 +27,30 @@
|
|||
},
|
||||
"homepage": "https://github.com/RealOrangeOne/tstatic#readme",
|
||||
"dependencies": {
|
||||
"basic-auth": "^1.1.0",
|
||||
"basic-auth": "=1.1.0",
|
||||
"compression": "=1.6.2",
|
||||
"connect-static-file": "=1.1.2",
|
||||
"express": "=4.14.0",
|
||||
"express-basic-auth": "=0.2.3",
|
||||
"docopt": "=0.6.2",
|
||||
"express": "=4.14.1",
|
||||
"express-basic-auth": "=0.3.2",
|
||||
"express-ip-access-control": "=1.0.5",
|
||||
"express-winston": "=2.1.2",
|
||||
"express-winston": "=2.2.0",
|
||||
"helmet": "=3.4.0",
|
||||
"opbeat": "=4.7.0",
|
||||
"opbeat": "=4.11.0",
|
||||
"open": "=0.0.5",
|
||||
"serve-index": "=1.8.0",
|
||||
"winston": "=2.3.0"
|
||||
"winston": "=2.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint-config": "dabapps/eslint-config#2.0.5",
|
||||
"chai": "=3.5.0",
|
||||
"chai-as-promised": "=6.0.0",
|
||||
"mocha": "=3.2.0",
|
||||
"node-fetch": "=1.6.3",
|
||||
"nsp": "=2.6.2",
|
||||
"supertest": "=2.0.1"
|
||||
"supertest": "=3.0.0",
|
||||
"ts-node": "=2.1.0",
|
||||
"tslint": "=4.4.2",
|
||||
"typescript": "=2.1.6",
|
||||
"typings": "=2.1.0"
|
||||
}
|
||||
}
|
||||
|
|
7
scripts/test-helper.js
Normal file
7
scripts/test-helper.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
const chai = require('chai');
|
||||
const chaiAsPromised = require('chai-as-promised');
|
||||
|
||||
chai.expect();
|
||||
chai.use(chaiAsPromised);
|
||||
|
||||
process.env.NODE_ENV = 'test';
|
|
@ -1,9 +0,0 @@
|
|||
const staticFile = require('connect-static-file');
|
||||
const path = require('path');
|
||||
const { SERVE_DIR } = require('./consts');
|
||||
|
||||
const handle404 = staticFile(path.join(SERVE_DIR, '.404.html'));
|
||||
module.exports = function (request, response, next) {
|
||||
response.statusCode = 404;
|
||||
return handle404(request, response, next);
|
||||
};
|
|
@ -1,17 +0,0 @@
|
|||
const basicAuth = require('express-basic-auth');
|
||||
const { BASIC_AUTH_ENABLED } = require('./consts');
|
||||
|
||||
function basicAuthHandler(username, password) {
|
||||
return process.env.BASIC_AUTH_USERNAME === username && process.env.BASIC_AUTH_PASSWORD === password;
|
||||
}
|
||||
|
||||
if (BASIC_AUTH_ENABLED) {
|
||||
module.exports = basicAuth({
|
||||
authorizer: basicAuthHandler,
|
||||
challenge: true
|
||||
});
|
||||
} else {
|
||||
module.exports = (req, res, next) => next();
|
||||
}
|
||||
|
||||
|
40
src/cli.ts
Normal file
40
src/cli.ts
Normal file
|
@ -0,0 +1,40 @@
|
|||
import { docopt } from 'docopt';
|
||||
import { Options } from './types';
|
||||
|
||||
const PKG = require('../package.json');
|
||||
|
||||
const ARG_DATA = `
|
||||
${PKG.name}.
|
||||
${PKG.description}
|
||||
|
||||
Usage:
|
||||
tstatic <dir> [options]
|
||||
tstatic -h | --help
|
||||
tstatic --version
|
||||
|
||||
Options:
|
||||
-h --help Show this screen.
|
||||
--version Show version.
|
||||
-p <port> --port=<port> Port to listen on.
|
||||
-b <auth> --basic-auth=<auth> Enable basic-auth.
|
||||
-i <ips> --ips=<ips> Allowed IP addresses.
|
||||
-l --list-dir List Directory.
|
||||
--opbeat Enable Opbeat.
|
||||
-o --open Open in browser after start.
|
||||
`;
|
||||
|
||||
export default function getArgs() : Options {
|
||||
const rawArgs = docopt(ARG_DATA, {
|
||||
version: PKG.version,
|
||||
help: true
|
||||
});
|
||||
return {
|
||||
port: rawArgs['--port'] || process.env.PORT || 5000,
|
||||
allowed_ips: rawArgs['--ips'] ? rawArgs['--ips'].split(',') : [],
|
||||
basicAuth: rawArgs['--basic-auth'] ? rawArgs['--basic-auth'].split(':') : [],
|
||||
dirList: rawArgs['--list-dir'],
|
||||
serveDir: rawArgs['<dir>'],
|
||||
opbeat: rawArgs['--opbeat'],
|
||||
open: rawArgs['--open']
|
||||
};
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
const IN_TEST = process.env.NODE_ENV === 'test';
|
||||
|
||||
module.exports = {
|
||||
SERVE_DIR: IN_TEST ? 'site/' : process.argv[process.argv.length - 1],
|
||||
PORT: process.env.PORT || 5000,
|
||||
ALLOWED_IPS: process.env.ALLOWED_IPS ? process.env.ALLOWED_IPS.split(',') : undefined,
|
||||
IN_TEST,
|
||||
IN_PRODUCTION: process.env.NODE_ENV === 'production',
|
||||
DIR_LIST: process.env.DIR_LIST,
|
||||
BASIC_AUTH_ENABLED: process.env.BASIC_AUTH_USERNAME && process.env.BASIC_AUTH_PASSWORD
|
||||
};
|
17
src/index.ts
Normal file
17
src/index.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { docopt } from 'docopt';
|
||||
import createServer from './server';
|
||||
import getArgs from './cli';
|
||||
import * as open from 'open';
|
||||
|
||||
console.log("Starting Server...");
|
||||
|
||||
const ARGS = getArgs();
|
||||
const app = createServer(ARGS);
|
||||
|
||||
export const server = app.listen(ARGS.port, function () {
|
||||
const port = server.address().port;
|
||||
console.log("Server started on port " + port);
|
||||
if (ARGS.open) {
|
||||
open('http://0.0.0.0:' + port);
|
||||
}
|
||||
});
|
|
@ -1,17 +0,0 @@
|
|||
const winston = require('winston');
|
||||
const expressWinston = require('express-winston');
|
||||
|
||||
module.exports = expressWinston.logger({
|
||||
transports: [
|
||||
new winston.transports.Console({
|
||||
colorize: true
|
||||
})
|
||||
],
|
||||
meta: false,
|
||||
msg: '{{ req.url }} '
|
||||
.concat('status:{{ res.statusCode }} ')
|
||||
.concat('useragent:{{ req.headers["user-agent"] }} ')
|
||||
.concat('time:{{ res.responseTime }}ms'),
|
||||
colorize: true,
|
||||
statusLevels: true
|
||||
});
|
11
src/middleware/404.ts
Normal file
11
src/middleware/404.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
import { Request, Response } from 'express';
|
||||
import * as staticFile from 'connect-static-file'
|
||||
import * as path from 'path';
|
||||
|
||||
export default function handle404(serveDir : string) {
|
||||
const handle404Middleware = staticFile(path.join(serveDir, '.404.html'));
|
||||
return function (request : Request, response : Response, next : Function) {
|
||||
response.statusCode = 404;
|
||||
return handle404Middleware(request, response, next);
|
||||
}
|
||||
}
|
8
src/middleware/basic-auth.ts
Normal file
8
src/middleware/basic-auth.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
import * as basicAuth from 'express-basic-auth';
|
||||
|
||||
export default function basicAuthHandler(username : string, password : string) {
|
||||
return basicAuth({
|
||||
authorizer: (req_username : string, req_password : string) => req_username === username && req_password === password,
|
||||
challenge: true
|
||||
});
|
||||
}
|
17
src/middleware/logging.ts
Normal file
17
src/middleware/logging.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import * as winston from 'winston';
|
||||
import * as expressWinston from 'express-winston';
|
||||
|
||||
export default expressWinston.logger({
|
||||
transports: [
|
||||
new winston.transports.Console({
|
||||
colorize: true
|
||||
})
|
||||
],
|
||||
meta: false,
|
||||
msg: '{{ req.url }} '
|
||||
.concat('status:{{ res.statusCode }} ')
|
||||
.concat('useragent:{{ req.headers["user-agent"] }} ')
|
||||
.concat('time:{{ res.responseTime }}ms'),
|
||||
colorize: true,
|
||||
statusLevels: true
|
||||
});
|
28
src/middleware/static-files.ts
Normal file
28
src/middleware/static-files.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
import * as express from 'express';
|
||||
import * as serveIndex from 'serve-index';
|
||||
import * as path from 'path';
|
||||
|
||||
function isDirectory(url : string) : boolean {
|
||||
return /\/$/.test(url);
|
||||
}
|
||||
|
||||
export function indexHandle(request : express.Request, response : express.Response, next : Function) {
|
||||
if (isDirectory(request.url)) {
|
||||
request.url = path.join(request.url, 'index.html');
|
||||
}
|
||||
return next();
|
||||
}
|
||||
|
||||
export function staticFileHandle(serveDir : string) {
|
||||
return express.static(serveDir, {
|
||||
dotfiles: 'ignore',
|
||||
index: false,
|
||||
redirect: true
|
||||
});
|
||||
}
|
||||
|
||||
export function serveIndexHandle(serveDir : string) {
|
||||
return serveIndex(serveDir, {
|
||||
icons: true
|
||||
});
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
console.log('Starting Server...');
|
||||
|
||||
const app = require('express')();
|
||||
const consts = require('./consts');
|
||||
|
||||
const compression = require('compression');
|
||||
const helmet = require('helmet');
|
||||
const serveIndex = require('serve-index');
|
||||
const AccessControl = require('express-ip-access-control');
|
||||
const opbeat = require('opbeat').start({
|
||||
active: consts.IN_PRODUCTION
|
||||
});
|
||||
|
||||
const logging = require('./logging');
|
||||
const staticFiles = require('./static-files');
|
||||
const handle404 = require('./404');
|
||||
const basicAuth = require('./basic-auth');
|
||||
|
||||
if (consts.ALLOWED_IPS) {
|
||||
app.set('trust proxy', true);
|
||||
app.use(AccessControl({
|
||||
mode: 'allow',
|
||||
allows: consts.ALLOWED_IPS,
|
||||
statusCode: 404
|
||||
}));
|
||||
}
|
||||
|
||||
// Custom Middleware
|
||||
app.use(logging);
|
||||
app.use(basicAuth);
|
||||
|
||||
if (consts.DIR_LIST) {
|
||||
app.use(serveIndex(consts.SERVE_DIR, {
|
||||
icons: true
|
||||
}));
|
||||
} else {
|
||||
app.use(staticFiles.indexHandle);
|
||||
}
|
||||
|
||||
app.use(staticFiles.static);
|
||||
app.use(handle404);
|
||||
|
||||
// Library
|
||||
app.use(compression({ level: 9 }));
|
||||
app.use(helmet());
|
||||
app.use(opbeat.middleware.express());
|
||||
|
||||
const server = app.listen(consts.PORT, function () {
|
||||
console.log('Server started on ' + server.address().port);
|
||||
});
|
||||
|
||||
module.exports = server;
|
53
src/server.ts
Normal file
53
src/server.ts
Normal file
|
@ -0,0 +1,53 @@
|
|||
import * as express from 'express';
|
||||
|
||||
import * as AccessControl from 'express-ip-access-control';
|
||||
import * as compression from 'compression';
|
||||
import * as helmet from 'helmet';
|
||||
import * as opbeat from 'opbeat';
|
||||
|
||||
import logging from './middleware/logging';
|
||||
import basicAuthHandler from './middleware/basic-auth';
|
||||
import { serveIndexHandle, indexHandle, staticFileHandle } from './middleware/static-files';
|
||||
import handle404 from './middleware/404';
|
||||
|
||||
import { Options } from './types';
|
||||
|
||||
export default function createServer(opts : Options) : express.Application {
|
||||
const app = express();
|
||||
|
||||
if (process.env.NODE_ENV !== 'test') {
|
||||
app.use(logging);
|
||||
}
|
||||
|
||||
if (opts.allowed_ips.length) {
|
||||
app.set('trust proxy', true);
|
||||
app.use(AccessControl({
|
||||
mode: 'allow',
|
||||
allows: opts.allowed_ips,
|
||||
statusCode: 404
|
||||
}));
|
||||
}
|
||||
|
||||
if (opts.basicAuth.length) {
|
||||
app.use(basicAuthHandler(opts.basicAuth[0], opts.basicAuth[1]));
|
||||
}
|
||||
|
||||
if (opts.dirList) {
|
||||
app.use(serveIndexHandle(opts.serveDir));
|
||||
} else {
|
||||
app.use(indexHandle);
|
||||
}
|
||||
|
||||
app.use(staticFileHandle(opts.serveDir));
|
||||
app.use(handle404(opts.serveDir));
|
||||
|
||||
app.use(compression({ level: 9 }));
|
||||
app.use(helmet());
|
||||
if (opts.opbeat) {
|
||||
app.use(opbeat.start({
|
||||
active: opts.opbeat
|
||||
}).middleware.express());
|
||||
}
|
||||
|
||||
return app;
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
const express = require('express');
|
||||
const path = require('path');
|
||||
const { SERVE_DIR } = require('./consts');
|
||||
|
||||
module.exports.indexHandle = function (request, response, next) {
|
||||
if (request.url.endsWith('/')) {
|
||||
request.url = path.join(request.url, 'index.html');
|
||||
}
|
||||
next();
|
||||
};
|
||||
|
||||
module.exports.static = express.static(SERVE_DIR, {
|
||||
dotfiles: 'ignore',
|
||||
index: false,
|
||||
redirect: true
|
||||
});
|
12
src/types/fakes.d.ts
vendored
Normal file
12
src/types/fakes.d.ts
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
/* Mock types that dont exist */
|
||||
|
||||
declare module 'express-ip-access-control';
|
||||
declare module 'connect-static-file';
|
||||
declare module 'express-basic-auth';
|
||||
declare module 'winston'; // doesnt like console transport
|
||||
declare module 'express-winston';
|
||||
declare module 'opbeat';
|
||||
declare module 'docopt';
|
||||
declare module 'open';
|
||||
declare module 'node-fetch';
|
||||
declare module 'chai';
|
10
src/types/index.ts
Normal file
10
src/types/index.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
|
||||
export interface Options {
|
||||
port: number;
|
||||
allowed_ips: string[];
|
||||
basicAuth: string[];
|
||||
dirList: boolean;
|
||||
serveDir: string;
|
||||
opbeat: boolean;
|
||||
open: boolean;
|
||||
}
|
14
tests/helpers.ts
Normal file
14
tests/helpers.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
import createServer from '../src/server';
|
||||
import { Options } from '../src/types';
|
||||
import fetch from 'node-fetch';
|
||||
|
||||
|
||||
export function runServer(opts: Object, url : string, callback: Function) {
|
||||
const app = createServer(opts as Options);
|
||||
const server = app.listen(1234, function () {
|
||||
return fetch('http://0.0.0.0:1234' + url).then(function (response : any) {
|
||||
server.close();
|
||||
callback(response);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
const request = require('supertest');
|
||||
const fs = require('fs');
|
||||
|
||||
|
||||
describe('Server', function () {
|
||||
var server;
|
||||
before(function () {
|
||||
server = require('../src/server');
|
||||
});
|
||||
|
||||
after(function () {
|
||||
server.close();
|
||||
});
|
||||
|
||||
it('responds to /', function (done) {
|
||||
request(server)
|
||||
.get('/')
|
||||
.expect(200, done);
|
||||
});
|
||||
|
||||
it('returns 404 on bad path', function (done) {
|
||||
request(server)
|
||||
.get('/foo/bar')
|
||||
.expect(404, done);
|
||||
});
|
||||
|
||||
describe('index route', function () {
|
||||
const body = fs.readFileSync(__dirname + '/../site/index.html').toString();
|
||||
|
||||
it('should render /index.html', function (done) {
|
||||
request(server)
|
||||
.get('/index.html')
|
||||
.expect(200, body, done);
|
||||
});
|
||||
|
||||
it('should render /', function (done) {
|
||||
request(server)
|
||||
.get('/')
|
||||
.expect(200, body, done);
|
||||
});
|
||||
});
|
||||
});
|
61
tests/server.test.ts
Normal file
61
tests/server.test.ts
Normal file
|
@ -0,0 +1,61 @@
|
|||
import { expect } from 'chai';
|
||||
import { runServer } from './helpers';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
|
||||
describe('Server', function () {
|
||||
it('should test', function () {
|
||||
expect(2 + 2).to.equal(4);
|
||||
});
|
||||
|
||||
it('Should be usable', function (done) {
|
||||
runServer({
|
||||
allowed_ips: [],
|
||||
basicAuth: [],
|
||||
dirList: false,
|
||||
serveDir: 'site/',
|
||||
opbeat: false,
|
||||
open: false
|
||||
}, '/index.html', function (response : any) {
|
||||
expect(response.status).to.equal(200);
|
||||
expect(response.url).to.include('/index.html');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Should respond with 404 on bad path', function (done) {
|
||||
runServer({
|
||||
allowed_ips: [],
|
||||
basicAuth: [],
|
||||
dirList: false,
|
||||
serveDir: 'site/',
|
||||
opbeat: false,
|
||||
open: false
|
||||
}, '/foo/bar', function (response : any) {
|
||||
expect(response.ok).to.be.false;
|
||||
expect(response.status).to.equal(404);
|
||||
expect(response.text()).to.eventually.include('Cannot GET').notify(done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('index route', function () {
|
||||
const body = fs.readFileSync(path.join(__dirname, '..', 'site', 'index.html')).toString();
|
||||
|
||||
['', '/', '/index.html'].forEach(function (path : string) {
|
||||
it('should render ' + path, function (done) {
|
||||
runServer({
|
||||
allowed_ips: [],
|
||||
basicAuth: [],
|
||||
dirList: false,
|
||||
serveDir: 'site/',
|
||||
opbeat: false,
|
||||
open: false
|
||||
}, path, function (response : any) {
|
||||
expect(response.status).to.equal(200);
|
||||
expect(response.text()).to.eventually.equal(body).notify(done);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
28
tsconfig.json
Normal file
28
tsconfig.json
Normal file
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"noImplicitAny": true,
|
||||
"experimentalDecorators": true,
|
||||
"preserveConstEnums": true,
|
||||
"allowJs": true,
|
||||
"sourceMap": true,
|
||||
"pretty": true
|
||||
},
|
||||
"filesGlob": [
|
||||
"typings/index.d.ts",
|
||||
"src/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"dist",
|
||||
"node_modules",
|
||||
"scripts/",
|
||||
"tests/"
|
||||
],
|
||||
"typeRoots": [
|
||||
"node_modules",
|
||||
"typings",
|
||||
"src/types"
|
||||
],
|
||||
"compileOnSave": false
|
||||
}
|
7
tslint.json
Normal file
7
tslint.json
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"extends": "tslint:recommended",
|
||||
"rules": {
|
||||
"quotemark": [true, "single"],
|
||||
"trailing-comma": [false]
|
||||
}
|
||||
}
|
16
typings.json
Normal file
16
typings.json
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"compression": "registry:dt/compression#0.0.0+20160725212620",
|
||||
"debug": "registry:npm/debug#2.0.0+20160723033700",
|
||||
"express": "registry:npm/express#4.14.0+20160925001530",
|
||||
"helmet": "registry:dt/helmet#0.0.0+20161005184000",
|
||||
"serve-index": "registry:dt/serve-index#1.7.2+20160428043022"
|
||||
},
|
||||
"globalDependencies": {
|
||||
"node": "registry:dt/node#7.0.0+20170204020307"
|
||||
},
|
||||
"globalDevDependencies": {
|
||||
"chai": "registry:dt/chai#3.4.0+20170217154556",
|
||||
"mocha": "registry:dt/mocha#2.2.5+20170204022515"
|
||||
}
|
||||
}
|
Reference in a new issue