Socket
Socket
Sign inDemoInstall

vandium

Package Overview
Dependencies
67
Maintainers
1
Versions
56
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 6.1.0 to 7.0.0-Beta1

lib/auth/auth.js

13

CHANGELOG.md
# Change Log
## 7.0.0 (TBD)
New:
* `apigateway` handler that contains defaults to reduce the code required to
implement a lambda handler.
* Support for JWKS keys via `useJwks()`
* `createHandler()` now the preferred way to create lambda handlers and allows
the use of hooks.
* Handler hooks to inspect or stub functionality for testing purposes. Can be
used to bypass JWT validation in unit tests when private keys are unknown.
## 6.1.0 (2020-02-13)

@@ -4,0 +17,0 @@

353

lib/event_types/api/api_handler.js

@@ -1,339 +0,80 @@

const MethodHandler = require( './method' );
const JWTValidator = require( './jwt' );
const Protection = require( './protection' );
const constants = require( './constants' );
const TypedHandler = require( '../typed' );
const MethodHandler = require( './method' );
const responseProcessor = require( './response' );
const BaseAPIHandler = require( './base_api_handler' );
const { processCookies } = require( './cookies' );
class APIHandler extends BaseAPIHandler {
const { processBody } = require( './body' );
constructor( options = {} ) {
const { processHeaderValue } = require( './helper' );
super( options );
const { isFunction, parseBoolean } = require( '../../utils' );
this.methodHandlers = {};
this._currentMethodHandler = null;
const { types } = require( '../../validation' );
this.pipeline.stage( 'methodValidation', (state) => {
const Pipeline = require( '../pipeline' );
let { event } = state;
const PREPROCESSOR_PIPELINE_STAGES = [
let method = event.httpMethod;
'methodValidation',
'eventNormalization',
'bodyProcessing',
'protection',
'cookies',
'jwt',
'validation',
'extractExecutor'
];
let methodHandler = this.methodHandlers[ method ];
class APIHandler extends TypedHandler {
if( !methodHandler ) {
constructor( options = {} ) {
super( 'apigateway', options );
this._initPipeline();
this.authorization();
this.bodyEncoding( options.bodyEncoding );
this._headers = {};
this.protection( options.protection );
this.methodHandlers = {};
this._onErrorHandler = (err) => err;
this.afterFunc = function() {};
}
authorization( authConfig ) {
return this.jwt( authConfig );
}
jwt( options = {} ) {
const jwt = new JWTValidator( options );
this.pipeline.stage( 'jwt', ( { event } ) => {
jwt.validate( event );
});
return this;
}
formURLEncoded( enabled = true ) {
return this.bodyEncoding( enabled ? 'formURLEncoded' : 'auto' );
}
skipBodyParse() {
return this.bodyEncoding( 'none' );
}
bodyEncoding( encoding = 'auto' ) {
// switch( encoding ) {
//
// case 'formURLEncoded':
// case 'auto':
// case 'none':
// //this._bodyEncoding = encoding;
// break;
//
// default:
// throw new Error( `Unsupported body encoding type: ${encoding}` );
// }
this.pipeline.stage( 'bodyProcessing', (state) => {
const { event } = state;
if( event.body ) {
event.rawBody = event.body;
event.body = processBody( event.body, encoding );
}
});
return this;
}
headers( values = {} ) {
for( let name in values ) {
this.header( name, values[ name ] );
throw new Error( 'handler not defined for http method: ' + method );
}
return this;
}
state.extra = { method, methodHandler };
});
}
header( name, value ) {
currentMethodHandler() {
processHeaderValue( this._headers, name, value );
if( !this._currentMethodHandler ) {
return this;
}
throw new Error( 'Method not selected' );
}
protection( options ) {
return this._currentMethodHandler;
}
this._protection = new Protection( options );
addMethodsToHandler( lambdaHandler ) {
return this;
}
super.addMethodsToHandler( lambdaHandler );
cors( options = {} ) {
[
'jwt',
'authorization',
'handler'
const headerListValue = ( value ) => {
].forEach( (handlerMethod) => this.addlambdaHandlerMethod( handlerMethod, lambdaHandler ) );
if( Array.isArray( value ) ) {
constants.HTTP_METHODS.forEach( (methodType) => {
value = value.join( ', ' );
}
this.addlambdaHandlerMethod( methodType, lambdaHandler );
this.addlambdaHandlerMethod( methodType.toLowerCase(), lambdaHandler );
});
}
return value;
};
_addHandler( type, ...args ) {
this.header( 'Access-Control-Allow-Origin', options.allowOrigin );
this.header( 'Access-Control-Allow-Credentials', options.allowCredentials );
this.header( 'Access-Control-Expose-Headers', headerListValue( options.exposeHeaders ) );
this.header( 'Access-Control-Max-Age', options.maxAge );
this.header( 'Access-Control-Allow-Headers', headerListValue( options.allowHeaders ) );
const methodHandler = new MethodHandler();
return this;
}
if( args.length > 1 ) {
onError( onErrorHandler ) {
methodHandler.setValidation( args[ 0 ] );
methodHandler.setHandler( args[ 1 ] );
}
else if( args.length === 1 ) {
this._onErrorHandler = onErrorHandler;
methodHandler.setHandler( args[ 0 ] );
}
return this;
}
this.methodHandlers[ type ] = methodHandler;
this._currentMethodHandler = methodHandler;
validation( functionOrOptions ) {
let options = functionOrOptions;
if( isFunction( functionOrOptions ) ) {
options = functionOrOptions( types );
}
this.currentMethodHandler.setValidation( options );
return this;
}
handler( handler ) {
this.currentMethodHandler.setHandler( handler );
return this;
}
onResponse( onResponseHandler ) {
this.currentMethodHandler.setOnResponse( onResponseHandler );
return this;
}
addMethodsToHandler( lambdaHandler ) {
super.addMethodsToHandler( lambdaHandler );
[
'jwt',
'authorization',
'formURLEncoded',
'header',
'headers',
'protection',
'cors',
'onError',
'onResponse',
'validation',
'handler'
].forEach( (handlerMethod) => this.addlambdaHandlerMethod( handlerMethod, lambdaHandler));
constants.HTTP_METHODS.forEach( (methodType) => {
this.addlambdaHandlerMethod( methodType, lambdaHandler );
this.addlambdaHandlerMethod( methodType.toLowerCase(), lambdaHandler );
});
}
executePreprocessors( state ) {
super.executePreprocessors( state );
//execute pipeline
this.pipeline.executorSync().run( state );
}
async processResult( result, context, { methodHandler } ) {
const responseObject = responseProcessor.processResult( result, context, this._headers );
return await this.processResponse( responseObject, methodHandler );
}
async processError( error, context, { methodHandler } ) {
let updatedError = await this._onErrorHandler( error, context.event, context );
if( updatedError ) {
error = updatedError;
}
const responseObject = responseProcessor.processError( error, this._headers );
return await this.processResponse( responseObject, methodHandler );
}
/**
* Single conduit to processing responses
*/
async processResponse( responseObject, methodHandler ) {
const result = await methodHandler.onResponse( responseObject.result );
return { result };
}
get currentMethodHandler() {
if( !this._currentMethodHandler ) {
throw new Error( 'Method not selected' );
}
return this._currentMethodHandler;
}
_addHandler( type, ...args ) {
const methodHandler = new MethodHandler();
if( args.length > 1 ) {
methodHandler.setValidation( args[ 0 ] );
methodHandler.setHandler( args[ 1 ] );
}
else if( args.length === 1 ) {
methodHandler.setHandler( args[ 0 ] );
}
this.methodHandlers[ type ] = methodHandler;
this._currentMethodHandler = methodHandler;
return this;
}
_initPipeline() {
this.pipeline = new Pipeline( PREPROCESSOR_PIPELINE_STAGES );
this.pipeline.stage( 'methodValidation', (state) => {
let { event } = state;
let method = event.httpMethod;
let methodHandler = this.methodHandlers[ method ];
if( !methodHandler ) {
throw new Error( 'handler not defined for http method: ' + method );
}
state.extra = { method, methodHandler };
});
this.pipeline.stage( 'eventNormalization', ( { event }) => {
event.queryStringParameters = event.queryStringParameters || {};
event.multiValueQueryStringParameters = event.multiValueQueryStringParameters || {};
event.pathParameters = event.pathParameters || {};
});
this.pipeline.stage( 'protection', ( { event }) => {
this._protection.validate( event );
});
this.pipeline.stage( 'cookies', ( { event }) => {
event.cookies = processCookies( event.headers );
});
this.pipeline.stage( 'validation', ( { event, extra: { methodHandler } } ) => {
methodHandler.validator.validate( event );
});
this.pipeline.stage( 'extractExecutor', (state) => {
const { extra: { methodHandler } } = state;
state.executor = methodHandler.executor;
});
}
return this;
}
}

@@ -340,0 +81,0 @@

const APIHandler = require( './api_handler' );
function createHandler( options ) {
const APIGateway = require( './apigateway' );
return new APIHandler( options ).createLambda();
function api( options ) {
return new APIHandler( options ).createLambda();
}
module.exports = createHandler;
function apigateway( handler ) {
return new APIGateway().handler( handler );
}
module.exports = {
api,
apigateway,
};

@@ -1,8 +0,8 @@

const utils = require( '../../utils' );
const { applyValues, parseBoolean, valueFromPath } = require( '../../utils' );
const jwt = require( '../../jwt' );
const { decode, formatPublicKey, resolveAlgorithm, validateXSRF } = require( '../../jwt' );
const jwkToPem = require('jwk-to-pem');
const resolveAlgorithm = jwt.resolveAlgorithm;
const { getConfig: getAuthConfig } = require( '../../auth' );

@@ -17,3 +17,3 @@ const DEFAULT_JWT_TOKEN_PATH = 'headers.Authorization';

return utils.applyValues( options[ name ], ...otherValues );
return applyValues( options[ name ], ...otherValues );
}

@@ -23,10 +23,10 @@

let value = optionValue( options, name, ...otherValues );
let value = optionValue( options, name, ...otherValues );
if( !value ) {
if( !value ) {
throw new Error( `missing required jwt configuration value: ${name}` );
}
throw new Error( `missing required jwt configuration value: ${name}` );
}
return value;
return value;
}

@@ -36,98 +36,104 @@

constructor( options = {} ) {
constructor( options = {} ) {
if( options === false ) {
if( options === false || options === true ) {
options = { enabled: false };
}
options = { enabled: options };
}
else {
const { jwk } = options;
const { jwt } = getAuthConfig();
if( jwk ) {
options = {
const { alg, use } = jwk;
...(jwt || {}),
...options,
}
}
if( alg !== 'RS256' ) {
const { jwk } = options;
throw new Error( 'Unsupported algorithm in JKS: ' + alg );
}
if( jwk ) {
if( use !== 'sig' ) {
const { alg, use } = jwk;
throw new Error( 'Key is not set to signature use' );
}
if( alg !== 'RS256' ) {
this.algorithm = alg;
this.key = jwkToPem( jwk );
}
else {
throw new Error( 'Unsupported algorithm in JKS: ' + alg );
}
const algorithm = options.algorithm || process.env.VANDIUM_JWT_ALGORITHM;
if( use !== 'sig' ) {
if( (options.enabled === false) || !algorithm ) {
throw new Error( 'Key is not set to signature use' );
}
this.enabled = false;
return;
}
this.algorithm = alg;
this.key = jwkToPem( jwk );
}
else {
this.algorithm = resolveAlgorithm( algorithm );
const algorithm = options.algorithm;
if( this.algorithm === 'RS256' ) {
if( options.enabled === false ) {
const key = requiredOption( options, 'publicKey', options.key,
process.env.VANDIUM_JWT_PUBKEY, process.env.VANDIUM_JWT_KEY );
this.enabled = false;
return;
}
this.key = jwt.formatPublicKey( key );
}
else {
this.algorithm = resolveAlgorithm( algorithm );
this.key = requiredOption( options, 'secret', options.key,
process.env.VANDIUM_JWT_SECRET, process.env.VANDIUM_JWT_KEY );
}
}
if( this.algorithm === 'RS256' ) {
this.xsrf = utils.parseBoolean( optionValue( options, 'xsrf', process.env.VANDIUM_JWT_USE_XSRF, false ) );
const key = requiredOption( options, 'publicKey', options.key );
if( this.xsrf ) {
this.key = formatPublicKey( key );
}
else {
this.xsrfTokenPath = optionValue( options, 'xsrfToken', process.env.VANDIUM_JWT_XSRF_TOKEN_PATH,
DEFAULT_XSRF_TOKEN_PATH ).split( '.' );
this.xsrfClaimPath = optionValue( options, 'xsrfClaim',
process.env.VANDIUM_JWT_XSRF_CLAIM_PATH, DEFAULT_XSRF_CLAIM_PATH ).split( '.' );
}
this.key = requiredOption( options, 'secret', options.key );
}
}
this.tokenPath = optionValue( options, 'token', process.env.VANDIUM_JWT_TOKEN_PATH, DEFAULT_JWT_TOKEN_PATH ).split( '.' );
this.xsrf = parseBoolean( optionValue( options, 'xsrf', false ) );
this.enabled = true;
if( this.xsrf ) {
this.xsrfTokenPath = optionValue( options, 'xsrfToken', DEFAULT_XSRF_TOKEN_PATH ).split( '.' );
this.xsrfClaimPath = optionValue( options, 'xsrfClaim', DEFAULT_XSRF_CLAIM_PATH ).split( '.' );
}
validate( event ) {
this.tokenPath = optionValue( options, 'token', DEFAULT_JWT_TOKEN_PATH ).split( '.' );
if( !this.enabled ) {
this.enabled = true;
}
// nothing to validate
return;
}
validate( event ) {
let token = utils.valueFromPath( event, this.tokenPath );
if( !this.enabled ) {
// Authorization Bearer
if( token && token.startsWith( 'Bearer' ) ) {
// nothing to validate
return;
}
token = token.replace( 'Bearer', '' ).trim();
}
let token = valueFromPath( event, this.tokenPath );
let decoded = jwt.decode( token, this.algorithm, this.key );
// Authorization Bearer
if( token && token.startsWith( 'Bearer' ) ) {
if( this.xsrf ) {
token = token.replace( 'Bearer', '' ).trim();
}
let xsrfToken = utils.valueFromPath( event, this.xsrfTokenPath );
let decoded = decode( token, this.algorithm, this.key );
jwt.validateXSRF( decoded, xsrfToken, this.xsrfClaimPath );
}
if( this.xsrf ) {
event.jwt = decoded;
let xsrfToken = valueFromPath( event, this.xsrfTokenPath );
validateXSRF( decoded, xsrfToken, this.xsrfClaimPath );
}
event.jwt = decoded;
}
}
module.exports = JWTValidator;

@@ -5,5 +5,5 @@ const Handler = require( './handler' );

constructor( options = {} ) {
constructor() {
super( options );
super();
}

@@ -19,8 +19,14 @@

function createHandler( options ) {
function createHandler( handler, options ) {
return new CustomHandler( options )
.createLambda();
const instance = new CustomHandler( options );
if( handler ) {
instance.handler( handler );
}
return instance.createLambda();
}
module.exports = createHandler;

@@ -9,21 +9,21 @@ const utils = require( '../utils' );

let promise;
let promise;
try {
try {
if( func.length <= 1 ) {
if( func.length <= 1 ) {
promise = Promise.resolve( func( handlerContext ) );
}
else {
promise = utils.asPromise( func, handlerContext );
}
promise = Promise.resolve( func( handlerContext ) );
}
catch( err ) {
else {
promise = Promise.reject( err );
promise = utils.asPromise( func, handlerContext );
}
}
catch( err ) {
return promise;
promise = Promise.reject( err );
}
return promise;
}

@@ -33,7 +33,7 @@

if( safeContext.callbackWaitsForEmptyEventLoop === false ) {
if( safeContext.callbackWaitsForEmptyEventLoop === false ) {
// let lambda context know that we don't want to wait for the empty event loop
context.callbackWaitsForEmptyEventLoop = false;
}
// let lambda context know that we don't want to wait for the empty event loop
context.callbackWaitsForEmptyEventLoop = false;
}
}

@@ -43,10 +43,10 @@

const safe = {
const safe = {
...context,
getRemainingTimeInMillis: context.getRemainingTimeInMillis,
event,
};
...context,
getRemainingTimeInMillis: context.getRemainingTimeInMillis,
event,
};
return safe;
return safe;
}

@@ -56,183 +56,185 @@

constructor() {
constructor() {
this._configuration = {};
this._configuration = {};
this.afterFunc = () => {};
this.afterFunc = () => {};
this._execPipeline = this._createPipeline();
this._execPipeline = this._createPipeline();
this.eventProcessor( (event) => event );
}
this.eventProcessor( (event) => event );
}
addMethodsToHandler( lambdaHandler ) {
addMethodsToHandler( lambdaHandler ) {
this.addlambdaHandlerMethod( 'before', lambdaHandler );
this.addlambdaHandlerMethod( 'callbackWaitsForEmptyEventLoop', lambdaHandler );
this.addlambdaHandlerMethod( 'finally', lambdaHandler );
}
this.addlambdaHandlerMethod( 'before', lambdaHandler );
this.addlambdaHandlerMethod( 'callbackWaitsForEmptyEventLoop', lambdaHandler );
this.addlambdaHandlerMethod( 'finally', lambdaHandler );
}
addlambdaHandlerMethod( methodName, lambdaHandler ) {
addlambdaHandlerMethod( methodName, lambdaHandler ) {
lambdaHandler[ methodName ] = ( ...args ) => {
lambdaHandler[ methodName ] = ( ...args ) => {
this[ methodName ]( ...args );
return lambdaHandler;
}
this[ methodName ]( ...args );
return lambdaHandler;
}
}
handler( handlerFunc ) {
handler( handlerFunc ) {
this.executor = executors.create( handlerFunc );
this.executor = executors.create( handlerFunc );
return this;
}
return this;
}
executePreprocessors( state ) {
executePreprocessors( state ) {
if( this._configuration.callbackWaitsForEmptyEventLoop === false ) {
if( this._configuration.callbackWaitsForEmptyEventLoop === false ) {
state.context.callbackWaitsForEmptyEventLoop = false;
}
state.context.callbackWaitsForEmptyEventLoop = false;
}
}
async processResult( result /*, context*/ ) {
async processResult( result /*, context*/ ) {
return { result };
}
return { result };
}
async processError( error /*, context*/ ) {
async processError( error /*, context*/ ) {
return { error };
}
return { error };
}
async execute( event, context ) {
async execute( event, context, hooks ) {
const safeContext = makeSafeContext( event, context );
const safeContext = makeSafeContext( event, context );
try {
try {
const { error, result } = await this._executePipeline( event, safeContext );
const { error, result } = await this._executePipeline( event, safeContext, hooks );
if( error ) {
if( error ) {
throw error
}
throw error
}
return result;
}
finally {
return result;
}
finally {
updateContext( context, safeContext );
}
updateContext( context, safeContext );
}
}
async _executePipeline( event, context ) {
async _executePipeline( event, context, hooks ) {
let state = {
const state = {
event: utils.clone( event ),
context,
executor: this.executor,
extra: {},
};
event: utils.clone( event ),
context,
executor: this.executor,
extra: {},
hooks,
};
const pipeline = this._execPipeline.executor();
const pipeline = this._execPipeline.executor();
try {
try {
const result = await pipeline.run( state );
const result = await pipeline.run( state );
return await this.processResult( result, state.context, state.extra );
}
catch( err ) {
return await this.processResult( result, state.context, state.extra );
}
catch( err ) {
return await this.processError( err, state.context, state.extra );
}
finally {
return await this.processError( err, state.context, state.extra );
}
finally {
if( pipeline.wasStageRun( 'beforeHandler' ) ) {
if( pipeline.wasStageRun( 'beforeHandler' ) ) {
try {
try {
await asPromise( this.afterFunc, state.context );
}
catch( err ) {
await asPromise( this.afterFunc, state.context );
}
catch( err ) {
console.log( 'uncaught exception during finally:', err );
}
}
console.log( 'uncaught exception during finally:', err );
}
}
}
}
before( beforeFunc ) {
before( beforeFunc ) {
this._execPipeline.stage( 'beforeHandler', async (state) => {
this._execPipeline.stage( 'beforeHandler', async (state) => {
const { context } = state;
const { context } = state;
context.additional = await asPromise( beforeFunc, context );
});
context.additional = await asPromise( beforeFunc, context );
});
return this;
}
return this;
}
callbackWaitsForEmptyEventLoop( enabled = true) {
callbackWaitsForEmptyEventLoop( enabled = true) {
this._configuration.callbackWaitsForEmptyEventLoop = enabled;
return this;
}
this._configuration.callbackWaitsForEmptyEventLoop = enabled;
return this;
}
finally( afterFunc ) {
finally( afterFunc ) {
this.afterFunc = afterFunc;
return this;
}
this.afterFunc = afterFunc;
return this;
}
eventProcessor( eventProc ) {
eventProcessor( eventProc ) {
this._execPipeline.stage( 'runHandler', async (state) => {
this._execPipeline.stage( 'runHandler', async (state) => {
const { event, context, executor } = state;
const { event, context, executor } = state;
return await executor( eventProc( event ), context );
});
return await executor( eventProc( event ), context );
});
return this;
}
return this;
}
createLambda() {
createLambda() {
let lambdaHandler = async ( event, context ) => {
const lambdaHandler = async ( event, context ) => {
return this.execute( event, context );
};
return this.execute( event, context );
};
this.addMethodsToHandler( lambdaHandler );
this.addMethodsToHandler( lambdaHandler );
return lambdaHandler;
}
lambdaHandler.execute = async ( ...params ) => this.execute( ...params );
_createPipeline() {
return lambdaHandler;
}
let pipeline = new Pipeline( [ 'preprocessors', 'validateExecutor', 'beforeHandler', 'runHandler' ] );
_createPipeline() {
const pipeline = new Pipeline( [ 'preprocessors', 'validateExecutor', 'beforeHandler', 'runHandler' ] );
pipeline.stage( 'preprocessors', (state) => {
pipeline.stage( 'preprocessors', (state) => {
this.executePreprocessors( state );
});
this.executePreprocessors( state );
});
pipeline.stage( 'validateExecutor', (state) => {
pipeline.stage( 'validateExecutor', (state) => {
if( !state.executor ) {
if( !state.executor ) {
throw new Error( 'handler not defined' );
}
});
throw new Error( 'handler not defined' );
}
});
return pipeline;
}
return pipeline;
}
}
module.exports = Handler;

@@ -11,10 +11,10 @@ 'use strict';

module.exports = {};
const { api, apigateway } = require( './api' );
// specialized
module.exports.api = require( './api' );
module.exports.generic = require( './custom' );
const generic = require( './custom' );
function asEventInfo( obj ) {
function getTypes() {
const asEventInfo = ( obj ) => {
if( isObject( obj ) ) {

@@ -27,6 +27,13 @@

return { name: obj, type: obj };
}
}
// record types
[
const eventTypes = {
// specialized
api,
generic,
};
// record types
[
's3',

@@ -41,11 +48,11 @@ 'dynamodb',

].forEach( ( obj ) => {
].forEach( ( obj ) => {
const { name, type } = asEventInfo( obj );
module.exports[ name ] = ( ...args ) => record( type, ...args );
});
eventTypes[ name ] = ( ...args ) => record( type, ...args );
});
// simple event
[
// simple event
[
'cloudformation',

@@ -59,3 +66,3 @@ { name: 'logs', type: 'cloudwatch' },

].forEach( ( obj ) => {
].forEach( ( obj ) => {

@@ -66,8 +73,22 @@ const { name, type } = asEventInfo( obj );

module.exports[ name ] = ( ...args ) => cloudwatch( name, ...args );
eventTypes[ name ] = ( ...args ) => cloudwatch( name, ...args );
}
else {
module.exports[ name ] = ( ...args ) => basic( type, ...args );
eventTypes[ name ] = ( ...args ) => basic( type, ...args );
}
});
});
const handlerTypes = {
apigateway,
...eventTypes,
};
return { handlerTypes, eventTypes };
}
module.exports = {
...getTypes()
};

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

class Pipeline {

@@ -5,5 +6,5 @@

this.executionOrder = [ ...stageOrder ];
this.handlers = new Map();
this.handlers = {};
stageOrder.forEach( (stage) => this.handlers.set( stage, () => {} ) );
}

@@ -13,9 +14,9 @@

if( !this.executionOrder.includes( stageName ) ) {
if( !this.handlers.has( stageName ) ) {
throw new Error( `Invalid stage: ${stageName}` );
}
throw new Error( `Invalid stage: ${stageName}` );
}
this.handlers[ stageName ] = handler;
return this;
this.handlers.set( stageName, handler );
return this;
}

@@ -25,3 +26,3 @@

return new PipelineExecutorAsync( this );
return new PipelineExecutorAsync( Array.from( this.handlers.entries() ) );
}

@@ -31,42 +32,48 @@

return new PipelineExecutorSync( this );
return new PipelineExecutorSync( Array.from( this.handlers.entries() ) );
}
}
const noOpenHook = () => {};
class PipelineExecutorBase {
constructor( pipeline ) {
constructor( handlers ) {
this.executionOrder = [ ...pipeline.executionOrder ];
this.handlers = { ...pipeline.handlers };
this.handlers = handlers;
this._resetExecState();
}
this._resetExecState();
}
wasStageRun( stageName ) {
wasStageRun( stageName ) {
const { last } = this.execState;
const { stagesRun } = this.execState;
if( last ) {
return stagesRun.includes( stageName );
}
const lastIndex = this.executionOrder.indexOf( last );
const stageIndex = this.executionOrder.indexOf( stageName );
_resetExecState() {
if( lastIndex > -1 && stageIndex > -1 ) {
this.execState = {
return (lastIndex >= stageIndex);
}
}
last: null,
current: null,
stagesRun: [],
};
}
}
return false;
}
function getHandlerExecs( stage, handler, hooks ) {
_resetExecState() {
const methodHook = hooks[ stage ] || {};
this.execState = {
const {
last: null,
current: null,
};
}
before = noOpenHook,
stub : handlerExec = handler,
after = noOpenHook,
} = methodHook;
return [ before, handlerExec, after ];
}

@@ -76,29 +83,32 @@

constructor( pipeline ) {
constructor( pipeline ) {
super( pipeline );
}
super( pipeline );
}
async run( state ) {
async run( state ) {
this._resetExecState();
this._resetExecState();
let lastResult;
const { hooks = {} } = state;
for( let method of this.executionOrder ) {
let lastResult;
const handler = this.handlers[method];
for( let [stage,stageHandler] of this.handlers ) {
if( handler ) {
this.execState.current = stage;
this.execState.current = method;
const [ beforeHandler, handler, afterHandler ] = getHandlerExecs( stage, stageHandler, hooks );
lastResult = await handler( state );
beforeHandler( state, stage );
this.execState.last = method;
}
}
lastResult = await handler( state );
return lastResult;
afterHandler( state, stage );
this.execState.stagesRun.push( stage );
}
return lastResult;
}
}

@@ -117,16 +127,19 @@

const { hooks = {} } = state;
let lastResult;
for( let method of this.executionOrder ) {
for( let [stage,stageHandler] of this.handlers ) {
const handler = this.handlers[method];
this.execState.current = stage;
if( handler ) {
const [ beforeHandler, handler, afterHandler ] = getHandlerExecs( stage, stageHandler, hooks );
this.execState.current = method;
beforeHandler( state, stage );
lastResult = handler( state );
lastResult = handler( state );
this.execState.last = method;
}
afterHandler( state, stage );
this.execState.stagesRun.push( stage );
}

@@ -133,0 +146,0 @@

@@ -12,17 +12,17 @@ // load environment variables from SSM (if configured)

const eventTypes = require( './event_types' );
const { eventTypes } = require( './event_types' );
const createHandler = require( './create-handler' );
const { useJwks } = require( './auth' );
const vandium = {
types: validation.types
types: validation.types,
...eventTypes,
useJwks,
createHandler,
};
//////////////////
// event types
// ///////////////
for( let type in eventTypes ) {
vandium[ type ] = eventTypes[ type ];
}
module.exports = Object.freeze( vandium );
{
"name": "vandium",
"version": "6.1.0",
"version": "7.0.0-Beta1",
"description": "AWS Lambda framework for building functions using Node.js for API Gateway, IoT applications, and other AWS events",

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

"scripts": {
"test": "nyc mocha '**/__tests__/*' --recursive",
"test": "nyc mocha 'lib/**/__tests__/*' --recursive",
"lint": "eslint"

@@ -60,2 +60,3 @@ },

"jwk-to-pem": "^2.0.3",
"jwks-source": "^1.0.0",
"jwt-simple": "^0.5.6",

@@ -67,3 +68,3 @@ "qs": "^6.5.2",

"app-root-path": "^3.0.0",
"aws-sdk": "^2.618.0",
"aws-sdk": "^2.620.0",
"chai": "^4.1.2",

@@ -70,0 +71,0 @@ "dotenv": "^8.2.0",

SocketSocket SOC 2 Logo

Product

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc