An in-memory StorageProvider — blobs in a Map, plus the three inspection
methods that make that useful.
npm install @apograph/media-provider-memoryimport { createMemoryStorageProvider } from '@apograph/media-provider-memory';
createMemoryStorageProvider({ maxTotalBytes: 256 * 1024 * 1024 });Shipped, not test scaffolding
The same call the copilot’s fake provider
makes: a loop nobody can drive without a key and a network is a loop nobody
exercises.
Storage needed it more. Before this package existed, the server’s end-to-end
suite stood up its own Map-backed provider inline — a second implementation of
the port that no rule held to the contract. It had already drifted: a
missing key rejected with a bare Error rather than the port’s not-found error,
so the route that maps that error to a 404 was never exercised by any run.
Not for a deployment
Blobs die with the process. And the media plugin’s boot check refuses to start a database whose rows were written by anything else — including a previous run of this one, whose bytes are gone.
What it adds to the port
| Method | What it does |
|---|---|
keys() | Every stored key, sorted |
totalBytes() | The store’s current size |
clear() | Empties it |
Those are the provider’s own API, not the port’s — the core never sees them. A test harness turns them into its own reset and assertion helpers.
MemoryStoreFullError is raised when a put would push the store past
maxTotalBytes (256 MB by default). A test that uploads more than it meant to
should fail as a test, not as an out-of-memory kill that takes the whole run
with it.
Two decisions worth knowing
contentTypeMetadata: true, where local disk
declares false. A Map has somewhere to put the content type and a filesystem
does not. It is the only provider that declares it, so it is also the only place
the true branch of that capability is exercised.
put buffers, and says so — streamingPut: false. Bytes are metered for
size and checksum and nothing reaches the Map until the whole body has
arrived, which is the port’s all-or-nothing rule met by construction rather than
by cleanup: a body that fails mid-stream leaves the store exactly as it was.
Keys are built the same way the local provider builds them. The port says a key
is opaque, so this is not required — but a key that reads the same in both makes
a storage_key in a database dump legible, and lets an assertion be shared.