class MemoryAdapter
implements IDatabaseAdapter
Since 0.1.0

In-memory implementation of IDatabaseAdapter.

Stores entities in plain Map structures, supporting basic CRUD, filtering, sorting, pagination, and transaction semantics.

Properties

Portable isolation levels this adapter can honestly provide.

Methods

Begin a transaction, returning a handle that can open transaction-scoped data sources as well as commit and roll back.

connect(): Promise<void>
countEntities(
entity: string,
where: Record<string, unknown>,
): Promise<number>

Count entities matching a filter.

createDataSource(
entity: string,
primaryKey?: string | readonly string[]
): DataSource

Open a non-transactional data source for the named entity.

deleteEntity(
entity: string,
): Promise<boolean>

Delete an entity by primary key.

disconnect(): Promise<void>
findEntityById(
entity: string,
): Promise<Record<string, unknown> | null>

Find a single entity by its primary key value.

findPageInternal(
entity: string,
getRecords: () => Record<string, unknown>[]
): Promise<PageResult>

Core findPage implementation shared between the non-transactional data source and the transaction overlay. The getRecords thunk lets the two callers — the committed store and the per-tx overlay — each supply their visible row set without duplicating the cursor-handling logic.

Pipeline:

  1. Decode the incoming cursor. When absent, the walk starts at page one. When malformed, reject by name.
  2. When present, verify the sort fingerprint so a cross-sort cursor is refused rather than served a silently wrong page.
  3. Build the portable keyset predicate with keysetPredicate, conjoin it with the caller's own filter (when present), and apply where / filter / orderBy in the same order as findAll.
  4. Fetch limit + 1 rows (the one-extra-row probe): if more than limit are returned there IS a next page and the last returned row yields the next cursor; otherwise the page is terminal and nextCursor is null.
  5. When a projection is active, the key columns are added to the internal select so they participate in the probe and are available for cursor minting; they are stripped from the returned rows so the caller's projection is what comes back — plan §8 risk.

decoded.orderedValues carries the value of EVERY ordered field (in orderBy order) from the last row of the previous page — not just key column values. This is what keysetPredicate indexes by position to build the "row after this one" comparison.

getStore(
entity: string,
primaryKey?: string | readonly string[]
): EntityStore

Returns the internal store for an entity, creating it lazily.

insertEntity(
entity: string,
data: Partial<Record<string, unknown>>
): Promise<Record<string, unknown>>

Insert a new entity. Generates key values if absent.

isReady(): boolean
queryEntities(
entity: string,
): Promise<Record<string, unknown>[]>

Query entities with full filtering, sorting, and pagination.

rawQuery<T>(
_sql: string,
_params?: unknown[]
): Promise<T[]>

Execute a raw query in the backend's own dialect.

updateEntity(
entity: string,
data: Partial<Record<string, unknown>>
): Promise<Record<string, unknown>>

Update an existing entity by primary key, merging fields.