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

daf-core

Package Overview
Dependencies
Maintainers
6
Versions
151
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

daf-core - npm Package Compare versions

Comparing version 7.0.0-beta.45 to 7.0.0-beta.46

src/__tests__/agent.subscriber.test.ts

32

build/agent.d.ts

@@ -58,2 +58,4 @@ import { IAgent, IPluginMethodMap, IAgentPlugin, TAgent, IAgentPluginSchema } from './types/IAgent';

private protectedMethods;
private readonly eventBus;
private readonly eventQueue;
/**

@@ -103,2 +105,32 @@ * Constructs a new instance of the `Agent` class

execute<P = any, R = any>(method: string, args: P): Promise<R>;
/**
* Broadcasts an `Event` to potential listeners.
*
* Listeners are `IEventListener` instances that declare `eventTypes`
* and implement an `async onEvent({type, data}, context)` method.
* Note that `IAgentPlugin` is also an `IEventListener` so plugins can be listeners for events.
*
* During creation, the agent automatically registers listener plugins
* to the `eventTypes` that they declare.
*
* Events are processed asynchronously, so the general pattern to be used is fire-and-forget.
* Ex: `agent.emit('foo', {eventData})`
*
* In situations where you need to make sure that all events in the queue have been exhausted,
* the `Promise` returned by `emit` can be awaited.
* Ex: `await agent.emit('foo', {eventData})`
*
* In case an error is thrown while processing an event, the error is re-emitted as an event
* of type `error` with a `EventListenerError` as payload.
*
* Note that `await agent.emit()` will NOT throw an error. To process errors, use a listener
* with `eventTypes: ["error"]` in the definition.
*
* @param eventType - the type of event being emitted
* @param data - event payload.
* Use the same `data` type for events of a particular `eventType`.
*
* @public
*/
emit(eventType: string, data: any): Promise<void>;
}

@@ -105,0 +137,0 @@ /**

131

build/agent.js

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

var debug_1 = __importDefault(require("debug"));
var events_1 = require("events");
/**

@@ -120,3 +121,5 @@ * Filters unauthorized methods. By default all methods are authorized

this.methods = {};
this.protectedMethods = ['execute', 'availableMethods'];
this.protectedMethods = ['execute', 'availableMethods', 'emit'];
this.eventBus = new events_1.EventEmitter();
this.eventQueue = [];
this.context = options === null || options === void 0 ? void 0 : options.context;

@@ -126,18 +129,53 @@ this.schema = {

schemas: __assign({}, ValidationError_1.default.components.schemas),
methods: {}
}
methods: {},
},
};
if (options === null || options === void 0 ? void 0 : options.plugins) {
var _loop_1 = function (plugin) {
var e_4, _a;
this_1.methods = __assign(__assign({}, this_1.methods), filterUnauthorizedMethods(plugin.methods || {}, options.authorizedMethods));
if (plugin.schema) {
this_1.schema = {
components: {
schemas: __assign(__assign({}, this_1.schema.components.schemas), plugin.schema.components.schemas),
methods: __assign(__assign({}, this_1.schema.components.methods), plugin.schema.components.methods),
},
};
}
if ((plugin === null || plugin === void 0 ? void 0 : plugin.eventTypes) && (plugin === null || plugin === void 0 ? void 0 : plugin.onEvent)) {
var _loop_3 = function (eventType) {
this_1.eventBus.on(eventType, function (args) {
var _a;
var promise = (_a = plugin === null || plugin === void 0 ? void 0 : plugin.onEvent) === null || _a === void 0 ? void 0 : _a.call(plugin, { type: eventType, data: args }, __assign(__assign({}, _this.context), { agent: _this }));
_this.eventQueue.push(promise);
promise === null || promise === void 0 ? void 0 : promise.catch(function (rejection) {
if (eventType !== 'error') {
_this.eventBus.emit('error', rejection);
}
else {
_this.eventQueue.push(Promise.reject(new Error('ErrorEventHandlerError: throwing an error in an error handler should crash')));
}
});
});
};
try {
for (var _b = (e_4 = void 0, __values(plugin.eventTypes)), _c = _b.next(); !_c.done; _c = _b.next()) {
var eventType = _c.value;
_loop_3(eventType);
}
}
catch (e_4_1) { e_4 = { error: e_4_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_4) throw e_4.error; }
}
}
};
var this_1 = this;
try {
for (var _c = __values(options.plugins), _d = _c.next(); !_d.done; _d = _c.next()) {
var plugin = _d.value;
this.methods = __assign(__assign({}, this.methods), filterUnauthorizedMethods(plugin.methods, options.authorizedMethods));
if (plugin.schema) {
this.schema = {
components: {
schemas: __assign(__assign({}, this.schema.components.schemas), plugin.schema.components.schemas),
methods: __assign(__assign({}, this.schema.components.methods), plugin.schema.components.methods)
}
};
}
_loop_1(plugin);
}

@@ -156,6 +194,6 @@ }

}
var _loop_1 = function (method) {
if (!this_1.protectedMethods.includes(method)) {
var _loop_2 = function (method) {
if (!this_2.protectedMethods.includes(method)) {
//@ts-ignore
this_1[method] = function (args) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
this_2[method] = function (args) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
return [2 /*return*/, this.execute(method, args)];

