New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@lbu/server

Package Overview
Dependencies
Maintainers
1
Versions
98
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@lbu/server - npm Package Compare versions

Comparing version 0.0.6 to 0.0.7

src/middleware/cors.js

19

index.js

@@ -1,17 +0,10 @@

const { getApp } = require("./src/app");
const {
createBodyParsers,
getBodyParser,
getMultipartBodyParser,
} = require("./src/middleware");
const compose = require("koa-compose");
import compose from "koa-compose";
module.exports = {
getApp,
export { compose };
export { getApp } from "./src/app.js";
export {
createBodyParsers,
getBodyParser,
getMultipartBodyParser,
compose,
};
AppError,
} from "./src/middleware/index.js";
{
"name": "@lbu/server",
"version": "0.0.6",
"version": "0.0.7",
"description": "Koa server and common middleware",
"main": "index.js",
"type": "module",
"keywords": [

@@ -16,9 +17,7 @@ "lightbase",

"dependencies": {
"@lbu/insight": "^0.0.6",
"@lbu/stdlib": "^0.0.6",
"@lbu/insight": "^0.0.7",
"@lbu/stdlib": "^0.0.7",
"koa": "2.11.0",
"koa-body": "4.1.1",
"koa-compose": "4.1.0",
"koa-helmet": "5.2.0",
"koa2-cors": "2.0.6"
"koa-compose": "4.1.0"
},

@@ -39,3 +38,3 @@ "author": {

},
"gitHead": "a7b150d9265f449127dc812d4bcef7fb803d6d63"
"gitHead": "4c2199aeb1052bab67b3b1355bd648086736abf7"
}

@@ -27,16 +27,15 @@ # @lbu/server

- @lbu/cli: Project template, and simple script runner
- @lbu/code-gen: Flexible code generators. Supports generating validators,
router, SQL and more
- @lbu/code-gen: Flexible code generators. Supports generating router, validator
- @lbu/insight: Opinionated logger
- @lbu/server: Wrap around Koa and some useful middleware
- @lbu/stdlib: Growing library with features like uuid generation and background
jobs
- @lbu/stdlib: Growing library of various common utilities like uuid & a basic
templating system
## Roadmap
- [ ] @lbu/store: Common abstraction for FileSystem, Redis, Memory support for
queues, KV store etc
- [ ] @lbu/code-gen: More plugins
- [ ] @lbu/code-gen: OpenAPI importer
- [ ] @lbu/features: Feature flag implementation based on @lbu/store & support
for code-gen
- [ ] @lbu/code-gen: Postgres query generator
## Docs

@@ -43,0 +42,0 @@

@@ -1,9 +0,9 @@

const Koa = require("koa");
const {
import Koa from "koa";
import {
defaultHeaders,
errorHandler,
healthHandler,
logMiddleware,
notFoundHandler,
logMiddleware,
defaultHeaders,
} = require("./middleware");
} from "./middleware/index.js";

@@ -13,13 +13,17 @@ /**

* @param {Object=} opts
* @param {boolean} [opts.proxy=false]
* @param {boolean} [opts.disableHeaders=false]
* @param {boolean} [opts.enableHealthRoute=true]
* @param {KoaErrorHandler=} opts.onError
* @param {boolean} [opts.proxy]
* @param {boolean} [opts.disableHeaders]
* @param {boolean} [opts.disableHealthRoute]
* @param {ErrorHandlerOptions} [opts.errorOptions]
* @param {Object} opts.headers Argument for defaultHeaders middleware
* @param {CorsOptions} opts.headers.cors Argument for defaultHeaders middleware
*/
const getApp = (opts = {}) => {
export const getApp = (opts = {}) => {
const app = new Koa();
app.proxy = opts.proxy === true;
app.proxy =
opts.proxy === undefined
? process.env.NODE_ENV === "production"
: opts.proxy;
if (opts.enableHealthRoute !== false) {
if (opts.disableHealthRoute !== true) {
app.use(healthHandler());

@@ -29,6 +33,6 @@ }

app.use(logMiddleware());
app.use(errorHandler(opts.onError));
app.use(errorHandler(opts.errorOptions || {}));
app.use(notFoundHandler());
if (!opts.disableHeaders) {
if (opts.disableHeaders !== true) {
app.use(defaultHeaders(opts.headers));

@@ -39,5 +43,1 @@ }

};
module.exports = {
getApp,
};

@@ -1,3 +0,3 @@

const koaBody = require("koa-body");
const { merge } = require("@lbu/stdlib");
import { merge } from "@lbu/stdlib";
import koaBody from "koa-body";

@@ -12,3 +12,3 @@ let memoizeBodyParser;

*/
const createBodyParsers = (opts = {}) => {
export const createBodyParsers = (opts = {}) => {
const multiPartOpts = merge({}, opts);

@@ -28,3 +28,3 @@

*/
const getBodyParser = () => {
export const getBodyParser = () => {
if (memoizeBodyParser === undefined) {

@@ -45,3 +45,3 @@ throw new Error(

*/
const getMultipartBodyParser = () => {
export const getMultipartBodyParser = () => {
if (memoizeMultipartBodyParser === undefined) {

@@ -55,7 +55,1 @@ throw new Error(

};
module.exports = {
createBodyParsers,
getBodyParser,
getMultipartBodyParser,
};

@@ -0,3 +1,82 @@

import { isNil } from "@lbu/stdlib";
/**
* @callback KoaErrorHandler
* AppErrors represent errors, that should immediately stop the request and return a
* status and other meta data directly
*/
export class AppError extends Error {
/**
* Create a new AppError
* @param {string} key
* @param {number} status
* @param {Object} [info={}]
* @param {Error} [originalError]
*/
constructor(key, status, info, originalError) {
super();
this.key = key;
this.status = status;
this.info = info || {};
this.originalError = originalError;
Object.setPrototypeOf(this, AppError.prototype);
if (isNil(key) || isNil(status)) {
return AppError.serverError(
{
appErrorConstruct: {
key,
status,
},
},
this,
);
}
}
/**
* Throw a new 404 not found error
* @param {Object} [info={}]
* @param {Error} [error]
* @return {AppError}
*/
static notFound(info = {}, error = undefined) {
return new AppError("error.server.notFound", 404, info, error);
}
/**
* Throw a new 405 Not implemented error
* @param {Object} [info={}]
* @param {Error} [error]
* @return {AppError}
*/
static notImplemented(info = {}, error = undefined) {
return new AppError("error.server.notImplemented", 405, info, error);
}
/**
* Throw a new 500 internal server error
* @param {Object} [info={}]
* @param {Error} [error]
* @return {AppError}
*/
static serverError(info = {}, error = undefined) {
return new AppError("error.server.internal", 500, info, error);
}
/**
* Throw a new 400 validation error
* @param {string} key
* @param {Object} [info={}]
* @param {Error} [error]
* @return {AppError}
*/
static validationError(key, info = {}, error = undefined) {
return new AppError(key, 400, info, error);
}
}
/**
* @callback CustomErrorHandler
* @param ctx Koa Context

@@ -8,34 +87,84 @@ * @param {Error} err

const { NotFoundError } = require("./notFound");
/**
* @callback AppErrorHandler
* @param ctx Koa Context
* @param {string} key
* @param {Object} info
* @returns {Object} The any data extracted from the key
*/
/**
* @type CustomErrorHandler
* Default onError handler that doesn't handle anything
*/
const defaultOnError = () => false;
/**
* @type AppErrorHandler
* Default onAppError handler that builds a simple object with key, message and info.
*/
const defaultOnAppError = (ctx, key, info) => ({ key, message: key, info });
/**
* @typedef {Object} ErrorHandlerOptions
* @property {AppErrorHandler} [onAppError] Called to set the initial body when the
* error is an AppError
* @property {CustomErrorHandler} [onError] Called before all others to let the user
* handle their own errors
* @property {boolean} [leakError] Useful on development and staging environments to
* just dump the error to the consumer
*/
/**
* Handle any upstream errors
* @param {KoaErrorHandler} onError
* @param {ErrorHandlerOptions} opts
* @returns {function(...[*]=)}
*/
const errorHandler = onError => async (ctx, next) => {
try {
await next();
} catch (error) {
if (onError && onError(ctx, error)) {
return;
}
export const errorHandler = ({ onAppError, onError, leakError }) => {
onAppError = onAppError || defaultOnAppError;
onError = onError || defaultOnError;
leakError = leakError === true;
if (error instanceof NotFoundError) {
ctx.body = {
message: "Not found",
};
} else {
ctx.log.error({
error,
return async (ctx, next) => {
try {
await next();
} catch (error) {
if (onError(ctx, error)) {
return;
}
let err = error;
let log = ctx.log.info;
if (!(error instanceof AppError)) {
log = ctx.log.error;
err = new AppError("error.server.internal", 500, {}, error);
}
ctx.status = err.status;
ctx.body = onAppError(ctx, err.key, err.info);
let originalError = undefined;
if (err.originalError) {
originalError = {
name: err.originalError.name,
message: err.originalError.message,
stack: err.originalError.stack.split("\n"),
};
}
log({
type: "API_ERROR",
status: err.status,
key: err.key,
info: err.info,
originalError,
});
ctx.status = 500;
ctx.body = {
message: "Internal server error",
};
if (!isNil(err.originalError) && leakError) {
ctx.body.info = ctx.body.info || {};
ctx.body.info._error = originalError;
}
}
}
};
};
module.exports = {
errorHandler,
};

@@ -1,20 +0,22 @@

const koaHelmet = require("koa-helmet");
const cors = require("koa2-cors");
import { cors } from "./cors.js";
const noop = () => {};
/**
* TODO: Replace with custom code calling Helmet, and custom cors implementation
* @param {Object} [opts=]
* @param {Object=} opts.helmet Helmet configuration see koa-helmet
* @param {Object=} opts.cors Cors configuration see koa2-cors
* @param {Object} [opts]
* @param {CorsOptions} opts.cors Cors configuration see koa2-cors
*/
const defaultHeaders = (opts = {}) => {
const helmetExec = koaHelmet(opts.helmet);
export const defaultHeaders = (opts = {}) => {
// Excerpt from default helmet headers
// When serving static files, some extra headers should be added
// See: https://helmetjs.github.io/docs/
const standardHeaders = {
"X-DNS-Prefetch-Control": "off",
"Strict-Transport-Security": "max-age=5184000; includeSubDomains", // 60 day default
};
const corsOptions = opts.cors || {};
corsOptions.returnNext = false;
const corsExec = cors(opts.cors);
return async (ctx, next) => {
// At the moment, both do not rely on next, so just use a noop
await helmetExec(ctx, noop);
await corsExec(ctx, noop);
return (ctx, next) => {
ctx.set(standardHeaders);
corsExec(ctx);

@@ -24,5 +26,1 @@ return next();

};
module.exports = {
defaultHeaders,
};
/**
* Middleware that immediately returns on ANY /_health
*/
const healthHandler = () => (ctx, next) => {
export const healthHandler = () => (ctx, next) => {
if (ctx.path === "/_health") {

@@ -11,5 +11,1 @@ ctx.body = "";

};
module.exports = {
healthHandler,
};

@@ -1,22 +0,10 @@

const {
export {
createBodyParsers,
getBodyParser,
getMultipartBodyParser,
} = require("./body");
const { errorHandler } = require("./error");
const { defaultHeaders } = require("./headers");
const { healthHandler } = require("./health");
const { logMiddleware } = require("./log");
const { NotFoundError, notFoundHandler } = require("./notFound");
module.exports = {
createBodyParsers,
errorHandler,
defaultHeaders,
getBodyParser,
getMultipartBodyParser,
healthHandler,
logMiddleware,
NotFoundError,
notFoundHandler,
};
} from "./body.js";
export { AppError, errorHandler } from "./error.js";
export { defaultHeaders } from "./headers.js";
export { healthHandler } from "./health.js";
export { logMiddleware } from "./log.js";
export { notFoundHandler } from "./notFound.js";

@@ -1,4 +0,4 @@

const { newLogger } = require("@lbu/insight");
const { isNil, uuid } = require("@lbu/stdlib");
const { Transform } = require("stream");
import { newLogger } from "@lbu/insight";
import { isNil, uuid } from "@lbu/stdlib";
import { Transform } from "stream";

@@ -70,3 +70,3 @@ /**

*/
const logMiddleware = () => async (ctx, next) => {
export const logMiddleware = () => async (ctx, next) => {
const startTime = process.hrtime.bigint();

@@ -103,5 +103,1 @@

};
module.exports = {
logMiddleware,
};

@@ -1,26 +0,12 @@

/**
* Error to be used when a path is not found
*/
class NotFoundError extends Error {
constructor() {
super();
import { AppError } from "./error.js";
Object.setPrototypeOf(this, NotFoundError.prototype);
}
}
/**
* Middleware that sets a 404 and throws a NotFoundError
*/
const notFoundHandler = () => async (ctx, next) => {
export const notFoundHandler = () => async (ctx, next) => {
await next();
ctx.status = ctx.status || 404;
if (ctx.status === 404) {
throw new NotFoundError();
throw AppError.notFound();
}
};
module.exports = {
NotFoundError,
notFoundHandler,
};
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