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

@plumier/core

Package Overview
Dependencies
Maintainers
1
Versions
645
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@plumier/core - npm Package Compare versions

Comparing version 1.0.0-dev11.14 to 1.0.0-dev11.15

lib/application-pipeline.d.ts

23

lib/authorization.d.ts

@@ -1,6 +0,6 @@

import { ActionResult, Invocation, Middleware, RouteInfo, AuthorizeMetadataInfo } from "./types";
declare type AuthorizeCallback = (info: AuthorizeMetadataInfo, location: "Class" | "Parameter" | "Method") => boolean | Promise<boolean>;
import { AuthorizationContext, ActionContext, RouteInfo, Configuration } from "./types";
declare type AuthorizerFunction = (info: AuthorizationContext, location: "Class" | "Parameter" | "Method") => boolean | Promise<boolean>;
interface AuthorizeDecorator {
type: "plumier-meta:authorize";
authorize: string | AuthorizeCallback | Authorizer;
authorize: string | AuthorizerFunction | Authorizer;
tag: string;

@@ -10,15 +10,8 @@ location: "Class" | "Parameter" | "Method";

interface Authorizer {
authorize(info: AuthorizeMetadataInfo, location: "Class" | "Parameter" | "Method"): boolean | Promise<boolean>;
authorize(info: AuthorizationContext, location: "Class" | "Parameter" | "Method"): boolean | Promise<boolean>;
}
declare type RoleField = string | ((value: any) => Promise<string[]>);
declare function updateRouteAccess(routes: RouteInfo[], globals?: (...args: any[]) => void): void;
declare class AuthorizeMiddleware implements Middleware {
private roleField;
private global?;
constructor(roleField: RoleField, global?: ((...args: any[]) => void) | undefined);
private getRole;
private checkUserAccessToRoute;
private checkUserAccessToParameters;
execute(invocation: Readonly<Invocation>): Promise<ActionResult>;
}
export { AuthorizeCallback, RoleField, Authorizer, updateRouteAccess, AuthorizeMiddleware, AuthorizeDecorator };
declare function getAuthorizeDecorators(info: RouteInfo, globalDecorator?: (...args: any[]) => void): AuthorizeDecorator[];
declare function updateRouteAuthorizationAccess(routes: RouteInfo[], config: Configuration): void;
declare function checkAuthorize(ctx: ActionContext): Promise<void>;
export { AuthorizerFunction, RoleField, Authorizer, checkAuthorize, AuthorizeDecorator, getAuthorizeDecorators, updateRouteAuthorizationAccess };

@@ -47,2 +47,3 @@ "use strict";

}
exports.getAuthorizeDecorators = getAuthorizeDecorators;
async function checkParameter(path, meta, value, info) {

@@ -84,61 +85,55 @@ if (value === undefined)

}
async function checkUserAccessToRoute(decorators, info) {
if (decorators.some(x => x.tag === "Public"))
return;
if (info.role.length === 0)
throw new types_1.HttpStatusError(http_status_1.HttpStatus.Forbidden, "Forbidden");
const conditions = await Promise.all(decorators.map(x => executeDecorator(x, info)));
//use OR condition
//if ALL condition doesn't authorize user then throw
if (conditions.length > 0 && conditions.every(x => x === false))
throw new types_1.HttpStatusError(http_status_1.HttpStatus.Unauthorized, "Unauthorized");
}
async function checkUserAccessToParameters(meta, values, info) {
const unauthorizedPaths = await checkParameters([], meta, values, info);
if (unauthorizedPaths.length > 0)
throw new types_1.HttpStatusError(401, `Unauthorized to populate parameter paths (${unauthorizedPaths.join(", ")})`);
}
async function getRole(user, roleField) {
if (!user)
return [];
if (typeof roleField === "function")
return await roleField(user);
else {
const role = user[roleField];
return Array.isArray(role) ? role : [role];
}
}
/* ------------------------------------------------------------------------------- */
/* --------------------------- MAIN IMPLEMENTATION ------------------------------- */
/* ------------------------------------------------------------------------------- */
function updateRouteAccess(routes, globals) {
routes.forEach(x => {
const decorators = getAuthorizeDecorators(x, globals);
if (decorators.length > 0)
x.access = decorators.map(x => x.tag).join("|");
else
x.access = "Authenticated";
});
function updateRouteAuthorizationAccess(routes, config) {
if (config.enableAuthorization) {
routes.forEach(x => {
const decorators = getAuthorizeDecorators(x, config.globalAuthorizationDecorators);
if (decorators.length > 0)
x.access = decorators.map(x => x.tag).join("|");
else
x.access = "Authenticated";
});
}
}
exports.updateRouteAccess = updateRouteAccess;
class AuthorizeMiddleware {
constructor(roleField, global) {
this.roleField = roleField;
this.global = global;
}
async getRole(user) {
if (!user)
return [];
if (typeof this.roleField === "function")
return await this.roleField(user);
else {
const role = user[this.roleField];
return Array.isArray(role) ? role : [role];
}
}
async checkUserAccessToRoute(decorators, info) {
if (decorators.some(x => x.tag === "Public"))
return;
if (info.role.length === 0)
throw new types_1.HttpStatusError(http_status_1.HttpStatus.Forbidden, "Forbidden");
const conditions = await Promise.all(decorators.map(x => executeDecorator(x, info)));
//use OR condition
//if ALL condition doesn't authorize user then throw
if (conditions.length > 0 && conditions.every(x => x === false))
throw new types_1.HttpStatusError(http_status_1.HttpStatus.Unauthorized, "Unauthorized");
}
async checkUserAccessToParameters(meta, values, info) {
const unauthorizedPaths = await checkParameters([], meta, values, info);
if (unauthorizedPaths.length > 0)
throw new types_1.HttpStatusError(401, `Unauthorized to populate parameter paths (${unauthorizedPaths.join(", ")})`);
}
async execute(invocation) {
if (!invocation.context.route)
return invocation.proceed();
const { route, parameters, state } = invocation.context;
const decorator = getAuthorizeDecorators(invocation.context.route, this.global);
const userRoles = await this.getRole(invocation.context.state.user);
const info = { role: userRoles, parameters, user: state.user, route, ctx: invocation.context };
exports.updateRouteAuthorizationAccess = updateRouteAuthorizationAccess;
async function checkAuthorize(ctx) {
if (ctx.config.enableAuthorization) {
const { route, parameters, state, config } = ctx;
const decorator = getAuthorizeDecorators(route, config.globalAuthorizationDecorators);
const userRoles = await getRole(state.user, config.roleField);
const info = { role: userRoles, user: state.user, route, ctx };
//check user access
await this.checkUserAccessToRoute(decorator, info);
await checkUserAccessToRoute(decorator, info);
//if ok check parameter access
await this.checkUserAccessToParameters(invocation.context.route.action.parameters, invocation.context.parameters, info);
//if all above passed then proceed
return invocation.proceed();
await checkUserAccessToParameters(route.action.parameters, parameters, info);
}
}
exports.AuthorizeMiddleware = AuthorizeMiddleware;
exports.checkAuthorize = checkAuthorize;
/// <reference types="node" />
import { IncomingHttpHeaders } from "http";
import { Context, Request } from "koa";
import { ParameterReflection } from "tinspector";
interface BindingDecorator {

@@ -17,3 +16,3 @@ type: "ParameterBinding";

}
declare const binder: (ctx: Context, par: ParameterReflection) => any;
declare function binder(ctx: Context): any[];
export { RequestPart, HeaderPart, BindingDecorator, binder };

@@ -27,3 +27,6 @@ "use strict";

}
const binder = chain(bindDecorator, bindByName, bindBody);
const binderChain = chain(bindDecorator, bindByName, bindBody);
function binder(ctx) {
return ctx.route.action.parameters.map(x => binderChain(ctx, x));
}
exports.binder = binder;

@@ -18,2 +18,2 @@ declare type Class = new (...args: any[]) => any;

declare function findFilesRecursive(path: string): string[];
export { getChildValue, Class, hasKeyOf, isCustomClass, consoleLog, findFilesRecursive, };
export { getChildValue, Class, hasKeyOf, isCustomClass, consoleLog, findFilesRecursive };

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

import { AuthorizeCallback, Authorizer } from "./authorization";
import { AuthorizerFunction, Authorizer } from "./authorization";
declare class AuthDecoratorImpl {
custom(callback: AuthorizeCallback, tag?: string): (...args: any[]) => void;
custom(callback: AuthorizerFunction, tag?: string): (...args: any[]) => void;
custom(authorizer: Authorizer, tag?: string): (...args: any[]) => void;

@@ -5,0 +5,0 @@ custom(id: string, tag?: string): (...args: any[]) => void;

import { val } from "typedconverter";
export { val };
export { AuthorizeCallback, AuthorizeMiddleware, RoleField, updateRouteAccess, Authorizer } from "./authorization";
export { AuthorizerFunction, checkAuthorize, RoleField, Authorizer } from "./authorization";
export { HeaderPart, RequestPart, BindingDecorator, binder } from "./binder";
export { invoke } from "./middleware-pipeline";
export { invoke } from "./application-pipeline";
export { response } from "./response";
export { analyzeRoutes, generateRoutes, printAnalysis } from "./route-generator";
export { generateRoutes } from "./route-generator";
export { analyzeRoutes, printAnalysis } from "./route-analyzer";
export { router } from "./router";
export { ValidationMiddleware } from "./validator";
export { Class, consoleLog, findFilesRecursive, getChildValue, hasKeyOf, isCustomClass } from "./common";

@@ -16,2 +16,2 @@ export { AuthDecoratorImpl, authorize } from "./decorator.authorize";

export { HttpStatus } from "./http-status";
export { ActionResult, Application, AuthorizeMetadataInfo, Configuration, DefaultFacility, CustomValidator, DependencyResolver, Facility, FileParser, FileUploadInfo, HttpMethod, HttpStatusError, Invocation, KoaMiddleware, Middleware, MiddlewareFunction, MiddlewareDecorator, MiddlewareUtil, PlumierApplication, PlumierConfiguration, RedirectActionResult, RouteContext, RouteInfo, RouteAnalyzerFunction, RouteAnalyzerIssue, ValidatorDecorator, ValidatorFunction, ValidatorInfo, ValidationError, errorMessage, AsyncValidatorResult, DefaultDependencyResolver } from "./types";
export { ActionResult, Application, AuthorizationContext as AuthorizationContext, Configuration, DefaultFacility, CustomValidator, DependencyResolver, Facility, FileParser, FileUploadInfo, HttpMethod, HttpStatusError, Invocation, KoaMiddleware, Middleware, MiddlewareFunction, MiddlewareDecorator, MiddlewareUtil, PlumierApplication, PlumierConfiguration, RedirectActionResult, ActionContext, RouteInfo, RouteAnalyzerFunction, RouteAnalyzerIssue, ValidatorDecorator, CustomValidatorFunction as CustomValidatorFunction, ValidatorContext, ValidationError, errorMessage, AsyncValidatorResult, DefaultDependencyResolver } from "./types";

@@ -6,18 +6,16 @@ "use strict";

var authorization_1 = require("./authorization");
exports.AuthorizeMiddleware = authorization_1.AuthorizeMiddleware;
exports.updateRouteAccess = authorization_1.updateRouteAccess;
exports.checkAuthorize = authorization_1.checkAuthorize;
var binder_1 = require("./binder");
exports.binder = binder_1.binder;
var middleware_pipeline_1 = require("./middleware-pipeline");
exports.invoke = middleware_pipeline_1.invoke;
var application_pipeline_1 = require("./application-pipeline");
exports.invoke = application_pipeline_1.invoke;
var response_1 = require("./response");
exports.response = response_1.response;
var route_generator_1 = require("./route-generator");
exports.analyzeRoutes = route_generator_1.analyzeRoutes;
exports.generateRoutes = route_generator_1.generateRoutes;
exports.printAnalysis = route_generator_1.printAnalysis;
var route_analyzer_1 = require("./route-analyzer");
exports.analyzeRoutes = route_analyzer_1.analyzeRoutes;
exports.printAnalysis = route_analyzer_1.printAnalysis;
var router_1 = require("./router");
exports.router = router_1.router;
var validator_1 = require("./validator");
exports.ValidationMiddleware = validator_1.ValidationMiddleware;
var common_1 = require("./common");

@@ -24,0 +22,0 @@ exports.consoleLog = common_1.consoleLog;

import { Class } from "./common";
import { HttpMethod, RouteInfo, RouteAnalyzerIssue, RouteAnalyzerFunction } from "./types";
import { HttpMethod, RouteInfo } from "./types";
interface RouteDecorator {

@@ -15,9 +15,3 @@ name: "Route";

}
interface TestResult {
route: RouteInfo;
issues: RouteAnalyzerIssue[];
}
declare function generateRoutes(executionPath: string, controller: string | Class[] | Class): RouteInfo[];
declare function analyzeRoutes(routes: RouteInfo[], extensions?: RouteAnalyzerFunction[]): TestResult[];
declare function printAnalysis(results: TestResult[]): void;
export { analyzeRoutes, generateRoutes, printAnalysis, RouteDecorator, IgnoreDecorator, RootDecorator };
export { generateRoutes, RouteDecorator, IgnoreDecorator, RootDecorator };
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const chalk_1 = tslib_1.__importDefault(require("chalk"));
const fs_1 = require("fs");

@@ -34,5 +32,2 @@ const path_1 = require("path");

}
function getActionName(route) {
return `${route.controller.name}.${route.action.name}(${route.action.parameters.map(x => x.name).join(", ")})`;
}
function getRoot(rootPath, path) {

@@ -125,143 +120,1 @@ const part = path.slice(rootPath.length).split("/").filter(x => !!x)

exports.generateRoutes = generateRoutes;
/* ------------------------------------------------------------------------------- */
/* --------------------------- ANALYZER FUNCTION --------------------------------- */
/* ------------------------------------------------------------------------------- */
//------ Analyzer Helpers
function getModelsInParameters(par) {
return par
.map((x, i) => ({ type: x.type, index: i }))
.filter(x => x.type && common_1.isCustomClass(x.type))
.map(x => ({ meta: tinspector_1.reflect((Array.isArray(x.type) ? x.type[0] : x.type)), index: x.index }));
}
function traverseModel(par) {
const models = getModelsInParameters(par).map(x => x.meta);
const child = models.map(x => traverseModel(x.properties))
.filter((x) => Boolean(x))
.reduce((a, b) => a.concat(b), []);
return models.concat(child);
}
function traverseArray(parent, par) {
const models = getModelsInParameters(par);
if (models.length > 0) {
return models.map((x, i) => traverseArray(x.meta.name, x.meta.properties))
.flatten();
}
return par.filter(x => x.type === Array)
.map(x => `${parent}.${x.name}`);
}
function backingParameterTest(route, allRoutes) {
const ids = route.url.split("/")
.filter(x => x.startsWith(":"))
.map(x => x.substring(1).toLowerCase());
const missing = ids.filter(id => route.action.parameters.map(x => x.name.toLowerCase()).indexOf(id) === -1);
if (missing.length > 0) {
return {
type: "error",
message: types_1.errorMessage.RouteDoesNotHaveBackingParam.format(missing.join(", "))
};
}
else
return { type: "success" };
}
function metadataTypeTest(route, allRoutes) {
const hasTypeInfo = route.action
.parameters.some(x => Boolean(x.type));
if (!hasTypeInfo && route.action.parameters.length > 0) {
return {
type: "warning",
message: types_1.errorMessage.ActionDoesNotHaveTypeInfo
};
}
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: types_1.errorMessage.DuplicateRouteFound.format(dup.map(x => getActionName(x)).join(" "))
};
}
else
return { type: "success" };
}
function modelTypeInfoTest(route, allRoutes) {
const classes = traverseModel(route.action.parameters)
.filter(x => x.properties.every(par => typeof par.type == "undefined"))
.map(x => x.type);
//get only unique type
const noTypeInfo = Array.from(new Set(classes));
if (noTypeInfo.length > 0) {
return {
type: "warning",
message: types_1.errorMessage.ModelWithoutTypeInformation.format(noTypeInfo.map(x => x.name).join(", "))
};
}
else
return { type: "success" };
}
function arrayTypeInfoTest(route, allRoutes) {
const issues = traverseArray(`${route.controller.name}.${route.action.name}`, route.action.parameters);
const array = Array.from(new Set(issues));
if (array.length > 0) {
return {
type: "warning",
message: types_1.errorMessage.ArrayWithoutTypeInformation.format(array.join(", "))
};
}
else
return { type: 'success' };
}
/* ------------------------------------------------------------------------------- */
/* -------------------------------- ANALYZER ------------------------------------- */
/* ------------------------------------------------------------------------------- */
function analyzeRoute(route, tests, allRoutes) {
const issues = tests.map(test => {
return test(route, allRoutes);
})
.filter(x => x.type != "success");
return { route, issues };
}
function analyzeRoutes(routes, extensions = []) {
const tests = [
backingParameterTest, metadataTypeTest,
duplicateRouteTest, modelTypeInfoTest,
arrayTypeInfoTest
];
return routes.map(x => analyzeRoute(x, tests.concat(extensions), routes));
}
exports.analyzeRoutes = analyzeRoutes;
function printAnalysis(results) {
const data = results.map(x => {
const method = x.route.method.toUpperCase();
const action = getActionName(x.route);
const issues = x.issues.map(issue => ` - ${issue.type} ${issue.message}`);
return { method, url: x.route.url, action, issues, access: x.route.access };
});
console.log();
console.log("Route Analysis Report");
if (data.length == 0)
console.log("No controller found");
const paddings = {
number: data.length.toString().length,
action: Math.max(...data.map(x => x.action.length)),
method: Math.max(...data.map(x => x.method.length)),
access: Math.max(...data.map(x => x.access && x.access.length || 0)),
};
data.forEach((x, i) => {
const num = (i + 1).toString().padStart(paddings.number);
const action = x.action.padEnd(paddings.action);
const method = x.method.padEnd(paddings.method);
const access = x.access && (" " + x.access.padEnd(paddings.access)) || "";
const color = x.issues.length === 0 ? (x) => x : x.issues.some(x => x.startsWith(" - error")) ? chalk_1.default.red : chalk_1.default.yellow;
console.log(color(`${num}. ${action} ->${access} ${method} ${x.url}`));
x.issues.forEach(x => {
const color = x.startsWith(" - warning") ? chalk_1.default.yellow : chalk_1.default.red;
console.log(color(x));
});
});
if (data.length > 0)
console.log();
}
exports.printAnalysis = printAnalysis;

@@ -5,3 +5,3 @@ "use strict";

const tinspector_1 = require("tinspector");
const middleware_pipeline_1 = require("./middleware-pipeline");
const application_pipeline_1 = require("./application-pipeline");
const types_1 = require("./types");

@@ -46,3 +46,3 @@ // --------------------------------------------------------------------- //

}
const result = await middleware_pipeline_1.pipe(ctx, ctx.route);
const result = await application_pipeline_1.pipe(ctx);
await result.execute(ctx);

