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

@loopback/context

Package Overview
Dependencies
Maintainers
8
Versions
196
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@loopback/context - npm Package Compare versions

Comparing version 3.6.0 to 3.7.0

22

CHANGELOG.md

@@ -6,2 +6,24 @@ # Change Log

# [3.7.0](https://github.com/strongloop/loopback-next/compare/@loopback/context@3.6.0...@loopback/context@3.7.0) (2020-05-07)
### Bug Fixes
* **context:** allow binding keys to be used with composeInterceptors() ([0663c04](https://github.com/strongloop/loopback-next/commit/0663c0425b77cbbfa6391e0c4bd92f56b590a548))
### Features
* **context:** add registerInterceptor helper function and app.interceptor ([c760966](https://github.com/strongloop/loopback-next/commit/c76096684771ffaf535b75b025892ccfb057bff0))
* **context:** allow composition of intercetors ([261e9eb](https://github.com/strongloop/loopback-next/commit/261e9eb7d197fc480ab241bdd3b70b8a6e272908))
* **context:** allows bindings with singleton/context scopes to be refreshed ([8155147](https://github.com/strongloop/loopback-next/commit/8155147ceae756b60a0c9289f94ea8be6199c6d7))
* **context:** allows default namespace for bindings from classes ([ec2da01](https://github.com/strongloop/loopback-next/commit/ec2da01d766881da1c90dd47c50f8af319e04614))
* **context:** consolidate uuid generation and testing ([5abe25e](https://github.com/strongloop/loopback-next/commit/5abe25ecc2632b0d25140b5e863dfee446c29a01))
* **context:** force interceptor functions to return a value ([5663a76](https://github.com/strongloop/loopback-next/commit/5663a7642cbbb43fab08020d398393d0aabeed86))
* **context:** relax parameter type for isProviderClass() ([aafe7d0](https://github.com/strongloop/loopback-next/commit/aafe7d002a3bc0d2a1db5aceb054f25cb4f4f11f))
# [3.6.0](https://github.com/strongloop/loopback-next/compare/@loopback/context@3.5.1...@loopback/context@3.6.0) (2020-04-29)

@@ -8,0 +30,0 @@

3

dist/binding-decorator.d.ts
import { BindingSpec } from './binding-inspector';
import { Provider } from './provider';
import { Constructor } from './value-promise';

@@ -25,3 +24,3 @@ /**

*/
function provider(...specs: BindingSpec[]): (target: Constructor<Provider<unknown>>) => void;
function provider(...specs: BindingSpec[]): (target: Constructor<unknown>) => void;
}

@@ -42,3 +42,3 @@ import { MetadataAccessor } from '@loopback/metadata';

*/
export declare function isProviderClass<T>(cls: Constructor<T | Provider<T>>): cls is Constructor<Provider<T>>;
export declare function isProviderClass<T>(cls: unknown): cls is Constructor<Provider<T>>;
/**

@@ -113,7 +113,9 @@ * A factory function to create a template function to bind the target class

/**
* Artifact name, such as `my-rest-server` and `my-controller`
* Artifact name, such as `my-rest-server` and `my-controller`. It
* overrides the name tag
*/
name?: string;
/**
* Namespace for the binding key, such as `servers` and `controllers`
* Namespace for the binding key, such as `servers` and `controllers`. It
* overrides the default namespace or namespace tag
*/

@@ -126,2 +128,6 @@ namespace?: string;

/**
* Default namespace if the binding does not have an explicit namespace
*/
defaultNamespace?: string;
/**
* Default scope if the binding does not have an explicit scope

@@ -128,0 +134,0 @@ */

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

var _a;
return typeof ((_a = cls === null || cls === void 0 ? void 0 : cls.prototype) === null || _a === void 0 ? void 0 : _a.value) === 'function';
return (typeof cls === 'function' && typeof ((_a = cls.prototype) === null || _a === void 0 ? void 0 : _a.value) === 'function');
}

@@ -208,3 +208,3 @@ exports.isProviderClass = isProviderClass;

function buildBindingKey(cls, options = {}) {
var _a, _b, _c, _d;
var _a, _b, _c, _d, _e;
if (options.key)

@@ -219,13 +219,13 @@ return options.key;

return key;
let namespace = (_a = options.namespace) !== null && _a !== void 0 ? _a : bindingTemplate.tagMap[keys_1.ContextTags.NAMESPACE];
let namespace = (_b = (_a = options.namespace) !== null && _a !== void 0 ? _a : bindingTemplate.tagMap[keys_1.ContextTags.NAMESPACE]) !== null && _b !== void 0 ? _b : options.defaultNamespace;
if (!namespace) {
const namespaces = Object.assign({}, exports.DEFAULT_TYPE_NAMESPACES, options.typeNamespaceMapping);
// Derive the key from type + name
let type = (_b = options.type) !== null && _b !== void 0 ? _b : bindingTemplate.tagMap[keys_1.ContextTags.TYPE];
let type = (_c = options.type) !== null && _c !== void 0 ? _c : bindingTemplate.tagMap[keys_1.ContextTags.TYPE];
if (!type) {
type = (_c = bindingTemplate.tagNames.find(t => namespaces[t] != null)) !== null && _c !== void 0 ? _c : keys_1.ContextTags.CLASS;
type = (_d = bindingTemplate.tagNames.find(t => namespaces[t] != null)) !== null && _d !== void 0 ? _d : keys_1.ContextTags.CLASS;
}
namespace = getNamespace(type, namespaces);
}
const name = (_d = options.name) !== null && _d !== void 0 ? _d : (bindingTemplate.tagMap[keys_1.ContextTags.NAME] || cls.name);
const name = (_e = options.name) !== null && _e !== void 0 ? _e : (bindingTemplate.tagMap[keys_1.ContextTags.NAME] || cls.name);
key = `${namespace}.${name}`;

@@ -232,0 +232,0 @@ return key;

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

Object.defineProperty(exports, "__esModule", { value: true });
const uuid_1 = require("uuid");
const value_promise_1 = require("./value-promise");
class BindingKey {

@@ -106,4 +106,4 @@ constructor(key, propertyPath) {

const prefix = namespace ? `${namespace}.` : '';
const uuid = uuid_1.v4();
return BindingKey.create(`${prefix}${uuid}`);
const name = value_promise_1.uuid();
return BindingKey.create(`${prefix}${name}`);
}

@@ -110,0 +110,0 @@ }

@@ -189,2 +189,11 @@ /// <reference types="node" />

/**
* Invalidate the binding cache so that its value will be reloaded next time.
* This is useful to force reloading a singleton when its configuration or
* dependencies are changed.
* **WARNING**: The state held in the cached value will be gone.
*
* @param ctx - Context object
*/
refresh(ctx: Context): void;
/**
* This is an internal function optimized for performance.

@@ -191,0 +200,0 @@ * Users should use `@inject(key)` or `ctx.get(key)` instead.

@@ -189,2 +189,25 @@ "use strict";

}
/**
* Invalidate the binding cache so that its value will be reloaded next time.
* This is useful to force reloading a singleton when its configuration or
* dependencies are changed.
* **WARNING**: The state held in the cached value will be gone.
*
* @param ctx - Context object
*/
refresh(ctx) {
if (!this._cache)
return;
if (this.scope === BindingScope.SINGLETON) {
// Cache the value
const ownerCtx = ctx.getOwnerContext(this.key);
if (ownerCtx != null) {
this._cache.delete(ownerCtx);
}
}
else if (this.scope === BindingScope.CONTEXT) {
// Cache the value at the current context
this._cache.delete(ctx);
}
}
// Implementation

@@ -191,0 +214,0 @@ getValue(ctx, optionsOrSession) {

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

const events_1 = require("events");
const uuid_1 = require("uuid");
const binding_1 = require("./binding");

@@ -91,3 +90,3 @@ const binding_config_1 = require("./binding-config");

generateName() {
const id = uuid_1.v4();
const id = value_promise_1.uuid();
if (this.constructor === Context)

@@ -94,0 +93,0 @@ return id;

@@ -8,6 +8,11 @@ import { BindingFilter } from './binding-filter';

/**
* Any type except `void`. We use this type to enforce that interceptor functions
* always return a value (including undefined or null).
*/
export declare type NonVoid = string | number | boolean | null | undefined | object;
/**
* The `next` function that can be used to invoke next generic interceptor in
* the chain
*/
export declare type Next = () => ValueOrPromise<InvocationResult>;
export declare type Next = () => ValueOrPromise<NonVoid>;
/**

@@ -18,2 +23,23 @@ * An interceptor function to be invoked in a chain for the given context.

*
* We choose `NonVoid` as the return type to avoid possible bugs that an
* interceptor forgets to return the value from `next()`. For example, the code
* below will fail to compile.
*
* ```ts
* const myInterceptor: Interceptor = async (ctx, next) {
* // preprocessing
* // ...
*
* // There is a subtle bug that the result from `next()` is not further
* // returned back to the upstream interceptors
* const result = await next();
*
* // postprocessing
* // ...
* // We must have `return ...` here
* // either return `result` or another value if the interceptor decides to
* // have its own response
* }
* ```
*
* @typeParam C - `Context` class or a subclass of `Context`

@@ -24,5 +50,5 @@ * @param context - Context object

*
* @returns The invocation result as a value (sync) or promise (async)
* @returns The invocation result as a value (sync) or promise (async).
*/
export declare type GenericInterceptor<C extends Context = Context> = (context: C, next: Next) => ValueOrPromise<InvocationResult>;
export declare type GenericInterceptor<C extends Context = Context> = (context: C, next: Next) => ValueOrPromise<NonVoid>;
/**

@@ -66,4 +92,8 @@ * Interceptor function or a binding key that resolves a generic interceptor

*/
invokeInterceptors(): ValueOrPromise<InvocationResult>;
invokeInterceptors(finalHandler?: Next): ValueOrPromise<InvocationResult>;
/**
* Use the interceptor chain as an interceptor
*/
asInterceptor(): GenericInterceptor<C>;
/**
* Invoke downstream interceptors or the target method

@@ -90,1 +120,6 @@ */

export declare function invokeInterceptors<C extends Context = Context, T = InvocationResult>(context: C, interceptors: GenericInterceptorOrKey<C>[]): ValueOrPromise<T | undefined>;
/**
* Compose a list of interceptors as a single interceptor
* @param interceptors - A list of interceptor functions or binding keys
*/
export declare function composeInterceptors<C extends Context = Context>(...interceptors: GenericInterceptorOrKey<C>[]): GenericInterceptor<C>;

@@ -18,5 +18,7 @@ "use strict";

* @param interceptors - Interceptor functions or binding keys
* @param finalHandler - An optional final handler
*/
constructor(interceptors) {
constructor(interceptors, finalHandler = () => undefined) {
this.interceptors = interceptors;
this.finalHandler = finalHandler;
this._index = 0;

@@ -72,8 +74,16 @@ }

*/
invokeInterceptors() {
invokeInterceptors(finalHandler) {
// Create a state for each invocation to provide isolation
const state = new InterceptorChainState(this.getInterceptors());
const state = new InterceptorChainState(this.getInterceptors(), finalHandler);
return this.next(state);
}
/**
* Use the interceptor chain as an interceptor
*/
asInterceptor() {
return (ctx, next) => {
return this.invokeInterceptors(next);
};
}
/**
* Invoke downstream interceptors or the target method

@@ -84,3 +94,3 @@ */

// No more interceptors
return undefined;
return state.finalHandler();
}

@@ -129,2 +139,13 @@ // Invoke the next interceptor in the chain

exports.invokeInterceptors = invokeInterceptors;
/**
* Compose a list of interceptors as a single interceptor
* @param interceptors - A list of interceptor functions or binding keys
*/
function composeInterceptors(...interceptors) {
return (ctx, next) => {
const interceptor = new GenericInterceptorChain(ctx, interceptors).asInterceptor();
return interceptor(ctx, next);
};
}
exports.composeInterceptors = composeInterceptors;
//# sourceMappingURL=interceptor-chain.js.map
import { MetadataAccessor } from '@loopback/metadata';
import { BindingTemplate } from './binding';
import { BindingSpec } from './binding-inspector';
import { Binding, BindingTemplate } from './binding';
import { BindingFromClassOptions, BindingSpec } from './binding-inspector';
import { Context } from './context';
import { GenericInterceptor, GenericInterceptorOrKey } from './interceptor-chain';
import { InvocationArgs, InvocationContext, InvocationOptions, InvocationResult } from './invocation';
import { ValueOrPromise } from './value-promise';
import { Provider } from './provider';
import { Constructor, ValueOrPromise } from './value-promise';
/**

@@ -114,1 +115,25 @@ * A specialized InvocationContext for interceptors

export declare function invokeMethodWithInterceptors(context: Context, target: object, methodName: string, args: InvocationArgs, options?: InvocationOptions): ValueOrPromise<InvocationResult>;
/**
* Options for an interceptor binding
*/
export interface InterceptorBindingOptions extends BindingFromClassOptions {
/**
* Global or local interceptor
*/
global?: boolean;
/**
* Group name for a global interceptor
*/
group?: string;
/**
* Source filter for a global interceptor
*/
source?: string | string[];
}
/**
* Register an interceptor function or provider class to the given context
* @param ctx - Context object
* @param interceptor - An interceptor function or provider class
* @param options - Options for the interceptor binding
*/
export declare function registerInterceptor(ctx: Context, interceptor: Interceptor | Constructor<Provider<Interceptor>>, options?: InterceptorBindingOptions): Binding<Interceptor>;

@@ -12,2 +12,4 @@ "use strict";

const binding_decorator_1 = require("./binding-decorator");
const binding_inspector_1 = require("./binding-inspector");
const binding_key_1 = require("./binding-key");
const binding_sorter_1 = require("./binding-sorter");

@@ -245,2 +247,53 @@ const interceptor_chain_1 = require("./interceptor-chain");

exports.invokeMethodWithInterceptors = invokeMethodWithInterceptors;
/**
* Register an interceptor function or provider class to the given context
* @param ctx - Context object
* @param interceptor - An interceptor function or provider class
* @param options - Options for the interceptor binding
*/
function registerInterceptor(ctx, interceptor, options = {}) {
var _a, _b, _c;
let { global } = options;
const { group, source } = options;
if (group != null || source != null) {
// If group or source is set, assuming global
global = global !== false;
}
const namespace = ((_b = (_a = options.namespace) !== null && _a !== void 0 ? _a : options.defaultNamespace) !== null && _b !== void 0 ? _b : global) ? keys_1.GLOBAL_INTERCEPTOR_NAMESPACE
: keys_1.LOCAL_INTERCEPTOR_NAMESPACE;
let binding;
if (binding_inspector_1.isProviderClass(interceptor)) {
binding = binding_inspector_1.createBindingFromClass(interceptor, {
defaultNamespace: namespace,
...options,
});
if (binding.tagMap[keys_1.ContextTags.GLOBAL_INTERCEPTOR]) {
global = true;
}
ctx.add(binding);
}
else {
let key = options.key;
if (!key) {
const name = (_c = options.name) !== null && _c !== void 0 ? _c : interceptor.name;
if (!name) {
key = binding_key_1.BindingKey.generate(namespace).key;
}
else {
key = `${namespace}.${name}`;
}
}
binding = ctx
.bind(key)
.to(interceptor);
}
if (global) {
binding.apply(asGlobalInterceptor(group));
if (source) {
binding.tag({ [keys_1.ContextTags.GLOBAL_INTERCEPTOR_SOURCE]: source });
}
}
return binding;
}
exports.registerInterceptor = registerInterceptor;
//# sourceMappingURL=interceptor.js.map

@@ -49,2 +49,6 @@ import { ConfigurationResolver } from './binding-config';

/**
* Default namespace for local interceptors
*/
export declare const LOCAL_INTERCEPTOR_NAMESPACE = "interceptors";
/**
* Namespace for context bindings

@@ -51,0 +55,0 @@ */

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

/**
* Default namespace for local interceptors
*/
exports.LOCAL_INTERCEPTOR_NAMESPACE = 'interceptors';
/**
* Namespace for context bindings

@@ -57,0 +61,0 @@ */

/**
* This module contains types for values and/or promises as well as a set of
* utility methods to handle values and/or promises.
*/
/**
* A class constructor accepting arbitrary arguments.

@@ -110,1 +106,9 @@ */

export declare function transformValueOrPromise<T, V>(valueOrPromise: ValueOrPromise<T>, transformer: (val: T) => ValueOrPromise<V>): ValueOrPromise<V>;
/**
* A utility to generate uuid v4
*/
export declare function uuid(): string;
/**
* A regular expression for testing uuid v4 PATTERN
*/
export declare const UUID_PATTERN: RegExp;

@@ -8,2 +8,7 @@ "use strict";

/**
* This module contains types for values and/or promises as well as a set of
* utility methods to handle values and/or promises.
*/
const uuid_1 = require("uuid");
/**
* Check whether a value is a Promise-like instance.

@@ -232,2 +237,13 @@ * Recognizes both native promises and third-party promise libraries.

exports.transformValueOrPromise = transformValueOrPromise;
/**
* A utility to generate uuid v4
*/
function uuid() {
return uuid_1.v4();
}
exports.uuid = uuid;
/**
* A regular expression for testing uuid v4 PATTERN
*/
exports.UUID_PATTERN = /[0-9A-F]{8}-[0-9A-F]{4}-[4][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}/i;
//# sourceMappingURL=value-promise.js.map
{
"name": "@loopback/context",
"version": "3.6.0",
"version": "3.7.0",
"description": "LoopBack's container for Inversion of Control",

@@ -21,13 +21,13 @@ "engines": {

"dependencies": {
"@loopback/metadata": "^2.1.2",
"@loopback/metadata": "^2.1.3",
"@types/debug": "^4.1.5",
"debug": "^4.1.1",
"p-event": "^4.1.0",
"tslib": "^1.11.1",
"uuid": "^7.0.3"
"tslib": "^1.11.2",
"uuid": "^8.0.0"
},
"devDependencies": {
"@loopback/build": "^5.3.0",
"@loopback/eslint-config": "^6.0.5",
"@loopback/testlab": "^3.1.2",
"@loopback/build": "^5.3.1",
"@loopback/eslint-config": "^6.0.6",
"@loopback/testlab": "^3.1.3",
"@types/bluebird": "^3.5.30",

@@ -60,3 +60,3 @@ "@types/node": "^10.17.21",

},
"gitHead": "9ecee6fc8648b8f0999be6c13934d4756e9b0ddc"
"gitHead": "50c3f06d942f8bae8f0c32a3775ff98a7498e4fd"
}

@@ -17,3 +17,2 @@ // Copyright IBM Corp. 2018,2019. All Rights Reserved.

} from './binding-inspector';
import {Provider} from './provider';
import {Constructor} from './value-promise';

@@ -101,4 +100,4 @@

...specs: BindingSpec[]
): (target: Constructor<Provider<unknown>>) => void {
return (target: Constructor<Provider<unknown>>) => {
): (target: Constructor<unknown>) => void {
return (target: Constructor<unknown>) => {
if (!isProviderClass(target)) {

@@ -105,0 +104,0 @@ throw new Error(`Target ${target} is not a Provider`);

@@ -60,5 +60,7 @@ // Copyright IBM Corp. 2018,2019. All Rights Reserved.

export function isProviderClass<T>(
cls: Constructor<T | Provider<T>>,
cls: unknown,
): cls is Constructor<Provider<T>> {
return typeof cls?.prototype?.value === 'function';
return (
typeof cls === 'function' && typeof cls.prototype?.value === 'function'
);
}

@@ -205,7 +207,9 @@

/**
* Artifact name, such as `my-rest-server` and `my-controller`
* Artifact name, such as `my-rest-server` and `my-controller`. It
* overrides the name tag
*/
name?: string;
/**
* Namespace for the binding key, such as `servers` and `controllers`
* Namespace for the binding key, such as `servers` and `controllers`. It
* overrides the default namespace or namespace tag
*/

@@ -218,2 +222,6 @@ namespace?: string;

/**
* Default namespace if the binding does not have an explicit namespace
*/
defaultNamespace?: string;
/**
* Default scope if the binding does not have an explicit scope

@@ -319,3 +327,5 @@ */

let namespace =
options.namespace ?? bindingTemplate.tagMap[ContextTags.NAMESPACE];
options.namespace ??
bindingTemplate.tagMap[ContextTags.NAMESPACE] ??
options.defaultNamespace;
if (!namespace) {

@@ -322,0 +332,0 @@ const namespaces = Object.assign(

@@ -6,3 +6,4 @@ // Copyright IBM Corp. 2018,2020. All Rights Reserved.

import {v4} from 'uuid';
import {uuid} from './value-promise';
export type BindingAddress<T = unknown> = string | BindingKey<T>;

@@ -131,5 +132,5 @@

const prefix = namespace ? `${namespace}.` : '';
const uuid = v4();
return BindingKey.create(`${prefix}${uuid}`);
const name = uuid();
return BindingKey.create(`${prefix}${name}`);
}
}

@@ -273,2 +273,24 @@ // Copyright IBM Corp. 2017,2020. All Rights Reserved.

/**
* Invalidate the binding cache so that its value will be reloaded next time.
* This is useful to force reloading a singleton when its configuration or
* dependencies are changed.
* **WARNING**: The state held in the cached value will be gone.
*
* @param ctx - Context object
*/
refresh(ctx: Context) {
if (!this._cache) return;
if (this.scope === BindingScope.SINGLETON) {
// Cache the value
const ownerCtx = ctx.getOwnerContext(this.key);
if (ownerCtx != null) {
this._cache.delete(ownerCtx);
}
} else if (this.scope === BindingScope.CONTEXT) {
// Cache the value at the current context
this._cache.delete(ctx);
}
}
/**
* This is an internal function optimized for performance.

@@ -275,0 +297,0 @@ * Users should use `@inject(key)` or `ctx.get(key)` instead.

@@ -8,3 +8,2 @@ // Copyright IBM Corp. 2017,2020. All Rights Reserved.

import {EventEmitter} from 'events';
import {v4 as uuidv4} from 'uuid';
import {Binding, BindingInspectOptions, BindingTag} from './binding';

@@ -41,2 +40,3 @@ import {

isPromiseLike,
uuid,
ValueOrPromise,

@@ -156,3 +156,3 @@ } from './value-promise';

private generateName() {
const id = uuidv4();
const id = uuid();
if (this.constructor === Context) return id;

@@ -159,0 +159,0 @@ return `${this.constructor.name}-${id}`;

@@ -16,6 +16,12 @@ // Copyright IBM Corp. 2019,2020. All Rights Reserved.

/**
* Any type except `void`. We use this type to enforce that interceptor functions
* always return a value (including undefined or null).
*/
export type NonVoid = string | number | boolean | null | undefined | object;
/**
* The `next` function that can be used to invoke next generic interceptor in
* the chain
*/
export type Next = () => ValueOrPromise<InvocationResult>;
export type Next = () => ValueOrPromise<NonVoid>;

@@ -27,2 +33,23 @@ /**

*
* We choose `NonVoid` as the return type to avoid possible bugs that an
* interceptor forgets to return the value from `next()`. For example, the code
* below will fail to compile.
*
* ```ts
* const myInterceptor: Interceptor = async (ctx, next) {
* // preprocessing
* // ...
*
* // There is a subtle bug that the result from `next()` is not further
* // returned back to the upstream interceptors
* const result = await next();
*
* // postprocessing
* // ...
* // We must have `return ...` here
* // either return `result` or another value if the interceptor decides to
* // have its own response
* }
* ```
*
* @typeParam C - `Context` class or a subclass of `Context`

@@ -33,3 +60,3 @@ * @param context - Context object

*
* @returns The invocation result as a value (sync) or promise (async)
* @returns The invocation result as a value (sync) or promise (async).
*/

@@ -39,3 +66,3 @@ export type GenericInterceptor<C extends Context = Context> = (

next: Next,
) => ValueOrPromise<InvocationResult>;
) => ValueOrPromise<NonVoid>;

@@ -60,4 +87,8 @@ /**

* @param interceptors - Interceptor functions or binding keys
* @param finalHandler - An optional final handler
*/
constructor(private interceptors: GenericInterceptorOrKey<C>[]) {}
constructor(
public readonly interceptors: GenericInterceptorOrKey<C>[],
public readonly finalHandler: Next = () => undefined,
) {}

@@ -146,5 +177,8 @@ /**

*/
invokeInterceptors(): ValueOrPromise<InvocationResult> {
invokeInterceptors(finalHandler?: Next): ValueOrPromise<InvocationResult> {
// Create a state for each invocation to provide isolation
const state = new InterceptorChainState<C>(this.getInterceptors());
const state = new InterceptorChainState<C>(
this.getInterceptors(),
finalHandler,
);
return this.next(state);

@@ -154,2 +188,11 @@ }

/**
* Use the interceptor chain as an interceptor
*/
asInterceptor(): GenericInterceptor<C> {
return (ctx, next) => {
return this.invokeInterceptors(next);
};
}
/**
* Invoke downstream interceptors or the target method

@@ -162,3 +205,3 @@ */

// No more interceptors
return undefined;
return state.finalHandler();
}

@@ -217,1 +260,17 @@ // Invoke the next interceptor in the chain

}
/**
* Compose a list of interceptors as a single interceptor
* @param interceptors - A list of interceptor functions or binding keys
*/
export function composeInterceptors<C extends Context = Context>(
...interceptors: GenericInterceptorOrKey<C>[]
): GenericInterceptor<C> {
return (ctx, next) => {
const interceptor = new GenericInterceptorChain(
ctx,
interceptors,
).asInterceptor();
return interceptor(ctx, next);
};
}

@@ -18,3 +18,9 @@ // Copyright IBM Corp. 2019,2020. All Rights Reserved.

import {bind} from './binding-decorator';
import {BindingSpec} from './binding-inspector';
import {
BindingFromClassOptions,
BindingSpec,
createBindingFromClass,
isProviderClass,
} from './binding-inspector';
import {BindingAddress, BindingKey} from './binding-key';
import {sortBindingsByPhase} from './binding-sorter';

@@ -37,4 +43,6 @@ import {Context} from './context';

GLOBAL_INTERCEPTOR_NAMESPACE,
LOCAL_INTERCEPTOR_NAMESPACE,
} from './keys';
import {tryWithFinally, ValueOrPromise} from './value-promise';
import {Provider} from './provider';
import {Constructor, tryWithFinally, ValueOrPromise} from './value-promise';
const debug = debugFactory('loopback:context:interceptor');

@@ -350,1 +358,76 @@

}
/**
* Options for an interceptor binding
*/
export interface InterceptorBindingOptions extends BindingFromClassOptions {
/**
* Global or local interceptor
*/
global?: boolean;
/**
* Group name for a global interceptor
*/
group?: string;
/**
* Source filter for a global interceptor
*/
source?: string | string[];
}
/**
* Register an interceptor function or provider class to the given context
* @param ctx - Context object
* @param interceptor - An interceptor function or provider class
* @param options - Options for the interceptor binding
*/
export function registerInterceptor(
ctx: Context,
interceptor: Interceptor | Constructor<Provider<Interceptor>>,
options: InterceptorBindingOptions = {},
) {
let {global} = options;
const {group, source} = options;
if (group != null || source != null) {
// If group or source is set, assuming global
global = global !== false;
}
const namespace =
options.namespace ?? options.defaultNamespace ?? global
? GLOBAL_INTERCEPTOR_NAMESPACE
: LOCAL_INTERCEPTOR_NAMESPACE;
let binding: Binding<Interceptor>;
if (isProviderClass(interceptor)) {
binding = createBindingFromClass(interceptor, {
defaultNamespace: namespace,
...options,
});
if (binding.tagMap[ContextTags.GLOBAL_INTERCEPTOR]) {
global = true;
}
ctx.add(binding);
} else {
let key = options.key;
if (!key) {
const name = options.name ?? interceptor.name;
if (!name) {
key = BindingKey.generate<Interceptor>(namespace).key;
} else {
key = `${namespace}.${name}`;
}
}
binding = ctx
.bind(key as BindingAddress<Interceptor>)
.to(interceptor as Interceptor);
}
if (global) {
binding.apply(asGlobalInterceptor(group));
if (source) {
binding.tag({[ContextTags.GLOBAL_INTERCEPTOR_SOURCE]: source});
}
}
return binding;
}

@@ -62,2 +62,7 @@ // Copyright IBM Corp. 2018,2020. All Rights Reserved.

/**
* Default namespace for local interceptors
*/
export const LOCAL_INTERCEPTOR_NAMESPACE = 'interceptors';
/**
* Namespace for context bindings

@@ -64,0 +69,0 @@ */

@@ -11,2 +11,3 @@ // Copyright IBM Corp. 2018,2020. All Rights Reserved.

import {v4 as uuidv4} from 'uuid';
/**

@@ -274,1 +275,13 @@ * A class constructor accepting arbitrary arguments.

}
/**
* A utility to generate uuid v4
*/
export function uuid() {
return uuidv4();
}
/**
* A regular expression for testing uuid v4 PATTERN
*/
export const UUID_PATTERN = /[0-9A-F]{8}-[0-9A-F]{4}-[4][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}/i;

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc