/**
* 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
}
}