@@ -49,0 +49,0 @@ }

@@ -7,2 +7,3 @@ import Koa, { Context } from "koa";

import { SetOption } from 'cookies';
import { RoleField } from './authorization';
export declare class ActionResult {

@@ -47,3 +48,3 @@ body?: any;

export interface Invocation {
context: Readonly<Context>;
ctx: Readonly<Context>;
proceed(): Promise<ActionResult>;

@@ -56,3 +57,2 @@ }

config: Readonly<Configuration>;
parameters?: any[];
}

@@ -63,3 +63,3 @@ interface DefaultState {

}
export interface RouteContext extends Context {
export interface ActionContext extends Context {
route: Readonly<RouteInfo>;

@@ -151,7 +151,7 @@ parameters: any[];

type: "ValidatorDecorator";
validator: ValidatorFunction | string | symbol;
validator: CustomValidatorFunction | string | symbol;
}
export interface ValidatorInfo {
export interface ValidatorContext {
name: string;
ctx: RouteContext;
ctx: ActionContext;
parent?: {

@@ -167,11 +167,11 @@ value: any;

}
export declare type ValidatorFunction = (value: any, info: ValidatorInfo) => undefined | string | AsyncValidatorResult[] | Promise<AsyncValidatorResult[] | string | undefined>;
export declare type CustomValidatorFunction = (value: any, info: ValidatorContext) => undefined | string | AsyncValidatorResult[] | Promise<AsyncValidatorResult[] | string | undefined>;
export interface CustomValidator {
validate(value: any, info: ValidatorInfo): undefined | string | AsyncValidatorResult[] | Promise<AsyncValidatorResult[] | string | undefined>;
validate(value: any, info: ValidatorContext): undefined | string | AsyncValidatorResult[] | Promise<AsyncValidatorResult[] | string | undefined>;
}
export interface AuthorizeMetadataInfo {
export interface AuthorizationContext {
value?: any;
role: string[];
user: any;
ctx: RouteContext;
ctx: ActionContext;
}

@@ -220,2 +220,14 @@ export interface FileUploadInfo {

analyzers?: RouteAnalyzerFunction[];
/**
* Role field / function used to specify current login user role inside JWT claim for authorization
*/
roleField: RoleField;
/**
* Global authorization decorators, use mergeDecorator for multiple
*/
globalAuthorizationDecorators?: (...args: any[]) => void;
/**
* Enable/disable authorization, when enabled all routes will be private by default. Default false
*/
enableAuthorization: boolean;
}

@@ -222,0 +234,0 @@ export interface PlumierConfiguration extends Configuration {

@@ -67,7 +67,7 @@ "use strict";

execute: async (x) => {
await middleware(x.context, async () => {
await middleware(x.ctx, async () => {
const nextResult = await x.proceed();
await nextResult.execute(x.context);
await nextResult.execute(x.ctx);
});
return ActionResult.fromContext(x.context);
return ActionResult.fromContext(x.ctx);
}

@@ -74,0 +74,0 @@ };

@@ -1,16 +0,12 @@

import { ActionResult, AsyncValidatorResult, Invocation, Middleware, ValidatorFunction, CustomValidator } from "./types";
import { AsyncValidatorResult, CustomValidator, ActionContext, CustomValidatorFunction } from "./types";
declare module "typedconverter" {
namespace val {
function custom(validator: ValidatorFunction): (...arg: any[]) => void;
function custom(validator: CustomValidatorFunction): (...arg: any[]) => void;
function custom(validator: CustomValidator): (...arg: any[]) => void;
function custom(id: string): (...arg: any[]) => void;
function custom(id: symbol): (...arg: any[]) => void;
function custom(val: ValidatorFunction | string | symbol | CustomValidator): (...arg: any[]) => void;
function result(path: string, messages: string | string[]): AsyncValidatorResult[];
}
}
declare class ValidationMiddleware implements Middleware {
constructor();
execute(invocation: Readonly<Invocation>): Promise<ActionResult>;
}
export { ValidationMiddleware };
declare function validate(ctx: ActionContext): Promise<any[]>;
export { validate };

@@ -6,3 +6,2 @@ "use strict";

const tc = tslib_1.__importStar(require("typedconverter"));
const binder_1 = require("./binder");
const common_1 = require("./common");

@@ -65,4 +64,4 @@ const types_1 = require("./types");

//sync validations
for (const parMeta of ctx.route.action.parameters) {
const rawParameter = binder_1.binder(ctx, parMeta);
for (const [index, parMeta] of ctx.route.action.parameters.entries()) {
const rawParameter = ctx.parameters[index];
const parValue = tc.validate(rawParameter, {

@@ -87,21 +86,6 @@ decorators: parMeta.decorators, path: parMeta.name, type: parMeta.type || Object,

}
return (issues.length > 0) ? { issues, value: undefined } : { value: result };
if (issues.length > 0)
throw new types_1.ValidationError(issues.map(x => ({ path: x.path.split("."), messages: x.messages })));
return result;
}
// --------------------------------------------------------------------- //
// ----------------------------- MIDDLEWARE ---------------------------- //
// --------------------------------------------------------------------- //
class ValidationMiddleware {
constructor() { }
async execute(invocation) {
const ctx = invocation.context;
if (!ctx.route)
return invocation.proceed();
const result = await validate(invocation.context);
if (result.issues)
throw new types_1.ValidationError(result.issues
.map(x => ({ path: x.path.split("."), messages: x.messages })));
ctx.parameters = result.value;
return invocation.proceed();
}
}
exports.ValidationMiddleware = ValidationMiddleware;
exports.validate = validate;
{
"name": "@plumier/core",
"version": "1.0.0-dev11.14+feae170",
"version": "1.0.0-dev11.15+7313eb2",
"description": "Delightful Node.js Rest Framework",

@@ -41,3 +41,3 @@ "main": "lib/index.js",

},
"gitHead": "feae170e8302c3db06c54ad4f34df84a904aacd8",
"gitHead": "7313eb26d1992e5ffa25402fce8230f05e79743b",
"devDependencies": {

@@ -44,0 +44,0 @@ "upath": "^1.2.0"

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