npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

prisma-arktype

v2.5.0

Published

Generate ArkType schemas from your Prisma schema

Readme

prisma-arktype

Generate ArkType validation schemas from your Prisma schema.

This package is heavily inspired by and based on the structure of prismabox, which generates TypeBox schemas from Prisma schemas.

Features

  • 🎯 Type-safe validation - Generate ArkType schemas that match your Prisma models
  • 🔄 Automatic generation - Schemas are generated automatically when you run prisma generate
  • 📦 Comprehensive coverage - Generates schemas for models, relations, where clauses, select, include, orderBy, and more
  • 🎨 Customizable - Control schema generation with annotations
  • 🚀 Zero config - Works out of the box with sensible defaults

Installation

npm install prisma-arktype arktype
# or
pnpm add prisma-arktype arktype
# or
yarn add prisma-arktype arktype

Usage

Basic Setup

Add the generator to your schema.prisma file:

generator prisma-arktype {
  provider = "prisma-arktype"
  output   = "./generated/validators"
}

model User {
  id        String   @id @default(cuid())
  email     String   @unique
  name      String?
  posts     Post[]
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

model Post {
  id        String   @id @default(cuid())
  title     String
  content   String?
  published Boolean  @default(false)
  author    User     @relation(fields: [authorId], references: [id])
  authorId  String
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

Then run:

npx prisma generate

Configuration Options

Configure the generator in your schema.prisma:

generator prisma-arktype {
  provider                     = "prisma-arktype"
  output                       = "./generated/validators"
  arktypeImportDependencyName  = "arktype"
  ignoredKeysOnInputModels     = ["id", "createdAt", "updatedAt"]
}

Configuration Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | output | string | "./prisma/generated/validators" | Output directory for generated schemas | | arktypeImportDependencyName | string | "arktype" | The package name to import from | | ignoredKeysOnInputModels | string[] | ["id", "createdAt", "updatedAt"] | Fields to exclude from input models |

Generated Schemas

For each model, the generator creates multiple schema types:

  • ModelPlain - Scalar fields only (strings, numbers, dates, enums) - no relations
  • ModelRelations - Relationship fields only, referencing related model Plain types
  • Model - Complete composite schema combining Plain & Relations
  • ModelWhere - Where clause schema for filtering
  • ModelWhereUnique - Unique where clause schema for finding specific records
  • ModelCreate - Input schema for creating records
  • ModelUpdate - Input schema for updating records
  • ModelSelect - Schema for selecting specific fields
  • ModelInclude - Schema for including relations
  • ModelOrderBy - Schema for ordering results

Enums are generated as separate reusable types that are imported and referenced by models that use them.

Using Generated Schemas

import { type } from "arktype";
import { User, UserCreate, UserWhere } from "./generated/validators";

// Validate a user object
const userResult = User(someUserData);
if (userResult instanceof type.errors) {
  console.error(userResult.summary);
} else {
  // userResult is validated user data
  console.log(userResult);
}

// Validate create input
const createData = {
  email: "[email protected]",
  name: "John Doe"
};

const createResult = UserCreate(createData);
// ...

// Validate where clauses
const whereClause = {
  email: "[email protected]"
};

const whereResult = UserWhere(whereClause);
// ...

Where Clause Filters

Where clauses support advanced filtering through dedicated filter types. Fields can accept either direct values or filter objects with comparison operators.

Filter Types

String Filters

String fields can use StringFilter for advanced text filtering:

import { UserWhere } from "./generated/validators";

// Direct value
const result1 = UserWhere({ email: "[email protected]" });

// Filter object
const result2 = UserWhere({
  email: {
    contains: "example",      // Contains substring
    startsWith: "user",       // Starts with prefix
    endsWith: ".com",         // Ends with suffix
    equals: "[email protected]", // Exact match
    not: "[email protected]", // Not equal to
    in: ["[email protected]", "[email protected]"], // In array
    notIn: ["[email protected]"], // Not in array
    gt: "a",                  // Greater than (lexicographic)
    gte: "a",                 // Greater than or equal
    lt: "z",                  // Less than
    lte: "z"                  // Less than or equal
  }
});

Available operations: contains, startsWith, endsWith, equals, not, in, notIn, gt, gte, lt, lte

Number Filters

Integer fields (Int, BigInt) use IntFilter, while floating-point fields (Float, Decimal) use NumberFilter:

import { PostWhere } from "./generated/validators";

// Direct value
const result1 = PostWhere({ views: 100 });

// Filter object for integers
const result2 = PostWhere({
  views: {
    equals: 100,
    gt: 50,                   // Greater than
    gte: 50,                  // Greater than or equal
    lt: 200,                  // Less than
    lte: 200,                 // Less than or equal
    in: [100, 200, 300],      // In array
    notIn: [0],               // Not in array
    not: 0                    // Not equal to
  }
});

// Filter object for floats/decimals
const result3 = PostWhere({
  rating: {
    gte: 4.5,
    lte: 5.0
  }
});

Available operations: equals, gt, gte, lt, lte, in, notIn, not

Boolean Filters

Boolean fields use BooleanFilter:

import { PostWhere } from "./generated/validators";

// Direct value
const result1 = PostWhere({ published: true });

// Filter object
const result2 = PostWhere({
  published: {
    equals: true,
    not: false
  }
});

Available operations: equals, not

Enum Filters

Enum fields use the generic enumFilter:

import { PaymentWhere } from "./generated/validators";

// Direct enum value
const result1 = PaymentWhere({ currency: "USD" });

// Filter object
const result2 = PaymentWhere({
  currency: {
    equals: "USD",
    in: ["USD", "EUR", "GBP"],
    notIn: ["JPY"],
    not: "CAD"
  }
});

Available operations: equals, in, notIn, not

DateTime Filters

DateTime fields use DateTimeFilter:

import { PostWhere } from "./generated/validators";

// Direct Date value
const result1 = PostWhere({ createdAt: new Date("2024-01-01") });

// Filter object
const result2 = PostWhere({
  createdAt: {
    equals: new Date("2024-01-01"),
    gt: new Date("2024-01-01"),   // After
    gte: new Date("2024-01-01"),  // On or after
    lt: new Date("2024-12-31"),   // Before
    lte: new Date("2024-12-31"),  // On or before
    in: [new Date("2024-01-01"), new Date("2024-06-01")],
    notIn: [new Date("2024-07-04")],
    not: new Date("2024-01-01")
  }
});

Available operations: equals, gt, gte, lt, lte, in, notIn, not

Array Filters

Array fields use specialized array filters with operations for list matching:

import { TagWhere } from "./generated/validators";

// String arrays
const result1 = TagWhere({
  labels: {
    isEmpty: false,           // Array is empty
    has: "important",         // Array contains value
    hasEvery: ["tag1", "tag2"], // Array contains all values
    hasSome: ["tag1", "tag2"],  // Array contains at least one value
    equals: ["exact", "match"]  // Array exactly matches
  }
});

// Number arrays
const result2 = ScoresWhere({
  values: {
    isEmpty: false,
    has: 100,
    hasEvery: [90, 95, 100],
    hasSome: [100, 200],
    equals: [90, 95, 100]
  }
});

// Enum arrays
const result3 = PermissionsWhere({
  roles: {
    isEmpty: false,
    has: "ADMIN",
    hasEvery: ["USER", "ADMIN"],
    hasSome: ["ADMIN", "MODERATOR"],
    equals: ["USER"]
  }
});

Available array filter types:

  • StringArrayFilter - for String[] fields
  • NumberArrayFilter - for Int[], Float[], Decimal[] fields
  • BigIntArrayFilter - for BigInt[] fields
  • arrayFilter(EnumType) - for enum array fields

Available operations: isEmpty, has, hasEvery, hasSome, equals

Combining Filters

You can combine multiple filters in a single where clause:

import { PostWhere } from "./generated/validators";

const complexQuery = PostWhere({
  title: { contains: "TypeScript" },
  views: { gte: 100 },
  published: true,
  rating: { gte: 4.0 },
  createdAt: {
    gte: new Date("2024-01-01"),
    lt: new Date("2024-12-31")
  }
});

Generated Code Examples

Enum Generation

For a Prisma enum like:

enum Currency {
  USD
  EUR
  GBP
}

The generator creates a separate reusable type:

// Currency.ts
import { type } from "arktype";

export const Currency = type("'USD' | 'EUR' | 'GBP'");

Which is then imported and used in models:

// PaymentPlain.ts
import { type } from "arktype";
import { Currency } from "./Currency";

export const PaymentPlain = type({
  "id": "string",
  "amount": "number",
  "currency": Currency,        // Required enum
  "status?": Currency.or("null") // Optional enum
});

Relation Generation

For Prisma models with relations like:

model User {
  id    String  @id
  email String
  posts Post[]
}

model Post {
  id       String @id
  title    String
  author   User   @relation(fields: [authorId], references: [id])
  authorId String
}

The generator creates Plain types (without relations):

// UserPlain.ts
export const UserPlain = type({
  "id": "string",
  "email": "string"
});

// PostPlain.ts
export const PostPlain = type({
  "id": "string",
  "title": "string",
  "authorId": "string"
});

And Relations types that reference the Plain types:

// UserRelations.ts
import { PostPlain } from "./PostPlain";

export const UserRelations = type({
  "posts": PostPlain.array() // Array of Post objects
});

// PostRelations.ts
import { UserPlain } from "./UserPlain";

export const PostRelations = type({
  "author": UserPlain // Single User object
});

The combined model merges both:

// User.ts
import { UserPlain } from "./UserPlain";
import { UserRelations } from "./UserRelations";

export const User = type(() => UserPlain.and(UserRelations));

Annotations

Control schema generation using annotations in your Prisma schema. All annotations are added as documentation comments (///).

Available Annotations

| Annotation | Scope | Description | |------------|-------|-------------| | @prisma-arktype.hide | Model or Field | Completely hide from all generated schemas | | @prisma-arktype.input.hide | Field | Hide from Create and Update input schemas | | @prisma-arktype.create.input.hide | Field | Hide from Create input schema only | | @prisma-arktype.update.input.hide | Field | Hide from Update input schema only | | @prisma-arktype.schema="<schema>" | Field | Custom ArkType schema (inline or external) | | @prisma-arktype.typeOverwrite="<type>" | Field | Override the generated ArkType type |

Hide Fields/Models

Completely exclude models or fields from all generated schemas:

/// @prisma-arktype.hide
model InternalModel {
  id String @id
  secret String
}

model User {
  id String @id
  email String
  /// @prisma-arktype.hide
  passwordHash String
}

Hide from Input Models

Control which fields appear in Create and Update schemas:

model User {
  id String @id
  email String

  /// @prisma-arktype.input.hide
  /// Hidden from both Create and Update
  computedField String

  /// @prisma-arktype.create.input.hide
  /// Only appears in Update schema
  lastModified DateTime

  /// @prisma-arktype.update.input.hide
  /// Only appears in Create schema
  initialStatus String
}

Type Override

Override the default type mapping with custom ArkType type strings:

model User {
  id String @id
  /// @prisma-arktype.typeOverwrite="string.email"
  email String
  /// @prisma-arktype.typeOverwrite="string.url"
  website String
  /// @prisma-arktype.typeOverwrite="string.numeric"
  phone String
}

This allows you to use any ArkType type definition, including built-in refinements like string.email, string.url, number.integer, etc.

Custom Schemas

Bring your own ArkType schemas for any field using @prisma-arktype.schema:

model User {
  id String @id

  /// Inline schema for structured JSON
  /// @prisma-arktype.schema="{ name: 'string', age: 'number' }"
  profile Json

  /// External schema from a file (named export)
  /// @prisma-arktype.schema="../schemas/address:AddressSchema"
  address Json

  /// External schema (default export)
  /// @prisma-arktype.schema="../schemas/config"
  settings Json
}

Import Path Rules:

  • Paths are relative to the generated validators directory
  • Named exports use colon syntax: "path:ExportName"
  • Default exports omit the colon: "path"
  • Works with ANY field type (not just Json)

Priority: schema > typeOverwrite > default type mapping

Example external schema file (schemas/address.ts):

import { type } from "arktype";

export const AddressSchema = type({
  street: "string",
  city: "string",
  zipCode: "string",
  country: "string",
});

Type Mapping

Prisma types are mapped to ArkType as follows:

| Prisma Type | ArkType Type | Example Output | |-------------|--------------|----------------| | String | "string" | "string" | | Int | "number.integer" | "number.integer" | | BigInt | "number.integer" | "number.integer" | | Float | "number" | "number" | | Decimal | "number" | "number" | | Boolean | "boolean" | "boolean" | | DateTime | "Date" | "Date" | | Json | "unknown" | "unknown" | | Bytes | "instanceof Buffer" | "instanceof Buffer" | | Enums | Reference to enum type | Currency (imported from ./Currency) | | Relations | Reference to related Plain type | PostPlain or PostPlain.array() |

Special Handling

  • Optional fields: Use ? on the key name ("name?": "string")
  • Nullable fields: Add | null to the type ("string | null")
  • Arrays: Use .array() syntax for lists (type("string").array() or Currency.array())
  • Enums: Generated as separate reusable type definitions and imported where used
  • Relations: Reference the Plain type of the related model, imported automatically

Differences from prismabox

While this package is inspired by prismabox, there are some key differences:

  1. ArkType vs TypeBox: Uses ArkType's syntax and type system instead of TypeBox
  2. Simpler type definitions: ArkType's string-based syntax makes schemas more readable
  3. No nullable wrapper: ArkType handles nullable types directly with union syntax
  4. Different validation API: Uses ArkType's validation approach

Development

Setup

# Clone the repository
git clone https://github.com/yourusername/prisma-arktype.git
cd prisma-arktype

# Install dependencies
pnpm install

# Build the project
pnpm build

# Run tests
pnpm test

# Run tests in watch mode
pnpm test:watch

# Run linter
pnpm lint

# Fix linting issues
pnpm lint:fix

Testing

This library has a completely schema-independent test suite using self-contained test models in prisma/schema/test-models.prisma.

Running Tests

# Run all tests
pnpm test:e2e

# Run tests in watch mode
pnpm test:watch

Test Architecture

The test suite is designed to be 100% independent of production schemas:

  • Self-Contained Schema - prisma/schema/test-models.prisma contains all models needed for testing
  • No Production Dependencies - Tests work even if production schemas don't exist
  • Comprehensive Coverage - Test models cover all Prisma types, relations, and generator features
  • Portable - Can be used across different projects or extracted as a standalone test suite

Test Model Categories

The test schema includes specialized models for testing:

  1. Basic CRUD - TestUser, TestPost, TestProfile
  2. All Prisma Types - TestAllTypes (String, Int, BigInt, Float, Decimal, Boolean, DateTime, Json, Bytes)
  3. Relations - One-to-one, one-to-many, many-to-many, composite keys
  4. Annotations - @prisma-arktype.hide, @prisma-arktype.input.hide, @prisma-arktype.typeOverwrite
  5. Query Operations - Select, Include, OrderBy schemas
  6. Enums - TestCurrency, TestStatus

Adding New Tests

  1. Add test models to prisma/schema/test-models.prisma if needed
  2. Update mapping in __tests__/config/model-mapping.ts to reference your models
  3. Write tests using helper functions from __tests__/utils/test-helpers.ts
  4. Run tests - pnpm test

See existing test files for examples.

Why Schema-Independent?

  • ✅ Tests never break due to production schema changes
  • ✅ Contributors can run tests without setting up production databases
  • ✅ Tests can be run in isolation (CI/CD, local development)
  • ✅ Clear, documented examples of generator usage
  • ✅ Easy to test new features by adding new test models

Publishing

This project uses Changesets for version management and publishing.

Creating a changeset

When you make changes that should be included in the next release:

pnpm changeset

This will prompt you to:

  1. Select the type of change (major, minor, patch)
  2. Provide a description of the changes

Commit the generated changeset file along with your changes.

Publishing workflow

  1. Create a changeset for your changes
  2. Open a PR with your changes and the changeset
  3. Merge the PR - The GitHub Action will automatically create a "Version Packages" PR
  4. Review and merge the Version Packages PR - This will:
    • Update the version in package.json
    • Update the CHANGELOG.md
    • Publish the package to npm
    • Create a GitHub release

Manual publishing (maintainers only)

# Build and publish
pnpm release

Prerequisites:

  • Set up NPM_TOKEN secret in GitHub repository settings
  • Ensure you have publish access to the npm package

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Create a changeset (pnpm changeset)
  5. Commit your changes following the commit message format (see below)
  6. Push to the branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

Commit Message Format

This project uses Conventional Commits. Commit messages are automatically linted using commitlint and lefthook.

Format: <type>(<scope>): <subject>

Types:

  • feat: New feature
  • fix: Bug fix
  • docs: Documentation changes
  • style: Code style changes (formatting, etc.)
  • refactor: Code refactoring
  • perf: Performance improvements
  • test: Adding or updating tests
  • build: Build system changes
  • ci: CI/CD changes
  • chore: Other changes

Examples:

git commit -m "feat: add support for custom type validators"
git commit -m "fix: resolve issue with nullable DateTime fields"
git commit -m "docs: update installation instructions"
git commit -m "refactor: simplify where clause generation"

Git Hooks

This project uses lefthook to manage git hooks:

  • commit-msg: Validates commit message format
  • pre-commit: Runs linter and checks for debug statements
  • pre-push: Runs tests before pushing

To skip hooks (use sparingly):

git commit --no-verify -m "your message"

License

MIT

Credits

This package is heavily based on prismabox by m1212e. Many thanks for the excellent foundation and architecture!

Related Projects

  • ArkType - TypeScript's 1:1 validator
  • Prisma - Next-generation ORM for Node.js & TypeScript
  • prismabox - Generate TypeBox schemas from Prisma (inspiration for this project)