@zvk/db-kit
v0.2.3
Published
Framework-agnostic repository, query, transaction, idempotency, and adapter helpers for ZVK applications.
Readme
@zvk/db-kit
Framework-agnostic repository, query, transaction, idempotency, and adapter helpers for ZVK applications.
import { createRepositoryService, createRepositoryWorkflow } from "@zvk/db-kit";
import { evaluateIdempotencyClaim } from "@zvk/db-kit/idempotency";
import { firstRowOrNull, hasReturnedRow, normalizeCursorPaginationInput } from "@zvk/db-kit/query";
import type { CursorPaginationQuery, PaginationQuery } from "@zvk/db-kit/query";
import { resolveLocalDatabasePath, createSqlitePragmaStatements, createMigrationJournalTableSql } from "@zvk/db-kit/local-sqlite";
import { createDrizzleRepositoryAdapter } from "@zvk/db-kit/drizzle";
import { createDrizzleSelectLimitChain, createMemoryRepository } from "@zvk/db-kit/test-utils";
import { openBunSqliteDatabase, applySqlitePragmas } from "@zvk/db-kit/local-sqlite/bun";
import { createTemporarySqlitePath, createInMemoryMigrationJournal } from "@zvk/db-kit/local-sqlite/test-utils";See ../../docs/package-boundary-matrix.md for the package-family runtime
boundary matrix. The root package and pure query/repository subpaths stay
browser-safe; Drizzle and local SQLite helpers stay on explicit adapter,
Node-only, or test-only subpaths.
Use evaluateIdempotencyClaim for provider-neutral webhook/job claim decisions after an app maps its
own persistence row into an idempotency claim snapshot.
Use firstRowOrNull, exactlyOneRowOrNull, and hasReturnedRow for common
database row-array normalization around app-owned query builders.
Use createRepositoryWorkflow when an app already has a repository port and
wants a small service recipe for CRUD operations plus paginated lists and
single-row list lookups:
const projectWorkflow = createRepositoryWorkflow<
Project,
ProjectCreate,
ProjectUpdate,
PaginationQuery & { readonly organizationId: string }
>({
entityName: "Project",
repository: projectRepository,
pagination: {
defaultLimit: 20,
maxLimit: 100
}
});
const projects = await projectWorkflow.listPage({
organizationId,
limit: 50,
offset: 0
});
const firstProject = await projectWorkflow.findFirst({
organizationId
});The workflow helper only normalizes limit/offset, calls the repository
list and optional count ports, returns createPaginatedListResult, and
keeps all data inside Result envelopes. App code still owns schemas, filters,
authorization, tenancy, SQL, logging, and whether count ignores pagination
while respecting app-owned filters.
For cursor or seek pagination, extend an app-owned query type from
CursorPaginationQuery and pass opaque cursor fields through the workflow:
type ProjectCursorQuery = CursorPaginationQuery & {
readonly organizationId: string;
};
const pagination = normalizeCursorPaginationInput({
afterCursor: request.query.after,
limit: 50,
maxLimit: 100
});normalizeCursorPaginationInput only normalizes limit/offset and preserves
cursor, beforeCursor, and afterCursor values as app-owned opaque strings.
Apps remain responsible for cursor encoding, stable sort keys, seek predicates,
database-specific SQL, and deciding whether offset and cursor fields may be
combined for a route.
Use @zvk/db-kit/local-sqlite for local database path resolution, pragma plan
generation, and journal-table SQL helpers. This keeps app bootstrapping and migration
state setup deterministic without forcing app frameworks to own these reusable
concerns.
Use @zvk/db-kit/local-sqlite/bun for Bun-specific SQLite open/exec helpers.
Open adapters accept an open callback and apply pragma statements before returning the live handle.
Use @zvk/db-kit/local-sqlite/test-utils for framework-neutral filesystem and
migration-journal test helpers.
The root package stays runtime-dependent only on @zvk/contracts. The optional @zvk/db-kit/drizzle subpath provides structural helpers for apps that already use Drizzle ORM, without owning app schemas, migrations, or database policy.
Apps remain responsible for concrete schemas, migration SQL files, migration ordering, repair policy, authorization, tenancy checks, product naming, and business rules.
Use @zvk/db-kit/test-utils for framework-neutral repository fakes and Drizzle
chain test doubles. The Drizzle chain helpers do not import a test framework;
apps that need spy assertions can pass their own mock-function wrapper.
Repo Skill
Use .codex/skills/use-zvk-db-kit/SKILL.md when maintaining this package.
See ../../docs/package-boundary-matrix.md for the browser-safe, adapter-only, Node-only, and test-only subpaths.
