Skip to content

arki-labs/contracts

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@arki/contracts

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/contracts

Peer-installs:

  • drizzle-orm
  • zod (v4)
  • zod-form-data

Why

drizzle-zod's createSelectSchema walks Drizzle's dataType strings to infer Zod shapes. That mechanism loses three things:

  1. Branded ID types declared via varchar('id').$type<\usr_${string}`>()collapse to plainstring`.
  2. jsonb('col').$type<Shape>() shapes collapse to unknown.
  3. 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.string().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 { pgTable, varchar, jsonb } from 'drizzle-orm/pg-core';
import { createSelectSchema, createInsertSchema } from '@arki/contracts';

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: 'a@example.com', 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

  • createSelectSchema(table, refine?) — branded select schema.
  • createInsertSchema(table, refine?) — branded insert schema.
  • createUpdateSchema(table, refine?) — every field optional, otherwise like insert.
  • COLUMN_ZOD_SCHEMASymbol.for('@arki/contracts/columnZodSchema') side-channel for ID factories.
  • bufferSchema, jsonSchema, literalSchema, createSchemaFactory — re-exported from drizzle-orm/zod.
  • formData — re-exported zod-form-data namespace.
  • z, ZodError, every Zod export — re-exported from zod/v4.

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.

License

MIT. See LICENSE.

About

[Read-only mirror] Shared Zod schemas and Drizzle contract helpers — branded ID-aware select/insert/update schemas with auto-applied column refinements.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors