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

plumier

Package Overview
Dependencies
Maintainers
1
Versions
652
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

plumier - npm Package Compare versions

Comparing version 0.1.0-alpha.d43b984e to 1.0.0-alpha.5

LICENSE

59

lib/application.d.ts

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

/// <reference types="koa__cors" />
import Cors from "@koa/cors";
import { ActionResult, Application, Class, Configuration, DefaultFacility, Facility, Invocation, KoaMiddleware, Middleware, PlumierApplication, PlumierConfiguration, RouteInfo, ValidatorFunction } from "@plumier/core";
import Koa, { Context } from "koa";
import { ActionResult, Application, Configuration, Facility, Invocation, KoaMiddleware, PlumierApplication, PlumierConfiguration, Middleware } from "./framework";
export interface RouteContext extends Koa.Context {
route: Readonly<RouteInfo>;
parameters: any[];
}
export interface BodyParserOption {
enableTypes?: string[];
encode?: string;
formLimit?: string;
jsonLimit?: string;
strict?: boolean;
detectJSON?: (ctx: Koa.Context) => boolean;
extendTypes?: {
json?: string[];
form?: string[];
text?: string[];
};
onerror?: (err: Error, ctx: Koa.Context) => void;
}
export declare class MiddlewareInvocation implements Invocation {

@@ -11,10 +31,42 @@ private middleware;

export declare class ActionInvocation implements Invocation {
context: Context;
constructor(context: Context);
context: RouteContext;
constructor(context: RouteContext);
proceed(): Promise<ActionResult>;
}
export declare function pipe(middleware: Middleware[], context: Context, invocation: Invocation): Invocation;
/**
* Preset configuration for building web api. This facility contains:
*
* body parser: koa-bodyparser
*
* cors: @koa/cors
*/
export declare class WebApiFacility extends DefaultFacility {
private opt?;
constructor(opt?: {
controller?: string | Class | Class[] | undefined;
bodyParser?: BodyParserOption | undefined;
cors?: Cors.Options | undefined;
validators?: {
[key: string]: ValidatorFunction;
} | undefined;
} | undefined);
setup(app: Readonly<PlumierApplication>): void;
}
/**
* Preset configuration for building restful style api. This facility contains:
*
* body parser: koa-bodyparser
*
* cors: @koa/cors
*
* default response status: { get: 200, post: 201, put: 204, delete: 204 }
*/
export declare class RestfulApiFacility extends WebApiFacility {
setup(app: Readonly<PlumierApplication>): void;
}
export declare class Plumier implements PlumierApplication {
readonly config: Readonly<PlumierConfiguration>;
readonly koa: Koa;
private globalMiddleware;
constructor();

@@ -25,3 +77,4 @@ use(option: KoaMiddleware): Application;

set(config: Partial<Configuration>): Application;
private createRoutes;
initialize(): Promise<Koa>;
}

186

lib/application.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const debug_1 = tslib_1.__importDefault(require("debug"));
const cors_1 = tslib_1.__importDefault(require("@koa/cors"));
const core_1 = require("@plumier/core");
const validator_1 = require("@plumier/validator");
const fs_1 = require("fs");
const koa_1 = tslib_1.__importDefault(require("koa"));
const koa_bodyparser_1 = tslib_1.__importDefault(require("koa-bodyparser"));
const path_1 = require("path");
const util_1 = require("util");
const binder_1 = require("./binder");
const framework_1 = require("./framework");
const router_1 = require("./router");
const log = debug_1.default("plum:app");
/* ------------------------------------------------------------------------------- */

@@ -27,2 +26,10 @@ /* ------------------------------- INVOCATIONS ----------------------------------- */

exports.MiddlewareInvocation = MiddlewareInvocation;
class NotFoundActionInvocation {
constructor(context) {
this.context = context;
}
proceed() {
throw new core_1.HttpStatusError(404);
}
}
class ActionInvocation {

@@ -33,16 +40,23 @@ constructor(context) {

async proceed() {
const { request, route, config } = this.context;
const controller = config.dependencyResolver.resolve(route.controller.object);
const parameters = binder_1.bindParameter(request, route.action, config.converters);
const result = controller[route.action.name].apply(controller, parameters);
const { route, config } = this.context;
const controller = config.dependencyResolver.resolve(route.controller.type);
//check validation
if (config.validator) {
const param = (i) => route.action.parameters[i];
const validate = (value, i) => config.validator(value, param(i), this.context, this.context.config.validators);
const result = await Promise.all(this.context.parameters.map((value, index) => validate(value, index)));
const issues = result.flatten();
if (issues.length > 0)
throw new core_1.ValidationError(issues);
}
const result = controller[route.action.name].apply(controller, this.context.parameters);
const awaitedResult = await Promise.resolve(result);
const status = config.responseStatus && config.responseStatus[route.method] || 200;
if (result instanceof framework_1.ActionResult) {
result.status = result.status || status;
log(`[Action Invocation] Method: ${framework_1.b(route.method)} Status config: ${framework_1.b(util_1.inspect(config.responseStatus, false, null))} Status: ${framework_1.b(result.status)} `);
return Promise.resolve(result);
//if instance of action result, return immediately
if (awaitedResult && awaitedResult.execute) {
awaitedResult.status = awaitedResult.status || status;
return awaitedResult;
}
else {
const awaitedResult = await Promise.resolve(result);
log(`[Action Invocation] Method: ${route.method} Status config: ${framework_1.b(util_1.inspect(config.responseStatus, false, null))} Status: ${framework_1.b(status)} `);
return new framework_1.ActionResult(awaitedResult, status);
return new core_1.ActionResult(awaitedResult, status);
}

@@ -52,5 +66,2 @@ }

exports.ActionInvocation = ActionInvocation;
/* ------------------------------------------------------------------------------- */
/* ------------------------- MIDDLEWARE PIPELINE --------------------------------- */
/* ------------------------------------------------------------------------------- */
function pipe(middleware, context, invocation) {

@@ -61,14 +72,64 @@ return middleware.reverse().reduce((prev, cur) => new MiddlewareInvocation(cur, context, prev), invocation);

/* ------------------------------------------------------------------------------- */
/* --------------------------- REQUEST HANDLER ----------------------------------- */
/* -------------------------------- FACILITIES ----------------------------------- */
/* ------------------------------------------------------------------------------- */
async function requestHandler(ctx) {
const controllerMiddleware = router_1.extractDecorators(ctx.route);
const pipeline = pipe(controllerMiddleware, ctx, new ActionInvocation(ctx));
const result = await pipeline.proceed();
result.execute(ctx);
log(`[Request Handler] ${framework_1.b(ctx.path)} -> ${framework_1.b(ctx.route.controller.name)}.${framework_1.b(ctx.route.action.name)}`);
log(`[Request Handler] Request Query: ${framework_1.b(util_1.inspect(ctx.query, false, null))}`);
log(`[Request Handler] Request Header: ${framework_1.b(util_1.inspect(ctx.headers, false, null))}`);
log(`[Request Handler] Request Body: ${framework_1.b(util_1.inspect(result.body, false, null))}`);
/**
* Preset configuration for building web api. This facility contains:
*
* body parser: koa-bodyparser
*
* cors: @koa/cors
*/
class WebApiFacility extends core_1.DefaultFacility {
constructor(opt) {
super();
this.opt = opt;
}
setup(app) {
app.koa.use(async (ctx, next) => {
try {
await next();
}
catch (e) {
if (e instanceof core_1.ValidationError) {
ctx.body = e.issues;
ctx.status = e.status;
}
else if (e instanceof core_1.ConversionError) {
ctx.body = [e.issues];
ctx.status = e.status;
}
else if (e instanceof core_1.HttpStatusError)
ctx.throw(e.status, e);
else
ctx.throw(500, e);
}
});
app.koa.use(koa_bodyparser_1.default(this.opt && this.opt.bodyParser));
app.koa.use(cors_1.default(this.opt && this.opt.cors));
if (this.opt && this.opt.controller)
app.set({ controller: this.opt.controller });
if (this.opt && this.opt.validators)
app.set({ validators: this.opt.validators });
app.set({
validator: (value, meta, ctx, validators) => validator_1.validate(value, meta.decorators, [meta.name], ctx, validators)
});
}
}
exports.WebApiFacility = WebApiFacility;
/**
* Preset configuration for building restful style api. This facility contains:
*
* body parser: koa-bodyparser
*
* cors: @koa/cors
*
* default response status: { get: 200, post: 201, put: 204, delete: 204 }
*/
class RestfulApiFacility extends WebApiFacility {
setup(app) {
super.setup(app);
app.set({ responseStatus: { post: 201, put: 204, delete: 204 } });
}
}
exports.RestfulApiFacility = RestfulApiFacility;
/* ------------------------------------------------------------------------------- */

@@ -79,17 +140,12 @@ /* --------------------------- MAIN APPLICATION ---------------------------------- */

constructor() {
this.globalMiddleware = [];
this.koa = new koa_1.default();
this.config = {
mode: "debug",
middleware: [],
facilities: [],
controller: path_1.join(process.cwd(), "./controller"),
dependencyResolver: new framework_1.DefaultDependencyResolver()
};
this.config = Object.assign({}, core_1.DefaultConfiguration, { middleware: [], facilities: [] });
}
use(option) {
if (typeof option === "function") {
this.koa.use(option);
this.globalMiddleware.push(core_1.MiddlewareUtil.fromKoa(option));
}
else {
this.koa.use(framework_1.MiddlewareUtil.toKoa(option));
this.globalMiddleware.push(option);
}

@@ -99,4 +155,6 @@ return this;

set(config) {
if (framework_1.hasKeyOf(config, "setup"))
if (core_1.hasKeyOf(config, "setup")) {
config.setup(this);
this.config.facilities.push(config);
}
else

@@ -106,18 +164,44 @@ Object.assign(this.config, config);

}
createRoutes(executionPath) {
let routes = [];
if (typeof this.config.controller === "string") {
const path = path_1.isAbsolute(this.config.controller) ? this.config.controller :
path_1.join(executionPath, this.config.controller);
if (!fs_1.existsSync(path))
throw new Error(core_1.errorMessage.ControllerPathNotFound.format(path));
routes = core_1.routeGenerator.transformModule(path);
}
else if (Array.isArray(this.config.controller)) {
routes = this.config.controller.map(x => core_1.routeGenerator.transformController(x))
.flatten();
}
else {
routes = core_1.routeGenerator.transformController(this.config.controller);
}
return routes;
}
async initialize() {
try {
let routes = [];
if (typeof this.config.controller === "string") {
if (!fs_1.existsSync(this.config.controller))
throw new Error(framework_1.StringUtil.format(framework_1.errorMessage.ControllerPathNotFound, this.config.controller));
routes = await router_1.transformModule(this.config.controller);
if (process.env["NODE_ENV"] === "production")
Object.assign(this.config, { mode: "production" });
//get file location of script who initialized the application to calculate the controller path
//module.parent.parent.filename -> because Plumier app also exported in plumier/src/index.ts
let routes = this.createRoutes(path_1.dirname(module.parent.parent.filename));
for (const facility of this.config.facilities) {
await facility.initialize(this, routes);
}
else {
routes = this.config.controller.map(x => router_1.transformController(x))
.reduce((a, b) => a.concat(b), []);
}
if (this.config.mode === "debug")
router_1.printAnalysis(router_1.analyzeRoutes(routes));
await Promise.all(this.config.facilities.map(x => x.setup(this)));
this.koa.use(router_1.router(routes, this.config, requestHandler));
core_1.routeGenerator.printAnalysis(core_1.routeGenerator.analyzeRoutes(routes));
const decorators = {};
this.koa.use(router_1.router(routes, this.config, ctx => {
if (ctx.route && ctx.parameters) {
//execute global middleware and controller
const middleware = decorators[ctx.route.url] || (decorators[ctx.route.url] = this.globalMiddleware.concat(core_1.middleware.extractDecorators(ctx.route)));
return pipe(middleware, ctx, new ActionInvocation(ctx));
}
else {
//execute global middleware only
return pipe(this.globalMiddleware.slice(0), ctx, new NotFoundActionInvocation(ctx));
}
}));
return this.koa;

@@ -124,0 +208,0 @@ }

@@ -1,2 +0,5 @@

export { ActionResult, Application, bind, Configuration, DependencyResolver, Facility, HeaderPart, HttpMethod, HttpStatusError, Invocation, KoaMiddleware, middleware, Middleware, PlumierApplication, PlumierConfiguration, RequestPart, route, RouteInfo, TypeConverter, WebApiFacility } from "./framework";
export { Plumier } from "./application";
export { authorize, ActionResult, Application, bind, Configuration, Class, DependencyResolver, Facility, FileUploadInfo, FileParser, HeaderPart, HttpMethod, HttpStatusError, Invocation, KoaMiddleware, middleware, Middleware, domain, PlumierApplication, PlumierConfiguration, RequestPart, route, RouteInfo, ConversionError, ValidationError, ValidationIssue, ValidatorStore, ValidatorFunction, ValidatorId, DefaultFacility, converter, binder, routeGenerator, security, response } from "@plumier/core";
export { WebApiFacility, RestfulApiFacility } from "./application";
export { val } from "@plumier/validator";
import { Plumier } from "./application";
export default Plumier;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var framework_1 = require("./framework");
exports.ActionResult = framework_1.ActionResult;
exports.bind = framework_1.bind;
exports.HttpStatusError = framework_1.HttpStatusError;
exports.middleware = framework_1.middleware;
exports.route = framework_1.route;
exports.WebApiFacility = framework_1.WebApiFacility;
var core_1 = require("@plumier/core");
exports.authorize = core_1.authorize;
exports.ActionResult = core_1.ActionResult;
exports.bind = core_1.bind;
exports.HttpStatusError = core_1.HttpStatusError;
exports.middleware = core_1.middleware;
exports.domain = core_1.domain;
exports.route = core_1.route;
exports.ConversionError = core_1.ConversionError;
exports.ValidationError = core_1.ValidationError;
exports.ValidatorId = core_1.ValidatorId;
exports.DefaultFacility = core_1.DefaultFacility;
exports.converter = core_1.converter;
exports.binder = core_1.binder;
exports.routeGenerator = core_1.routeGenerator;
exports.security = core_1.security;
exports.response = core_1.response;
var application_1 = require("./application");
exports.Plumier = application_1.Plumier;
exports.WebApiFacility = application_1.WebApiFacility;
exports.RestfulApiFacility = application_1.RestfulApiFacility;
var validator_1 = require("@plumier/validator");
exports.val = validator_1.val;
const application_2 = require("./application");
exports.default = application_2.Plumier;

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

import { Configuration, Invocation, RouteInfo } from "@plumier/core";
import { Context } from "koa";
import { RouteInfo, Class, Configuration, Middleware } from "./framework";
import { ClassReflection } from "./libs/reflect";
interface Issue {
type: "error" | "warning" | "success";
message?: string;
}
interface TestResult {
route: RouteInfo;
issues: Issue[];
}
export declare function striveController(name: string): string;
export declare function getControllerRoute(controller: ClassReflection): string;
export declare function extractDecorators(route: RouteInfo): Middleware[];
export declare function transformController(object: ClassReflection | Class): RouteInfo[];
export declare function transformModule(path: string): Promise<RouteInfo[]>;
export declare function router(infos: RouteInfo[], config: Configuration, handler: (ctx: Context) => Promise<void>): (ctx: Context, next: () => Promise<void>) => Promise<void>;
export declare function analyzeRoutes(routes: RouteInfo[]): TestResult[];
export declare function printAnalysis(results: TestResult[]): void;
export {};
export declare function router(infos: RouteInfo[], config: Configuration, handler: (ctx: Context) => Invocation): (ctx: Context, next: () => Promise<void>) => Promise<void>;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const debug_1 = tslib_1.__importDefault(require("debug"));
const Fs = tslib_1.__importStar(require("fs"));
const Path = tslib_1.__importStar(require("path"));
const core_1 = require("@plumier/core");
const path_to_regexp_1 = tslib_1.__importDefault(require("path-to-regexp"));
const framework_1 = require("./framework");
const reflect_1 = require("./libs/reflect");
const util_1 = require("util");
const chalk_1 = tslib_1.__importDefault(require("chalk"));
const log = debug_1.default("plum:router");
/* ------------------------------------------------------------------------------- */
/* ------------------------------- HELPERS --------------------------------------- */
/* ------------------------------------------------------------------------------- */
function striveController(name) {
return name.substring(0, name.lastIndexOf("Controller")).toLowerCase();
}
exports.striveController = striveController;
function getControllerRoute(controller) {
const root = controller.decorators.find((x) => x.name == "Root");
return (root && root.url) || `/${striveController(controller.name)}`;
}
exports.getControllerRoute = getControllerRoute;
function extractDecorators(route) {
const classDecorator = route.controller.decorators.filter(x => x.name == "Middleware");
const methodDecorator = route.action.decorators.filter(x => x.name == "Middleware");
const extract = (d) => d.map(x => x.value).reduce((a, b) => a.concat(b), []);
return extract(classDecorator)
.concat(extract(methodDecorator))
.reverse();
}
exports.extractDecorators = extractDecorators;
function getActionName(route) {
return `${route.controller.name}.${route.action.name}(${route.action.parameters.map(x => x.name).join(", ")})`;
}
function resolvePath(path) {
//resolve provided path directory or file
if (Fs.lstatSync(path).isDirectory())
return Fs.readdirSync(path)
//take only *.js
.filter(x => Path.extname(x) === ".js")
//add root path + file name
.map(x => Path.join(path, x));
else
return [path];
}
/* ------------------------------------------------------------------------------- */
/* ---------------------------------- TRANSFORMER -------------------------------- */
/* ------------------------------------------------------------------------------- */
function transformRouteDecorator(controller, method) {
if (method.decorators.some((x) => x.name == "Ignore"))
return;
const root = getControllerRoute(controller);
const decorator = method.decorators.find((x) => x.name == "Route");
const result = { action: method, method: decorator.method, controller: controller };
//absolute route
if (decorator.url && decorator.url.startsWith("/"))
return Object.assign({}, result, { url: decorator.url });
//empty string
else if (decorator.url === "")
return Object.assign({}, result, { url: root });
//relative route
else {
const actionUrl = decorator.url || method.name.toLowerCase();
return Object.assign({}, result, { url: [root, actionUrl].join("/") });
}
}
function transformRegular(controller, method) {
return {
method: "get",
url: `${getControllerRoute(controller)}/${method.name.toLowerCase()}`,
action: method,
controller: controller,
};
}
function transformController(object) {
const controller = typeof object === "function" ? reflect_1.reflect(object) : object;
if (!controller.name.toLowerCase().endsWith("controller"))
return [];
return controller.methods.map(method => {
//first priority is decorator
if (method.decorators.some((x) => x.name == "Ignore" || x.name == "Route"))
return transformRouteDecorator(controller, method);
else
return transformRegular(controller, method);
})
//ignore undefined
.filter(x => Boolean(x));
}
exports.transformController = transformController;
async function transformModule(path) {
//read all files and get module reflection
const modules = await Promise.all(resolvePath(path)
//reflect the file
.map(x => reflect_1.reflect(x)));
//get all module.members and combine into one array
return modules.reduce((a, b) => a.concat(b.members), [])
//take only the controller class
.filter(x => x.type === "Class" && x.name.toLowerCase().endsWith("controller"))
//traverse and change into route
.map(x => transformController(x))
//flatten the result
.reduce((a, b) => a.concat(b), []);
}
exports.transformModule = transformModule;
/* ------------------------------------------------------------------------------- */
/* ------------------------------- ROUTER ---------------------------------------- */
/* ------------------------------------------------------------------------------- */
function checkUrlMatch(route, ctx) {
function toRegExp(route, path) {
const keys = [];
const regexp = path_to_regexp_1.default(route.url, keys);
const match = regexp.exec(ctx.path);
return { keys, match, method: route.method.toUpperCase(), route };
const match = regexp.exec(path);
const query = !match ? {} : keys.reduce((a, b, i) => {
a[b.name] = match[i + 1];
return a;
}, {});
return { match, query, method: route.method.toUpperCase(), route };
}
function router(infos, config, handler) {
const matchers = {};
const getMatcher = (path, method) => infos.map(x => toRegExp(x, path)).find(x => Boolean(x.match) && x.method == method);
return async (ctx, next) => {
const match = infos.map(x => checkUrlMatch(x, ctx))
.find(x => Boolean(x.match) && x.method == ctx.method);
const key = `${ctx.method}${ctx.path}`;
const match = matchers[key] || (matchers[key] = getMatcher(ctx.path, ctx.method));
ctx.config = config;
if (match) {
log(`[Router] Match route ${framework_1.b(match.route.method)} ${framework_1.b(match.route.url)} with ${framework_1.b(ctx.method)} ${framework_1.b(ctx.path)}`);
//assign config and route to context
Object.assign(ctx, { config, route: match.route });
//add query
const query = match.keys.reduce((a, b, i) => {
a[b.name.toString().toLowerCase()] = match.match[i + 1];
return a;
}, {});
log(`[Router] Extracted parameter from url ${framework_1.b(util_1.inspect(query, false, null))}`);
Object.assign(ctx.query, query);
await handler(ctx);
Object.assign(ctx.request.query, match.query);
const parameters = core_1.binder.bindParameter(ctx, match.route.action, config.converters);
ctx.route = match.route;
ctx.parameters = parameters;
}
else {
log(`[Router] Not route match ${framework_1.b(ctx.method)} ${framework_1.b(ctx.url)}`);
await next();
}
const invocation = handler(ctx);
const result = await invocation.proceed();
await result.execute(ctx);
};
}
exports.router = router;
/* ------------------------------------------------------------------------------- */
/* --------------------------- ANALYZER FUNCTION --------------------------------- */
/* ------------------------------------------------------------------------------- */
function backingParameterTest(route, allRoutes) {
const ids = route.url.split("/")
.filter(x => x.startsWith(":"))
.map(x => x.substring(1));
const missing = ids.filter(id => route.action.parameters.map(x => x.name).indexOf(id) === -1);
if (missing.length > 0) {
return {
type: "error",
message: framework_1.StringUtil.format(framework_1.errorMessage.RouteDoesNotHaveBackingParam, missing.join(", "))
};
}
else
return { type: "success" };
}
function metadataTypeTest(route, allRoutes) {
const hasTypeInfo = route.action
.parameters.some(x => Boolean(x.typeAnnotation));
if (!hasTypeInfo) {
return {
type: "warning",
message: framework_1.errorMessage.ActionDoesNotHaveTypeInfo
};
}
else
return { type: "success" };
}
function multipleDecoratorTest(route, allRoutes) {
const decorator = route.action.decorators.filter(x => x.name == "Route");
if (decorator.length > 1) {
return {
type: "error",
message: framework_1.errorMessage.MultipleDecoratorNotSupported
};
}
else
return { type: "success" };
}
function duplicateRouteTest(route, allRoutes) {
const dup = allRoutes.filter(x => x.url == route.url && x.method == route.method);
if (dup.length > 1) {
return {
type: "error",
message: framework_1.StringUtil.format(framework_1.errorMessage.DuplicateRouteFound, dup.map(x => getActionName(x)).join(" "))
};
}
else
return { type: "success" };
}
/* ------------------------------------------------------------------------------- */
/* -------------------------------- ANALYZER ------------------------------------- */
/* ------------------------------------------------------------------------------- */
function analyzeRoute(route, tests, allRoutes) {
const issues = tests.map(test => test(route, allRoutes))
.filter(x => x.type != "success");
return { route, issues };
}
function analyzeRoutes(routes) {
const tests = [
backingParameterTest, metadataTypeTest, multipleDecoratorTest,
duplicateRouteTest
];
return routes.map(x => analyzeRoute(x, tests, routes));
}
exports.analyzeRoutes = analyzeRoutes;
function printAnalysis(results) {
const data = results.map(x => {
const method = framework_1.StringUtil.padRight(x.route.method.toUpperCase(), 5);
const action = getActionName(x.route);
const issues = x.issues.map(issue => ` - ${issue.type} ${issue.message}`);
return { method, url: x.route.url, action, issues };
});
data.forEach((x, i) => {
const action = framework_1.StringUtil.padRight(x.action, Math.max(...data.map(x => x.action.length)));
const method = framework_1.StringUtil.padRight(x.method, Math.max(...data.map(x => x.method.length)));
const url = framework_1.StringUtil.padRight(x.url, Math.max(...data.map(x => x.url.length)));
const issueColor = (issue) => issue.startsWith(" - warning") ? chalk_1.default.yellow(issue) : chalk_1.default.red(issue);
const color = x.issues.length == 0 ? (x) => x :
x.issues.some(x => x.startsWith(" - warning")) ? chalk_1.default.yellow : chalk_1.default.red;
console.log(color(`${i + 1}. ${action} -> ${method} ${url}`));
x.issues.forEach(issue => console.log(issueColor(issue)));
});
}
exports.printAnalysis = printAnalysis;
{
"name": "plumier",
"version": "0.1.0-alpha.d43b984e",
"description": "A testing friendly Web API framework",
"version": "1.0.0-alpha.5+5f97250",
"description": "Delightful Node.js Rest API Framework powered by Koa and TypeScript",
"main": "lib/index.js",

@@ -9,3 +9,3 @@ "types": "lib/index.d.ts",

"MVC",
"Express",
"Koa",
"IoC",

@@ -18,29 +18,64 @@ "Dependency Injection",

"scripts": {
"compile": "tsc -p tsconfig.build.json"
"compile": "tsc -p tsconfig.build.json",
"benchmark": "ts-node test/benchmark/run"
},
"author": "Ketut Sandiarsa",
"license": "ISC",
"license": "MIT",
"dependencies": {
"@koa/cors": "^2.2.1",
"@types/chalk": "^2.2.0",
"@types/debug": "^0.0.30",
"@types/koa": "^2.0.46",
"@koa/cors": "^3.0.0",
"@plumier/core": "1.0.0-alpha.5+5f97250",
"@plumier/validator": "1.0.0-alpha.5+5f97250",
"@types/glob": "^7.1.1",
"@types/koa": "^2.0.48",
"@types/koa-bodyparser": "^5.0.0",
"@types/koa__cors": "^2.2.2",
"chalk": "^2.4.1",
"debug": "^3.1.0",
"koa": "^2.5.1",
"@types/koa__cors": "^2.2.3",
"@types/validator": "^10.9.0",
"chalk": "^2.4.2",
"glob": "^7.1.3",
"koa": "^2.7.0",
"koa-bodyparser": "^4.2.1",
"path-to-regexp": "^2.2.1",
"tslib": "^1.9.2"
"path-to-regexp": "^3.0.0",
"tinspector": "^2.2.0",
"tslib": "^1.9.3"
},
"peerDependencies": {
"reflect-metadata": "^0.1.12"
},
"devDependencies": {
"@types/supertest": "^2.0.4",
"@plumier/jwt": "1.0.0-alpha.5+5f97250",
"@plumier/multipart": "1.0.0-alpha.5+5f97250",
"@plumier/serve-static": "1.0.0-alpha.5+5f97250",
"@types/body-parser": "^1.17.0",
"@types/cors": "^2.8.4",
"@types/express": "^4.16.1",
"@types/express-jwt": "^0.0.42",
"@types/fs-extra": "^5.0.5",
"@types/joi": "^14.3.1",
"@types/jsonwebtoken": "^8.3.0",
"@types/koa-router": "^7.0.39",
"@types/rimraf": "^2.0.2",
"@types/supertest": "^2.0.7",
"autocannon": "^3.2.0",
"benalu": "^2.0.0-beta-1",
"supertest": "^3.1.0",
"typescript": "^2.9.2"
}
"body-parser": "^1.18.3",
"cors": "^2.8.5",
"express": "^4.16.4",
"express-jwt": "^5.3.1",
"fs-extra": "^7.0.1",
"joi": "^14.3.1",
"jsonwebtoken": "^8.4.0",
"koa-router": "^7.4.0",
"rimraf": "^2.6.3",
"supertest": "^4.0.0",
"ts-node": "^8.0.2",
"typescript": "^3.3.3333"
},
"bugs": {
"url": "https://github.com/plumier/plumier/issues"
},
"repository": {
"url": "https://github.com/plumier/plumier"
},
"homepage": "https://plumierjs.com",
"publishConfig": {
"access": "public"
},
"gitHead": "5f97250cf3b0e9378c65d0dcd14b1a7642402643"
}
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