@@ -165,7 +203,7 @@ }); }); };

};
var this_1 = this;
var this_2 = this;
try {
for (var _e = __values(Object.keys(this.methods)), _f = _e.next(); !_f.done; _f = _e.next()) {
var method = _f.value;
_loop_1(method);
_loop_2(method);
}

@@ -246,2 +284,61 @@ }

};
/**
* Broadcasts an `Event` to potential listeners.
*
* Listeners are `IEventListener` instances that declare `eventTypes`
* and implement an `async onEvent({type, data}, context)` method.
* Note that `IAgentPlugin` is also an `IEventListener` so plugins can be listeners for events.
*
* During creation, the agent automatically registers listener plugins
* to the `eventTypes` that they declare.
*
* Events are processed asynchronously, so the general pattern to be used is fire-and-forget.
* Ex: `agent.emit('foo', {eventData})`
*
* In situations where you need to make sure that all events in the queue have been exhausted,
* the `Promise` returned by `emit` can be awaited.
* Ex: `await agent.emit('foo', {eventData})`
*
* In case an error is thrown while processing an event, the error is re-emitted as an event
* of type `error` with a `EventListenerError` as payload.
*
* Note that `await agent.emit()` will NOT throw an error. To process errors, use a listener
* with `eventTypes: ["error"]` in the definition.
*
* @param eventType - the type of event being emitted
* @param data - event payload.
* Use the same `data` type for events of a particular `eventType`.
*
* @public
*/
Agent.prototype.emit = function (eventType, data) {
return __awaiter(this, void 0, void 0, function () {
var e_5;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
this.eventBus.emit(eventType, data);
_a.label = 1;
case 1:
if (!(this.eventQueue.length > 0)) return [3 /*break*/, 6];
_a.label = 2;
case 2:
_a.trys.push([2, 4, , 5]);
return [4 /*yield*/, this.eventQueue.shift()];
case 3:
_a.sent();
return [3 /*break*/, 5];
case 4:
e_5 = _a.sent();
//nop
if (e_5.message.startsWith('ErrorEventHandlerError')) {
throw e_5;
}
return [3 /*break*/, 5];
case 5: return [3 /*break*/, 1];
case 6: return [2 /*return*/];
}
});
});
};
return Agent;

@@ -248,0 +345,0 @@ }());

