Skip to content

v0.5.0 — the storage layer, finished

Choose a tag to compare

@SteliyanH SteliyanH released this 31 Aug 09:24
· 11 commits to main since this release
bf93ff7

The three pre-1.0 roadmap items, shipped.

FileImageStore

The store most apps would otherwise write themselves: images as files in a directory you nominate, referenced by the project rather than embedded in it.

Tokens are relativefile:<name>.png, resolved against the store's directory — and that is the substantive detail rather than tidiness. An iOS app's container is /var/mobile/Containers/Data/Application/<UUID>/, and that UUID changes: on reinstall, on restore from backup, sometimes across an OS update. An absolute path written into a project on Monday can point nowhere on Friday, with the project itself perfectly intact.

Names are content hashes, so the same image is stored once and a token is stable across saves — re-saving an unchanged project produces identical bytes. prune(keeping:) deletes what a composition no longer refers to. Absolute tokens from hand-rolled stores still resolve, so nothing that exists stops opening.

SchemaMigrator

Steps operate on the raw JSON, not on KadrDocument — because an old document by definition doesn't decode into today's types. That is the whole reason a migration is needed, so a mechanism that requires decoding first can only handle the changes that didn't need it.

A gap in the chain is refused, not skipped: treating a missing step as a no-op hands back a document nobody migrated, which then gets saved over the original.

registered is empty and a test asserts it — a statement about the format's history, not a placeholder. Every change so far has been an added optional field. The runner is proven today against synthetic steps, because the day a migration is needed is the worst day to find out the mechanism doesn't work.

A committed fixture corpus

A broad schema-1 document — every clip kind, a nested track, filters with identities, animations, audio ramps, all three overlay kinds, crop, captions — decoded on every run, including a byte-for-byte re-encode.

This is the only test in the package that can catch a change breaking yesterday's files. Every other one encodes and decodes with today's code, so both sides move together and drift cancels out. The generator that writes the corpus is disabled on purpose: a suite that can rewrite its own evidence proves nothing.

Left open, deliberately

Async image resolution (PHImageManager is callback-based while ImageStore is synchronous — making that async changes the encode path for everyone, so it wants a real caller first), and the deletion policy when two projects share one store directory.

111 tests, 39 new.