Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(message-handler): Rewire promise rejections as Error objects and #300

Merged
merged 1 commit into from
Dec 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@
"test:integration-build": "yarn test:integration-prepare && yarn test:integration-pretty",
"test:integration-prepare": "ts-node --project packages/tsconfig.settings.json ./scripts/prepare-integration-tests.ts",
"test:integration-pretty":"prettier --write __tests__/shared/documentationExamples.ts",
"test:integration": "yarn test:integration-build && yarn test",
"test": "jest --config=jest.json --maxWorkers=2",
"test:watch": "jest --config=jest.json --watch --verbose --coverage=false",
"test:integration": "yarn test:integration-build && yarn test:ci",
"test:ci": "jest --config=jest.json --maxWorkers=2",
"test": "jest --config=jest.json --coverage=false",
"test:watch": "yarn test --watch --verbose",
"daf": "./packages/daf-cli/bin/daf.js",
"prettier": "prettier --write '{packages,__tests__, !build}/**/*.ts'",
"build-clean": "rimraf ./packages/*/build ./packages/*/node_modules ./packages/*/tsconfig.tsbuildinfo && jest --clearCache",
Expand Down
6 changes: 6 additions & 0 deletions packages/daf-core/api/daf-core.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ export class Agent implements IAgent {
readonly methods: IPluginMethodMap;
}

// @public
export const CoreEvents: {
error: string;
warning: string;
};

// @public
export function createAgent<T extends IPluginMethodMap>(options: IAgentOptions): TAgent<T>;

Expand Down
11 changes: 6 additions & 5 deletions packages/daf-core/src/__tests__/agent.subscriber.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Agent } from '../agent'
import { CoreEvents } from '../coreEvents'
import { IEventListener } from '../types/IAgent'