@@ -15,2 +15,3 @@ /**

execute: <A = any, R = any>(method: string, args: A) => Promise<R>;
emit: (eventType: string, data: any) => Promise<void>;
}

@@ -41,7 +42,29 @@ /**

/**
* Describes a listener interface that needs to be implemented by components interested
* in listening to events emitted by an agent.
*
* @public
*/
export interface IEventListener {
/**
* Declares the event types that this listener is interested in.
* @public
*/
readonly eventTypes?: string[];
/**
* Processes an event emitted by the agent.
* @param context - Execution context. Requires agent with {@link daf-core#IDataStore} methods
* @public
*/
onEvent?(event: {
type: string;
data: any;
}, context: IAgentContext<{}>): Promise<void>;
}
/**
* Agent plugin interface
* @public
*/
export interface IAgentPlugin {
readonly methods: IPluginMethodMap;
export interface IAgentPlugin extends IEventListener {
readonly methods?: IPluginMethodMap;
readonly schema?: IAgentPluginSchema;

@@ -48,0 +71,0 @@ }

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

# [7.0.0-beta.46](https://github.com/uport-project/daf/compare/v7.0.0-beta.45...v7.0.0-beta.46) (2020-11-19)
### Features
* Add event system to agent ([#262](https://github.com/uport-project/daf/issues/262)) ([9a6747e](https://github.com/uport-project/daf/commit/9a6747e84037613d396e14a6f68cb2de8275ddca))
# [7.0.0-beta.45](https://github.com/uport-project/daf/compare/v7.0.0-beta.44...v7.0.0-beta.45) (2020-10-22)

@@ -8,0 +19,0 @@

4

package.json
{
"name": "daf-core",
"description": "DID Agent Framework Core Logic & Interfaces.",
"version": "7.0.0-beta.45",
"version": "7.0.0-beta.46",
"main": "build/index.js",

@@ -42,3 +42,3 @@ "types": "build/index.d.ts",

"keywords": [],
"gitHead": "a50275b95d273399882aad4eba702b6169aea61d"
"gitHead": "b97ff3b0a7c34d49215173e4ec76b2d093892c36"
}

@@ -17,5 +17,5 @@ import { Agent } from '../agent'

await agent.doSomething({ foo: 'baz' })
expect(plugin.methods.doSomething).toBeCalledWith({ foo: 'baz' }, { agent })
expect(plugin.methods?.doSomething).toBeCalledWith({ foo: 'baz' }, { agent })
await agent.execute('doSomething', { foo: 'bar' })
expect(plugin.methods.doSomething).toBeCalledWith({ foo: 'bar' }, { agent })
expect(plugin.methods?.doSomething).toBeCalledWith({ foo: 'bar' }, { agent })
})

@@ -70,3 +70,3 @@

await agent.bar({ foo: 'baz' })
expect(plugin.methods.bar).toBeCalledWith({ foo: 'baz' }, { agent })
expect(plugin.methods?.bar).toBeCalledWith({ foo: 'baz' }, { agent })
await agent.execute('baz', { foo: 'bar' })

@@ -93,3 +93,3 @@ expect(baz).toBeCalledWith({ foo: 'bar' }, { agent })

await agent.doSomething({ foo: 'baz' })
expect(plugin.methods.doSomething).toBeCalledWith(
expect(plugin.methods?.doSomething).toBeCalledWith(
{ foo: 'baz' },

@@ -99,3 +99,3 @@ { agent, authorizedDid: 'did:example:123' },

await agent.execute('doSomething', { foo: 'bar' })
expect(plugin.methods.doSomething).toBeCalledWith(
expect(plugin.methods?.doSomething).toBeCalledWith(
{ foo: 'bar' },

@@ -102,0 +102,0 @@ { agent, authorizedDid: 'did:example:123' },

@@ -5,2 +5,3 @@ import { IAgent, IPluginMethodMap, IAgentPlugin, TAgent, IAgentPluginSchema } from './types/IAgent'

import Debug from 'debug'
import { EventEmitter } from 'events'

@@ -86,7 +87,10 @@ /**

readonly methods: IPluginMethodMap = {}
private schema: IAgentPluginSchema
private context?: Record<string, any>
private protectedMethods = ['execute', 'availableMethods']
private protectedMethods = ['execute', 'availableMethods', 'emit']
private readonly eventBus: EventEmitter = new EventEmitter()
private readonly eventQueue: (Promise<any> | undefined)[] = []
/**

@@ -100,10 +104,10 @@ * Constructs a new instance of the `Agent` class

this.context = options?.context
this.schema = {
components: {
schemas: {
...ValidationErrorSchema.components.schemas
...ValidationErrorSchema.components.schemas,
},
methods: {}
}
methods: {},
},
}

@@ -115,3 +119,3 @@

...this.methods,
...filterUnauthorizedMethods(plugin.methods, options.authorizedMethods),
...filterUnauthorizedMethods(plugin.methods || {}, options.authorizedMethods),
}

@@ -128,7 +132,28 @@ if (plugin.schema) {

...plugin.schema.components.methods,
}
}
},
},
}
}
if (plugin?.eventTypes && plugin?.onEvent) {
for (const eventType of plugin.eventTypes) {
this.eventBus.on(eventType, (args) => {
const promise = plugin?.onEvent?.(
{ type: eventType, data: args },
{ ...this.context, agent: this },
)
this.eventQueue.push(promise)
promise?.catch((rejection) => {
if (eventType !== 'error') {
this.eventBus.emit('error', rejection)
} else {
this.eventQueue.push(
Promise.reject(
new Error('ErrorEventHandlerError: throwing an error in an error handler should crash'),
),
)
}
})
})
}
}
}

@@ -208,2 +233,45 @@ }

}
/**
* Broadcasts an `Event` to potential listeners.
*
* Listeners are `IEventListener` instances that declare `eventTypes`
* and implement an `async onEvent({type, data}, context)` method.
* Note that `IAgentPlugin` is also an `IEventListener` so plugins can be listeners for events.
*
* During creation, the agent automatically registers listener plugins
* to the `eventTypes` that they declare.
*
* Events are processed asynchronously, so the general pattern to be used is fire-and-forget.
* Ex: `agent.emit('foo', {eventData})`
*
* In situations where you need to make sure that all events in the queue have been exhausted,
* the `Promise` returned by `emit` can be awaited.
* Ex: `await agent.emit('foo', {eventData})`
*
* In case an error is thrown while processing an event, the error is re-emitted as an event
* of type `error` with a `EventListenerError` as payload.
*
* Note that `await agent.emit()` will NOT throw an error. To process errors, use a listener
* with `eventTypes: ["error"]` in the definition.
*
* @param eventType - the type of event being emitted
* @param data - event payload.
* Use the same `data` type for events of a particular `eventType`.
*
* @public
*/
async emit(eventType: string, data: any): Promise<void> {
this.eventBus.emit(eventType, data)
while (this.eventQueue.length > 0) {
try {
await this.eventQueue.shift()
} catch (e) {
//nop
if (e.message.startsWith('ErrorEventHandlerError')) {
throw e
}
}
}
}
}

@@ -210,0 +278,0 @@

@@ -16,2 +16,3 @@ /**

execute: <A = any, R = any>(method: string, args: A) => Promise<R>
emit: (eventType: string, data: any) => Promise<void>
}

@@ -44,2 +45,21 @@

/**
* Describes a listener interface that needs to be implemented by components interested
* in listening to events emitted by an agent.
*
* @public
*/
export interface IEventListener {
/**
* Declares the event types that this listener is interested in.
* @public
*/
readonly eventTypes?: string[]
/**
* Processes an event emitted by the agent.
* @param context - Execution context. Requires agent with {@link daf-core#IDataStore} methods
* @public
*/
onEvent?(event: { type: string; data: any }, context: IAgentContext<{}>): Promise<void>
}

@@ -50,4 +70,4 @@ /**

*/
export interface IAgentPlugin {
readonly methods: IPluginMethodMap
export interface IAgentPlugin extends IEventListener {
readonly methods?: IPluginMethodMap
readonly schema?: IAgentPluginSchema

@@ -94,2 +114,1 @@ }

}

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