OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-rooms / lib / json-schema.js

53 lines · javascript ref:
/**
 * jsonSchema — helper to build a Room schema from a single apply function
 *
 * Most domain schemas (issues, orgs, todos) just want JSON encoding +
 * a switch in the apply function. This helper saves them from defining
 * encodeOp/decodeOp/validateOp boilerplate.
 *
 * Usage:
 *
 *   import { jsonSchema } from 'hyper-rooms'
 *
 *   const todosSchema = jsonSchema({
 *     async apply (batch, op, host) {
 *       if (op.type === 'add-todo') {
 *         await batch.put(`todo:${op.id}`, { text: op.text, done: false })
 *       }
 *     },
 *     // optional: validate ops before encoding
 *     validate (op) {
 *       if (op.type === 'add-todo' && !op.text) throw new Error('text required')
 *     }
 *   })
 *
 *   const room = new Room(corestore, { schema: todosSchema })
 */

import b4a from 'b4a'

export function jsonSchema ({ apply, validate } = {}) {
  if (typeof apply !== 'function') {
    throw new Error('jsonSchema requires an apply function')
  }

  return {
    encodeOp (op) {
      return b4a.from(JSON.stringify(op), 'utf8')
    },

    decodeOp (buf) {
      const str = b4a.toString(buf, 'utf8')
      return JSON.parse(str)
    },

    validateOp (op) {
      if (!op || typeof op !== 'object') throw new Error('op must be an object')
      if (typeof op.type !== 'string') throw new Error('op.type must be a string')
      if (validate) validate(op)
    },

    apply
  }
}