Appearance
Memory adapter
An in-memory SaveAdapter backed by a Map. Nothing persists beyond the process — which is exactly what tests, SSR and ephemeral sessions want.
ts
import { MemoryAdapter } from "@idlekitjs/storage/memory";Usage
ts
import { SaveManager } from "@idlekitjs/core";
import { MemoryAdapter } from "@idlekitjs/storage/memory";
const save = new SaveManager<State>({
key: "test",
version: 1,
adapter: new MemoryAdapter(),
});In tests
The main use: exercising real save/load flows — including migrations and the loaded event — without a browser:
ts
import { describe, it, expect } from "vitest";
import { createEngine, SaveManager } from "@idlekitjs/core";
import { MemoryAdapter } from "@idlekitjs/storage/memory";
it("restores state through a save round-trip", async () => {
const adapter = new MemoryAdapter();
const save = new SaveManager<State>({ key: "t", version: 1, adapter });
const engine = createEngine<State>({ initialState: { coins: 42 } });
await save.save(engine.state);
const fresh = createEngine<State>({ initialState: { coins: 0 } });
const freshSave = new SaveManager<State>({ key: "t", version: 1, adapter });
await fresh.load(freshSave);
expect(fresh.state.coins).toBe(42);
});You can also pre-seed the adapter to simulate an existing save (old versions for migration tests, a savedAt in the past for offline-progress tests):
ts
adapter.write(
"t",
JSON.stringify({ version: 1, savedAt: Date.now() - 3_600_000, state: { coins: 10 } }),
);Notes
- Each
MemoryAdapterinstance is its own isolated store — share the instance if twoSaveManagers must see the same data. - All methods are synchronous; the
SaveManagerawaits them anyway, so the calling code is identical to any other backend.