Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

bay

Package Overview
Dependencies
Maintainers
4
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

bay - npm Package Compare versions

Comparing version 0.0.2 to 0.1.1

exceptions.js

175

application.js
'use strict';
const koa = require('koa');
const co = require('co');
const _ = require('lodash');
const delegate = require('delegates');
const http = require('http');
const loader = require('./loader');
const Router = require('./lib/router');
const compose = require('koa-compose');
const filter = require('filter-match').filter;
const Router = require('./lib/router/router');
const resolver = require('resolve-keypath').resolver;
const requireDir = require('require-dir');
const onFinished = require('on-finished');
const parse = require('parseurl');
const exceptions = require('./exceptions');
const statuses = require('statuses');
const path = require('path')
const base = path.dirname(module.parent.filename);
const path = require('path');

@@ -18,23 +23,157 @@ class BayApplication {

}
this.app = koa();
this.base = options.base || base;
this.env = process.env.NODE_ENV || 'development';
this.subdomainOffset = 2;
this.middleware = [];
this.getVersion = options.getVersion;
this.proxy = options.proxy;
this.base = options.base;
if (!this.base) {
throw new Error('missing base path');
}
this.router = new Router();
_.assign(this.app, options);
delegate(this, 'app')
.method('use')
.method('callback')
.method('inspect')
.method('toJSON')
this.getController = resolver(requireDir(path.join(this.base, 'controllers'), { recurse: true }), '/');
this.getVersionTransformer = resolver(requireDir(path.join(this.base, 'versions'), { recurse: true }), '/');
}
/**
* Use the given middleware `fn`.
*
* @param {GeneratorFunction} fn
* @return {Application} self
* @api public
*/
use(fn) {
this.middleware.push(fn);
return this;
}
listen() {
const loaders = loader(this.base);
this.app.use(loaders.router(this.router, loaders.controller));
const server = http.createServer(this.app.callback());
const server = http.createServer(this.callback());
return server.listen.apply(server, arguments);
}
/**
* Return JSON representation.
* We only bother showing settings.
*
* @return {Object}
* @api public
*/
toJSON() {
return _.pick(this, ['subdomainOffset', 'proxy', 'env']);
}
callback() {
const self = this;
return function (req, res) {
res.statusCode = 404;
// Find the matching route
let match
try {
match = self.router.match(parse(req).pathname, req.method);
} catch (err) {
return self.handleError(req, res, err);
}
if (!match) {
return self.handleError(req, res, new exceptions.RoutingError('No route matches'));
}
// Resolve the controller
const actionName = match.handler.action;
const controllerName = match.handler.controller;
const ControllerClass = self.getController(controllerName);
if (!ControllerClass) {
return self.handleError(req, res, new exceptions.RoutingError(`Controller ${controllerName} not found`));
}
if (!ControllerClass.prototype[actionName]) {
return self.handleError(req, res,
new exceptions.RoutingError(`Action ${controllerName}#${actionName} not found`));
}
onFinished(res, function (err) {
if (err) {
self.handleError(req, res, convertToError(err));
}
});
const controller = new ControllerClass(self, req, res);
controller.route = match;
controller.params = match.params;
const middlewares = self.middleware.slice();
if (self.getVersion) {
const version = self.getVersion(controller);
const versionTransformer = self.getVersionTransformer(`${version}/${controllerName}`);
if (versionTransformer && versionTransformer[actionName]) {
middlewares.push(versionTransformer[actionName]);
}
}
if (controller._middleware) {
filter(actionName, controller._middleware).forEach(v => {
middlewares.push(typeof v.name === 'function' ? v.name : controller[v.name]);
});
}
middlewares.push(function *fillRespondBody(next) {
const body = yield controller[actionName];
if (typeof body !== 'undefined') {
controller.body = body;
}
yield next;
});
co.wrap(compose(middlewares)).call(controller).then(function () {
controller.respond();
}).catch(function (err) {
self.handleError(req, res, convertToError(err));
});
};
}
handleError(req, res, err) {
if (res.headerSent || !res.socket || !res.socket.writable) {
err.headerSent = true;
return;
}
// unset all headers
res._headers = {};
// force text/plain
res.setHeader('Content-Type', 'text/plain');
// ENOENT support
if (err.code === 'ENOENT') {
err.status = 404;
}
// default to 500
if (typeof err.status !== 'number' || !statuses[err.status]) {
err.status = 500;
}
// respond
const code = statuses[err.status];
const msg = err.expose ? err.message : code;
res.statusCode = code;
res.setHeader('Content-Length', Buffer.byteLength(msg));
res.end(msg);
}
}
function convertToError(err) {
return err instanceof Error ? err : new Error(`non-error thrown: ${err}`);
}
module.exports = BayApplication;
exports.exceptions = exceptions;

