- BaseKVStorage / BaseEventStorage / BaseDocumentStorage define the API once; implementations provide only raw primitives (client and server share an API) - Drop KV indexes, query planner, unique indexes; document stores take index fields - Escape every char <= '/' so child keys stay contiguous; skip-scan is now simple - Event-sourced documents = event storage + any document store for projections - New folder layout (kv-storage, event-storage, document-storage, utils); tests only in test/ Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017Qxbkp4tA7G5SCWjzWuxmE
25 lines
1.2 KiB
TypeScript
25 lines
1.2 KiB
TypeScript
import { createServer } from 'node:http'
|
|
import type { AddressInfo } from 'node:net'
|
|
|
|
/** Serves a `Request → Response` handler over a real socket (test helper). */
|
|
export async function serve(handle: (request: Request) => Promise<Response>): Promise<{ url: string; close: () => Promise<void> }> {
|
|
const server = createServer(async (req, res) => {
|
|
const chunks: Buffer[] = []
|
|
for await (const chunk of req) chunks.push(chunk as Buffer)
|
|
const response = await handle(
|
|
new Request(`http://localhost${req.url}`, { method: req.method, body: req.method === 'POST' ? Buffer.concat(chunks) : undefined }),
|
|
)
|
|
res.writeHead(response.status, Object.fromEntries(response.headers))
|
|
if (!response.body) return void res.end()
|
|
const reader = response.body.getReader()
|
|
res.on('close', () => void reader.cancel().catch(() => {}))
|
|
for (let next = await reader.read(); !next.done; next = await reader.read()) res.write(next.value)
|
|
res.end()
|
|
})
|
|
await new Promise<void>((resolve) => server.listen(0, '127.0.0.1', resolve))
|
|
return {
|
|
url: `http://127.0.0.1:${(server.address() as AddressInfo).port}`,
|
|
close: () => new Promise((resolve) => (server.closeAllConnections(), server.close(() => resolve()))),
|
|
}
|
|
}
|