Teardown

In-memory

The dependency-free in-memory storage adapter for tests and prototyping.

createMemoryStorage(seed?) returns a dependency-free TeardownStorage backed by plain Maps. It is the primary test fake for the domain services (the core of the SDK's TDD strategy) and is handy for local prototyping and demos.

It is single-process and non-persistent — everything is lost when the process exits. Do not use it in production.

Usage

import { createTeardown } from "@teardown/server";
import { createMemoryStorage } from "@teardown/server/adapters/memory";

const td = createTeardown({
  storage: createMemoryStorage(),
  config: { sessionSecret: "test-secret" },
});

Seeding

Identify and events resolve the request against the projects and environments you seed. In hosted/multi-tenant mode they also authenticate the API key against apiKeys; in single-tenant mode (tenant on createTeardown) you can omit apiKeys entirely. The in-memory store starts empty, so seed the fixtures up front via the optional MemorySeed:

import { createMemoryStorage } from "@teardown/server/adapters/memory";

const storage = createMemoryStorage({
  projects: [
    {
      id: "proj_1",
      org_id: "org_1",
      name: "Demo",
      slug: "demo",
      type: "EXPO",
      status: "ACTIVE",
      push_notifications_enabled: false,
      first_session_at: null,
      created_at: new Date().toISOString(),
      updated_at: new Date().toISOString(),
    },
  ],
  environments: [
    {
      id: "env_1",
      project_id: "proj_1",
      name: "Production",
      slug: "production",
      type: "PRODUCTION",
      created_at: new Date().toISOString(),
      updated_at: new Date().toISOString(),
    },
  ],
  apiKeys: [{ key: "pk_test_123", project_id: "proj_1", org_id: "org_1" }],
});

MemorySeed

FieldTypeDescription
projectsProjectEntity[]Projects to seed (looked up by the API-key auth and the management services)
environmentsEnvironmentEntity[]Environments to seed (resolved by environment_slug during identify/events)
apiKeysArray<{ key; key_id?; project_id; org_id }>Publishable keys mapped to their project/org. key_id defaults to a random uuid

Everything created at runtime (users, devices, sessions, versions, builds, push tokens, events) is generated with random UUID ids and ISO-8601 timestamps, matching the entity conventions.

Behaviour parity

The in-memory adapter implements the same subtle behaviours a production storage layer must, so it's a faithful stand-in for service-level tests:

  • sessions.findValidForDevice returns the newest non-expired session (newest-first by created_at), matching the production query.
  • builds.update setting status marks the build status_overridden = true, unless an explicit status_overridden is also passed (then the explicit value wins).
  • builds.updateStatusByVersion resets status_overridden = false on every build (a full cascade supersedes manual overrides); updateStatusByVersionExcludingOverridden skips overridden builds.
  • versions.upsertByName / builds.upsertByVersionBuildPlatform return the existing row on a natural-key conflict.

It intentionally does not implement transaction, which exercises the runtime's no-mandatory-transaction path.

Testing with a fixed clock

Combine the in-memory store with an injected clock for deterministic assertions on timestamps and generated ids:

const td = createTeardown({
  storage: createMemoryStorage(),
  config: { sessionSecret: "test-secret" },
  clock: {
    now: () => new Date("2026-01-01T00:00:00.000Z"),
    uuid: () => "00000000-0000-0000-0000-000000000000",
  },
});