function sleep(ms: number) {
Expand Down Expand Up @@ -77,7 +78,7 @@ describe('daf-core agent', () => {
},
}
const errorHandler: IEventListener = {
eventTypes: ['error'],
eventTypes: [CoreEvents.error],
onEvent: jest.fn(),
}
const agent = new Agent({
Expand All @@ -88,7 +89,7 @@ describe('daf-core agent', () => {

expect(errorHandler.onEvent).toBeCalledWith(
{
type: 'error',
type: CoreEvents.error,
data: new Error("I can't handle it!!!!"),
},
{ agent: agent },
Expand All @@ -105,9 +106,9 @@ describe('daf-core agent', () => {
},
}
const errorHandler: IEventListener = {
eventTypes: ['error'],
eventTypes: [CoreEvents.error],
onEvent: async ({ type, data }, context) => {
expect(type).toBe('error')
expect(type).toBe(CoreEvents.error)
const err = data as Error
expect(err.message).toMatch("I can't handle it after waiting so long!!!!")
},
Expand Down Expand Up @@ -176,7 +177,7 @@ describe('daf-core agent', () => {
},
}
const errorHandler: IEventListener = {
eventTypes: ['error'],
eventTypes: [CoreEvents.error],
onEvent: async () => {
throw new Error('barError')
},
Expand Down
9 changes: 5 additions & 4 deletions packages/daf-core/src/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { validateArguments, validateReturnType } from './validator'
import ValidationErrorSchema from './schemas/ValidationError'
import Debug from 'debug'
import { EventEmitter } from 'events'
import { CoreEvents } from './coreEvents'

/**
* Filters unauthorized methods. By default all methods are authorized
Expand Down Expand Up @@ -146,8 +147,8 @@ export class Agent implements IAgent {
)
this.eventQueue.push(promise)
promise?.catch((rejection) => {
if (eventType !== 'error') {
this.eventBus.emit('error', rejection)
if (eventType !== CoreEvents.error) {
this.eventBus.emit(CoreEvents.error, rejection)
} else {
this.eventQueue.push(
Promise.reject(
Expand Down Expand Up @@ -254,10 +255,10 @@ export class Agent implements IAgent {
* 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.
* of type `CoreEvents.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.
* with `eventTypes: [ CoreEvents.error ]` in the definition.
*
* @param eventType - the type of event being emitted
* @param data - event payload.
Expand Down
20 changes: 20 additions & 0 deletions packages/daf-core/src/coreEvents.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* This collection defines the core event types.
*
* @public
*/
export const CoreEvents = {
/**
* This event type is used to signal an error to event listeners.
*
* @public
*/
error: 'ev_err',

/**
* This event type is used to signal a warning to event listeners.
*
* @public
*/
warning: 'ev_warn',
}
1 change: 1 addition & 0 deletions packages/daf-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/
export { Agent, createAgent, IAgentOptions } from './agent'
export { ValidationError } from './validator'
export { CoreEvents } from './coreEvents'
export * from './types/IAgent'
export * from './types/IDataStore'
export * from './types/IIdentity'
Expand Down
4 changes: 2 additions & 2 deletions packages/daf-did-comm/src/action-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,13 @@ export class DIDComm implements IAgentPlugin {
})
}

return Promise.reject('Message not sent')
return Promise.reject(new Error('Message not sent'))
} catch (e) {
return Promise.reject(e)
}
} else {
debug('No Messaging service in didDoc')
return Promise.reject('No service endpoint')
return Promise.reject(new Error('No service endpoint'))
}
}
}
4 changes: 2 additions & 2 deletions packages/daf-did-jwt/src/__tests__/message-handler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,12 @@ describe('daf-did-jwt', () => {
it('should reject unknown message type', async () => {
const mockNextHandler = {
setNext: jest.fn(),
handle: jest.fn().mockRejectedValue('Unsupported message type'),
handle: jest.fn().mockRejectedValue(new Error('Unsupported message type')),
}
const handler = new JwtMessageHandler()
handler.setNext(mockNextHandler)
const message = new Message({ raw: 'test', metaData: [{ type: 'test' }] })
expect(handler.handle(message, context)).rejects.toEqual('Unsupported message type')
await expect(handler.handle(message, context)).rejects.toThrow('Unsupported message type')
})

it('should set data field for VC jwt', async () => {
Expand Down
8 changes: 4 additions & 4 deletions packages/daf-elem-did/src/identity-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export class ElemIdentityProvider extends AbstractIdentityProvider {
})

if (response.status !== 200) {
return Promise.reject(response.statusText)
return Promise.reject(new Error(response.statusText))
}

const identity: Omit<IIdentity, 'provider'> = {
Expand All @@ -82,7 +82,7 @@ export class ElemIdentityProvider extends AbstractIdentityProvider {
context: IContext,
): Promise<any> {
if (!identity.controllerKeyId) throw Error('ControllerKeyId does not exist')

const primaryKey = await await context.agent.keyManagerGetKey({ kid: identity.controllerKeyId })

debug('Fetching list of previous operations')
Expand All @@ -91,7 +91,7 @@ export class ElemIdentityProvider extends AbstractIdentityProvider {

debug('Operations count:', operations.length)
if (operations.length === 0) {
return Promise.reject('There should be at least one operation')
return Promise.reject(new Error('There should be at least one operation'))
}

const lastOperation = operations.pop()
Expand Down Expand Up @@ -120,7 +120,7 @@ export class ElemIdentityProvider extends AbstractIdentityProvider {

if (response2.status !== 200) {
debug(response2.statusText)
return Promise.reject(response2.statusText)
return Promise.reject(new Error(response2.statusText))
}

debug('Success. New publicKey:', key.publicKeyHex)
Expand Down
28 changes: 28 additions & 0 deletions packages/daf-message-handler/src/__tests__/default.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,34 @@
import { createAgent, IAgentContext, IMessageHandler } from 'daf-core/src'
import { MessageHandler } from '..'
import { AbstractMessageHandler, Message } from '../../build'

jest.setTimeout(30000)

class DummyHandler extends AbstractMessageHandler {
async handle(message: Message, context: IAgentContext<{}>): Promise<Message> {
return super.handle(message, context)
}
}

describe('daf-message-handler', () => {
const a = 100
it('should run a dummy test', () => {
expect(a).toEqual(100)
})

let agent = createAgent<IMessageHandler>({
plugins: [
new MessageHandler({
messageHandlers: [new DummyHandler()],
}),
],
})

it('should reject unknown message', async () => {
expect.assertions(1)
const raw = 'some message of unknown format'
await expect(agent.handleMessage({ raw, save: false, metaData: [{ type: 'test' }] })).rejects.toThrow(
'Unsupported message type',
)
})
})
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { IAgentContext } from 'daf-core'
import { Message } from './message'

export const unsupportedMessageTypeError = 'Unsupported message type'
export const unsupportedMessageTypeError = new Error('Unsupported message type')

/**
* An abstract class for creating {@link daf-message-handler#MessageHandler} plugins
Expand Down
5 changes: 3 additions & 2 deletions packages/daf-message-handler/src/message-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
IMessageHandler,
IHandleMessageArgs,
schema,
CoreEvents,
} from 'daf-core'
import { Message } from './message'
import { AbstractMessageHandler } from './abstract-message-handler'
Expand All @@ -15,7 +16,7 @@ const debug = Debug('daf:message-handler')
export const EventTypes = {
validatedMessage: 'validatedMessage',
savedMessage: 'savedMessage',
error: 'error',
error: CoreEvents.error,
}

/**
Expand Down Expand Up @@ -54,7 +55,7 @@ export class MessageHandler implements IAgentPlugin {
const { raw, metaData, save } = args
debug('%o', { raw, metaData, save })
if (!this.messageHandler) {
return Promise.reject('Message handler not provided')
return Promise.reject(new Error('Message handler not provided'))
}

try {
Expand Down
8 changes: 4 additions & 4 deletions packages/daf-resolver/src/universal-resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ export class UniversalResolver {
const ddo = await result.json()
return ddo.didDocument
} catch (e) {
return Promise.reject(e.message)
return Promise.reject(e)
}
}
}

return resolve
}
}
}
2 changes: 1 addition & 1 deletion packages/daf-typeorm/api/daf-typeorm.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ export class DataStoreORM implements IAgentPlugin {
}

// @public (undocumented)
export const Entities: (typeof Credential_2 | typeof Identity | typeof Claim | typeof Presentation | typeof Message | typeof Key | typeof Service)[];
export const Entities: (typeof Identity | typeof Message | typeof Claim | typeof Credential_2 | typeof Presentation | typeof Key | typeof Service)[];

// @public (undocumented)
export interface FindArgs<TColumns> {
Expand Down
11 changes: 4 additions & 7 deletions packages/daf-url/src/__tests__/message-handler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ describe('daf-url', () => {

it('should reject unknown message type', async () => {
const message = new Message({ raw: 'test', metaData: [{ type: 'test' }] })
expect(messageHandler.handle(message, context)).rejects.toEqual('Unsupported message type')
await expect(messageHandler.handle(message, context)).rejects.toThrow('Unsupported message type')
})

it('should transform message after standard URL', async () => {
Expand All @@ -32,19 +32,16 @@ describe('daf-url', () => {
},
],
})
expect(messageHandler.handle(message, context)).rejects.toEqual('Unsupported message type')
await expect(messageHandler.handle(message, context)).rejects.toThrow('Unsupported message type')
expect(message.raw).toEqual(JWT)
})

it('should try to load data from URL if URL is not standard', async () => {
const message = new Message({ raw: 'https://example.com/public-profile.jwt' })
fetchMock.mockResponse('mockbody')
expect.assertions(2)
try {
await messageHandler.handle(message, context)
} catch (e) {
expect(e).toMatch('Unsupported message type')
}

await expect(messageHandler.handle(message, context)).rejects.toThrow('Unsupported message type')

expect(message.raw).toEqual('mockbody')
})
Expand Down
2 changes: 1 addition & 1 deletion packages/daf-w3c/src/__tests__/message-handler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ describe('daf-w3c', () => {

it('should reject unknown message type', async () => {
const message = new Message({ raw: 'test', metaData: [{ type: 'test' }] })
expect(handler.handle(message, context)).rejects.toEqual('Unsupported message type')
await expect(handler.handle(message, context)).rejects.toThrow('Unsupported message type')
})

it('should return handled VC message', async () => {
Expand Down