supazod
v4.5.0
Published
Generate Zod schemas from Supabase CLI generated types
Readme
Supazod
Generate Zod schemas from Typescript types generated by the Supabase CLI.
Quick Start
$ pnpm add --D supazod
$ supabase gen types typescript --local > types.ts
# Generate schemas with separate types file
$ pnpm supazod -i types.ts -o schemas.ts -t schemas.d.ts -s public,schema_a,schema_b
# Or generate everything in a single file with inline types
$ pnpm supazod -i types.ts -o schemas.ts --inline-typesThat's it! Check your schemas.ts file - you should have Zod schemas generated for all your tables, views, enums and functions.
PowerShell Users (Windows)
PowerShell's > redirect operator outputs UTF-16 by default, which supazod cannot read. Use Out-File with -Encoding utf8 instead:
# Local database
supabase gen types typescript --local | Out-File -FilePath types.ts -Encoding utf8
# From supabase.com
supabase gen types typescript --project-id <project-id> | Out-File -FilePath types.ts -Encoding utf8Generated Output
Supazod generates clean, consistent schema names:
// ✅ Clean naming (v2.0+)
export const publicUsersInsertSchema = z.object({...});
export const publicUsersUpdateSchema = z.object({...});
export const publicUserStatusSchema = z.union([...]);
export const publicGetStatusArgsSchema = z.object({...});
// TypeScript types without "Schema" suffix
export type PublicUsersInsert = z.infer<typeof generated.publicUsersInsertSchema>;
export type PublicUserStatus = z.infer<typeof generated.publicUserStatusSchema>;Inline Types
Use --inline-types (or -I) to generate both Zod schemas and TypeScript types in a single file:
$ pnpm supazod -i types.ts -o schemas.ts --inline-typesThis generates a single schemas.ts file with everything included:
// schemas.ts - single file output
import { z } from "zod";
export const publicUsersRowSchema = z.object({
id: z.number(),
username: z.string(),
// ...
});
export const publicUserStatusSchema = z.union([
z.literal("ONLINE"),
z.literal("OFFLINE"),
]);
// Types are included directly in the same file
export type PublicUsersRow = z.infer<typeof publicUsersRowSchema>;
export type PublicUserStatus = z.infer<typeof publicUserStatusSchema>;This is useful when you prefer a simpler setup without managing separate .d.ts files.
You can also enable this via the config file:
// supazod.config.ts
import { defineConfig } from 'supazod';
export default defineConfig({
inlineTypes: true,
});Configuration
TypeScript Configuration (Recommended)
Create a supazod.config.ts file for type-safe configuration with IntelliSense:
import { defineConfig } from 'supazod';
export default defineConfig({
namingConfig: {
// TypeScript provides autocomplete for placeholders:
// {schema}, {table}, {operation}, {function}, {name}
tableOperationPattern: '{schema}_{table}_{operation}',
tableSchemaPattern: '{schema}{table}{operation}',
enumPattern: '{schema}_{name}_Enum',
enumSchemaPattern: '{schema}{name}',
functionArgsPattern: '{schema}_{function}_Args',
functionArgsSchemaPattern: '{schema}{function}Args',
functionReturnsPattern: '{schema}_{function}_Returns',
functionReturnsSchemaPattern: '{schema}{function}Returns',
// Capitalization and formatting
capitalizeSchema: true,
capitalizeNames: true,
separator: '_',
}
});JSON Configuration
{
"namingConfig": {
"tableOperationPattern": "{schema}_{table}_{operation}",
"tableSchemaPattern": "{schema}{table}{operation}",
"enumPattern": "{schema}_{name}_Enum",
"enumSchemaPattern": "{schema}{name}",
"capitalizeSchema": true,
"capitalizeNames": true,
"separator": "_"
}
}Supported config files:
supazod.config.ts(recommended)supazod.config.jssupazod.config.json.supazodrc.ts.supazodrc.js.supazodrc.json
CLI Options
supazod [options]
-i, --input <path> Input TypeScript file
-o, --output <path> Output Zod schemas file
-t, --types-output <path> Output type definitions (optional)
-s, --schema <name> Schema to process (optional, defaults to all)
-I, --inline-types Include types in schema file (no separate .d.ts)
-v, --verbose Enable debug logs
# Naming Configuration (overrides config file)
--table-operation-pattern <pattern> Pattern for table operations
--table-schema-pattern <pattern> Pattern for table schema constants
--enum-pattern <pattern> Pattern for enums
--enum-schema-pattern <pattern> Pattern for enum schema constants
--function-args-pattern <pattern> Pattern for function arguments
--function-args-schema-pattern <pattern> Pattern for function arg schema constants
--function-returns-pattern <pattern> Pattern for function returns
--function-returns-schema-pattern <pattern> Pattern for function return schema constants
--config <path> Path to a Supazod config file
--capitalize-schema <boolean> Capitalize schema names
--capitalize-names <boolean> Capitalize type names
--separator <string> Separator between name partsExample with Custom Naming
# Generate with custom naming patterns
$ pnpm supazod -i types.ts -o schemas.ts \
--table-operation-pattern '{schema}_{table}_{operation}' \
--table-schema-pattern '{schema}{table}{operation}' \
--enum-pattern '{schema}_{name}_Enum' \
--enum-schema-pattern '{schema}{name}' \
--separator '_'Separating Type and Schema Names
For each naming pattern there is an optional companion for the generated Zod schema constants (for example tableSchemaPattern).
Use these when you want custom suffixes on TypeScript types without affecting the schema identifiers that appear in schemas.ts.
Patterns now preserve any separators you include (like _ or -) in the emitted type aliases and schema constants, so you can rely on the exact formatting you configure.
Available Placeholders
{schema}- Database schema name (e.g., "public", "auth"){table}- Table name (e.g., "users", "posts"){operation}- Operation type ("Insert", "Update", "Row"){function}- Function name (e.g., "get_status"){name}- Type name (e.g., "user_status" for enums)
Features
- 🎯 Complete Coverage: Full support for tables, views, enums, functions and composite types
- 🔧 Multi-Schema: Process multiple database schemas with a single command
- 📦 Type Declarations: Generate corresponding
.d.tsfiles alongside Zod schemas - 📄 Inline Types: Option to include types directly in the schema file (
--inline-types) - ⚙️ Type-Safe Configuration: TypeScript config with IntelliSense support
- 🏷️ Flexible Naming: Customizable naming patterns with placeholders
- ✨ Clean Output: Fixed schema naming (no more "SchemaSchema" duplication)
Programmatic API
import { generateContent } from 'supazod';
const result = await generateContent({
input: './types.ts',
output: './schema.ts',
schema: ['public'],
inlineTypes: true, // Include types in schema file
namingConfig: {
tableOperationPattern: '{schema}_{table}_{operation}',
enumPattern: '{schema}_{name}_Enum',
}
});Migration from v1.x
If upgrading from v1.x, see MIGRATION.md for detailed migration instructions. The main changes:
- ✅ Fixed duplicated "Schema" suffixes (
publicUsersInsertSchemaSchema→publicUsersInsertSchema) - ✅ Clean TypeScript type names (removed "Schema" suffix from types)
- ✅ New type-safe configuration system
Credits
This project started as a fork of supabase-to-zod by @psteinroe. While maintaining the original concept, the codebase has been completely rewritten to provide better performance, enhanced type safety, and a more robust architecture. Thanks to psteinroe for the initial inspiration! 💚
