The COW version-control surface (fork, branches, checkout, commit,
getHistory/streamHistory, asOfCommit, brain.versions) is gone, along with
its subsystems: src/versioning/, the COW object store (CommitLog,
CommitObject, RefManager, TreeObject), HistoricalStorageAdapter, and the
TypeAwareHNSWIndex path it kept alive. The Db API (now/transact/asOf/
with/persist/restore) is the one versioning model in 8.0.
Survivors and replacements:
- BlobStorage survives (the VFS stores file content through it), relocated
to src/storage/blobStorage.ts with binaryDataCodec.ts; its adapter
interface is now BlobStoreAdapter, slimmed to the consumed surface
(write/read/has/delete/getMetadata + MIME-aware compression policy).
- brain.migrate() backup branches are replaced by persist-before-migrate:
MigrateOptions.backupTo persists a hard-link snapshot of the current
generation before any transform runs; MigrationResult.backupPath reports
it, and brain.restore(path) brings it back wholesale.
- CLI: cow.ts (fork/branch/checkout/history/migrate) is replaced by
snapshot.ts — snapshot <path>, restore <path>, history (tx-log),
generation.
- New public read API: brain.transactionLog({limit}) exposes the reified
tx-log (generation/timestamp/meta, newest first) that backs the CLI
history command; TxLogEntry is exported.
Tests: superseded suites deleted; fork/commit blocks excised from shared
suites; BlobStorage tests relocated + reworked against the slimmed store;
migration tests now prove the backupTo snapshot/restore round trip; new
transactionLog coverage in db-mvcc.
85 lines
2.4 KiB
TypeScript
85 lines
2.4 KiB
TypeScript
/**
|
|
* TestWrappingAdapter: Real blob store adapter for testing
|
|
*
|
|
* This adapter ACTUALLY wraps binary data in JSON (like production storage)
|
|
* to properly test the unwrap logic in BlobStorage.
|
|
*
|
|
* Unlike InMemoryBlobAdapter which stores Buffers directly,
|
|
* this adapter simulates real storage behavior:
|
|
* 1. Compresses with gzip
|
|
* 2. Wraps binary as {_binary: true, data: "base64..."}
|
|
* 3. Parses JSON on read (returns JS object, not Buffer)
|
|
*
|
|
* This ensures tests exercise the ACTUAL code path that caused v5.10.0 regression.
|
|
*/
|
|
|
|
import { BlobStoreAdapter } from '../../src/storage/blobStorage.js'
|
|
import { gzip, gunzip } from 'zlib'
|
|
import { promisify } from 'util'
|
|
|
|
const gzipAsync = promisify(gzip)
|
|
const gunzipAsync = promisify(gunzip)
|
|
|
|
export class TestWrappingAdapter implements BlobStoreAdapter {
|
|
private storage = new Map<string, Buffer>()
|
|
|
|
async get(key: string): Promise<any | undefined> {
|
|
const compressed = this.storage.get(key)
|
|
if (!compressed) {
|
|
return undefined
|
|
}
|
|
|
|
// Decompress (like real storage)
|
|
const decompressed = await gunzipAsync(compressed)
|
|
|
|
// Parse JSON (like real storage)
|
|
// This returns a JS object: {_binary: true, data: "base64..."}
|
|
// NOT a Buffer!
|
|
return JSON.parse(decompressed.toString())
|
|
}
|
|
|
|
async put(key: string, data: Buffer): Promise<void> {
|
|
// Use key-based dispatch (matches the baseStorage blob adapter)
|
|
// NO GUESSING - key format explicitly declares data type
|
|
const obj = key.includes('-meta:') || key.startsWith('ref:')
|
|
? JSON.parse(data.toString()) // Metadata/refs: ALWAYS JSON
|
|
: { _binary: true, data: data.toString('base64') } // Blobs: ALWAYS binary
|
|
|
|
// Stringify to JSON
|
|
const jsonStr = JSON.stringify(obj)
|
|
|
|
// Compress (like real storage)
|
|
const compressed = await gzipAsync(Buffer.from(jsonStr))
|
|
|
|
// Store compressed data
|
|
this.storage.set(key, compressed)
|
|
}
|
|
|
|
async delete(key: string): Promise<void> {
|
|
this.storage.delete(key)
|
|
}
|
|
|
|
async list(prefix: string): Promise<string[]> {
|
|
const keys: string[] = []
|
|
for (const key of this.storage.keys()) {
|
|
if (key.startsWith(prefix)) {
|
|
keys.push(key)
|
|
}
|
|
}
|
|
return keys
|
|
}
|
|
|
|
/**
|
|
* Clear all storage (for test cleanup)
|
|
*/
|
|
clear(): void {
|
|
this.storage.clear()
|
|
}
|
|
|
|
/**
|
|
* Get storage size (for testing)
|
|
*/
|
|
size(): number {
|
|
return this.storage.size
|
|
}
|
|
}
|