From 83126ea87fd245062ab86bb30a5c6c531e3c8b81 Mon Sep 17 00:00:00 2001 From: Andrew Osheroff Date: Wed, 11 Jun 2025 12:53:59 -0700 Subject: [PATCH 1/2] Offset must be persisted in the JSON --- builder.cjs | 4 ++ test/basic.js | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+) diff --git a/builder.cjs b/builder.cjs index 275addf..c895360 100644 --- a/builder.cjs +++ b/builder.cjs @@ -22,6 +22,9 @@ class HyperdispatchNamespace { module.exports = class Hyperdispatch { constructor (schema, dispatchJson, { offset, dispatchDir = null, schemaDir = null } = {}) { + if (dispatchJson && Number.isInteger(dispatchJson.offset) && dispatchJson.offset !== offset) { + throw new Error('Cannot change the hyperdispatch offset once it has been defined once') + } this.schema = schema this.version = dispatchJson ? dispatchJson.version : 0 this.offset = dispatchJson ? dispatchJson.offset : (offset || 0) @@ -94,6 +97,7 @@ module.exports = class Hyperdispatch { toJSON () { return { version: this.version, + offset: this.offset, schema: this.handlers.map(({ type, ...h }) => h) } } diff --git a/test/basic.js b/test/basic.js index ff6ad2c..4cc6a17 100644 --- a/test/basic.js +++ b/test/basic.js @@ -136,3 +136,140 @@ test('can both encode and decode ops', async t => { t.is(decoded1.value.id, 10) t.is(decoded2.value.str, 'world') }) + +test('basic two namespaces with interleaved op additions', async t => { + t.plan(6) + + const hd = await createTestSchema(t) + hd.rebuild({ + schema: schema => { + const ns = schema.namespace('test') + ns.register({ + name: 'request', + fields: [ + { + name: 'id', + type: 'uint' + } + ] + }) + }, + dispatch: hyperdispatch => { + const ns1 = hyperdispatch.namespace('test1') + ns1.register({ + name: 'test-request-1', + requestType: '@test/request' + }) + const ns2 = hyperdispatch.namespace('test2') + ns2.register({ + name: 'test-request-2', + requestType: '@test/request' + }) + } + }, { offset: 2 }) + hd.rebuild({ + schema: schema => { + const ns = schema.namespace('test') + ns.register({ + name: 'request', + fields: [ + { + name: 'id', + type: 'uint' + } + ] + }) + }, + dispatch: hyperdispatch => { + const ns1 = hyperdispatch.namespace('test1') + ns1.register({ + name: 'test-request-1', + requestType: '@test/request' + }) + const ns2 = hyperdispatch.namespace('test2') + ns2.register({ + name: 'test-request-2', + requestType: '@test/request' + }) + ns1.register({ + name: 'test-request-3', + requestType: '@test/request' + }) + } + }, { offset: 2 }) + const { encode, Router } = hd.module + + const r = new Router() + r.add('@test1/test-request-1', (req, ctx) => { + t.is(ctx, 'some-context') + t.is(req.id, 10) + }) + r.add('@test2/test-request-2', (req, ctx) => { + t.is(ctx, 'some-context') + t.is(req.id, 20) + }) + r.add('@test1/test-request-3', (req, ctx) => { + t.is(ctx, 'another-context') + t.is(req.id, 30) + }) + + await r.dispatch(encode('@test1/test-request-1', { id: 10 }), 'some-context') + await r.dispatch(encode('@test2/test-request-2', { id: 20 }), 'some-context') + await r.dispatch(encode('@test1/test-request-3', { id: 30 }), 'another-context') +}) + +test('cannot change the offset', async t => { + const hd = await createTestSchema(t) + hd.rebuild({ + schema: schema => { + const ns = schema.namespace('test') + ns.register({ + name: 'request', + fields: [ + { + name: 'id', + type: 'uint' + } + ] + }) + }, + dispatch: hyperdispatch => { + const ns1 = hyperdispatch.namespace('test1') + ns1.register({ + name: 'test-request-1', + requestType: '@test/request' + }) + } + }, { offset: 2 }) + + try { + hd.rebuild({ + schema: schema => { + const ns = schema.namespace('test') + ns.register({ + name: 'request', + fields: [ + { + name: 'id', + type: 'uint' + } + ] + }) + }, + dispatch: hyperdispatch => { + const ns1 = hyperdispatch.namespace('test1') + ns1.register({ + name: 'test-request-1', + requestType: '@test/request' + }) + ns1.register({ + name: 'test-request-2', + requestType: '@test/request' + }) + } + }, { offset: 4 }) + t.fail('rebuilding with different offset did not throw') + } catch { + t.pass('rebuilding with different offset should throw') + } +}) From 28bc2ce4fe88e85911a504160e68f9c7b6f61bac Mon Sep 17 00:00:00 2001 From: Andrew Osheroff Date: Wed, 11 Jun 2025 12:57:36 -0700 Subject: [PATCH 2/2] Constructor offset check does not need Number.isInteger --- builder.cjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder.cjs b/builder.cjs index c895360..91911a5 100644 --- a/builder.cjs +++ b/builder.cjs @@ -22,7 +22,7 @@ class HyperdispatchNamespace { module.exports = class Hyperdispatch { constructor (schema, dispatchJson, { offset, dispatchDir = null, schemaDir = null } = {}) { - if (dispatchJson && Number.isInteger(dispatchJson.offset) && dispatchJson.offset !== offset) { + if (dispatchJson && dispatchJson.offset !== offset) { throw new Error('Cannot change the hyperdispatch offset once it has been defined once') } this.schema = schema