Automerge backed Markdown editor for the Atmosphere
Something went wrong. Try again.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495import { createServer } from 'vite'import { chromium } from 'playwright'
const executablePath = process.env.PLAYWRIGHT_CHROMIUM_BINif (!executablePath) throw new Error('Set PLAYWRIGHT_CHROMIUM_BIN to Chromium')const server = await createServer({ configFile: false, server: { host: '127.0.0.1', port: 0 } })let browsertry { await server.listen() const address = server.httpServer.address() browser = await chromium.launch({ executablePath, headless: true }) const url = `http://127.0.0.1:${address.port}/tests/invariants/indexing/minisearch-delta-spike.html` const vocabulary = ['garden', 'orchard', 'biodiversity', 'meeting', 'planning', 'research', 'record', 'backlinks', 'journal', 'task', 'proposal', 'design', 'software', 'writing', 'recipe', 'ingredients', 'history', 'projects', 'community', 'markdown'] const queries = ['biodiversity', 'biodiversitty', 'orch', 'orchard', 'meeting', 'recipe', 'community', 'garden planning'] for (const count of [1000, 10000]) { const context = await browser.newContext() try { const page = await context.newPage() const open = async () => { await page.goto(url) await page.waitForFunction(() => Boolean(window.miniSpike)) } const input = { count, vocabulary, queries } await open() const first = await page.evaluate(async ({ count, vocabulary }) => { const notes = Array.from({ length: count }, (_, i) => { const terms = Array.from({ length: 75 }, (_, j) => vocabulary[(i * 7 + j * 13 + Math.floor(i / 11)) % vocabulary.length]).join(' ') const name = `${vocabulary[i % vocabulary.length]}-${i}.md` return { id: `automerge:note-${i}`, heads: `heads-${i}`, name, path: `notes/${vocabulary[i % vocabulary.length]}/${name}`, content: `# ${name}\n${terms}\n[[note-${(i + 17) % count}]]` } }) return window.miniSpike.initialize(notes) }, input) await open() const warm = await page.evaluate(async ({ count, vocabulary, queries }) => { const notes = Array.from({ length: count }, (_, i) => { const terms = Array.from({ length: 75 }, (_, j) => vocabulary[(i * 7 + j * 13 + Math.floor(i / 11)) % vocabulary.length]).join(' ') const name = `${vocabulary[i % vocabulary.length]}-${i}.md` return { id: `automerge:note-${i}`, heads: `heads-${i}`, name, path: `notes/${vocabulary[i % vocabulary.length]}/${name}`, content: `# ${name}\n${terms}\n[[note-${(i + 17) % count}]]` } }) const restoreMs = window.miniSpike.restoreMs const reconcileStarted = performance.now() const changed = await window.miniSpike.reconcile(notes) const reconcileMs = performance.now() - reconcileStarted const changedNote = { ...notes[count - 1], heads: 'edited-heads', content: 'extraordinary xylophone only-this-document' } const editStarted = performance.now() await window.miniSpike.upsert(changedNote) const editMs = performance.now() - editStarted notes[count - 1] = changedNote const compared = window.miniSpike.oracle(notes, queries) return { restoreMs, reconcileMs, changed, editMs, deltaCount: await window.miniSpike.deltaCount(), parity: compared.map(item => ({ query: item.query, top50IdsEqual: JSON.stringify(item.actual.map(result => result.id)) === JSON.stringify(item.fresh.map(result => result.id)), exactScoresEqual: JSON.stringify(item.actual.map(result => result.score)) === JSON.stringify(item.fresh.map(result => result.score)) })), } }, input) await open() const replay = await page.evaluate(async ({ count, vocabulary, queries }) => { const notes = Array.from({ length: count }, (_, i) => { const terms = Array.from({ length: 75 }, (_, j) => vocabulary[(i * 7 + j * 13 + Math.floor(i / 11)) % vocabulary.length]).join(' ') const name = `${vocabulary[i % vocabulary.length]}-${i}.md` return { id: `automerge:note-${i}`, heads: `heads-${i}`, name, path: `notes/${vocabulary[i % vocabulary.length]}/${name}`, content: `# ${name}\n${terms}\n[[note-${(i + 17) % count}]]` } }) notes[count - 1] = { ...notes[count - 1], heads: 'edited-heads', content: 'extraordinary xylophone only-this-document' } const compared = window.miniSpike.oracle(notes, queries) return { restoreMs: window.miniSpike.restoreMs, replayed: window.miniSpike.replayed, parity: compared.map(item => ({ query: item.query, top50IdsEqual: JSON.stringify(item.actual.map(result => result.id)) === JSON.stringify(item.fresh.map(result => result.id)), exactScoresEqual: JSON.stringify(item.actual.map(result => result.score)) === JSON.stringify(item.fresh.map(result => result.score)) })) } }, input) const repeated = await page.evaluate(async ({ count, vocabulary, queries }) => { const notes = Array.from({ length: count }, (_, i) => { const terms = Array.from({ length: 75 }, (_, j) => vocabulary[(i * 7 + j * 13 + Math.floor(i / 11)) % vocabulary.length]).join(' ') const name = `${vocabulary[i % vocabulary.length]}-${i}.md` return { id: `automerge:note-${i}`, heads: `heads-${i}`, name, path: `notes/${vocabulary[i % vocabulary.length]}/${name}`, content: `# ${name}\n${terms}\n[[note-${(i + 17) % count}]]` } }) const spike = window.miniSpike const id = count - 1 for (let i = 0; i < 100; i++) { notes[id] = { ...notes[id], heads: `edit-${i}`, content: `biodiversity garden meeting revision ${i}` } await spike.upsert(notes[id]) } const summarize = () => spike.oracle(notes, queries).map(item => ({ query: item.query, sameOrder: JSON.stringify(item.actual.map(result => result.id)) === JSON.stringify(item.fresh.map(result => result.id)), top10Overlap: item.actual.slice(0, 10).filter(result => item.fresh.slice(0, 10).some(other => other.id === result.id)).length, firstScores: [item.actual[0]?.score, item.fresh[0]?.score], })) const before = { stats: spike.stats(), queries: summarize() } await spike.vacuum() return { before, after: { stats: spike.stats(), queries: summarize() }, deltaCount: await spike.deltaCount() } }, input) console.log(JSON.stringify({ count, first, warm, replay, repeated }, null, 2)) } finally { await context.close() } }} finally { await browser?.close() await server.close()}