Skip to content
Open
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
12 changes: 6 additions & 6 deletions example.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
const Hyperschema = require('hyperschema')
const Hyperdispatch = require('hyperdispatch')

const SCHEMA_DIR = './spec/hyperschema'
const DISPATCH_DIR = './spec/hyperdispatch'

const schema = Hyperschema.from(SCHEMA_DIR)
const ns1 = schema.namespace('example')
Expand All @@ -22,12 +24,9 @@ ns1.register({
})

// Write the schema to disk
Hyperschema.toDisk(schema)

const Hyperdispatch = require('hyperdispatch')

const DISPATCH_DIR = './spec/hyperdispatch'
const hyperdispatch = Hyperdispatch.from(SCHEMA_DIR, DISPATCH_DIR)
const hyperdispatch = Hyperdispatch.from(DISPATCH_DIR)
hyperdispatch.registerSchema(schema)

const ns2 = hyperdispatch.namespace('example')

Expand All @@ -45,7 +44,8 @@ ns2.register({
requestType: '@example/request2'
})

// Write the hyperdispatch configuration to disk
// Write the hyperdispatch/hyperschema configurations to disk
Hyperschema.toDisk(schema)
Hyperdispatch.toDisk(hyperdispatch)

const { Router, dispatch } = require('./spec/hyperdispatch')
Expand Down
29 changes: 15 additions & 14 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
const p = require('path')
const fs = require('fs')
const Hyperschema = require('hyperschema')

const generateCode = require('./lib/codegen')

const CODE_FILE_NAME = 'index.js'
const MESSAGES_FILE_NAME = 'messages.js'
const DISPATCH_JSON_FILE_NAME = 'dispatch.json'

class HyperdispatchNamespace {
Expand All @@ -21,12 +19,11 @@ class HyperdispatchNamespace {
}

module.exports = class Hyperdispatch {
constructor (schema, dispatchJson, { offset, dispatchDir = null, schemaDir = null } = {}) {
this.schema = schema
constructor (dispatchJson, { offset, dispatchDir = null } = {}) {
this.version = dispatchJson ? dispatchJson.version : 0
this.offset = dispatchJson ? dispatchJson.offset : (offset || 0)
this.dispatchDir = dispatchDir
this.schemaDir = schemaDir
this.schema = null

this.namespaces = new Map()
this.handlersByName = new Map()
Expand All @@ -51,6 +48,8 @@ module.exports = class Hyperdispatch {
}

register (fqn, description) {
if (!this.schema) throw new Error('registerSchema must be called with a Hyperschema instance before registering handlers')

const existingByName = this.handlersByName.get(fqn)
const existingById = Number.isInteger(description.id) ? this.handlersById.get(description.id) : null
if (existingByName && existingById) {
Expand Down Expand Up @@ -89,15 +88,19 @@ module.exports = class Hyperdispatch {
}
}

registerSchema (schema) {
if (this.schema) throw new Error('Already registered a hyperschema instance')
this.schema = schema
}

toJSON () {
return {
version: this.version,
schema: this.handlers.map(({ type, ...h }) => h)
}
}

static from (schemaJson, dispatchJson, opts) {
const schema = Hyperschema.from(schemaJson)
static from (dispatchJson, opts) {
if (typeof dispatchJson === 'string') {
const jsonFilePath = p.join(p.resolve(dispatchJson), DISPATCH_JSON_FILE_NAME)
let exists = false
Expand All @@ -107,23 +110,21 @@ module.exports = class Hyperdispatch {
} catch (err) {
if (err.code !== 'ENOENT') throw err
}
opts = { ...opts, dispatchDir: dispatchJson, schemaDir: schemaJson }
if (exists) return new this(schema, JSON.parse(fs.readFileSync(jsonFilePath)), opts)
return new this(schema, null, opts)
opts = { ...opts, dispatchDir: dispatchJson }
if (exists) return new this(JSON.parse(fs.readFileSync(jsonFilePath)), opts)
return new this(null, opts)
}
return new this(schema, dispatchJson, opts)
return new this(dispatchJson, opts)
}

static toDisk (hyperdispatch, dispatchDir) {
if (!dispatchDir) dispatchDir = hyperdispatch.dispatchDir
fs.mkdirSync(dispatchDir, { recursive: true })

const messagesPath = p.join(p.resolve(dispatchDir), MESSAGES_FILE_NAME)
const dispatchJsonPath = p.join(p.resolve(dispatchDir), DISPATCH_JSON_FILE_NAME)
const codePath = p.join(p.resolve(dispatchDir), CODE_FILE_NAME)

fs.writeFileSync(dispatchJsonPath, JSON.stringify(hyperdispatch.toJSON(), null, 2), { encoding: 'utf-8' })
fs.writeFileSync(messagesPath, hyperdispatch.schema.toCode(), { encoding: 'utf-8' })
fs.writeFileSync(codePath, generateCode(hyperdispatch), { encoding: 'utf-8' })
fs.writeFileSync(codePath, generateCode(hyperdispatch, { directory: dispatchDir }), { encoding: 'utf-8' })
}
}
7 changes: 5 additions & 2 deletions lib/codegen.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
const p = require('path')
const s = require('generate-string')

module.exports = function generateCode (hyperdispatch) {
module.exports = function generateCode (hyperdispatch, { directory = '.' } = {}) {
const messagesPath = p.relative(p.resolve(directory), hyperdispatch.schema.dir).replaceAll('\\', '/')

let str = ''
str += '// This file is autogenerated by the hyperdispatch compiler\n'
str += '/* eslint-disable camelcase */\n'
str += '\n'
str += 'const { c, b4a, assert } = require(\'hyperdispatch/runtime\')\n'
str += 'const { version, getEncoding, setVersion } = require(\'./messages.js\')\n'
str += `const { version, getEncoding, setVersion } = require(${s(messagesPath)})\n`
str += '\n'
str += 'const defaultVersion = version\n'
str += '\n'
Expand Down
8 changes: 6 additions & 2 deletions test/helpers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,13 @@ class TestBuilder {
rebuild (builder, opts) {
const schema = Hyperschema.from(this.schemaDir)
builder.schema(schema)
Hyperschema.toDisk(schema)
const hyperdispatch = Hyperdispatch.from(this.schemaDir, this.dispatchDir, opts)

const hyperdispatch = Hyperdispatch.from(this.dispatchDir, opts)
hyperdispatch.registerSchema(schema)

builder.dispatch(hyperdispatch)

Hyperschema.toDisk(schema)
Hyperdispatch.toDisk(hyperdispatch)

if (this.module) {
Expand Down