Skip to content
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
20 changes: 12 additions & 8 deletions lib/codegen.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ module.exports = function generateCode(hyperdispatch, { esm = false }) {
str += '\n'

if (esm) {
str += "import { c, b4a, assert } from 'hyperdispatch/runtime'\n"
str += "import { c, b4a, assert, DispatchError, ERRORS } from 'hyperdispatch/runtime'\n"
str += "import { version, getEncoding, setVersion } from './messages.js'\n"
} else {
str += "const { c, b4a, assert } = require('hyperdispatch/runtime')\n"
str += "const { c, b4a, assert, DispatchError, ERRORS } = require('hyperdispatch/runtime')\n"
str += "const { version, getEncoding, setVersion } = require('./messages.js')\n"
}

Expand All @@ -35,7 +35,7 @@ module.exports = function generateCode(hyperdispatch, { esm = false }) {
str += ' break\n'
}
str += ' default:\n'
str += " throw new Error('Cannot register a handler for a nonexistent route: ' + name)\n"
str += ' throw DispatchError.NONEXISTENT_ROUTE(name)\n'
str += ' }\n'
str += ' this._missing--\n'
str += ' }\n'
Expand All @@ -61,7 +61,7 @@ module.exports = function generateCode(hyperdispatch, { esm = false }) {
str += ` return this._handler${handler.id}(op.value, context)\n`
}
str += ' default:\n'
str += " throw new Error('Handler not found for ID:' + op.id)\n"
str += ' throw DispatchError.HANDLER_NOT_FOUND_BY_ID(op.id)\n'
str += ' }\n'
str += ' }\n'
str += '}\n'
Expand Down Expand Up @@ -114,7 +114,7 @@ module.exports = function generateCode(hyperdispatch, { esm = false }) {
str += ` return route${handler.id}\n`
}
str += ' default:\n'
str += " throw new Error('Handler not found for name: ' + name)\n"
str += ' throw DispatchError.ROUTE_NOT_FOUND_BY_NAME(name)\n'
str += ' }\n'
str += '}\n'
str += '\n'
Expand All @@ -126,7 +126,7 @@ module.exports = function generateCode(hyperdispatch, { esm = false }) {
str += ` return route${handler.id}\n`
}
str += ' default:\n'
str += " throw new Error('Handler not found for ID: ' + id)\n"
str += ' throw DispatchError.HANDLER_NOT_FOUND_BY_ID(id)\n'
str += ' }\n'
str += '}\n'
str += '\n'
Expand All @@ -136,14 +136,18 @@ module.exports = function generateCode(hyperdispatch, { esm = false }) {
str += ' version,\n'
str += ' encode,\n'
str += ' decode,\n'
str += ' Router\n'
str += ' Router,\n'
str += ' DispatchError,\n'
str += ' ERRORS\n'
str += '}\n'
} else {
str += 'module.exports = {\n'
str += ' version,\n'
str += ' encode,\n'
str += ' decode,\n'
str += ' Router\n'
str += ' Router,\n'
str += ' DispatchError,\n'
str += ' ERRORS\n'
str += '}\n'
}

Expand Down
46 changes: 46 additions & 0 deletions lib/errors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
const ERRORS = {
NONEXISTENT_ROUTE: 'NONEXISTENT_ROUTE',
HANDLER_NOT_FOUND_BY_ID: 'HANDLER_NOT_FOUND_BY_ID',
ROUTE_NOT_FOUND_BY_NAME: 'ROUTE_NOT_FOUND_BY_NAME'
}

class DispatchError extends Error {
constructor(code, message, fn = DispatchError) {
super(message ? `${code}: ${message}` : code)
this.code = code
this.isDispatchError = true

if (Error.captureStackTrace) {
Error.captureStackTrace(this, fn)
}
}

static isDispatchError(err) {
return err?.isDispatchError === true
}

static NONEXISTENT_ROUTE(name) {
return new DispatchError(ERRORS.NONEXISTENT_ROUTE, name, DispatchError.NONEXISTENT_ROUTE)
}

static HANDLER_NOT_FOUND_BY_ID(id) {
return new DispatchError(
ERRORS.HANDLER_NOT_FOUND_BY_ID,
id,
DispatchError.HANDLER_NOT_FOUND_BY_ID
)
}

static ROUTE_NOT_FOUND_BY_NAME(name) {
return new DispatchError(
ERRORS.ROUTE_NOT_FOUND_BY_NAME,
name,
DispatchError.ROUTE_NOT_FOUND_BY_NAME
)
}
}

module.exports = {
DispatchError,
ERRORS
}
6 changes: 5 additions & 1 deletion runtime.cjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
const { DispatchError, ERRORS } = require('./lib/errors')

module.exports = {
c: require('compact-encoding'),
b4a: require('b4a'),
assert: require('nanoassert')
assert: require('nanoassert'),
DispatchError,
ERRORS
}
3 changes: 2 additions & 1 deletion runtime.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import c from 'compact-encoding'
import b4a from 'b4a'
import assert from 'nanoassert'
import { DispatchError, ERRORS } from './lib/errors'

export { c, b4a, assert }
export { c, b4a, assert, DispatchError, ERRORS }
2 changes: 1 addition & 1 deletion test/basic.js
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ test('basic dispatch to non-existent route throws', async (t) => {
await r.dispatch(encode('@test/test-request-1', { id: 10, str: 'hello' }), 'some-context')

const badMsg = { id: -1, name: '@test/invalid', value: 'error' }
await t.exception(r.dispatch(badMsg, 'invalid-context'), /Handler not found for ID:-1/)
await t.exception(r.dispatch(badMsg, 'invalid-context'), /HANDLER_NOT_FOUND_BY_ID/)
})

test('can both encode and decode string enums', async (t) => {
Expand Down