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

@antislop/zero-lucid-generator

v1.1.0

Published

Generate Zero schemas from Lucid ORM models

Readme

@antislop/zero-lucid-generator

Generate Zero schemas directly from your Lucid ORM models — no manual schema duplication.

Inspired by drizzle-zero and prisma-zero.


How it works

@antislop/zero-lucid-generator scans your Lucid model files, introspects their column and relation definitions at runtime, infers TypeScript types via ts-morph, and writes a typed Zero schema file you can import directly into your app.


Installation

npm add -D @antislop/zero-lucid-generator

@antislop/zero-lucid-generator is a dev-time generator. You only need it during development to regenerate the schema when models change.


Setup

1. Create a config file

Create lucid-zero.config.ts at the root of your project:

import type { Config } from '@antislop/zero-lucid-generator'

const config: Config = {
  modelsSourcePath: './app/models',
}

export default config

2. Run the generator

npx lucid-zero generate

This writes zero-schema.gen.ts next to your config file.

3. Import the schema

import { schema, zql } from './zero-schema.gen.js'

Config options

| Option | Type | Default | Description | |---|---|---|---| | modelsSourcePath | string | required | Path to your models directory, relative to the config file | | output | string | zero-schema.gen.ts | Output file path, relative to the config file | | format | boolean | false | Format the output with oxfmt (must be installed). Respects your .oxfmtrc.json. | | excludeModels | LucidModel[] | [] | Models to exclude from the generated schema | | columnTypes | Record<string, Record<string, string>> | {} | Override the inferred Zero type for specific columns |

Formatting with oxfmt

Set format: true to have the generated file automatically formatted on every run:

const config: Config = {
  modelsSourcePath: './app/models',
  format: true,
}

Install oxfmt in your project:

npm add -D oxfmt

The formatter picks up your .oxfmtrc.json / oxfmt.config.ts automatically, so the output will always match what your own format scripts produce.


CLI options

lucid-zero generate [options]

Options:
  -c, --config <path>     Path to config file     (default: lucid-zero.config.ts)
  -t, --tsconfig <path>   Path to tsconfig.json   (default: tsconfig.json next to config)

Column type inference

@antislop/zero-lucid-generator maps TypeScript types to Zero types automatically:

| TypeScript type | Zero type | |---|---| | string | string() | | number | number() | | boolean | boolean() | | DateTime / Date | number() (Unix ms) | | object / unknown / any | json() | | T \| null or T \| undefined | .optional() |

When inference isn't accurate — for example a JSON column with a known shape — use columnTypes:

import type { Config } from '@antislop/zero-lucid-generator'
import Session from "#models/session";

const config: Config = {
  modelsSourcePath: './app/models',
  columnTypes: {
    Issue: {
      // metadata is typed as `unknown` but has a known shape
      metadata: 'json<{ priority: number; labels: string[] }>()',
    },
    User: {
      // role is stored as a string enum
      role: 'enumeration<"admin" | "member" | "viewer">()',
    },
  },
  excludeModels: [Session],
}

export default config

Valid Zero base types: string, number, boolean, json, enumeration.


Example output

// zero-schema.gen.ts (auto-generated — do not edit)

import {
  createBuilder,
  createSchema,
  number,
  relationships,
  string,
  table,
} from "@rocicorp/zero";

export const users = table("users")
  .columns({
    id: number(),
    name: string(),
    email: string(),
  })
  .primaryKey("id");

export const posts = table("posts")
  .columns({
    id: number(),
    userId: number().from('user_id'),
    title: string(),
    body: string().optional(),
  })
  .primaryKey("id");

export const usersRelationships = relationships(users, ({ many }) => ({
  posts: many({
    sourceField: ["id"],
    destField: ["userId"],
    destSchema: posts,
  }),
}));

export const schema = createSchema({
  tables: [users, posts],
  relationships: [usersRelationships],
});

export type Schema = typeof schema;

export const zql = createBuilder(schema);

Supported relation types

| Lucid relation | Zero mapping | |---|---| | hasOne | one(...) | | hasMany | many(...) | | belongsTo | one(...) | | manyToMany | many([...chain]) via pivot table | | hasManyThrough | many([...chain]) |

Relations pointing to a model not found in modelsSourcePath are skipped with a warning.


Automating regeneration

Add a script to package.json to regenerate whenever models change:

{
  "scripts": {
    "zero:generate": "lucid-zero generate",
    "postinstall": "npm run zero:generate"
  }
}