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

@libar-dev/zod-convex-gen

v0.1.0

Published

Build-time Zod to Convex validator generator for eliminating runtime bundle size

Readme

@libar-dev/zod-convex-gen

Build-time Zod to Convex validator generator - eliminates Zod from runtime bundle

npm version License: MIT

The Problem

Convex applications using Zod at runtime can exceed the 64MB memory limit. The Zod library adds ~55-62MB of overhead, leaving minimal room for business logic.

The Solution

This package converts Zod schemas to pure Convex validators at build time, eliminating Zod from the runtime bundle entirely.

Results: 90% memory reduction (62MB → 10-15MB) with 100% type safety maintained.

Quick Start

1. Install

npm install --save-dev @libar-dev/zod-convex-gen tsx
# or: pnpm add -D @libar-dev/zod-convex-gen tsx

Requires: Zod 4.x, Node.js 20+

2. Create Schema

// src/table-schemas/users.ts
import { z } from 'zod';

export const UsersTableSchema = z.object({
  email: z.string().email(),
  name: z.string(),
  role: z.enum(['admin', 'user', 'guest']),
  createdAt: z.number(),
}).strict();

// Export type alias for hybrid pattern
export type User = z.infer<typeof UsersTableSchema>;

3. Generate Validators

npx zod-convex-gen

Creates convex/generatedValidators/users.ts:

// AUTO-GENERATED - DO NOT EDIT
import { v } from 'convex/values';

export const usersFields = {
  email: v.string(),
  name: v.string(),
  createdAt: v.float64(),
};

export const usersEnums = {
  role: v.union(v.literal('admin'), v.literal('user'), v.literal('guest')),
};

export const usersObject = v.object({ ...usersFields, ...usersEnums });
export const usersArray = v.array(usersObject);

4. Use in Convex Schema

// convex/schema.ts
import { defineSchema, defineTable } from 'convex/server';
import { usersFields, usersEnums } from './generatedValidators/users';

export default defineSchema({
  users: defineTable({ ...usersFields, ...usersEnums })
    .index('by_email', ['email']),
});

CLI Reference

Commands

| Command | Description | |---------|-------------| | generate | Generate validators (default) | | clean | Remove generated files | | info | Show configuration and loaders | | init | Create sample config file |

Options

| Option | Description | Default | |--------|-------------|---------| | -i, --input <path> | Input directory | src/table-schemas | | -o, --output <path> | Output directory | convex/generatedValidators | | -w, --watch | Watch mode | false | | -p, --pattern <pattern> | Schema export pattern | *TableSchema | | --loader <name> | TypeScript loader | tsx | | --dry-run | Validate without writing | false | | --no-format | Skip prettier formatting | false | | -v, --verbose | Verbose output | false |

Examples

# Development with auto-regeneration
npx zod-convex-gen --watch

# Custom directories
npx zod-convex-gen -i src/schemas -o convex/validators

# Validation only (CI)
npx zod-convex-gen --dry-run

# Clean stale files
npx zod-convex-gen clean --stale --force

Configuration

Zero Configuration

Works out of the box with these conventions:

  • Input: src/table-schemas/
  • Output: convex/generatedValidators/
  • Schema pattern: exports ending with TableSchema

Config File

Create zod-convex-gen.json or use npx zod-convex-gen init:

{
  "input": ["src/table-schemas", "src/validation-schemas"],
  "output": "convex/generatedValidators",
  "schemaPattern": "*TableSchema",
  "tableNameTransform": "camelCase",
  "format": true,
  "preserveDirectoryStructure": true,
  "maxInlineDepth": 2,
  "extractUnions": true
}

All Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | input | string \| string[] | src/table-schemas | Input directories | | output | string | convex/generatedValidators | Output directory | | schemaPattern | string | *TableSchema | Export name pattern | | tableNameTransform | string | camelCase | Name transform (camelCase, kebab-case, snake_case, none) | | format | boolean | true | Prettier formatting | | outputMode | string | multiple | multiple or single file | | preserveDirectoryStructure | boolean | true | Mirror input structure | | maxInlineDepth | number | 2 | Max nesting before extraction | | extractUnions | boolean | true | Extract nested unions | | includeTimestamp | boolean | false | Add timestamp to headers | | exclude | string[] | ['*.test.ts', '*.spec.ts'] | Files to exclude | | minFieldsForExtraction | number | 3 | Min fields to trigger extraction | | loader | string | tsx | TypeScript loader | | verbosity | string | quiet | silent, quiet, normal, verbose |

Troubleshooting

"No schemas found"

  1. Ensure schemas end with TableSchema:

    export const UsersTableSchema = z.object({...}); // ✅
    export const UserSchema = z.object({...});       // ❌
  2. Verify input directory exists: ls src/table-schemas/

  3. Check exports are named (not default):

    export const UsersTableSchema = ...  // ✅
    const UsersTableSchema = ...         // ❌ (missing export)

"Cannot load TypeScript file"

Install a TypeScript loader:

npm install --save-dev tsx  # Recommended
# or: ts-node, esbuild, @swc/core

Files not updating

Use watch mode during development:

npx zod-convex-gen --watch

Type errors after generation

Follow build order:

npx zod-convex-gen        # 1. Generate validators
npx convex codegen        # 2. Generate Convex types
npx tsc --noEmit          # 3. TypeScript validation

TS2589 "Type instantiation excessively deep"

This generator prevents most TS2589 errors by:

  1. Generating pre-composed validators (*Array, *Record, *OrNull)
  2. Auto-extracting deeply nested structures

To use correctly:

// ❌ WRONG - inline construction causes TS2589
returns: v.array(v.object(mySchemaFields))

// ✅ CORRECT - use pre-composed validator from generated output
returns: mySchemaArray

// ❌ WRONG - explicit Promise type conflicts with returns validator
handler: async (ctx, args): Promise<MyType> => { ... }

// ✅ CORRECT - let validator infer type
handler: async (ctx, args) => { ... }

// ❌ WRONG - variable annotation conflicts
const result: MyType = await ctx.runMutation(...);

// ✅ CORRECT - no annotation
const result = await ctx.runMutation(...);

If errors persist, reduce maxInlineDepth in config:

{ "maxInlineDepth": 1 }

See TS2589 Usage Guide for complete patterns including helper function anti-patterns, test helpers, and diagnostic commands.

Documentation

License

MIT