import test from 'brittle'
import Corestore from 'corestore'
import { mkdtempSync } from 'fs'
import { join } from 'path'
import { tmpdir } from 'os'
import { replicateAndSync } from 'autobase-test-helpers'
import { Room, jsonSchema, composeSchemas } from '../index.js'
function tmp () { return mkdtempSync(join(tmpdir(), 'rooms-compose-')) }
// Two disjoint toy op-domains, plus a shared idempotent op (set-meta) to
// exercise the documented "shared op.type runs all handlers" behaviour.
const alpha = jsonSchema({
validate (op) { if (op.type === 'put-a' && !op.id) throw new Error('put-a needs id') },
async apply (batch, op) {
if (op.type === 'put-a') await batch.put('a:' + op.id, { v: op.v })
else if (op.type === 'set-meta') await batch.put('meta:' + op.key, { value: op.value })
}
})
const beta = jsonSchema({
validate (op) { if (op.type === 'put-b' && !op.id) throw new Error('put-b needs id') },
async apply (batch, op) {
if (op.type === 'put-b') await batch.put('b:' + op.id, { v: op.v })
else if (op.type === 'set-meta') await batch.put('meta:' + op.key, { value: op.value })
}
})
test('composeSchemas: one Room carries two op-domains and replicates both', async (t) => {
const roomA = new Room(new Corestore(tmp()), {
schema: composeSchemas([alpha, beta]), namespace: 'shared'
})
await roomA.ready()
await roomA.append({ type: 'put-a', id: '1', v: 'aaa' })
await roomA.append({ type: 'put-b', id: '1', v: 'bbb' })
await roomA.append({ type: 'set-meta', key: 'k', value: 'm' })
await roomA.base.update()
const roomB = new Room(new Corestore(tmp()), {
schema: composeSchemas([alpha, beta]), namespace: 'shared', bootstrapKey: roomA.key
})
await roomB.ready()
await replicateAndSync([roomA.base, roomB.base])
const a = await roomB.view.get('a:1')
const b = await roomB.view.get('b:1')
const m = await roomB.view.get('meta:k')
t.is(a && a.value.v, 'aaa', 'domain A op replicated to B')
t.is(b && b.value.v, 'bbb', 'domain B op replicated to B')
t.is(m && m.value.value, 'm', 'shared set-meta applied once without error')
await roomA.close()
await roomB.close()
})
test('composeSchemas: validateOp runs every schema; cross-domain ops do not throw', async (t) => {
const room = new Room(new Corestore(tmp()), {
schema: composeSchemas([alpha, beta]), namespace: 's'
})
await room.ready()
// put-b is unknown to alpha's switch but valid for beta — must not throw.
await t.execution(room.append({ type: 'put-b', id: '2', v: 'x' }))
await room.close()
})
test('composeSchemas: rejects empty input', (t) => {
t.exception(() => composeSchemas([]))
t.exception(() => composeSchemas(null))
})