In-Memory
In-memory store backed by a Map - the test/reference adapter. Zero dependencies, isomorphic, and non-persistent. Ideal for unit tests; not for production.
Installation
This adapter has no peer dependencies and no runtime requirements - it’s pure JavaScript backed by a Map, so it runs unchanged in Node, Bun, Deno, the browser, and edge runtimes.
npm install files-sdkpnpm add files-sdkyarn add files-sdkbun add files-sdkUsage
The in-memory adapter implements the same Adapter contract as every cloud adapter, but stores objects in a Map instead of touching disk or a network. That makes it the near-universal choice for testing code that uses Files without standing up real storage - and it doubles as the reference adapter, since it’s the smallest complete implementation.
import { Files } from "files-sdk";
import { memory } from "files-sdk/memory";
// A fresh, empty store. Same Adapter contract as the cloud adapters,
// so you can swap it in for tests without changing any call sites.
const files = new Files({
adapter: memory(),
});
await files.upload("hello.txt", "hi");
const file = await files.download("hello.txt");
await file.text(); // "hi"
Seeding fixtures
Pass initial to pre-populate the store - handy when a test needs objects present up front. Each value is a body (a string or bytes) or an object that also pins contentType / metadata / cacheControl, the way an upload() call would.
import { memory } from "files-sdk/memory";
const adapter = memory({
initial: {
"users/1.json": '{"id":1}',
"logo.png": pngBytes, // a Uint8Array
"report.csv": {
body: "a,b,c\n1,2,3",
contentType: "text/csv",
metadata: { owner: "alice" },
},
},
});
The constructor is synchronous, so seed values must convert to bytes without awaiting - that rules out Blob/File and ReadableStream. Seed those by calling upload() after construction.
Options
initial?Record<string, MemorySeed>
Keys to pre-populate the store with, useful for tests that need fixtures present up front. Each value is a body (string or bytes) or an object that also pins `contentType` / `metadata` / `cacheControl`. Bodies are copied in, so later mutation of a passed buffer does not change the stored bytes.
Record<string, MemorySeed>Inspecting the store
The raw escape hatch is the backing Map, so a test can read or reset it directly without going through the adapter:
const adapter = memory();
const files = new Files({ adapter });
await files.upload("a.txt", "x");
adapter.raw.size; // 1
adapter.raw.has("a.txt"); // true
adapter.raw.clear(); // wipe between tests
Behavior notes
- Non-persistent. The store lives in the process. Everything is lost when the process exits, and two
Filesinstances built from separatememory()calls don’t share data. Not for production. - Value semantics. Bodies are copied in on upload (and on seed), so mutating a
Uint8Arrayyou passed in later doesn’t change the stored bytes. - Content ETag. The
etagis a stable hash of the bytes (a pure-JS polynomial rolling hash, nonode:crypto), so re-uploading identical content yields the same ETag - matching how real backends behave.
Compatibility
| Method | Status | Notes |
|---|---|---|
upload |
✅ | Pause/resume via control works in-process; a token cannot resume in a new instance (the store lives in process memory). |
download |
✅ | |
delete |
✅ | |
list |
✅ | |
search |
✅ | |
head |
✅ | |
exists |
✅ | |
copy |
✅ | |
url |
⚠️ | Returns an opaque, non-fetchable memory://{key} URL - there’s no server backing the store. Throws NotFound for a missing key (the way a real fetch would 404). expiresIn and responseContentDisposition round-trip as query params so URL-building call sites stay testable, but nothing resolves the URL. For working dev URLs use the fs adapter with urlBaseUrl, or a real cloud adapter. |
signedUploadUrl |
⚠️ | Returns an inert memory://{key} placeholder PUT target - there’s no real upload endpoint, so a client can’t actually PUT to it. expiresIn round-trips into the URL and contentType into the returned headers so the signing flow stays testable; maxSize and minSize are ignored. Use upload() to write bytes. |