285

controller.js
'use strict';
const delegate = require('delegates');
const requestLib = require('./lib/request');
const responseLib = require('./lib/response');
const Cookies = require('cookies');
const accepts = require('accepts');
const createError = require('http-errors');
const httpAssert = require('http-assert');
const Stream = require('stream');
const isJSON = require('koa-is-json');
const statuses = require('statuses');
class BayController {
constructor(ctx) {
this.ctx = ctx;
function BayController(app, req, res) {
const request = this.request = Object.create(requestLib);
const response = this.response = Object.create(responseLib);
delegate(this, 'ctx')
.getter('request')
.getter('response')
.getter('params')
.getter('route')
.getter('cookies');
this.app = request.app = response.app = app;
this.req = request.req = response.req = req;
this.res = request.res = response.res = res;
/**
* Response delegation.
*/
request.ctx = response.ctx = this;
request.response = response;
response.request = request;
delegate(this, 'response')
.method('attachment')
.method('redirect')
.method('remove')
.method('vary')
.method('set')
.method('append')
.access('status')
.access('message')
.access('length')
.access('type')
.access('lastModified')
.access('etag')
.access('body')
.getter('headerSent')
.getter('writable');
this.originalUrl = request.originalUrl = req.url;
this.cookies = new Cookies(req, res, this.keys);
this.accept = request.accept = accepts(req);
this.state = {};
}
/**
* Request delegation.
*/
/**
* Return JSON representation.
*
* Here we explicitly invoke .toJSON() on each
* object, as iteration will otherwise fail due
* to the getters and cause utilities such as
* clone() to fail.
*
* @return {Object}
* @api public
*/
BayController.prototype.toJSON = function () {
return {
request: this.request.toJSON(),
response: this.response.toJSON(),
app: this.app.toJSON(),
originalUrl: this.originalUrl,
req: '<original node req>',
res: '<original node res>',
socket: '<original node socket>'
};
};
delegate(this, 'request')
.method('acceptsLanguages')
.method('acceptsEncodings')
.method('acceptsCharsets')
.method('accepts')
.method('get')
.method('is')
.access('querystring')
.access('idempotent')
.access('socket')
.access('search')
.access('method')
.access('query')
.access('path')
.access('url')
.getter('origin')
.getter('href')
.getter('subdomains')
.getter('protocol')
.getter('host')
.getter('hostname')
.getter('header')
.getter('headers')
.getter('secure')
.getter('stale')
.getter('fresh')
.getter('ips')
.getter('ip');
/**
* Similar to .throw(), adds assertion.
*
* this.assert(this.user, 401, 'Please login!');
*
* See: https://github.com/jshttp/http-assert
*
* @param {Mixed} test
* @param {Number} [status=400]
* @param {String} message
* @api public
*/
BayController.prototype.assert = function (res, code, message) {
if (arguments.length === 1 || (arguments.length === 2 && typeof code === 'string')) {
return httpAssert(res, 400, code);
}
return httpAssert(res, code, message);
};
aroundAction(name, options) {
if (!options) {
options = {};
}
options.name = name;
if (!this._middleware) {
this._middleware = [];
}
this._middleware.push(options);
/**
* Throw an error with `msg` and optional `status`
* defaulting to 500. Note that these are user-level
* errors, and the message may be exposed to the client.
*
* this.throw(403)
* this.throw('name required', 400)
* this.throw(400, 'name required')
* this.throw('something exploded')
* this.throw(new Error('invalid'), 400);
* this.throw(400, new Error('invalid'));
*
* See: https://github.com/jshttp/http-errors
*
* @param {String|Number|Error} err, msg or status
* @param {String|Number|Error} [err, msg or status]
* @param {Object} [props]
* @api public
*/
BayController.prototype.throw = function (code, message) {
if (arguments.length === 1 && typeof code === 'string') {
throw createError(400, code);
}
throw createError(code, message);
};
/**
* Node-style asserting with HTTP errors being thrown
*
* This patch defaults the http code to 400
* rather than 500
*/
assert(res, code, message) {
if (arguments.length === 1 || (arguments.length === 2 && typeof code === 'string')) {
return this.ctx.assert(res, 400, code);
}
return this.ctx.assert(res, code, message);
/**
* Response helper.
*/
BayController.prototype.respond = function () {
const res = this.res;
if (res.headersSent || !this.writable) {
return;
}
/**
* Like #assert, but unconditionally throws
*/
throw(code, message) {
if (arguments.length === 1 && typeof code === 'string') {
return this.ctx.throw(400, code);
let body = this.body;
const code = this.status;
// ignore body
if (statuses.empty[code]) {
// strip headers
this.body = null;
return res.end();
}
if (this.method === 'HEAD') {
if (isJSON(body)) {
this.length = Buffer.byteLength(JSON.stringify(body));
}
return this.ctx.throw(code, message);
return res.end();
}
}
// status body
if (body === null || typeof body === 'undefined') {
this.type = 'text';
body = this.message || String(code);
this.length = Buffer.byteLength(body);
return res.end(body);
}
// responses
if (Buffer.isBuffer(body)) {
return res.end(body);
}
if (typeof body === 'string') {
return res.end(body);
}
if (body instanceof Stream) {
return body.pipe(res);
}
// body: json
body = JSON.stringify(body);
this.length = Buffer.byteLength(body);
res.end(body);
};
BayController.prototype.aroundAction = function (name, options) {
if (!options) {
options = {};
}
options.name = name;
if (!this._middleware) {
this._middleware = [];
}
this._middleware.push(options);
};
/**
* Response delegation.
*/
delegate(BayController.prototype, 'response')
.method('attachment')
.method('redirect')
.method('remove')
.method('vary')
.method('set')
.method('append')
.access('status')
.access('message')
.access('body')
.access('length')
.access('type')
.access('lastModified')
.access('etag')
.getter('headerSent')
.getter('writable');
/**
* Request delegation.
*/
delegate(BayController.prototype, 'request')
.method('acceptsLanguages')
.method('acceptsEncodings')
.method('acceptsCharsets')
.method('accepts')
.method('get')
.method('is')
.access('querystring')
.access('idempotent')
.access('socket')
.access('search')
.access('method')
.access('query')
.access('path')
.access('url')
.getter('origin')
.getter('href')
.getter('subdomains')
.getter('protocol')
.getter('host')
.getter('hostname')
.getter('header')
.getter('headers')
.getter('secure')
.getter('stale')
.getter('fresh')
.getter('ips')
.getter('ip');
module.exports = BayController;

@@ -7,3 +7,3 @@ 'use strict';

class Route {
constructor (methods, path, handler, options) {
constructor(methods, path, handler, options) {
this.options = _.defaults(options ? _.clone(options) : {}, {

@@ -18,3 +18,11 @@ middleware: []

this.regexp = pathToRegexp(path, this.keys = []);
this.handler = handler;
if (typeof handler === 'string') {
const key = handler.split('#');
this.handler = {
controller: key[0],
action: key[1]
};
} else {
this.handler = handler;
}
}

@@ -40,3 +48,3 @@

return {
params: params,
params,
path: m[0],

@@ -43,0 +51,0 @@ middlewares: this.options.middleware,

{
"name": "bay",
"version": "0.0.2",
"version": "0.1.1",
"description": "The framework",

@@ -15,14 +15,30 @@ "main": "index.js",

"dependencies": {
"debug": "^2.2.0",
"accepts": "^1.3.0",
"co": "^4.6.0",
"content-disposition": "^0.5.0",
"content-type": "^1.0.1",
"cookies": "^0.5.1",
"delegates": "^1.0.0",
"destroy": "^1.0.3",
"error-inject": "^1.0.0",
"escape-html": "^1.0.3",
"filter-match": "0.0.3",
"fresh": "^0.3.0",
"http-assert": "^1.1.1",
"http-errors": "^1.3.1",
"i": "^0.3.3",
"koa": "^1.1.2",
"koa-compose": "^2.3.0",
"koa-is-json": "^1.0.0",
"lodash": "^3.10.1",
"methods": "^1.1.1",
"mime-types": "^2.1.8",
"on-finished": "^2.3.0",
"parseurl": "^1.3.0",
"path-to-regexp": "^1.2.1",
"require-dir": "^0.3.0",
"resolve-keypath": "^1.1.0"
"resolve-keypath": "^1.1.0",
"statuses": "^1.2.1",
"type-is": "^1.6.10",
"vary": "^1.1.0"
}
}

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc