@arki/contracts
archivefor @arki/[email protected] · Tier 1: the stack
Shared Zod schemas and Drizzle contract helpers — branded ID-aware select / insert / update schemas with auto-applied column refinements.
Install
bun add @arki/contractsOther package managers
npm install @arki/contracts
pnpm add @arki/contracts
yarn add @arki/contractsRelease health for @arki/[email protected]
Doc examples
No example report was recorded for this version.
Open gaps
3 release checks fail
- check
file-agents-md - check
readme-h2-order - check
pkg-engines
Used by demos
No demo uses this package yet.
Runtimes
No engines field, so no runtime requirement is declared.
Benchmarks
No benchmarks are published for this version.
README
Shared Zod schemas and Drizzle contract helpers — branded ID-aware select / insert / update schemas with auto-applied column refinements.
Installation
npm install @arki/contracts
# or
bun add @arki/contracts
# or
pnpm add @arki/contractsDependencies: zod (v4) and zod-form-data.
The @arki/contracts/drizzle entry needs drizzle-orm (an optional peer dependency). The main entry never loads it.
Why
drizzle-zod's createSelectSchema walks Drizzle's dataType strings to infer Zod shapes. That mechanism loses three things:
- Branded ID types declared via
varchar('id').$type<\usr_${string}`>()collapse to plainstring`. jsonb('col').$type<Shape>()shapes collapse tounknown.- Runtime validation schemas stashed on a column by an ID-factory side-channel are not applied automatically.
@arki/contracts wraps drizzle-zod's factories so the output schema preserves the branded type and auto-applies any column-stashed runtime schema, with user-provided refines still winning.
Usage
Re-exported Zod surface
import { z } from '@arki/contracts';
const Email = z.email();The package re-exports everything from zod/v4, so you do not need a direct zod import alongside it.
Form data helpers
import { formData } from '@arki/contracts';
const schema = formData.zfd.formData({
name: formData.zfd.text(),
age: formData.zfd.numeric(),
});Branded select / insert / update schemas
import { jsonb, pgTable, varchar } from 'drizzle-orm/pg-core';
import { createInsertSchema, createSelectSchema } from '@arki/contracts/drizzle';
const users = pgTable('users', {
id: varchar('id').$type<`usr_${string}`>().primaryKey(),
email: varchar('email').notNull(),
profile: jsonb('profile').$type<{ displayName: string }>(),
});
const userSelect = createSelectSchema(users);
type User = z.infer<typeof userSelect>;
// { id: `usr_${string}`; email: string; profile: { displayName: string } | null }If an ID-factory stashed a Zod schema on a column via COLUMN_ZOD_SCHEMA, parsing rejects values with the wrong prefix:
userSelect.parse({ id: 'org_42', email: '[email protected]', profile: null });
// throws: id must start with "usr_"User-provided refines override the auto-applied schema:
const strictSelect = createSelectSchema(users, {
email: schema => schema.email(),
});API
Main entry, @arki/contracts (no Drizzle):
formData— re-exportedzod-form-datanamespace.z,ZodError, every Zod export — re-exported fromzod/v4.UserId,userIdSchema— shared id types.
Drizzle entry, @arki/contracts/drizzle:
createSelectSchema(table, refine?)— branded select schema.createInsertSchema(table, refine?)— branded insert schema.createUpdateSchema(table, refine?)— every field optional, otherwise like insert.COLUMN_ZOD_SCHEMA—Symbol.for('@arki/contracts/columnZodSchema')side-channel for ID factories.bufferSchema,jsonSchema,literalSchema,createSchemaFactory— re-exported fromdrizzle-orm/zod.
Documentation
@arki/contracts is framework-agnostic and works on its own. When you
compose it with the @arki/dot
application framework, see packages/dot/docs/ for plugin authoring,
lifecycle, and diagnostics.
Benchmarks
Building and using Zod schemas from a 15-column Drizzle table, compared with drizzle-orm/zod (which @arki/contracts wraps) and a hand-written Zod object.
Node v22.13.1 on Apple M2 Max, 2026-10-13. Median time per operation, lower is better.
Build select schema (15 columns)
Usually done once at startup.
| Library | Time / op | vs fastest |
|---|---|---|
| @arki/contracts createSelectSchema | 193.66 µs | 1.26× |
| drizzle-orm/zod createSelectSchema | 153.73 µs | fastest |
Build insert schema (15 columns)
| Library | Time / op | vs fastest |
|---|---|---|
| @arki/contracts createInsertSchema | 148.37 µs | 1.60× |
| drizzle-orm/zod createInsertSchema | 92.97 µs | fastest |
Parse one valid row
@arki/contracts and the hand-written schema check the id prefix "usr_"; plain drizzle-orm/zod only checks that id is a string.
| Library | Time / op | vs fastest |
|---|---|---|
| @arki/contracts select schema | 2.71 µs | 3.43× |
| drizzle-orm/zod select schema | 2.82 µs | 3.57× |
| hand-written z.object | 790.4 ns | fastest |
Read the rows with the contracts in mind:
- @arki/contracts calls drizzle-orm/zod and then adds branded types and the per-column runtime schemas stashed by ID factories; that extra work is the cost shown in the build rows.
- The hand-written schema does not read the table at all, so it only shows the floor for parsing.
Reproduce with bun run bench in the package directory; regenerate this section with bun run bench --write-readme.
License
MIT. See LICENSE.
Public imports
This version has no API index.