pg2zod 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/README.md +66 -0
- package/dist/cli.js +7 -1
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +49 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/{src-18pV45Fu.js → src-CEkWBxDB.js} +308 -2
- package/dist/src-CEkWBxDB.js.map +1 -0
- package/package.json +6 -6
- package/dist/src-18pV45Fu.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 9bb84ad: Add support for generating Zod schemas from database views and functions/procedures
|
|
8
|
+
|
|
9
|
+
**New Features:**
|
|
10
|
+
|
|
11
|
+
- Database views: Generate read-only Zod schemas from views (--views flag)
|
|
12
|
+
- Functions/Procedures: Generate parameter and return type schemas (--routines flag)
|
|
13
|
+
- Security-aware filtering: By default only SECURITY DEFINER functions are included
|
|
14
|
+
- Include SECURITY INVOKER functions with --security-invoker flag
|
|
15
|
+
|
|
16
|
+
**New CLI Options:**
|
|
17
|
+
|
|
18
|
+
- `--views`: Include database views in schema generation
|
|
19
|
+
- `--routines`: Include functions and procedures
|
|
20
|
+
- `--security-invoker`: Include SECURITY INVOKER routines (default: DEFINER only)
|
|
21
|
+
|
|
22
|
+
**API Changes:**
|
|
23
|
+
|
|
24
|
+
- Added `includeViews` option to SchemaGenerationOptions
|
|
25
|
+
- Added `includeRoutines` option to SchemaGenerationOptions
|
|
26
|
+
- Added `includeSecurityInvoker` option to SchemaGenerationOptions
|
|
27
|
+
- Added `ViewMetadata`, `RoutineMetadata`, and `RoutineParameterMetadata` types
|
|
28
|
+
- GenerationResult now includes `views` and `routines` arrays
|
|
29
|
+
|
|
3
30
|
## 2.0.0
|
|
4
31
|
|
|
5
32
|
### Major Changes
|
package/README.md
CHANGED
|
@@ -9,6 +9,8 @@ A modern TypeScript package that automatically generates high-quality, strict Zo
|
|
|
9
9
|
✨ **Comprehensive Type Coverage**
|
|
10
10
|
- All built-in PostgreSQL types (numeric, text, date/time, boolean, JSON, UUID, etc.)
|
|
11
11
|
- Custom types: enums, domains, composite types, range types
|
|
12
|
+
- Database views (read-only schemas)
|
|
13
|
+
- Functions and procedures (with parameter and return type schemas)
|
|
12
14
|
- Arrays (including multi-dimensional)
|
|
13
15
|
- Geometric types (point, box, circle, polygon, etc.)
|
|
14
16
|
- Network types (inet, cidr, macaddr)
|
|
@@ -66,6 +68,15 @@ pg-to-zod --database mydb --no-input-schemas --output schema.ts
|
|
|
66
68
|
# Include composite types (skipped by default)
|
|
67
69
|
pg-to-zod --database mydb --composite-types --output schema.ts
|
|
68
70
|
|
|
71
|
+
# Include database views
|
|
72
|
+
pg-to-zod --database mydb --views --output schema.ts
|
|
73
|
+
|
|
74
|
+
# Include functions/procedures (SECURITY DEFINER only by default)
|
|
75
|
+
pg-to-zod --database mydb --routines --output schema.ts
|
|
76
|
+
|
|
77
|
+
# Include all functions including SECURITY INVOKER
|
|
78
|
+
pg-to-zod --database mydb --routines --security-invoker --output schema.ts
|
|
79
|
+
|
|
69
80
|
# Use camelCase for field names
|
|
70
81
|
pg-to-zod --database mydb --camel-case -o schema.ts
|
|
71
82
|
|
|
@@ -173,6 +184,55 @@ export const Int4rangeSchema = z.tuple([z.number().int().nullable(), z.number().
|
|
|
173
184
|
export type Int4range = z.infer<typeof Int4rangeSchema>;
|
|
174
185
|
```
|
|
175
186
|
|
|
187
|
+
**Views:**
|
|
188
|
+
```sql
|
|
189
|
+
CREATE VIEW user_stats AS
|
|
190
|
+
SELECT
|
|
191
|
+
u.id,
|
|
192
|
+
u.username,
|
|
193
|
+
COUNT(o.id) as order_count
|
|
194
|
+
FROM users u
|
|
195
|
+
LEFT JOIN orders o ON u.id = o.user_id
|
|
196
|
+
GROUP BY u.id, u.username;
|
|
197
|
+
```
|
|
198
|
+
→
|
|
199
|
+
```typescript
|
|
200
|
+
/** View: public.user_stats (read-only) */
|
|
201
|
+
export const PublicUserStatsSchema = z.object({
|
|
202
|
+
id: z.number().int(),
|
|
203
|
+
username: z.string(),
|
|
204
|
+
order_count: z.number().int(),
|
|
205
|
+
});
|
|
206
|
+
export type PublicUserStats = z.infer<typeof PublicUserStatsSchema>;
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
**Functions/Procedures:**
|
|
210
|
+
```sql
|
|
211
|
+
CREATE FUNCTION get_user_by_id(user_id INTEGER)
|
|
212
|
+
RETURNS TABLE(id INTEGER, username VARCHAR, email VARCHAR) AS $$
|
|
213
|
+
BEGIN
|
|
214
|
+
RETURN QUERY SELECT u.id, u.username, u.email FROM users u WHERE u.id = user_id;
|
|
215
|
+
END;
|
|
216
|
+
$$ LANGUAGE plpgsql SECURITY DEFINER;
|
|
217
|
+
```
|
|
218
|
+
→
|
|
219
|
+
```typescript
|
|
220
|
+
/** FUNCTION: public.get_user_by_id */
|
|
221
|
+
export const PublicGetUserByIdParamsSchema = z.object({
|
|
222
|
+
/** integer (IN) */
|
|
223
|
+
user_id: z.number().int(),
|
|
224
|
+
});
|
|
225
|
+
export type PublicGetUserByIdParams = z.infer<typeof PublicGetUserByIdParamsSchema>;
|
|
226
|
+
|
|
227
|
+
/** Returns: record */
|
|
228
|
+
export const PublicGetUserByIdReturnSchema = z.array(z.object({
|
|
229
|
+
id: z.number().int(),
|
|
230
|
+
username: z.string(),
|
|
231
|
+
email: z.string(),
|
|
232
|
+
}));
|
|
233
|
+
export type PublicGetUserByIdReturn = z.infer<typeof PublicGetUserByIdReturnSchema>;
|
|
234
|
+
```
|
|
235
|
+
|
|
176
236
|
### Check Constraints
|
|
177
237
|
|
|
178
238
|
CHECK constraints are automatically parsed and translated to Zod validations:
|
|
@@ -222,6 +282,9 @@ export const PublicProductsSchema = z.object({
|
|
|
222
282
|
--exclude-tables <tables> Exclude these tables
|
|
223
283
|
--no-input-schemas Skip input schemas (generated by default)
|
|
224
284
|
--composite-types Include composite types (skipped by default)
|
|
285
|
+
--views Include database views (skipped by default)
|
|
286
|
+
--routines Include functions/procedures (skipped by default)
|
|
287
|
+
--security-invoker Include SECURITY INVOKER routines (default: DEFINER only)
|
|
225
288
|
--branded-types Use branded types for IDs (future)
|
|
226
289
|
--strict Fail on unmapped types
|
|
227
290
|
--no-comments Don't include comments
|
|
@@ -277,6 +340,9 @@ interface SchemaGenerationOptions {
|
|
|
277
340
|
excludeTables?: string[]; // Exclude these
|
|
278
341
|
generateInputSchemas?: boolean; // Generate Insert/Update schemas (default: true)
|
|
279
342
|
includeCompositeTypes?: boolean; // Include composite types (default: false)
|
|
343
|
+
includeViews?: boolean; // Include database views (default: false)
|
|
344
|
+
includeRoutines?: boolean; // Include functions/procedures (default: false)
|
|
345
|
+
includeSecurityInvoker?: boolean; // Include SECURITY INVOKER routines (default: false)
|
|
280
346
|
useBrandedTypes?: boolean; // Use branded types (future)
|
|
281
347
|
strictMode?: boolean; // Fail on unknown types
|
|
282
348
|
includeComments?: boolean; // Include comments (default: true)
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { n as generateZodSchemasString } from "./src-
|
|
2
|
+
import { n as generateZodSchemasString } from "./src-CEkWBxDB.js";
|
|
3
3
|
import * as fs from "node:fs/promises";
|
|
4
4
|
import * as path from "node:path";
|
|
5
5
|
|
|
@@ -35,6 +35,9 @@ function parseArgs() {
|
|
|
35
35
|
excludeTables: getArgArray(args, "--exclude-tables"),
|
|
36
36
|
generateInputSchemas: !args.includes("--no-input-schemas"),
|
|
37
37
|
includeCompositeTypes: args.includes("--composite-types"),
|
|
38
|
+
includeViews: args.includes("--views"),
|
|
39
|
+
includeRoutines: args.includes("--routines"),
|
|
40
|
+
includeSecurityInvoker: args.includes("--security-invoker"),
|
|
38
41
|
useBrandedTypes: args.includes("--branded-types"),
|
|
39
42
|
strictMode: args.includes("--strict"),
|
|
40
43
|
includeComments: !args.includes("--no-comments"),
|
|
@@ -103,6 +106,9 @@ GENERATION OPTIONS:
|
|
|
103
106
|
--exclude-tables <tables> Comma-separated list of tables to exclude
|
|
104
107
|
--no-input-schemas Skip generating input schemas (generated by default)
|
|
105
108
|
--composite-types Include composite types (skipped by default)
|
|
109
|
+
--views Include database views (skipped by default)
|
|
110
|
+
--routines Include functions/procedures (skipped by default)
|
|
111
|
+
--security-invoker Include SECURITY INVOKER routines (default: DEFINER only)
|
|
106
112
|
--branded-types Use branded types for IDs
|
|
107
113
|
--strict Fail on unmapped types instead of using z.unknown()
|
|
108
114
|
--no-comments Don't include comments in generated code
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","names":[],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport {generateZodSchemasString} from './index.js';\nimport type {DatabaseConfig, SchemaGenerationOptions} from './types.js';\n\nconst DEFAULT_OUTPUT = 'schema.ts';\n\n/**\n * Parse command line arguments\n */\nfunction parseArgs(): {\n config: DatabaseConfig;\n options: SchemaGenerationOptions;\n output: string;\n} {\n const args = process.argv.slice(2);\n\n if (args.includes('--help') || args.includes('-h')) {\n printHelp();\n process.exit(0);\n }\n\n if (args.includes('--version') || args.includes('-v')) {\n console.log('pg-to-zod 1.0.0');\n process.exit(0);\n }\n\n // Parse connection string or individual params\n const connectionUrl = getArg(args, '--url');\n let config: DatabaseConfig;\n\n if (connectionUrl) {\n config = parseConnectionUrl(connectionUrl);\n } else {\n config = {\n host: getArg(args, '--host') || process.env.PGHOST || 'localhost',\n port: parseInt(getArg(args, '--port') || process.env.PGPORT || '5432'),\n database: getArg(args, '--database') || process.env.PGDATABASE || 'postgres',\n user: getArg(args, '--user') || process.env.PGUSER || 'postgres',\n password: getArg(args, '--password') || process.env.PGPASSWORD || '',\n ssl: args.includes('--ssl'),\n };\n }\n\n const options: SchemaGenerationOptions = {\n schemas: getArgArray(args, '--schemas') || ['public'],\n tables: getArgArray(args, '--tables'),\n excludeTables: getArgArray(args, '--exclude-tables'),\n generateInputSchemas: !args.includes('--no-input-schemas'), // Default: true\n includeCompositeTypes: args.includes('--composite-types'), // Default: false\n useBrandedTypes: args.includes('--branded-types'),\n strictMode: args.includes('--strict'),\n includeComments: !args.includes('--no-comments'),\n useCamelCase: args.includes('--camel-case'),\n };\n\n const output = getArg(args, '--output') || getArg(args, '-o') || DEFAULT_OUTPUT;\n\n return {config, options, output};\n}\n\n/**\n * Get argument value\n */\nfunction getArg(args: string[], flag: string): string | undefined {\n const index = args.indexOf(flag);\n if (index !== -1 && index + 1 < args.length) {\n return args[index + 1];\n }\n return undefined;\n}\n\n/**\n * Get argument array value (comma-separated)\n */\nfunction getArgArray(args: string[], flag: string): string[] | undefined {\n const value = getArg(args, flag);\n if (value) {\n return value.split(',').map((s) => s.trim());\n }\n return undefined;\n}\n\n/**\n * Parse PostgreSQL connection URL\n */\nfunction parseConnectionUrl(url: string): DatabaseConfig {\n const match = url.match(\n /postgresql:\\/\\/([^:]+):([^@]+)@([^:\\/]+):(\\d+)\\/(.+)/\n );\n\n if (!match) {\n throw new Error('Invalid connection URL format');\n }\n\n const [, user, password, host, port, database] = match;\n\n return {\n host,\n port: parseInt(port),\n database,\n user,\n password,\n ssl: url.includes('sslmode=require'),\n };\n}\n\n/**\n * Print help message\n */\nfunction printHelp(): void {\n console.log(`\npg-to-zod - Generate strict Zod v4 schemas from PostgreSQL database\n\nUSAGE:\n pg-to-zod [OPTIONS]\n\nCONNECTION OPTIONS:\n --url <url> PostgreSQL connection URL\n (postgresql://user:pass@host:port/db)\n --host <host> Database host (default: localhost)\n --port <port> Database port (default: 5432)\n --database <database> Database name (default: postgres)\n --user <user> Database user (default: postgres)\n --password <password> Database password\n --ssl Use SSL connection\n\nGENERATION OPTIONS:\n --schemas <schemas> Comma-separated list of schemas (default: public)\n --tables <tables> Comma-separated list of tables to include\n --exclude-tables <tables> Comma-separated list of tables to exclude\n --no-input-schemas Skip generating input schemas (generated by default)\n --composite-types Include composite types (skipped by default)\n --branded-types Use branded types for IDs\n --strict Fail on unmapped types instead of using z.unknown()\n --no-comments Don't include comments in generated code\n --camel-case Use camelCase for field names\n\nOUTPUT OPTIONS:\n --output <file> Output file path (default: schema.ts)\n -o <file> Short form of --output\n\nOTHER OPTIONS:\n --help, -h Show this help message\n --version, -v Show version\n\nENVIRONMENT VARIABLES:\n PGHOST Database host\n PGPORT Database port\n PGDATABASE Database name\n PGUSER Database user\n PGPASSWORD Database password\n\nEXAMPLES:\n # Generate schemas from local database\n pg-to-zod --database mydb --output src/schemas.ts\n\n # Use connection URL\n pg-to-zod --url postgresql://user:pass@localhost:5432/mydb\n\n # Generate with input schemas and camelCase\n pg-to-zod --database mydb --input-schemas --camel-case\n\n # Include specific tables only\n pg-to-zod --database mydb --tables users,posts,comments\n\n # Exclude specific tables\n pg-to-zod --database mydb --exclude-tables migrations,internal\n\n # Multiple schemas\n pg-to-zod --database mydb --schemas public,auth,api\n`);\n}\n\n/**\n * Main CLI function\n */\nasync function main(): Promise<void> {\n try {\n const {config, options, output} = parseArgs();\n\n console.log('🔍 Introspecting database...');\n console.log(` Database: ${config.database}`);\n console.log(` Schemas: ${options.schemas?.join(', ') || 'public'}`);\n\n const schema = await generateZodSchemasString(config, options);\n\n // Write to file\n const outputPath = path.resolve(process.cwd(), output);\n await fs.writeFile(outputPath, schema, 'utf-8');\n\n console.log('✅ Schema generated successfully!');\n console.log(` Output: ${outputPath}`);\n\n // Count generated items\n const enumCount = (schema.match(/export const \\w+Schema = z\\.enum\\(/g) || []).length;\n const tableCount = (schema.match(/export const \\w+Schema = z\\.object\\({/g) || []).length - enumCount;\n\n console.log(` Tables: ${tableCount}`);\n console.log(` Enums: ${enumCount}`);\n\n // Show warnings if any\n if (schema.includes('// Warnings')) {\n const warningLines = schema\n .split('\\n')\n .filter((line) => line.startsWith('// - '))\n .map((line) => line.slice(5));\n\n if (warningLines.length > 0) {\n console.log('\\n⚠️ Warnings:');\n for (const warning of warningLines) {\n console.log(` ${warning}`);\n }\n }\n }\n\n } catch (error) {\n console.error('❌ Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n}\n\nmain();\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.js","names":[],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport {generateZodSchemasString} from './index.js';\nimport type {DatabaseConfig, SchemaGenerationOptions} from './types.js';\n\nconst DEFAULT_OUTPUT = 'schema.ts';\n\n/**\n * Parse command line arguments\n */\nfunction parseArgs(): {\n config: DatabaseConfig;\n options: SchemaGenerationOptions;\n output: string;\n} {\n const args = process.argv.slice(2);\n\n if (args.includes('--help') || args.includes('-h')) {\n printHelp();\n process.exit(0);\n }\n\n if (args.includes('--version') || args.includes('-v')) {\n console.log('pg-to-zod 1.0.0');\n process.exit(0);\n }\n\n // Parse connection string or individual params\n const connectionUrl = getArg(args, '--url');\n let config: DatabaseConfig;\n\n if (connectionUrl) {\n config = parseConnectionUrl(connectionUrl);\n } else {\n config = {\n host: getArg(args, '--host') || process.env.PGHOST || 'localhost',\n port: parseInt(getArg(args, '--port') || process.env.PGPORT || '5432'),\n database: getArg(args, '--database') || process.env.PGDATABASE || 'postgres',\n user: getArg(args, '--user') || process.env.PGUSER || 'postgres',\n password: getArg(args, '--password') || process.env.PGPASSWORD || '',\n ssl: args.includes('--ssl'),\n };\n }\n\n const options: SchemaGenerationOptions = {\n schemas: getArgArray(args, '--schemas') || ['public'],\n tables: getArgArray(args, '--tables'),\n excludeTables: getArgArray(args, '--exclude-tables'),\n generateInputSchemas: !args.includes('--no-input-schemas'), // Default: true\n includeCompositeTypes: args.includes('--composite-types'), // Default: false\n includeViews: args.includes('--views'), // Default: false\n includeRoutines: args.includes('--routines'), // Default: false\n includeSecurityInvoker: args.includes('--security-invoker'), // Default: false\n useBrandedTypes: args.includes('--branded-types'),\n strictMode: args.includes('--strict'),\n includeComments: !args.includes('--no-comments'),\n useCamelCase: args.includes('--camel-case'),\n };\n\n const output = getArg(args, '--output') || getArg(args, '-o') || DEFAULT_OUTPUT;\n\n return {config, options, output};\n}\n\n/**\n * Get argument value\n */\nfunction getArg(args: string[], flag: string): string | undefined {\n const index = args.indexOf(flag);\n if (index !== -1 && index + 1 < args.length) {\n return args[index + 1];\n }\n return undefined;\n}\n\n/**\n * Get argument array value (comma-separated)\n */\nfunction getArgArray(args: string[], flag: string): string[] | undefined {\n const value = getArg(args, flag);\n if (value) {\n return value.split(',').map((s) => s.trim());\n }\n return undefined;\n}\n\n/**\n * Parse PostgreSQL connection URL\n */\nfunction parseConnectionUrl(url: string): DatabaseConfig {\n const match = url.match(\n /postgresql:\\/\\/([^:]+):([^@]+)@([^:\\/]+):(\\d+)\\/(.+)/\n );\n\n if (!match) {\n throw new Error('Invalid connection URL format');\n }\n\n const [, user, password, host, port, database] = match;\n\n return {\n host,\n port: parseInt(port),\n database,\n user,\n password,\n ssl: url.includes('sslmode=require'),\n };\n}\n\n/**\n * Print help message\n */\nfunction printHelp(): void {\n console.log(`\npg-to-zod - Generate strict Zod v4 schemas from PostgreSQL database\n\nUSAGE:\n pg-to-zod [OPTIONS]\n\nCONNECTION OPTIONS:\n --url <url> PostgreSQL connection URL\n (postgresql://user:pass@host:port/db)\n --host <host> Database host (default: localhost)\n --port <port> Database port (default: 5432)\n --database <database> Database name (default: postgres)\n --user <user> Database user (default: postgres)\n --password <password> Database password\n --ssl Use SSL connection\n\nGENERATION OPTIONS:\n --schemas <schemas> Comma-separated list of schemas (default: public)\n --tables <tables> Comma-separated list of tables to include\n --exclude-tables <tables> Comma-separated list of tables to exclude\n --no-input-schemas Skip generating input schemas (generated by default)\n --composite-types Include composite types (skipped by default)\n --views Include database views (skipped by default)\n --routines Include functions/procedures (skipped by default)\n --security-invoker Include SECURITY INVOKER routines (default: DEFINER only)\n --branded-types Use branded types for IDs\n --strict Fail on unmapped types instead of using z.unknown()\n --no-comments Don't include comments in generated code\n --camel-case Use camelCase for field names\n\nOUTPUT OPTIONS:\n --output <file> Output file path (default: schema.ts)\n -o <file> Short form of --output\n\nOTHER OPTIONS:\n --help, -h Show this help message\n --version, -v Show version\n\nENVIRONMENT VARIABLES:\n PGHOST Database host\n PGPORT Database port\n PGDATABASE Database name\n PGUSER Database user\n PGPASSWORD Database password\n\nEXAMPLES:\n # Generate schemas from local database\n pg-to-zod --database mydb --output src/schemas.ts\n\n # Use connection URL\n pg-to-zod --url postgresql://user:pass@localhost:5432/mydb\n\n # Generate with input schemas and camelCase\n pg-to-zod --database mydb --input-schemas --camel-case\n\n # Include specific tables only\n pg-to-zod --database mydb --tables users,posts,comments\n\n # Exclude specific tables\n pg-to-zod --database mydb --exclude-tables migrations,internal\n\n # Multiple schemas\n pg-to-zod --database mydb --schemas public,auth,api\n`);\n}\n\n/**\n * Main CLI function\n */\nasync function main(): Promise<void> {\n try {\n const {config, options, output} = parseArgs();\n\n console.log('🔍 Introspecting database...');\n console.log(` Database: ${config.database}`);\n console.log(` Schemas: ${options.schemas?.join(', ') || 'public'}`);\n\n const schema = await generateZodSchemasString(config, options);\n\n // Write to file\n const outputPath = path.resolve(process.cwd(), output);\n await fs.writeFile(outputPath, schema, 'utf-8');\n\n console.log('✅ Schema generated successfully!');\n console.log(` Output: ${outputPath}`);\n\n // Count generated items\n const enumCount = (schema.match(/export const \\w+Schema = z\\.enum\\(/g) || []).length;\n const tableCount = (schema.match(/export const \\w+Schema = z\\.object\\({/g) || []).length - enumCount;\n\n console.log(` Tables: ${tableCount}`);\n console.log(` Enums: ${enumCount}`);\n\n // Show warnings if any\n if (schema.includes('// Warnings')) {\n const warningLines = schema\n .split('\\n')\n .filter((line) => line.startsWith('// - '))\n .map((line) => line.slice(5));\n\n if (warningLines.length > 0) {\n console.log('\\n⚠️ Warnings:');\n for (const warning of warningLines) {\n console.log(` ${warning}`);\n }\n }\n }\n\n } catch (error) {\n console.error('❌ Error:', error instanceof Error ? error.message : error);\n process.exit(1);\n }\n}\n\nmain();\n"],"mappings":";;;;;;AAOA,MAAM,iBAAiB;;;;AAKvB,SAAS,YAIP;CACE,MAAM,OAAO,QAAQ,KAAK,MAAM,EAAE;AAElC,KAAI,KAAK,SAAS,SAAS,IAAI,KAAK,SAAS,KAAK,EAAE;AAChD,aAAW;AACX,UAAQ,KAAK,EAAE;;AAGnB,KAAI,KAAK,SAAS,YAAY,IAAI,KAAK,SAAS,KAAK,EAAE;AACnD,UAAQ,IAAI,kBAAkB;AAC9B,UAAQ,KAAK,EAAE;;CAInB,MAAM,gBAAgB,OAAO,MAAM,QAAQ;CAC3C,IAAI;AAEJ,KAAI,cACA,UAAS,mBAAmB,cAAc;KAE1C,UAAS;EACL,MAAM,OAAO,MAAM,SAAS,IAAI,QAAQ,IAAI,UAAU;EACtD,MAAM,SAAS,OAAO,MAAM,SAAS,IAAI,QAAQ,IAAI,UAAU,OAAO;EACtE,UAAU,OAAO,MAAM,aAAa,IAAI,QAAQ,IAAI,cAAc;EAClE,MAAM,OAAO,MAAM,SAAS,IAAI,QAAQ,IAAI,UAAU;EACtD,UAAU,OAAO,MAAM,aAAa,IAAI,QAAQ,IAAI,cAAc;EAClE,KAAK,KAAK,SAAS,QAAQ;EAC9B;CAGL,MAAM,UAAmC;EACrC,SAAS,YAAY,MAAM,YAAY,IAAI,CAAC,SAAS;EACrD,QAAQ,YAAY,MAAM,WAAW;EACrC,eAAe,YAAY,MAAM,mBAAmB;EACpD,sBAAsB,CAAC,KAAK,SAAS,qBAAqB;EAC1D,uBAAuB,KAAK,SAAS,oBAAoB;EACzD,cAAc,KAAK,SAAS,UAAU;EACtC,iBAAiB,KAAK,SAAS,aAAa;EAC5C,wBAAwB,KAAK,SAAS,qBAAqB;EAC3D,iBAAiB,KAAK,SAAS,kBAAkB;EACjD,YAAY,KAAK,SAAS,WAAW;EACrC,iBAAiB,CAAC,KAAK,SAAS,gBAAgB;EAChD,cAAc,KAAK,SAAS,eAAe;EAC9C;CAED,MAAM,SAAS,OAAO,MAAM,WAAW,IAAI,OAAO,MAAM,KAAK,IAAI;AAEjE,QAAO;EAAC;EAAQ;EAAS;EAAO;;;;;AAMpC,SAAS,OAAO,MAAgB,MAAkC;CAC9D,MAAM,QAAQ,KAAK,QAAQ,KAAK;AAChC,KAAI,UAAU,MAAM,QAAQ,IAAI,KAAK,OACjC,QAAO,KAAK,QAAQ;;;;;AAQ5B,SAAS,YAAY,MAAgB,MAAoC;CACrE,MAAM,QAAQ,OAAO,MAAM,KAAK;AAChC,KAAI,MACA,QAAO,MAAM,MAAM,IAAI,CAAC,KAAK,MAAM,EAAE,MAAM,CAAC;;;;;AAQpD,SAAS,mBAAmB,KAA6B;CACrD,MAAM,QAAQ,IAAI,MACd,uDACH;AAED,KAAI,CAAC,MACD,OAAM,IAAI,MAAM,gCAAgC;CAGpD,MAAM,GAAG,MAAM,UAAU,MAAM,MAAM,YAAY;AAEjD,QAAO;EACH;EACA,MAAM,SAAS,KAAK;EACpB;EACA;EACA;EACA,KAAK,IAAI,SAAS,kBAAkB;EACvC;;;;;AAML,SAAS,YAAkB;AACvB,SAAQ,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+Dd;;;;;AAMF,eAAe,OAAsB;AACjC,KAAI;EACA,MAAM,EAAC,QAAQ,SAAS,WAAU,WAAW;AAE7C,UAAQ,IAAI,+BAA+B;AAC3C,UAAQ,IAAI,gBAAgB,OAAO,WAAW;AAC9C,UAAQ,IAAI,eAAe,QAAQ,SAAS,KAAK,KAAK,IAAI,WAAW;EAErE,MAAM,SAAS,MAAM,yBAAyB,QAAQ,QAAQ;EAG9D,MAAM,aAAa,KAAK,QAAQ,QAAQ,KAAK,EAAE,OAAO;AACtD,QAAM,GAAG,UAAU,YAAY,QAAQ,QAAQ;AAE/C,UAAQ,IAAI,mCAAmC;AAC/C,UAAQ,IAAI,cAAc,aAAa;EAGvC,MAAM,aAAa,OAAO,MAAM,sCAAsC,IAAI,EAAE,EAAE;EAC9E,MAAM,cAAc,OAAO,MAAM,yCAAyC,IAAI,EAAE,EAAE,SAAS;AAE3F,UAAQ,IAAI,cAAc,aAAa;AACvC,UAAQ,IAAI,aAAa,YAAY;AAGrC,MAAI,OAAO,SAAS,cAAc,EAAE;GAChC,MAAM,eAAe,OAChB,MAAM,KAAK,CACX,QAAQ,SAAS,KAAK,WAAW,QAAQ,CAAC,CAC1C,KAAK,SAAS,KAAK,MAAM,EAAE,CAAC;AAEjC,OAAI,aAAa,SAAS,GAAG;AACzB,YAAQ,IAAI,kBAAkB;AAC9B,SAAK,MAAM,WAAW,aAClB,SAAQ,IAAI,MAAM,UAAU;;;UAKnC,OAAO;AACZ,UAAQ,MAAM,YAAY,iBAAiB,QAAQ,MAAM,UAAU,MAAM;AACzE,UAAQ,KAAK,EAAE;;;AAIvB,MAAM"}
|
package/dist/index.d.ts
CHANGED
|
@@ -93,11 +93,46 @@ interface TableMetadata {
|
|
|
93
93
|
columns: string[];
|
|
94
94
|
}>;
|
|
95
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* View metadata
|
|
98
|
+
*/
|
|
99
|
+
interface ViewMetadata {
|
|
100
|
+
viewName: string;
|
|
101
|
+
schemaName: string;
|
|
102
|
+
columns: ColumnMetadata[];
|
|
103
|
+
viewDefinition: string | null;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Routine (function/procedure) parameter metadata
|
|
107
|
+
*/
|
|
108
|
+
interface RoutineParameterMetadata {
|
|
109
|
+
parameterName: string;
|
|
110
|
+
dataType: string;
|
|
111
|
+
parameterMode: 'IN' | 'OUT' | 'INOUT' | 'VARIADIC';
|
|
112
|
+
ordinalPosition: number;
|
|
113
|
+
udtName: string;
|
|
114
|
+
isNullable: boolean;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Routine (function/procedure) metadata
|
|
118
|
+
*/
|
|
119
|
+
interface RoutineMetadata {
|
|
120
|
+
routineName: string;
|
|
121
|
+
schemaName: string;
|
|
122
|
+
routineType: 'FUNCTION' | 'PROCEDURE';
|
|
123
|
+
securityType: 'DEFINER' | 'INVOKER';
|
|
124
|
+
parameters: RoutineParameterMetadata[];
|
|
125
|
+
returnType: string | null;
|
|
126
|
+
returnUdtName: string | null;
|
|
127
|
+
returnsSet: boolean;
|
|
128
|
+
}
|
|
96
129
|
/**
|
|
97
130
|
* Complete database schema metadata
|
|
98
131
|
*/
|
|
99
132
|
interface DatabaseMetadata {
|
|
100
133
|
tables: TableMetadata[];
|
|
134
|
+
views: ViewMetadata[];
|
|
135
|
+
routines: RoutineMetadata[];
|
|
101
136
|
enums: EnumMetadata[];
|
|
102
137
|
compositeTypes: CompositeTypeMetadata[];
|
|
103
138
|
rangeTypes: RangeTypeMetadata[];
|
|
@@ -117,6 +152,12 @@ interface SchemaGenerationOptions {
|
|
|
117
152
|
generateInputSchemas?: boolean;
|
|
118
153
|
/** Include composite types in generation (default: false) */
|
|
119
154
|
includeCompositeTypes?: boolean;
|
|
155
|
+
/** Include database views in generation (default: false) */
|
|
156
|
+
includeViews?: boolean;
|
|
157
|
+
/** Include database functions/procedures in generation (default: false) */
|
|
158
|
+
includeRoutines?: boolean;
|
|
159
|
+
/** Include security invoker routines (default: false, only security definer) */
|
|
160
|
+
includeSecurityInvoker?: boolean;
|
|
120
161
|
/** Use branded types for IDs and specific fields */
|
|
121
162
|
useBrandedTypes?: boolean;
|
|
122
163
|
/** Strict mode: fail on unmapped types instead of using z.unknown() */
|
|
@@ -143,6 +184,14 @@ interface GeneratedSchema {
|
|
|
143
184
|
*/
|
|
144
185
|
interface GenerationResult {
|
|
145
186
|
schemas: GeneratedSchema[];
|
|
187
|
+
views: Array<{
|
|
188
|
+
name: string;
|
|
189
|
+
code: string;
|
|
190
|
+
}>;
|
|
191
|
+
routines: Array<{
|
|
192
|
+
name: string;
|
|
193
|
+
code: string;
|
|
194
|
+
}>;
|
|
146
195
|
enums: Array<{
|
|
147
196
|
name: string;
|
|
148
197
|
code: string;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/introspect.ts","../src/generator.ts","../src/type-mapper.ts","../src/index.ts"],"sourcesContent":[],"mappings":";;AAGA;AAYA;AAkBiB,UA9BA,cAAA,CA8BuB;EASvB,IAAA,EAAA,MAAA;EASA,IAAA,EAAA,MAAA;EAaA,QAAA,EAAA,MAAA;EASA,IAAA,EAAA,MAAA;EAeA,QAAA,EAAA,MAAa;EAGnB,GAAA,CAAA,EAAA,OAAA,GAAA;IACS,kBAAA,EAAA,OAAA;EAEC,CAAA;;AASrB
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/introspect.ts","../src/generator.ts","../src/type-mapper.ts","../src/index.ts"],"sourcesContent":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { a as generateSchemas, c as toPascalCase, i as formatOutput, l as introspectDatabase, n as generateZodSchemasString, o as mapColumnToZod, r as src_default, s as toCamelCase, t as generateZodSchemas } from "./src-
|
|
1
|
+
import { a as generateSchemas, c as toPascalCase, i as formatOutput, l as introspectDatabase, n as generateZodSchemasString, o as mapColumnToZod, r as src_default, s as toCamelCase, t as generateZodSchemas } from "./src-CEkWBxDB.js";
|
|
2
2
|
|
|
3
3
|
export { src_default as default, formatOutput, generateSchemas, generateZodSchemas, generateZodSchemasString, introspectDatabase, mapColumnToZod, toCamelCase, toPascalCase };
|
|
@@ -9,8 +9,10 @@ async function introspectDatabase(config, options = {}) {
|
|
|
9
9
|
const pool = new Pool(config);
|
|
10
10
|
try {
|
|
11
11
|
const schemas = options.schemas ?? ["public"];
|
|
12
|
-
const [tables, enums, compositeTypes, rangeTypes, domains] = await Promise.all([
|
|
12
|
+
const [tables, views, routines, enums, compositeTypes, rangeTypes, domains] = await Promise.all([
|
|
13
13
|
introspectTables(pool, schemas, options),
|
|
14
|
+
options.includeViews ? introspectViews(pool, schemas) : Promise.resolve([]),
|
|
15
|
+
options.includeRoutines ? introspectRoutines(pool, schemas) : Promise.resolve([]),
|
|
14
16
|
introspectEnums(pool, schemas),
|
|
15
17
|
introspectCompositeTypes(pool, schemas),
|
|
16
18
|
introspectRangeTypes(pool, schemas),
|
|
@@ -18,6 +20,8 @@ async function introspectDatabase(config, options = {}) {
|
|
|
18
20
|
]);
|
|
19
21
|
return {
|
|
20
22
|
tables,
|
|
23
|
+
views,
|
|
24
|
+
routines,
|
|
21
25
|
enums,
|
|
22
26
|
compositeTypes,
|
|
23
27
|
rangeTypes,
|
|
@@ -305,6 +309,157 @@ async function introspectDomains(pool, schemas) {
|
|
|
305
309
|
}
|
|
306
310
|
return domains;
|
|
307
311
|
}
|
|
312
|
+
/**
|
|
313
|
+
* Introspect database views
|
|
314
|
+
*/
|
|
315
|
+
async function introspectViews(pool, schemas) {
|
|
316
|
+
const schemaFilter = schemas.map((_, i) => `$${i + 1}`).join(", ");
|
|
317
|
+
const viewsQuery = `
|
|
318
|
+
SELECT
|
|
319
|
+
table_name as view_name,
|
|
320
|
+
table_schema as schema_name,
|
|
321
|
+
view_definition
|
|
322
|
+
FROM information_schema.views
|
|
323
|
+
WHERE table_schema IN (${schemaFilter})
|
|
324
|
+
ORDER BY table_schema, table_name
|
|
325
|
+
`;
|
|
326
|
+
const viewsResult = await pool.query(viewsQuery, schemas);
|
|
327
|
+
const columnsQuery = `
|
|
328
|
+
SELECT
|
|
329
|
+
c.table_name as view_name,
|
|
330
|
+
c.table_schema as schema_name,
|
|
331
|
+
c.column_name,
|
|
332
|
+
c.ordinal_position,
|
|
333
|
+
c.data_type,
|
|
334
|
+
c.udt_name,
|
|
335
|
+
c.character_maximum_length,
|
|
336
|
+
c.numeric_precision,
|
|
337
|
+
c.numeric_scale,
|
|
338
|
+
c.datetime_precision,
|
|
339
|
+
c.is_nullable,
|
|
340
|
+
c.column_default,
|
|
341
|
+
COALESCE(
|
|
342
|
+
(
|
|
343
|
+
SELECT array_length(string_to_array(udt_name, '_'), 1) - 1
|
|
344
|
+
FROM information_schema.element_types e
|
|
345
|
+
WHERE e.object_schema = c.table_schema
|
|
346
|
+
AND e.object_name = c.table_name
|
|
347
|
+
AND e.collection_type_identifier = c.dtd_identifier
|
|
348
|
+
),
|
|
349
|
+
0
|
|
350
|
+
) as array_dimensions
|
|
351
|
+
FROM information_schema.columns c
|
|
352
|
+
WHERE c.table_schema IN (${schemaFilter})
|
|
353
|
+
AND c.table_name IN (
|
|
354
|
+
SELECT table_name
|
|
355
|
+
FROM information_schema.views
|
|
356
|
+
WHERE table_schema IN (${schemaFilter})
|
|
357
|
+
)
|
|
358
|
+
ORDER BY c.table_schema, c.table_name, c.ordinal_position
|
|
359
|
+
`;
|
|
360
|
+
const columnsResult = await pool.query(columnsQuery, schemas);
|
|
361
|
+
const views = viewsResult.rows.map((row) => ({
|
|
362
|
+
viewName: row.view_name,
|
|
363
|
+
schemaName: row.schema_name,
|
|
364
|
+
viewDefinition: row.view_definition,
|
|
365
|
+
columns: []
|
|
366
|
+
}));
|
|
367
|
+
for (const row of columnsResult.rows) {
|
|
368
|
+
const view = views.find((v) => v.viewName === row.view_name && v.schemaName === row.schema_name);
|
|
369
|
+
if (view) view.columns.push({
|
|
370
|
+
columnName: row.column_name,
|
|
371
|
+
dataType: row.data_type,
|
|
372
|
+
udtName: row.udt_name,
|
|
373
|
+
isNullable: row.is_nullable === "YES",
|
|
374
|
+
columnDefault: row.column_default,
|
|
375
|
+
ordinalPosition: row.ordinal_position,
|
|
376
|
+
characterMaximumLength: row.character_maximum_length,
|
|
377
|
+
numericPrecision: row.numeric_precision,
|
|
378
|
+
numericScale: row.numeric_scale,
|
|
379
|
+
datetimePrecision: row.datetime_precision,
|
|
380
|
+
arrayDimensions: row.array_dimensions,
|
|
381
|
+
isIdentity: false,
|
|
382
|
+
identityGeneration: null,
|
|
383
|
+
isGenerated: false,
|
|
384
|
+
generationExpression: null,
|
|
385
|
+
checkConstraints: []
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
return views;
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Introspect database routines (functions and procedures)
|
|
392
|
+
*/
|
|
393
|
+
async function introspectRoutines(pool, schemas) {
|
|
394
|
+
const schemaFilter = schemas.map((_, i) => `$${i + 1}`).join(", ");
|
|
395
|
+
const routinesQuery = `
|
|
396
|
+
SELECT
|
|
397
|
+
r.routine_name,
|
|
398
|
+
r.routine_schema as schema_name,
|
|
399
|
+
r.routine_type,
|
|
400
|
+
r.security_type,
|
|
401
|
+
r.data_type as return_type,
|
|
402
|
+
CASE
|
|
403
|
+
WHEN r.data_type = 'USER-DEFINED' THEN r.type_udt_name
|
|
404
|
+
ELSE r.data_type
|
|
405
|
+
END as return_udt_name,
|
|
406
|
+
CASE
|
|
407
|
+
WHEN r.data_type = 'ARRAY' THEN true
|
|
408
|
+
ELSE false
|
|
409
|
+
END as returns_set
|
|
410
|
+
FROM information_schema.routines r
|
|
411
|
+
WHERE r.routine_schema IN (${schemaFilter})
|
|
412
|
+
ORDER BY r.routine_schema, r.routine_name
|
|
413
|
+
`;
|
|
414
|
+
const routinesResult = await pool.query(routinesQuery, schemas);
|
|
415
|
+
const parametersQuery = `
|
|
416
|
+
SELECT
|
|
417
|
+
p.specific_name,
|
|
418
|
+
r.routine_name,
|
|
419
|
+
r.routine_schema as schema_name,
|
|
420
|
+
p.parameter_name,
|
|
421
|
+
p.parameter_mode,
|
|
422
|
+
p.ordinal_position,
|
|
423
|
+
p.data_type,
|
|
424
|
+
CASE
|
|
425
|
+
WHEN p.data_type = 'ARRAY' THEN p.udt_name
|
|
426
|
+
WHEN p.data_type = 'USER-DEFINED' THEN p.udt_name
|
|
427
|
+
ELSE p.data_type
|
|
428
|
+
END as udt_name,
|
|
429
|
+
CASE
|
|
430
|
+
WHEN p.parameter_mode = 'OUT' OR p.parameter_mode = 'INOUT' THEN 'YES'
|
|
431
|
+
ELSE 'NO'
|
|
432
|
+
END as is_nullable
|
|
433
|
+
FROM information_schema.parameters p
|
|
434
|
+
JOIN information_schema.routines r ON p.specific_name = r.specific_name
|
|
435
|
+
WHERE r.routine_schema IN (${schemaFilter})
|
|
436
|
+
AND p.parameter_mode IS NOT NULL
|
|
437
|
+
ORDER BY r.routine_schema, r.routine_name, p.ordinal_position
|
|
438
|
+
`;
|
|
439
|
+
const parametersResult = await pool.query(parametersQuery, schemas);
|
|
440
|
+
const routines = routinesResult.rows.map((row) => ({
|
|
441
|
+
routineName: row.routine_name,
|
|
442
|
+
schemaName: row.schema_name,
|
|
443
|
+
routineType: row.routine_type,
|
|
444
|
+
securityType: row.security_type,
|
|
445
|
+
returnType: row.return_type,
|
|
446
|
+
returnUdtName: row.return_udt_name,
|
|
447
|
+
returnsSet: row.returns_set,
|
|
448
|
+
parameters: []
|
|
449
|
+
}));
|
|
450
|
+
for (const row of parametersResult.rows) {
|
|
451
|
+
const routine = routines.find((r) => r.routineName === row.routine_name && r.schemaName === row.schema_name);
|
|
452
|
+
if (routine) routine.parameters.push({
|
|
453
|
+
parameterName: row.parameter_name || `param${row.ordinal_position}`,
|
|
454
|
+
dataType: row.data_type,
|
|
455
|
+
udtName: row.udt_name,
|
|
456
|
+
parameterMode: row.parameter_mode,
|
|
457
|
+
ordinalPosition: row.ordinal_position,
|
|
458
|
+
isNullable: row.is_nullable === "YES"
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
return routines;
|
|
462
|
+
}
|
|
308
463
|
|
|
309
464
|
//#endregion
|
|
310
465
|
//#region src/type-mapper.ts
|
|
@@ -547,6 +702,17 @@ function generateSchemas(metadata, options = {}) {
|
|
|
547
702
|
compositeTypes,
|
|
548
703
|
domains,
|
|
549
704
|
ranges,
|
|
705
|
+
views: metadata.views?.map((view) => ({
|
|
706
|
+
name: toPascalCase(view.schemaName) + toPascalCase(view.viewName),
|
|
707
|
+
code: generateViewSchema(view, metadata, options, warnings)
|
|
708
|
+
})) || [],
|
|
709
|
+
routines: (metadata.routines?.filter((routine) => {
|
|
710
|
+
if (routine.securityType === "INVOKER" && !options.includeSecurityInvoker) return false;
|
|
711
|
+
return true;
|
|
712
|
+
}) || []).map((routine) => ({
|
|
713
|
+
name: toPascalCase(routine.schemaName) + toPascalCase(routine.routineName),
|
|
714
|
+
code: generateRoutineSchema(routine, metadata, options, warnings)
|
|
715
|
+
})),
|
|
550
716
|
warnings
|
|
551
717
|
};
|
|
552
718
|
}
|
|
@@ -664,6 +830,134 @@ function generateDomainSchema(domain, metadata, options, warnings) {
|
|
|
664
830
|
return code;
|
|
665
831
|
}
|
|
666
832
|
/**
|
|
833
|
+
* Generate view schema (read-only)
|
|
834
|
+
*/
|
|
835
|
+
function generateViewSchema(view, metadata, options, warnings) {
|
|
836
|
+
const schemaPrefix = toPascalCase(view.schemaName);
|
|
837
|
+
const viewName = toPascalCase(view.viewName);
|
|
838
|
+
const schemaName = `${schemaPrefix}${viewName}Schema`;
|
|
839
|
+
const typeName = `${schemaPrefix}${viewName}`;
|
|
840
|
+
let code = "";
|
|
841
|
+
if (options.includeComments) code += `/** View: ${view.schemaName}.${view.viewName} (read-only) */\n`;
|
|
842
|
+
code += `export const ${schemaName} = z.object({\n`;
|
|
843
|
+
for (const column of view.columns) {
|
|
844
|
+
const fieldName = options.useCamelCase ? toCamelCase(column.columnName) : column.columnName;
|
|
845
|
+
const zodType = mapColumnToZod(column, metadata, options, warnings);
|
|
846
|
+
if (options.includeComments) code += ` /** ${column.dataType} */\n`;
|
|
847
|
+
code += ` ${fieldName}: ${zodType},\n`;
|
|
848
|
+
}
|
|
849
|
+
code += `});\n`;
|
|
850
|
+
code += `export type ${typeName} = z.infer<typeof ${schemaName}>;\n`;
|
|
851
|
+
return code;
|
|
852
|
+
}
|
|
853
|
+
/**
|
|
854
|
+
* Generate routine schema (function/procedure)
|
|
855
|
+
*/
|
|
856
|
+
function generateRoutineSchema(routine, metadata, options, warnings) {
|
|
857
|
+
const schemaPrefix = toPascalCase(routine.schemaName);
|
|
858
|
+
const routineName = toPascalCase(routine.routineName);
|
|
859
|
+
const paramsSchemaName = `${schemaPrefix}${routineName}ParamsSchema`;
|
|
860
|
+
const returnSchemaName = `${schemaPrefix}${routineName}ReturnSchema`;
|
|
861
|
+
const paramsTypeName = `${schemaPrefix}${routineName}Params`;
|
|
862
|
+
const returnTypeName = `${schemaPrefix}${routineName}Return`;
|
|
863
|
+
let code = "";
|
|
864
|
+
if (options.includeComments) code += `/** ${routine.routineType}: ${routine.schemaName}.${routine.routineName} */\n`;
|
|
865
|
+
const inParams = routine.parameters.filter((p) => p.parameterMode === "IN" || p.parameterMode === "INOUT");
|
|
866
|
+
if (inParams.length > 0) {
|
|
867
|
+
code += `export const ${paramsSchemaName} = z.object({\n`;
|
|
868
|
+
for (const param of inParams) {
|
|
869
|
+
const fieldName = options.useCamelCase ? toCamelCase(param.parameterName) : param.parameterName;
|
|
870
|
+
const zodType = mapColumnToZod({
|
|
871
|
+
columnName: param.parameterName,
|
|
872
|
+
dataType: param.dataType,
|
|
873
|
+
isNullable: param.isNullable,
|
|
874
|
+
columnDefault: null,
|
|
875
|
+
characterMaximumLength: null,
|
|
876
|
+
numericPrecision: null,
|
|
877
|
+
numericScale: null,
|
|
878
|
+
datetimePrecision: null,
|
|
879
|
+
udtName: param.udtName,
|
|
880
|
+
domainName: null,
|
|
881
|
+
arrayDimensions: 0,
|
|
882
|
+
isArray: param.dataType === "ARRAY"
|
|
883
|
+
}, metadata, options, warnings);
|
|
884
|
+
if (options.includeComments) code += ` /** ${param.dataType} (${param.parameterMode}) */\n`;
|
|
885
|
+
code += ` ${fieldName}: ${zodType},\n`;
|
|
886
|
+
}
|
|
887
|
+
code += `});\n`;
|
|
888
|
+
code += `export type ${paramsTypeName} = z.infer<typeof ${paramsSchemaName}>;\n\n`;
|
|
889
|
+
}
|
|
890
|
+
const outParams = routine.parameters.filter((p) => p.parameterMode === "OUT" || p.parameterMode === "INOUT");
|
|
891
|
+
if (routine.routineType === "FUNCTION" && routine.returnType && routine.returnType !== "void") {
|
|
892
|
+
if (outParams.length > 0) {
|
|
893
|
+
code += `export const ${returnSchemaName} = z.object({\n`;
|
|
894
|
+
for (const param of outParams) {
|
|
895
|
+
const fieldName = options.useCamelCase ? toCamelCase(param.parameterName) : param.parameterName;
|
|
896
|
+
const zodType = mapColumnToZod({
|
|
897
|
+
columnName: param.parameterName,
|
|
898
|
+
dataType: param.dataType,
|
|
899
|
+
isNullable: param.isNullable,
|
|
900
|
+
columnDefault: null,
|
|
901
|
+
characterMaximumLength: null,
|
|
902
|
+
numericPrecision: null,
|
|
903
|
+
numericScale: null,
|
|
904
|
+
datetimePrecision: null,
|
|
905
|
+
udtName: param.udtName,
|
|
906
|
+
domainName: null,
|
|
907
|
+
arrayDimensions: 0,
|
|
908
|
+
isArray: param.dataType === "ARRAY"
|
|
909
|
+
}, metadata, options, warnings);
|
|
910
|
+
if (options.includeComments) code += ` /** ${param.dataType} (${param.parameterMode}) */\n`;
|
|
911
|
+
code += ` ${fieldName}: ${zodType},\n`;
|
|
912
|
+
}
|
|
913
|
+
code += `});\n`;
|
|
914
|
+
} else {
|
|
915
|
+
const zodType = mapColumnToZod({
|
|
916
|
+
columnName: "return_value",
|
|
917
|
+
dataType: routine.returnType,
|
|
918
|
+
isNullable: false,
|
|
919
|
+
columnDefault: null,
|
|
920
|
+
characterMaximumLength: null,
|
|
921
|
+
numericPrecision: null,
|
|
922
|
+
numericScale: null,
|
|
923
|
+
datetimePrecision: null,
|
|
924
|
+
udtName: routine.returnUdtName || routine.returnType,
|
|
925
|
+
domainName: null,
|
|
926
|
+
arrayDimensions: 0,
|
|
927
|
+
isArray: routine.returnType === "ARRAY" || routine.returnsSet
|
|
928
|
+
}, metadata, options, warnings);
|
|
929
|
+
if (options.includeComments) code += `/** Returns: ${routine.returnType} */\n`;
|
|
930
|
+
if (routine.returnsSet) code += `export const ${returnSchemaName} = z.array(${zodType});\n`;
|
|
931
|
+
else code += `export const ${returnSchemaName} = ${zodType};\n`;
|
|
932
|
+
}
|
|
933
|
+
code += `export type ${returnTypeName} = z.infer<typeof ${returnSchemaName}>;\n`;
|
|
934
|
+
} else if (outParams.length > 0) {
|
|
935
|
+
code += `export const ${returnSchemaName} = z.object({\n`;
|
|
936
|
+
for (const param of outParams) {
|
|
937
|
+
const fieldName = options.useCamelCase ? toCamelCase(param.parameterName) : param.parameterName;
|
|
938
|
+
const zodType = mapColumnToZod({
|
|
939
|
+
columnName: param.parameterName,
|
|
940
|
+
dataType: param.dataType,
|
|
941
|
+
isNullable: param.isNullable,
|
|
942
|
+
columnDefault: null,
|
|
943
|
+
characterMaximumLength: null,
|
|
944
|
+
numericPrecision: null,
|
|
945
|
+
numericScale: null,
|
|
946
|
+
datetimePrecision: null,
|
|
947
|
+
udtName: param.udtName,
|
|
948
|
+
domainName: null,
|
|
949
|
+
arrayDimensions: 0,
|
|
950
|
+
isArray: param.dataType === "ARRAY"
|
|
951
|
+
}, metadata, options, warnings);
|
|
952
|
+
if (options.includeComments) code += ` /** ${param.dataType} (${param.parameterMode}) */\n`;
|
|
953
|
+
code += ` ${fieldName}: ${zodType},\n`;
|
|
954
|
+
}
|
|
955
|
+
code += `});\n`;
|
|
956
|
+
code += `export type ${returnTypeName} = z.infer<typeof ${returnSchemaName}>;\n`;
|
|
957
|
+
}
|
|
958
|
+
return code;
|
|
959
|
+
}
|
|
960
|
+
/**
|
|
667
961
|
* Generate table schema
|
|
668
962
|
*/
|
|
669
963
|
function generateTableSchema(table, metadata, options, warnings) {
|
|
@@ -795,6 +1089,18 @@ function formatOutput(result) {
|
|
|
795
1089
|
output += `// ============================================\n\n`;
|
|
796
1090
|
for (const schema of result.schemas) output += schema.typeDefinitions + "\n";
|
|
797
1091
|
}
|
|
1092
|
+
if (result.views && result.views.length > 0) {
|
|
1093
|
+
output += `// ============================================\n`;
|
|
1094
|
+
output += `// Views\n`;
|
|
1095
|
+
output += `// ============================================\n\n`;
|
|
1096
|
+
for (const view of result.views) output += view.code + "\n";
|
|
1097
|
+
}
|
|
1098
|
+
if (result.routines && result.routines.length > 0) {
|
|
1099
|
+
output += `// ============================================\n`;
|
|
1100
|
+
output += `// Routines (Functions/Procedures)\n`;
|
|
1101
|
+
output += `// ============================================\n\n`;
|
|
1102
|
+
for (const routine of result.routines) output += routine.code + "\n";
|
|
1103
|
+
}
|
|
798
1104
|
if (result.warnings.length > 0) {
|
|
799
1105
|
output += `// ============================================\n`;
|
|
800
1106
|
output += `// Warnings\n`;
|
|
@@ -832,4 +1138,4 @@ var src_default = {
|
|
|
832
1138
|
|
|
833
1139
|
//#endregion
|
|
834
1140
|
export { generateSchemas as a, toPascalCase as c, formatOutput as i, introspectDatabase as l, generateZodSchemasString as n, mapColumnToZod as o, src_default as r, toCamelCase as s, generateZodSchemas as t };
|
|
835
|
-
//# sourceMappingURL=src-
|
|
1141
|
+
//# sourceMappingURL=src-CEkWBxDB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"src-CEkWBxDB.js","names":[],"sources":["../src/introspect.ts","../src/type-mapper.ts","../src/generator.ts","../src/index.ts"],"sourcesContent":["import pg from 'pg';\nimport type {\n DatabaseConfig,\n DatabaseMetadata,\n TableMetadata,\n ViewMetadata,\n RoutineMetadata,\n EnumMetadata,\n CompositeTypeMetadata,\n RangeTypeMetadata,\n DomainMetadata,\n SchemaGenerationOptions,\n} from './types.js';\n\nconst { Pool } = pg;\n\n/**\n * Introspect a PostgreSQL database and return complete metadata\n */\nexport async function introspectDatabase(\n config: DatabaseConfig,\n options: SchemaGenerationOptions = {}\n): Promise<DatabaseMetadata> {\n const pool = new Pool(config);\n\n try {\n const schemas = options.schemas ?? ['public'];\n\n const [\n tables,\n views,\n routines,\n enums,\n compositeTypes,\n rangeTypes,\n domains,\n ] = await Promise.all([\n introspectTables(pool, schemas, options),\n options.includeViews ? introspectViews(pool, schemas) : Promise.resolve([]),\n options.includeRoutines ? introspectRoutines(pool, schemas) : Promise.resolve([]),\n introspectEnums(pool, schemas),\n introspectCompositeTypes(pool, schemas),\n introspectRangeTypes(pool, schemas),\n introspectDomains(pool, schemas),\n ]);\n\n return {\n tables,\n views,\n routines,\n enums,\n compositeTypes,\n rangeTypes,\n domains,\n };\n } finally {\n await pool.end();\n }\n}\n\n/**\n * Introspect tables and their columns\n */\nasync function introspectTables(\n pool: pg.Pool,\n schemas: string[],\n options: SchemaGenerationOptions\n): Promise<TableMetadata[]> {\n const schemaFilter = schemas.map((_, i) => `$${i + 1}`).join(', ');\n\n // Get all columns\n const columnsQuery = `\n SELECT \n c.table_schema,\n c.table_name,\n c.column_name,\n c.data_type,\n c.is_nullable,\n c.column_default,\n c.character_maximum_length,\n c.numeric_precision,\n c.numeric_scale,\n c.datetime_precision,\n c.udt_name,\n c.domain_name,\n COALESCE(\n (SELECT array_ndims(ARRAY[]::text[]) FROM information_schema.element_types e \n WHERE e.object_schema = c.table_schema \n AND e.object_name = c.table_name \n AND e.object_type = 'TABLE'\n AND e.collection_type_identifier = c.dtd_identifier\n ), 0\n ) as array_dimensions\n FROM information_schema.columns c\n WHERE c.table_schema IN (${schemaFilter})\n ORDER BY c.table_schema, c.table_name, c.ordinal_position\n `;\n\n const columnsResult = await pool.query(columnsQuery, schemas);\n\n // Get check constraints\n const constraintsQuery = `\n SELECT \n tc.table_schema,\n tc.table_name,\n tc.constraint_name,\n cc.check_clause,\n ccu.column_name\n FROM information_schema.table_constraints tc\n JOIN information_schema.check_constraints cc \n ON tc.constraint_name = cc.constraint_name \n AND tc.constraint_schema = cc.constraint_schema\n LEFT JOIN information_schema.constraint_column_usage ccu\n ON tc.constraint_name = ccu.constraint_name\n AND tc.constraint_schema = ccu.constraint_schema\n WHERE tc.constraint_type = 'CHECK'\n AND tc.table_schema IN (${schemaFilter})\n `;\n\n const constraintsResult = await pool.query(constraintsQuery, schemas);\n\n // Get primary keys\n const primaryKeysQuery = `\n SELECT \n tc.table_schema,\n tc.table_name,\n kcu.column_name\n FROM information_schema.table_constraints tc\n JOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n WHERE tc.constraint_type = 'PRIMARY KEY'\n AND tc.table_schema IN (${schemaFilter})\n ORDER BY kcu.ordinal_position\n `;\n\n const primaryKeysResult = await pool.query(primaryKeysQuery, schemas);\n\n // Get unique constraints\n const uniqueConstraintsQuery = `\n SELECT \n tc.table_schema,\n tc.table_name,\n tc.constraint_name,\n array_agg(kcu.column_name ORDER BY kcu.ordinal_position) as columns\n FROM information_schema.table_constraints tc\n JOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n WHERE tc.constraint_type = 'UNIQUE'\n AND tc.table_schema IN (${schemaFilter})\n GROUP BY tc.table_schema, tc.table_name, tc.constraint_name\n `;\n\n const uniqueConstraintsResult = await pool.query(uniqueConstraintsQuery, schemas);\n\n // Group by table\n const tableMap = new Map<string, TableMetadata>();\n\n for (const row of columnsResult.rows) {\n const tableKey = `${row.table_schema}.${row.table_name}`;\n\n if (!tableMap.has(tableKey)) {\n tableMap.set(tableKey, {\n tableName: row.table_name,\n schemaName: row.table_schema,\n columns: [],\n checkConstraints: [],\n primaryKeys: [],\n uniqueConstraints: [],\n });\n }\n\n const table = tableMap.get(tableKey)!;\n const isArray = row.data_type === 'ARRAY';\n\n table.columns.push({\n columnName: row.column_name,\n dataType: row.data_type,\n isNullable: row.is_nullable === 'YES',\n columnDefault: row.column_default,\n characterMaximumLength: row.character_maximum_length,\n numericPrecision: row.numeric_precision,\n numericScale: row.numeric_scale,\n datetimePrecision: row.datetime_precision,\n udtName: row.udt_name,\n domainName: row.domain_name,\n arrayDimensions: row.array_dimensions || 0,\n isArray,\n });\n }\n\n // Add check constraints\n for (const row of constraintsResult.rows) {\n const tableKey = `${row.table_schema}.${row.table_name}`;\n const table = tableMap.get(tableKey);\n if (table) {\n table.checkConstraints.push({\n constraintName: row.constraint_name,\n checkClause: row.check_clause,\n columnName: row.column_name,\n });\n }\n }\n\n // Add primary keys\n for (const row of primaryKeysResult.rows) {\n const tableKey = `${row.table_schema}.${row.table_name}`;\n const table = tableMap.get(tableKey);\n if (table) {\n table.primaryKeys.push(row.column_name);\n }\n }\n\n // Add unique constraints\n for (const row of uniqueConstraintsResult.rows) {\n const tableKey = `${row.table_schema}.${row.table_name}`;\n const table = tableMap.get(tableKey);\n if (table) {\n table.uniqueConstraints.push({\n constraintName: row.constraint_name,\n columns: row.columns,\n });\n }\n }\n\n // Filter tables based on options\n let tables = Array.from(tableMap.values());\n\n if (options.tables) {\n tables = tables.filter((t) => options.tables!.includes(t.tableName));\n }\n\n if (options.excludeTables) {\n tables = tables.filter((t) => !options.excludeTables!.includes(t.tableName));\n }\n\n return tables;\n}\n\n/**\n * Introspect enum types\n */\nasync function introspectEnums(\n pool: pg.Pool,\n schemas: string[]\n): Promise<EnumMetadata[]> {\n const schemaFilter = schemas.map((_, i) => `$${i + 1}`).join(', ');\n\n const query = `\n SELECT \n t.typname as enum_name,\n n.nspname as schema_name,\n array_agg(e.enumlabel ORDER BY e.enumsortorder) as enum_values\n FROM pg_type t\n JOIN pg_enum e ON t.oid = e.enumtypid\n JOIN pg_namespace n ON t.typnamespace = n.oid\n WHERE n.nspname IN (${schemaFilter})\n GROUP BY t.typname, n.nspname\n ORDER BY t.typname\n `;\n\n const result = await pool.query(query, schemas);\n\n return result.rows.map((row) => {\n // Handle PostgreSQL array format: {value1,value2,value3}\n let enumValues: string[];\n \n if (Array.isArray(row.enum_values)) {\n enumValues = row.enum_values;\n } else if (typeof row.enum_values === 'string') {\n // Parse PostgreSQL array format\n if (row.enum_values.startsWith('{') && row.enum_values.endsWith('}')) {\n enumValues = row.enum_values\n .slice(1, -1) // Remove { and }\n .split(',')\n .map((v: string) => v.trim());\n } else {\n enumValues = [row.enum_values];\n }\n } else {\n enumValues = [row.enum_values];\n }\n \n return {\n enumName: row.enum_name,\n enumValues,\n schemaName: row.schema_name,\n };\n });\n}\n\n/**\n * Introspect composite types\n */\nasync function introspectCompositeTypes(\n pool: pg.Pool,\n schemas: string[]\n): Promise<CompositeTypeMetadata[]> {\n const schemaFilter = schemas.map((_, i) => `$${i + 1}`).join(', ');\n\n const query = `\n SELECT \n t.typname as type_name,\n n.nspname as schema_name,\n a.attname as attribute_name,\n a.attnum as attribute_number,\n format_type(a.atttypid, a.atttypmod) as data_type\n FROM pg_type t\n JOIN pg_namespace n ON t.typnamespace = n.oid\n JOIN pg_class c ON t.typrelid = c.oid\n JOIN pg_attribute a ON c.oid = a.attrelid\n WHERE t.typtype = 'c'\n AND n.nspname IN (${schemaFilter})\n AND a.attnum > 0\n AND NOT a.attisdropped\n ORDER BY t.typname, a.attnum\n `;\n\n const result = await pool.query(query, schemas);\n\n const typeMap = new Map<string, CompositeTypeMetadata>();\n\n for (const row of result.rows) {\n const typeKey = `${row.schema_name}.${row.type_name}`;\n\n if (!typeMap.has(typeKey)) {\n typeMap.set(typeKey, {\n typeName: row.type_name,\n schemaName: row.schema_name,\n attributes: [],\n });\n }\n\n const type = typeMap.get(typeKey)!;\n type.attributes.push({\n attributeName: row.attribute_name,\n dataType: row.data_type,\n attributeNumber: row.attribute_number,\n });\n }\n\n return Array.from(typeMap.values());\n}\n\n/**\n * Introspect range types\n */\nasync function introspectRangeTypes(\n pool: pg.Pool,\n schemas: string[]\n): Promise<RangeTypeMetadata[]> {\n const schemaFilter = schemas.map((_, i) => `$${i + 1}`).join(', ');\n\n const query = `\n SELECT \n t.typname as range_name,\n n.nspname as schema_name,\n format_type(r.rngsubtype, NULL) as subtype\n FROM pg_type t\n JOIN pg_namespace n ON t.typnamespace = n.oid\n JOIN pg_range r ON t.oid = r.rngtypid\n WHERE n.nspname IN (${schemaFilter})\n ORDER BY t.typname\n `;\n\n const result = await pool.query(query, schemas);\n\n return result.rows.map((row) => ({\n rangeName: row.range_name,\n subtype: row.subtype,\n schemaName: row.schema_name,\n }));\n}\n\n/**\n * Introspect domain types\n */\nasync function introspectDomains(\n pool: pg.Pool,\n schemas: string[]\n): Promise<DomainMetadata[]> {\n const schemaFilter = schemas.map((_, i) => `$${i + 1}`).join(', ');\n\n // Get domain information\n const domainsQuery = `\n SELECT \n t.typname as domain_name,\n n.nspname as schema_name,\n format_type(t.typbasetype, t.typtypmod) as data_type,\n t.typnotnull as is_not_null,\n t.typdefault as domain_default,\n information_schema._pg_char_max_length(t.typbasetype, t.typtypmod) as character_maximum_length,\n information_schema._pg_numeric_precision(t.typbasetype, t.typtypmod) as numeric_precision,\n information_schema._pg_numeric_scale(t.typbasetype, t.typtypmod) as numeric_scale\n FROM pg_type t\n JOIN pg_namespace n ON t.typnamespace = n.oid\n WHERE t.typtype = 'd'\n AND n.nspname IN (${schemaFilter})\n ORDER BY t.typname\n `;\n\n const domainsResult = await pool.query(domainsQuery, schemas);\n\n // Get domain constraints\n const constraintsQuery = `\n SELECT \n t.typname as domain_name,\n n.nspname as schema_name,\n c.conname as constraint_name,\n pg_get_constraintdef(c.oid) as check_clause\n FROM pg_constraint c\n JOIN pg_type t ON c.contypid = t.oid\n JOIN pg_namespace n ON t.typnamespace = n.oid\n WHERE c.contype = 'c'\n AND n.nspname IN (${schemaFilter})\n `;\n\n const constraintsResult = await pool.query(constraintsQuery, schemas);\n\n const domains: DomainMetadata[] = domainsResult.rows.map((row) => ({\n domainName: row.domain_name,\n dataType: row.data_type,\n schemaName: row.schema_name,\n characterMaximumLength: row.character_maximum_length,\n numericPrecision: row.numeric_precision,\n numericScale: row.numeric_scale,\n isNullable: !row.is_not_null,\n domainDefault: row.domain_default,\n checkConstraints: [],\n }));\n\n // Add check constraints to domains\n for (const row of constraintsResult.rows) {\n const domain = domains.find(\n (d) => d.domainName === row.domain_name && d.schemaName === row.schema_name\n );\n if (domain) {\n domain.checkConstraints.push({\n constraintName: row.constraint_name,\n checkClause: row.check_clause,\n columnName: null,\n });\n }\n }\n\n return domains;\n}\n\n/**\n * Introspect database views\n */\nasync function introspectViews(\n pool: pg.Pool,\n schemas: string[]\n): Promise<ViewMetadata[]> {\n const schemaFilter = schemas.map((_, i) => `$${i + 1}`).join(', ');\n\n // Get view definitions\n const viewsQuery = `\n SELECT \n table_name as view_name,\n table_schema as schema_name,\n view_definition\n FROM information_schema.views\n WHERE table_schema IN (${schemaFilter})\n ORDER BY table_schema, table_name\n `;\n\n const viewsResult = await pool.query(viewsQuery, schemas);\n\n // Get columns for each view\n const columnsQuery = `\n SELECT \n c.table_name as view_name,\n c.table_schema as schema_name,\n c.column_name,\n c.ordinal_position,\n c.data_type,\n c.udt_name,\n c.character_maximum_length,\n c.numeric_precision,\n c.numeric_scale,\n c.datetime_precision,\n c.is_nullable,\n c.column_default,\n COALESCE(\n (\n SELECT array_length(string_to_array(udt_name, '_'), 1) - 1\n FROM information_schema.element_types e\n WHERE e.object_schema = c.table_schema\n AND e.object_name = c.table_name\n AND e.collection_type_identifier = c.dtd_identifier\n ),\n 0\n ) as array_dimensions\n FROM information_schema.columns c\n WHERE c.table_schema IN (${schemaFilter})\n AND c.table_name IN (\n SELECT table_name \n FROM information_schema.views \n WHERE table_schema IN (${schemaFilter})\n )\n ORDER BY c.table_schema, c.table_name, c.ordinal_position\n `;\n\n const columnsResult = await pool.query(columnsQuery, schemas);\n\n const views: ViewMetadata[] = viewsResult.rows.map((row) => ({\n viewName: row.view_name,\n schemaName: row.schema_name,\n viewDefinition: row.view_definition,\n columns: [],\n }));\n\n // Add columns to views\n for (const row of columnsResult.rows) {\n const view = views.find(\n (v) => v.viewName === row.view_name && v.schemaName === row.schema_name\n );\n if (view) {\n view.columns.push({\n columnName: row.column_name,\n dataType: row.data_type,\n udtName: row.udt_name,\n isNullable: row.is_nullable === 'YES',\n columnDefault: row.column_default,\n ordinalPosition: row.ordinal_position,\n characterMaximumLength: row.character_maximum_length,\n numericPrecision: row.numeric_precision,\n numericScale: row.numeric_scale,\n datetimePrecision: row.datetime_precision,\n arrayDimensions: row.array_dimensions,\n isIdentity: false,\n identityGeneration: null,\n isGenerated: false,\n generationExpression: null,\n checkConstraints: [],\n });\n }\n }\n\n return views;\n}\n\n/**\n * Introspect database routines (functions and procedures)\n */\nasync function introspectRoutines(\n pool: pg.Pool,\n schemas: string[]\n): Promise<RoutineMetadata[]> {\n const schemaFilter = schemas.map((_, i) => `$${i + 1}`).join(', ');\n\n // Get routine definitions\n const routinesQuery = `\n SELECT \n r.routine_name,\n r.routine_schema as schema_name,\n r.routine_type,\n r.security_type,\n r.data_type as return_type,\n CASE \n WHEN r.data_type = 'USER-DEFINED' THEN r.type_udt_name\n ELSE r.data_type\n END as return_udt_name,\n CASE\n WHEN r.data_type = 'ARRAY' THEN true\n ELSE false\n END as returns_set\n FROM information_schema.routines r\n WHERE r.routine_schema IN (${schemaFilter})\n ORDER BY r.routine_schema, r.routine_name\n `;\n\n const routinesResult = await pool.query(routinesQuery, schemas);\n\n // Get parameters for each routine\n const parametersQuery = `\n SELECT \n p.specific_name,\n r.routine_name,\n r.routine_schema as schema_name,\n p.parameter_name,\n p.parameter_mode,\n p.ordinal_position,\n p.data_type,\n CASE \n WHEN p.data_type = 'ARRAY' THEN p.udt_name\n WHEN p.data_type = 'USER-DEFINED' THEN p.udt_name\n ELSE p.data_type\n END as udt_name,\n CASE\n WHEN p.parameter_mode = 'OUT' OR p.parameter_mode = 'INOUT' THEN 'YES'\n ELSE 'NO'\n END as is_nullable\n FROM information_schema.parameters p\n JOIN information_schema.routines r ON p.specific_name = r.specific_name\n WHERE r.routine_schema IN (${schemaFilter})\n AND p.parameter_mode IS NOT NULL\n ORDER BY r.routine_schema, r.routine_name, p.ordinal_position\n `;\n\n const parametersResult = await pool.query(parametersQuery, schemas);\n\n const routines: RoutineMetadata[] = routinesResult.rows.map((row) => ({\n routineName: row.routine_name,\n schemaName: row.schema_name,\n routineType: row.routine_type as 'FUNCTION' | 'PROCEDURE',\n securityType: row.security_type as 'DEFINER' | 'INVOKER',\n returnType: row.return_type,\n returnUdtName: row.return_udt_name,\n returnsSet: row.returns_set,\n parameters: [],\n }));\n\n // Add parameters to routines\n for (const row of parametersResult.rows) {\n const routine = routines.find(\n (r) => r.routineName === row.routine_name && r.schemaName === row.schema_name\n );\n if (routine) {\n routine.parameters.push({\n parameterName: row.parameter_name || `param${row.ordinal_position}`,\n dataType: row.data_type,\n udtName: row.udt_name,\n parameterMode: row.parameter_mode,\n ordinalPosition: row.ordinal_position,\n isNullable: row.is_nullable === 'YES',\n });\n }\n }\n\n return routines;\n}\n","import type {\n ColumnMetadata,\n DatabaseMetadata,\n SchemaGenerationOptions,\n CheckConstraintMetadata,\n} from './types.js';\n\n/**\n * Map PostgreSQL column to Zod schema string with strict validation\n */\nexport function mapColumnToZod(\n column: ColumnMetadata,\n metadata: DatabaseMetadata,\n options: SchemaGenerationOptions,\n warnings: string[]\n): string {\n // Handle domains first\n if (column.domainName) {\n const domain = metadata.domains.find((d) => d.domainName === column.domainName);\n if (domain) {\n const schemaPrefix = toPascalCase(domain.schemaName);\n const domainName = toPascalCase(domain.domainName);\n let schema = `${schemaPrefix}${domainName}Schema`;\n return column.isNullable ? `${schema}.nullable()` : schema;\n }\n }\n\n // Handle arrays\n if (column.isArray) {\n const baseType = mapBaseTypeToZod(column, metadata, options, warnings);\n let arraySchema = `z.array(${baseType})`;\n \n // Multi-dimensional arrays\n if (column.arrayDimensions > 1) {\n for (let i = 1; i < column.arrayDimensions; i++) {\n arraySchema = `z.array(${arraySchema})`;\n }\n }\n \n return column.isNullable ? `${arraySchema}.nullable()` : arraySchema;\n }\n\n // Handle base types\n const baseSchema = mapBaseTypeToZod(column, metadata, options, warnings);\n return column.isNullable ? `${baseSchema}.nullable()` : baseSchema;\n}\n\n/**\n * Map base PostgreSQL type to Zod\n */\nfunction mapBaseTypeToZod(\n column: ColumnMetadata,\n metadata: DatabaseMetadata,\n options: SchemaGenerationOptions,\n warnings: string[]\n): string {\n let udtName = column.udtName;\n const dataType = column.dataType.toLowerCase();\n\n // PostgreSQL array types have underscore prefix (e.g., _text for text[], _int4 for integer[])\n // Strip the underscore to get the actual base type name\n if (column.isArray && udtName.startsWith('_')) {\n udtName = udtName.substring(1);\n }\n\n // Custom type mappings\n if (options.customTypeMappings?.[udtName]) {\n return options.customTypeMappings[udtName];\n }\n\n // Check if it's an enum\n const enumType = metadata.enums.find((e) => e.enumName === udtName);\n if (enumType) {\n const schemaPrefix = toPascalCase(enumType.schemaName);\n const enumName = toPascalCase(enumType.enumName);\n return `${schemaPrefix}${enumName}Schema`;\n }\n\n // Check if it's a composite type\n const compositeType = metadata.compositeTypes.find((t) => t.typeName === udtName);\n if (compositeType) {\n const schemaPrefix = toPascalCase(compositeType.schemaName);\n const typeName = toPascalCase(compositeType.typeName);\n // Add 'Composite' suffix to match generator\n return `${schemaPrefix}${typeName}CompositeSchema`;\n }\n\n // Check if it's a range type\n const rangeType = metadata.rangeTypes.find((r) => r.rangeName === udtName);\n if (rangeType) {\n const schemaPrefix = toPascalCase(rangeType.schemaName);\n const rangeName = toPascalCase(rangeType.rangeName);\n return `${schemaPrefix}${rangeName}Schema`;\n }\n\n // Map by data type or by udtName for arrays\n // For arrays, dataType will be 'ARRAY' so we need to check the udtName\n const typeToCheck = dataType === 'array' ? udtName : dataType;\n \n switch (typeToCheck) {\n // Numeric types\n case 'smallint':\n case 'integer':\n case 'int':\n case 'int2':\n case 'int4':\n return 'z.number().int()';\n \n case 'bigint':\n case 'int8':\n return 'z.bigint()';\n \n case 'decimal':\n case 'numeric':\n if (column.numericPrecision !== null && column.numericScale !== null) {\n return `z.number() /* precision: ${column.numericPrecision}, scale: ${column.numericScale} */`;\n }\n return 'z.number()';\n \n case 'real':\n case 'float4':\n return 'z.number()';\n \n case 'double precision':\n case 'float8':\n return 'z.number()';\n \n case 'money':\n return 'z.string().regex(/^\\\\$?[0-9,]+(\\\\.\\\\d{2})?$/)';\n\n // Text types\n case 'character varying':\n case 'varchar':\n if (column.characterMaximumLength) {\n return `z.string().max(${column.characterMaximumLength})`;\n }\n return 'z.string()';\n \n case 'character':\n case 'char':\n if (column.characterMaximumLength) {\n return `z.string().length(${column.characterMaximumLength})`;\n }\n return 'z.string()';\n \n case 'text':\n return 'z.string()';\n \n case 'citext':\n return 'z.string()';\n\n // Boolean\n case 'boolean':\n case 'bool':\n return 'z.boolean()';\n\n // Date/Time types\n case 'timestamp':\n case 'timestamp without time zone':\n return 'z.date()';\n \n case 'timestamp with time zone':\n case 'timestamptz':\n return 'z.date()';\n \n case 'date':\n return 'z.date()';\n \n case 'time':\n case 'time without time zone':\n return 'z.iso.time()';\n \n case 'time with time zone':\n case 'timetz':\n // PostgreSQL time with timezone, no direct Zod v4 equivalent\n return 'z.string().regex(/^\\\\d{2}:\\\\d{2}:\\\\d{2}(\\\\.\\\\d+)?[+-]\\\\d{2}:\\\\d{2}$/)';\n \n case 'interval':\n return 'z.iso.duration()';\n\n // UUID\n case 'uuid':\n return 'z.uuid()';\n\n // JSON types\n case 'json':\n return 'z.record(z.string(), z.unknown())';\n \n case 'jsonb':\n return 'z.record(z.string(), z.unknown())';\n\n // Network types\n case 'inet':\n // In Zod v4, use z.ipv4() or z.ipv6() but inet accepts both, so we use a union\n return 'z.union([z.ipv4(), z.ipv6()])';\n \n case 'cidr':\n // PostgreSQL cidr accepts both IPv4 and IPv6 CIDR notation\n return 'z.union([z.cidrv4(), z.cidrv6()])';\n \n case 'macaddr':\n return 'z.mac()';\n \n case 'macaddr8':\n // macaddr8 is 64-bit (8 bytes), standard z.mac() is 48-bit, use regex\n return 'z.string().regex(/^([0-9A-Fa-f]{2}[:-]){7}([0-9A-Fa-f]{2})$/)';\n\n // Bit string types\n case 'bit':\n if (column.characterMaximumLength) {\n return `z.string().regex(/^[01]{${column.characterMaximumLength}}$/)`;\n }\n return 'z.string().regex(/^[01]+$/)';\n \n case 'bit varying':\n case 'varbit':\n if (column.characterMaximumLength) {\n return `z.string().regex(/^[01]{0,${column.characterMaximumLength}}$/)`;\n }\n return 'z.string().regex(/^[01]*$/)';\n\n // Geometric types\n case 'point':\n return 'z.tuple([z.number(), z.number()])';\n \n case 'line':\n return 'z.object({ a: z.number(), b: z.number(), c: z.number() })';\n \n case 'lseg':\n return 'z.tuple([z.tuple([z.number(), z.number()]), z.tuple([z.number(), z.number()])])';\n \n case 'box':\n return 'z.tuple([z.tuple([z.number(), z.number()]), z.tuple([z.number(), z.number()])])';\n \n case 'path':\n return 'z.array(z.tuple([z.number(), z.number()]))';\n \n case 'polygon':\n return 'z.array(z.tuple([z.number(), z.number()]))';\n \n case 'circle':\n return 'z.object({ center: z.tuple([z.number(), z.number()]), radius: z.number() })';\n\n // Text search types\n case 'tsvector':\n return 'z.string() /* tsvector */';\n \n case 'tsquery':\n return 'z.string() /* tsquery */';\n\n // XML\n case 'xml':\n return 'z.string() /* XML */';\n\n // Binary data\n case 'bytea':\n return 'z.instanceof(Buffer)';\n\n // Other types\n case 'oid':\n return 'z.number().int().positive()';\n \n case 'regproc':\n case 'regprocedure':\n case 'regoper':\n case 'regoperator':\n case 'regclass':\n case 'regtype':\n case 'regrole':\n case 'regnamespace':\n case 'regconfig':\n case 'regdictionary':\n return 'z.string() /* PostgreSQL OID reference */';\n\n // pg_lsn\n case 'pg_lsn':\n return 'z.string().regex(/^[0-9A-F]+\\\\/[0-9A-F]+$/)';\n\n // User-defined base types or unknown\n default:\n const warning = `Unknown type: ${dataType} (udt: ${udtName}) in column ${column.columnName}`;\n warnings.push(warning);\n \n if (options.strictMode) {\n throw new Error(warning);\n }\n \n return 'z.unknown() /* unmapped type */';\n }\n}\n\n/**\n * Apply check constraints as Zod refinements\n */\nexport function applyCheckConstraints(\n columnName: string,\n baseSchema: string,\n constraints: CheckConstraintMetadata[]\n): string {\n let schema = baseSchema;\n\n for (const constraint of constraints) {\n // Try to parse simple check constraints\n const checkClause = constraint.checkClause.toLowerCase();\n\n // >= pattern\n const geMatch = checkClause.match(new RegExp(`${columnName}\\\\s*>=\\\\s*([\\\\d.]+)`));\n if (geMatch) {\n const value = geMatch[1];\n if (schema.includes('z.number()')) {\n schema = schema.replace('z.number()', `z.number().min(${value})`);\n } else if (schema.includes('z.bigint()')) {\n schema = schema.replace('z.bigint()', `z.bigint().min(${value}n)`);\n }\n continue;\n }\n\n // > pattern\n const gtMatch = checkClause.match(new RegExp(`${columnName}\\\\s*>\\\\s*([\\\\d.]+)`));\n if (gtMatch) {\n const value = parseFloat(gtMatch[1]);\n if (schema.includes('z.number()')) {\n schema = schema.replace('z.number()', `z.number().min(${value + Number.EPSILON})`);\n }\n continue;\n }\n\n // <= pattern\n const leMatch = checkClause.match(new RegExp(`${columnName}\\\\s*<=\\\\s*([\\\\d.]+)`));\n if (leMatch) {\n const value = leMatch[1];\n if (schema.includes('z.number()')) {\n schema = schema.replace('z.number()', `z.number().max(${value})`);\n } else if (schema.includes('z.bigint()')) {\n schema = schema.replace('z.bigint()', `z.bigint().max(${value}n)`);\n }\n continue;\n }\n\n // < pattern\n const ltMatch = checkClause.match(new RegExp(`${columnName}\\\\s*<\\\\s*([\\\\d.]+)`));\n if (ltMatch) {\n const value = parseFloat(ltMatch[1]);\n if (schema.includes('z.number()')) {\n schema = schema.replace('z.number()', `z.number().max(${value - Number.EPSILON})`);\n }\n continue;\n }\n\n // BETWEEN pattern\n const betweenMatch = checkClause.match(\n new RegExp(`${columnName}\\\\s*between\\\\s*([\\\\d.]+)\\\\s*and\\\\s*([\\\\d.]+)`)\n );\n if (betweenMatch) {\n const [, min, max] = betweenMatch;\n if (schema.includes('z.number()')) {\n schema = schema.replace('z.number()', `z.number().min(${min}).max(${max})`);\n }\n continue;\n }\n\n // IN pattern (standard SQL)\n const inMatch = checkClause.match(\n new RegExp(`${columnName}\\\\s*in\\\\s*\\\\(([^)]+)\\\\)`)\n );\n if (inMatch) {\n const values = inMatch[1].split(',').map((v: string) => v.trim().replace(/'/g, ''));\n if (schema.includes('z.string()')) {\n const enumValues = values.map((v: string) => `'${v}'`).join(', ');\n schema = `z.enum([${enumValues}])`;\n }\n continue;\n }\n\n // PostgreSQL ANY (ARRAY[...]) pattern\n const anyArrayMatch = checkClause.match(\n new RegExp(`\\\\(?${columnName}\\\\s*=\\\\s*any\\\\s*\\\\(array\\\\[([^\\\\]]+)\\\\]`)\n );\n if (anyArrayMatch) {\n // Extract values from ARRAY['val1'::text, 'val2'::text]\n const valuesStr = anyArrayMatch[1];\n const values = valuesStr\n .split(',')\n .map((v: string) => {\n const match = v.trim().match(/'([^']+)'/);\n return match ? match[1] : null;\n })\n .filter((v: string | null): v is string => v !== null);\n \n if (values.length > 0 && schema.includes('z.string()')) {\n const enumValues = values.map((v: string) => `'${v}'`).join(', ');\n schema = `z.enum([${enumValues}])`;\n continue;\n }\n }\n\n // REGEX/~ pattern\n const regexMatch = checkClause.match(\n new RegExp(`${columnName}\\\\s*~\\\\s*'([^']+)'`)\n );\n if (regexMatch) {\n const pattern = regexMatch[1];\n if (schema.includes('z.string()')) {\n schema = schema.replace('z.string()', `z.string().regex(/${pattern}/)`);\n }\n continue;\n }\n\n // LENGTH pattern\n const lengthMatch = checkClause.match(\n new RegExp(`length\\\\(${columnName}\\\\)\\\\s*([><=]+)\\\\s*([\\\\d]+)`)\n );\n if (lengthMatch) {\n const [, operator, value] = lengthMatch;\n if (schema.includes('z.string()')) {\n if (operator === '>=' || operator === '>') {\n schema = schema.replace('z.string()', `z.string().min(${value})`);\n } else if (operator === '<=' || operator === '<') {\n schema = schema.replace('z.string()', `z.string().max(${value})`);\n }\n }\n continue;\n }\n\n // If we can't parse it, add as a comment\n schema += ` /* CHECK: ${constraint.checkClause} */`;\n }\n\n return schema;\n}\n\n/**\n * Convert snake_case to PascalCase\n */\nexport function toPascalCase(str: string): string {\n return str\n .split('_')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join('');\n}\n\n/**\n * Convert snake_case to camelCase\n */\nexport function toCamelCase(str: string): string {\n const pascal = toPascalCase(str);\n return pascal.charAt(0).toLowerCase() + pascal.slice(1);\n}\n","import type {\n ColumnMetadata,\n DatabaseMetadata,\n GeneratedSchema,\n GenerationResult,\n SchemaGenerationOptions,\n TableMetadata,\n ViewMetadata,\n RoutineMetadata,\n} from './types.js';\nimport {applyCheckConstraints, mapColumnToZod, toCamelCase, toPascalCase,} from './type-mapper.js';\n\n/**\n * Generate Zod schemas from database metadata\n */\nexport function generateSchemas(\n metadata: DatabaseMetadata,\n options: SchemaGenerationOptions = {}\n): GenerationResult {\n const warnings: string[] = [];\n const schemas: GeneratedSchema[] = [];\n\n // Generate enum schemas\n const enums = metadata.enums.map((enumType) => ({\n name: toPascalCase(enumType.schemaName) + toPascalCase(enumType.enumName),\n code: generateEnumSchema(enumType.enumName, enumType.enumValues, options, enumType.schemaName),\n }));\n\n // Generate range type schemas\n const ranges = metadata.rangeTypes.map((rangeType) => ({\n name: toPascalCase(rangeType.schemaName) + toPascalCase(rangeType.rangeName),\n code: generateRangeSchema(rangeType.rangeName, rangeType.subtype, metadata, options, warnings, rangeType.schemaName),\n }));\n\n // Generate composite type schemas (only if flag is set)\n const compositeTypes = options.includeCompositeTypes\n ? metadata.compositeTypes.map((compositeType) => ({\n name: toPascalCase(compositeType.schemaName) + toPascalCase(compositeType.typeName) + 'Composite',\n code: generateCompositeTypeSchema(compositeType, metadata, options, warnings),\n }))\n : [];\n\n // Generate domain schemas\n const domains = metadata.domains.map((domain) => ({\n name: toPascalCase(domain.schemaName) + toPascalCase(domain.domainName),\n code: generateDomainSchema(domain, metadata, options, warnings),\n }));\n\n // Generate table schemas\n for (const table of metadata.tables) {\n const schema = generateTableSchema(table, metadata, options, warnings);\n schemas.push(schema);\n }\n\n // Generate view schemas\n const views = metadata.views?.map((view) => ({\n name: toPascalCase(view.schemaName) + toPascalCase(view.viewName),\n code: generateViewSchema(view, metadata, options, warnings),\n })) || [];\n\n // Generate routine schemas (filter by security type)\n const filteredRoutines = metadata.routines?.filter((routine) => {\n // By default, only include SECURITY DEFINER functions\n // Include SECURITY INVOKER only if explicitly requested\n if (routine.securityType === 'INVOKER' && !options.includeSecurityInvoker) {\n return false;\n }\n return true;\n }) || [];\n\n const routines = filteredRoutines.map((routine) => ({\n name: toPascalCase(routine.schemaName) + toPascalCase(routine.routineName),\n code: generateRoutineSchema(routine, metadata, options, warnings),\n }));\n\n return {\n schemas,\n enums,\n compositeTypes,\n domains,\n ranges,\n views,\n routines,\n warnings,\n };\n}\n\n/**\n * Generate enum schema\n */\nfunction generateEnumSchema(\n enumName: string,\n values: string[],\n options: SchemaGenerationOptions,\n schemaPrefix?: string\n): string {\n const baseName = toPascalCase(enumName);\n const fullName = schemaPrefix ? `${toPascalCase(schemaPrefix)}${baseName}` : baseName;\n const schemaName = `${fullName}Schema`;\n const typeName = fullName;\n\n const valuesStr = values.map((v) => `'${v}'`).join(', ');\n\n let code = '';\n\n if (options.includeComments) {\n code += `/** PostgreSQL enum: ${enumName} */\\n`;\n }\n\n code += `export const ${schemaName} = z.enum([${valuesStr}]);\\n`;\n code += `export type ${typeName} = z.infer<typeof ${schemaName}>;\\n`;\n\n return code;\n}\n\n/**\n * Generate range type schema\n */\nfunction generateRangeSchema(\n rangeName: string,\n subtype: string,\n _metadata: DatabaseMetadata,\n options: SchemaGenerationOptions,\n _warnings: string[],\n schemaPrefix?: string\n): string {\n const baseName = toPascalCase(rangeName);\n const fullName = schemaPrefix ? `${toPascalCase(schemaPrefix)}${baseName}` : baseName;\n const schemaName = `${fullName}Schema`;\n const typeName = fullName;\n\n // Map subtype to Zod schema\n const subtypeSchema = mapSubtypeToZod(subtype, _metadata);\n\n let code = '';\n\n if (options.includeComments) {\n code += `/** PostgreSQL range type: ${rangeName}<${subtype}> */\\n`;\n }\n\n // Ranges represented as [lower, upper] tuple with nullable bounds\n code += `export const ${schemaName} = z.tuple([${subtypeSchema}.nullable(), ${subtypeSchema}.nullable()]);\\n`;\n code += `export type ${typeName} = z.infer<typeof ${schemaName}>;\\n`;\n\n return code;\n}\n\n/**\n * Map PostgreSQL subtype to Zod for range types\n */\nfunction mapSubtypeToZod(subtype: string, _metadata: DatabaseMetadata): string {\n const normalized = subtype.toLowerCase();\n\n switch (normalized) {\n case 'integer':\n case 'int':\n case 'int4':\n return 'z.number().int()';\n case 'bigint':\n case 'int8':\n return 'z.bigint()';\n case 'numeric':\n case 'decimal':\n return 'z.number()';\n case 'date':\n return 'z.date()';\n case 'timestamp':\n case 'timestamp without time zone':\n case 'timestamp with time zone':\n case 'timestamptz':\n return 'z.date()';\n default:\n return 'z.unknown()';\n }\n}\n\n/**\n * Generate composite type schema\n */\nfunction generateCompositeTypeSchema(\n compositeType: any,\n metadata: DatabaseMetadata,\n options: SchemaGenerationOptions,\n warnings: string[]\n): string {\n const baseName = toPascalCase(compositeType.typeName);\n const schemaPrefix = toPascalCase(compositeType.schemaName);\n // Add 'Composite' suffix to distinguish from tables with same name\n const fullName = `${schemaPrefix}${baseName}Composite`;\n const schemaName = `${fullName}Schema`;\n const typeName = fullName;\n\n let code = '';\n\n if (options.includeComments) {\n code += `/** PostgreSQL composite type: ${compositeType.typeName} */\\n`;\n }\n\n code += `export const ${schemaName} = z.object({\\n`;\n\n for (const attr of compositeType.attributes) {\n const fieldName = options.useCamelCase ? toCamelCase(attr.attributeName) : attr.attributeName;\n\n // Create a mock column for type mapping\n const mockColumn: ColumnMetadata = {\n columnName: attr.attributeName,\n dataType: attr.dataType,\n isNullable: true, // Composite type attributes can be null\n columnDefault: null,\n characterMaximumLength: null,\n numericPrecision: null,\n numericScale: null,\n datetimePrecision: null,\n udtName: attr.dataType,\n domainName: null,\n arrayDimensions: 0,\n isArray: false,\n };\n\n const zodType = mapColumnToZod(mockColumn, metadata, options, warnings);\n\n if (options.includeComments) {\n code += ` /** ${attr.dataType} */\\n`;\n }\n code += ` ${fieldName}: ${zodType},\\n`;\n }\n\n code += `});\\n`;\n code += `export type ${typeName} = z.infer<typeof ${schemaName}>;\\n`;\n\n return code;\n}\n\n/**\n * Generate domain schema\n */\nfunction generateDomainSchema(\n domain: any,\n metadata: DatabaseMetadata,\n options: SchemaGenerationOptions,\n warnings: string[]\n): string {\n const baseName = toPascalCase(domain.domainName);\n const schemaPrefix = toPascalCase(domain.schemaName);\n const fullName = `${schemaPrefix}${baseName}`;\n const schemaName = `${fullName}Schema`;\n const typeName = fullName;\n\n // Create a mock column for type mapping\n const mockColumn: ColumnMetadata = {\n columnName: domain.domainName,\n dataType: domain.dataType,\n isNullable: domain.isNullable,\n columnDefault: domain.domainDefault,\n characterMaximumLength: domain.characterMaximumLength,\n numericPrecision: domain.numericPrecision,\n numericScale: domain.numericScale,\n datetimePrecision: null,\n udtName: domain.dataType,\n domainName: null,\n arrayDimensions: 0,\n isArray: false,\n };\n\n let zodType = mapColumnToZod(mockColumn, metadata, options, warnings);\n\n // Apply domain check constraints\n if (domain.checkConstraints.length > 0) {\n zodType = applyCheckConstraints(domain.domainName, zodType, domain.checkConstraints);\n }\n\n let code = '';\n\n if (options.includeComments) {\n code += `/** PostgreSQL domain: ${domain.domainName} (base: ${domain.dataType}) */\\n`;\n }\n\n code += `export const ${schemaName} = ${zodType};\\n`;\n code += `export type ${typeName} = z.infer<typeof ${schemaName}>;\\n`;\n\n return code;\n}\n\n/**\n * Generate view schema (read-only)\n */\nfunction generateViewSchema(\n view: ViewMetadata,\n metadata: DatabaseMetadata,\n options: SchemaGenerationOptions,\n warnings: string[]\n): string {\n const schemaPrefix = toPascalCase(view.schemaName);\n const viewName = toPascalCase(view.viewName);\n const schemaName = `${schemaPrefix}${viewName}Schema`;\n const typeName = `${schemaPrefix}${viewName}`;\n\n let code = '';\n\n if (options.includeComments) {\n code += `/** View: ${view.schemaName}.${view.viewName} (read-only) */\\n`;\n }\n\n code += `export const ${schemaName} = z.object({\\n`;\n\n for (const column of view.columns) {\n const fieldName = options.useCamelCase ? toCamelCase(column.columnName) : column.columnName;\n const zodType = mapColumnToZod(column, metadata, options, warnings);\n\n if (options.includeComments) {\n code += ` /** ${column.dataType} */\\n`;\n }\n code += ` ${fieldName}: ${zodType},\\n`;\n }\n\n code += `});\\n`;\n code += `export type ${typeName} = z.infer<typeof ${schemaName}>;\\n`;\n\n return code;\n}\n\n/**\n * Generate routine schema (function/procedure)\n */\nfunction generateRoutineSchema(\n routine: RoutineMetadata,\n metadata: DatabaseMetadata,\n options: SchemaGenerationOptions,\n warnings: string[]\n): string {\n const schemaPrefix = toPascalCase(routine.schemaName);\n const routineName = toPascalCase(routine.routineName);\n const paramsSchemaName = `${schemaPrefix}${routineName}ParamsSchema`;\n const returnSchemaName = `${schemaPrefix}${routineName}ReturnSchema`;\n const paramsTypeName = `${schemaPrefix}${routineName}Params`;\n const returnTypeName = `${schemaPrefix}${routineName}Return`;\n\n let code = '';\n\n if (options.includeComments) {\n code += `/** ${routine.routineType}: ${routine.schemaName}.${routine.routineName} */\\n`;\n }\n\n // Generate parameters schema (input)\n const inParams = routine.parameters.filter(\n (p) => p.parameterMode === 'IN' || p.parameterMode === 'INOUT'\n );\n\n if (inParams.length > 0) {\n code += `export const ${paramsSchemaName} = z.object({\\n`;\n\n for (const param of inParams) {\n const fieldName = options.useCamelCase ? toCamelCase(param.parameterName) : param.parameterName;\n\n // Create a mock column for type mapping\n const mockColumn: ColumnMetadata = {\n columnName: param.parameterName,\n dataType: param.dataType,\n isNullable: param.isNullable,\n columnDefault: null,\n characterMaximumLength: null,\n numericPrecision: null,\n numericScale: null,\n datetimePrecision: null,\n udtName: param.udtName,\n domainName: null,\n arrayDimensions: 0,\n isArray: param.dataType === 'ARRAY',\n };\n\n const zodType = mapColumnToZod(mockColumn, metadata, options, warnings);\n\n if (options.includeComments) {\n code += ` /** ${param.dataType} (${param.parameterMode}) */\\n`;\n }\n code += ` ${fieldName}: ${zodType},\\n`;\n }\n\n code += `});\\n`;\n code += `export type ${paramsTypeName} = z.infer<typeof ${paramsSchemaName}>;\\n\\n`;\n }\n\n // Generate return type schema (output)\n const outParams = routine.parameters.filter(\n (p) => p.parameterMode === 'OUT' || p.parameterMode === 'INOUT'\n );\n\n if (routine.routineType === 'FUNCTION' && routine.returnType && routine.returnType !== 'void') {\n // For functions with return values\n if (outParams.length > 0) {\n // Multiple output parameters - return object\n code += `export const ${returnSchemaName} = z.object({\\n`;\n\n for (const param of outParams) {\n const fieldName = options.useCamelCase ? toCamelCase(param.parameterName) : param.parameterName;\n\n const mockColumn: ColumnMetadata = {\n columnName: param.parameterName,\n dataType: param.dataType,\n isNullable: param.isNullable,\n columnDefault: null,\n characterMaximumLength: null,\n numericPrecision: null,\n numericScale: null,\n datetimePrecision: null,\n udtName: param.udtName,\n domainName: null,\n arrayDimensions: 0,\n isArray: param.dataType === 'ARRAY',\n };\n\n const zodType = mapColumnToZod(mockColumn, metadata, options, warnings);\n\n if (options.includeComments) {\n code += ` /** ${param.dataType} (${param.parameterMode}) */\\n`;\n }\n code += ` ${fieldName}: ${zodType},\\n`;\n }\n\n code += `});\\n`;\n } else {\n // Single return value\n const mockColumn: ColumnMetadata = {\n columnName: 'return_value',\n dataType: routine.returnType,\n isNullable: false,\n columnDefault: null,\n characterMaximumLength: null,\n numericPrecision: null,\n numericScale: null,\n datetimePrecision: null,\n udtName: routine.returnUdtName || routine.returnType,\n domainName: null,\n arrayDimensions: 0,\n isArray: routine.returnType === 'ARRAY' || routine.returnsSet,\n };\n\n const zodType = mapColumnToZod(mockColumn, metadata, options, warnings);\n \n if (options.includeComments) {\n code += `/** Returns: ${routine.returnType} */\\n`;\n }\n \n if (routine.returnsSet) {\n code += `export const ${returnSchemaName} = z.array(${zodType});\\n`;\n } else {\n code += `export const ${returnSchemaName} = ${zodType};\\n`;\n }\n }\n\n code += `export type ${returnTypeName} = z.infer<typeof ${returnSchemaName}>;\\n`;\n } else if (outParams.length > 0) {\n // Procedures with OUT parameters\n code += `export const ${returnSchemaName} = z.object({\\n`;\n\n for (const param of outParams) {\n const fieldName = options.useCamelCase ? toCamelCase(param.parameterName) : param.parameterName;\n\n const mockColumn: ColumnMetadata = {\n columnName: param.parameterName,\n dataType: param.dataType,\n isNullable: param.isNullable,\n columnDefault: null,\n characterMaximumLength: null,\n numericPrecision: null,\n numericScale: null,\n datetimePrecision: null,\n udtName: param.udtName,\n domainName: null,\n arrayDimensions: 0,\n isArray: param.dataType === 'ARRAY',\n };\n\n const zodType = mapColumnToZod(mockColumn, metadata, options, warnings);\n\n if (options.includeComments) {\n code += ` /** ${param.dataType} (${param.parameterMode}) */\\n`;\n }\n code += ` ${fieldName}: ${zodType},\\n`;\n }\n\n code += `});\\n`;\n code += `export type ${returnTypeName} = z.infer<typeof ${returnSchemaName}>;\\n`;\n }\n\n return code;\n}\n\n/**\n * Generate table schema\n */\nfunction generateTableSchema(\n table: TableMetadata,\n metadata: DatabaseMetadata,\n options: SchemaGenerationOptions,\n warnings: string[]\n): GeneratedSchema {\n // Include schema name to avoid collisions (e.g., PublicCommentThreadsSchema)\n const schemaPrefix = toPascalCase(table.schemaName);\n const tableName = toPascalCase(table.tableName);\n const schemaName = `${schemaPrefix}${tableName}`;\n const readSchemaName = `${schemaName}Schema`;\n const insertSchemaName = `${schemaName}InsertSchema`;\n const updateSchemaName = `${schemaName}UpdateSchema`;\n const typeName = schemaName;\n const insertTypeName = `${schemaName}Insert`;\n const updateTypeName = `${schemaName}Update`;\n\n // Generate read schema (complete)\n let readCode = '';\n\n if (options.includeComments) {\n readCode += `/** Table: ${table.schemaName}.${table.tableName} */\\n`;\n }\n\n readCode += `export const ${readSchemaName} = z.object({\\n`;\n\n for (const column of table.columns) {\n const fieldName = options.useCamelCase ? toCamelCase(column.columnName) : column.columnName;\n\n let zodType = mapColumnToZod(column, metadata, options, warnings);\n\n // Apply column-specific check constraints\n const columnConstraints = table.checkConstraints.filter(\n (c) => c.columnName === column.columnName\n );\n if (columnConstraints.length > 0) {\n zodType = applyCheckConstraints(column.columnName, zodType, columnConstraints);\n }\n\n if (options.includeComments) {\n const commentParts = [column.dataType];\n if (column.columnDefault) {\n commentParts.push(`default: ${column.columnDefault}`);\n }\n readCode += ` /** ${commentParts.join(', ')} */\\n`;\n }\n\n readCode += ` ${fieldName}: ${zodType},\\n`;\n }\n\n readCode += `});\\n`;\n readCode += `export type ${typeName} = z.infer<typeof ${readSchemaName}>;\\n`;\n\n // Generate insert and update schemas\n // Default to true if not specified\n let insertCode: string | undefined;\n let updateCode: string | undefined;\n\n if (options.generateInputSchemas !== false) {\n // Collect fields that should be optional for insert\n const optionalFields: Array<{ fieldName: string; zodType: string; comment?: string }> = [];\n\n for (const column of table.columns) {\n const fieldName = options.useCamelCase ? toCamelCase(column.columnName) : column.columnName;\n\n // Determine if field should be optional in insert\n const hasDefault = column.columnDefault !== null;\n const isSerial = column.columnDefault?.includes('nextval') ?? false;\n const isAutoGenerated = isSerial || column.columnDefault?.includes('gen_random_uuid()') || false;\n\n if (isAutoGenerated || hasDefault) {\n // Get the base type\n let zodType = mapColumnToZod(column, metadata, options, warnings);\n\n // Apply column-specific check constraints\n const columnConstraints = table.checkConstraints.filter(\n (c) => c.columnName === column.columnName\n );\n if (columnConstraints.length > 0) {\n zodType = applyCheckConstraints(column.columnName, zodType, columnConstraints);\n }\n\n // Make it optional\n zodType = `${zodType}.optional()`;\n\n let comment: string | undefined;\n if (options.includeComments) {\n const commentParts = [column.dataType];\n if (hasDefault) {\n commentParts.push(`default: ${column.columnDefault}`);\n }\n if (isSerial) {\n commentParts.push('auto-generated');\n }\n comment = commentParts.join(', ');\n }\n\n optionalFields.push({fieldName, zodType, comment});\n }\n }\n\n // Generate INSERT schema using .extend() if there are optional fields\n insertCode = '';\n\n if (options.includeComments) {\n insertCode += `/** Insert schema for ${table.tableName} */\\n`;\n }\n\n if (optionalFields.length === 0) {\n // No optional fields - just use the read schema directly\n insertCode += `export const ${insertSchemaName} = ${readSchemaName};\\n`;\n } else {\n // Use .extend() to override optional fields\n insertCode += `export const ${insertSchemaName} = ${readSchemaName}.extend({\\n`;\n\n for (const field of optionalFields) {\n if (field.comment) {\n insertCode += ` /** ${field.comment} */\\n`;\n }\n insertCode += ` ${field.fieldName}: ${field.zodType},\\n`;\n }\n\n insertCode += `});\\n`;\n }\n\n insertCode += `export type ${insertTypeName} = z.infer<typeof ${insertSchemaName}>;\\n`;\n\n // Generate UPDATE schema using .partial() - all fields optional\n updateCode = '';\n\n if (options.includeComments) {\n updateCode += `/** Update schema for ${table.tableName} (all fields optional) */\\n`;\n }\n\n updateCode += `export const ${updateSchemaName} = ${readSchemaName}.partial();\\n`;\n updateCode += `export type ${updateTypeName} = z.infer<typeof ${updateSchemaName}>;\\n`;\n }\n\n return {\n tableName: table.tableName,\n schemaName: table.schemaName,\n readSchema: readCode,\n inputSchema: insertCode,\n typeDefinitions: `${readCode}${insertCode ? '\\n' + insertCode : ''}${updateCode ? '\\n' + updateCode : ''}`,\n };\n}\n\n/**\n * Format the complete output file\n */\nexport function formatOutput(result: GenerationResult): string {\n let output = `/**\\n`;\n output += ` * ==========================================\\n`;\n output += ` * | GENERATED BY PG-TO-ZOD (TBP) |\\n`;\n output += ` * ==========================================\\n`;\n output += ` *\\n`;\n output += ` * ⚠️ DO NOT EDIT THIS FILE MANUALLY!\\n`;\n output += ` *\\n`;\n output += ` * This file was automatically generated from\\n`;\n output += ` * your PostgreSQL database schema.\\n`;\n output += ` *\\n`;\n output += ` * To regenerate, run:\\n`;\n output += ` * pg-to-zod --url <connection-url> -o <file>\\n`;\n output += ` *\\n`;\n output += ` * Any manual changes will be overwritten when\\n`;\n output += ` * the code is regenerated.\\n`;\n output += ` * ==========================================\\n`;\n output += ` */\\n\\n`;\n output += `import { z } from 'zod';\\n\\n`;\n\n // Enums\n if (result.enums.length > 0) {\n output += `// ============================================\\n`;\n output += `// Enums\\n`;\n output += `// ============================================\\n\\n`;\n\n for (const enumSchema of result.enums) {\n output += enumSchema.code + '\\n';\n }\n }\n\n // Domains\n if (result.domains.length > 0) {\n output += `// ============================================\\n`;\n output += `// Domains\\n`;\n output += `// ============================================\\n\\n`;\n\n for (const domain of result.domains) {\n output += domain.code + '\\n';\n }\n }\n\n // Ranges\n if (result.ranges.length > 0) {\n output += `// ============================================\\n`;\n output += `// Range Types\\n`;\n output += `// ============================================\\n\\n`;\n\n for (const range of result.ranges) {\n output += range.code + '\\n';\n }\n }\n\n // Composite types\n if (result.compositeTypes.length > 0) {\n output += `// ============================================\\n`;\n output += `// Composite Types\\n`;\n output += `// ============================================\\n\\n`;\n\n for (const compositeType of result.compositeTypes) {\n output += compositeType.code + '\\n';\n }\n }\n\n // Tables\n if (result.schemas.length > 0) {\n output += `// ============================================\\n`;\n output += `// Tables\\n`;\n output += `// ============================================\\n\\n`;\n\n for (const schema of result.schemas) {\n output += schema.typeDefinitions + '\\n';\n }\n }\n\n // Views\n if (result.views && result.views.length > 0) {\n output += `// ============================================\\n`;\n output += `// Views\\n`;\n output += `// ============================================\\n\\n`;\n\n for (const view of result.views) {\n output += view.code + '\\n';\n }\n }\n\n // Routines\n if (result.routines && result.routines.length > 0) {\n output += `// ============================================\\n`;\n output += `// Routines (Functions/Procedures)\\n`;\n output += `// ============================================\\n\\n`;\n\n for (const routine of result.routines) {\n output += routine.code + '\\n';\n }\n }\n\n // Warnings\n if (result.warnings.length > 0) {\n output += `// ============================================\\n`;\n output += `// Warnings\\n`;\n output += `// ============================================\\n`;\n output += `// The following warnings were generated:\\n`;\n\n for (const warning of result.warnings) {\n output += `// - ${warning}\\n`;\n }\n }\n\n return output;\n}\n","import {introspectDatabase} from './introspect.js';\nimport {formatOutput, generateSchemas} from './generator.js';\nimport type {DatabaseConfig, GenerationResult, SchemaGenerationOptions,} from './types.js';\n\nexport type {\n DatabaseConfig,\n SchemaGenerationOptions,\n GenerationResult,\n DatabaseMetadata,\n TableMetadata,\n ColumnMetadata,\n EnumMetadata,\n CompositeTypeMetadata,\n RangeTypeMetadata,\n DomainMetadata,\n CheckConstraintMetadata,\n GeneratedSchema,\n} from './types.js';\n\nexport {introspectDatabase} from './introspect.js';\nexport {generateSchemas, formatOutput} from './generator.js';\nexport {mapColumnToZod, toPascalCase, toCamelCase} from './type-mapper.js';\n\n/**\n * Main function: introspect database and generate Zod schemas\n */\nexport async function generateZodSchemas(\n config: DatabaseConfig,\n options: SchemaGenerationOptions = {}\n): Promise<GenerationResult> {\n const metadata = await introspectDatabase(config, options);\n return generateSchemas(metadata, options);\n}\n\n/**\n * Convenience function: generate schemas and return formatted output string\n */\nexport async function generateZodSchemasString(\n config: DatabaseConfig,\n options: SchemaGenerationOptions = {}\n): Promise<string> {\n const result = await generateZodSchemas(config, options);\n return formatOutput(result);\n}\n\n/**\n * Default export\n */\nexport default {\n generateZodSchemas,\n generateZodSchemasString,\n introspectDatabase,\n generateSchemas,\n formatOutput,\n};\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pg2zod",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Introspect PostgreSQL databases and generate strict, comprehensive Zod v4 schemas with full type coverage",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -34,16 +34,16 @@
|
|
|
34
34
|
"orm",
|
|
35
35
|
"prisma-alternative"
|
|
36
36
|
],
|
|
37
|
-
"author": "TBP",
|
|
37
|
+
"author": "Nkenna Amadi (TBP Studio)",
|
|
38
38
|
"license": "MIT",
|
|
39
39
|
"repository": {
|
|
40
40
|
"type": "git",
|
|
41
|
-
"url": "https://github.com/theNkennaAmadi/
|
|
41
|
+
"url": "https://github.com/theNkennaAmadi/pg-to-zod.git"
|
|
42
42
|
},
|
|
43
43
|
"bugs": {
|
|
44
|
-
"url": "https://github.com/theNkennaAmadi/
|
|
44
|
+
"url": "https://github.com/theNkennaAmadi/pg-to-zod/issues"
|
|
45
45
|
},
|
|
46
|
-
"homepage": "https://github.com/theNkennaAmadi/
|
|
46
|
+
"homepage": "https://github.com/theNkennaAmadi/pg-to-zod#readme",
|
|
47
47
|
"publishConfig": {
|
|
48
48
|
"access": "public",
|
|
49
49
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"typescript": "^5.7.2"
|
|
61
61
|
},
|
|
62
62
|
"engines": {
|
|
63
|
-
"node": ">=
|
|
63
|
+
"node": ">=20.0.0"
|
|
64
64
|
},
|
|
65
65
|
"scripts": {
|
|
66
66
|
"build": "tsdown",
|
package/dist/src-18pV45Fu.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"src-18pV45Fu.js","names":[],"sources":["../src/introspect.ts","../src/type-mapper.ts","../src/generator.ts","../src/index.ts"],"sourcesContent":["import pg from 'pg';\nimport type {\n DatabaseConfig,\n DatabaseMetadata,\n TableMetadata,\n EnumMetadata,\n CompositeTypeMetadata,\n RangeTypeMetadata,\n DomainMetadata,\n SchemaGenerationOptions,\n} from './types.js';\n\nconst { Pool } = pg;\n\n/**\n * Introspect a PostgreSQL database and return complete metadata\n */\nexport async function introspectDatabase(\n config: DatabaseConfig,\n options: SchemaGenerationOptions = {}\n): Promise<DatabaseMetadata> {\n const pool = new Pool(config);\n\n try {\n const schemas = options.schemas ?? ['public'];\n\n const [tables, enums, compositeTypes, rangeTypes, domains] = await Promise.all([\n introspectTables(pool, schemas, options),\n introspectEnums(pool, schemas),\n introspectCompositeTypes(pool, schemas),\n introspectRangeTypes(pool, schemas),\n introspectDomains(pool, schemas),\n ]);\n\n return {\n tables,\n enums,\n compositeTypes,\n rangeTypes,\n domains,\n };\n } finally {\n await pool.end();\n }\n}\n\n/**\n * Introspect tables and their columns\n */\nasync function introspectTables(\n pool: pg.Pool,\n schemas: string[],\n options: SchemaGenerationOptions\n): Promise<TableMetadata[]> {\n const schemaFilter = schemas.map((_, i) => `$${i + 1}`).join(', ');\n\n // Get all columns\n const columnsQuery = `\n SELECT \n c.table_schema,\n c.table_name,\n c.column_name,\n c.data_type,\n c.is_nullable,\n c.column_default,\n c.character_maximum_length,\n c.numeric_precision,\n c.numeric_scale,\n c.datetime_precision,\n c.udt_name,\n c.domain_name,\n COALESCE(\n (SELECT array_ndims(ARRAY[]::text[]) FROM information_schema.element_types e \n WHERE e.object_schema = c.table_schema \n AND e.object_name = c.table_name \n AND e.object_type = 'TABLE'\n AND e.collection_type_identifier = c.dtd_identifier\n ), 0\n ) as array_dimensions\n FROM information_schema.columns c\n WHERE c.table_schema IN (${schemaFilter})\n ORDER BY c.table_schema, c.table_name, c.ordinal_position\n `;\n\n const columnsResult = await pool.query(columnsQuery, schemas);\n\n // Get check constraints\n const constraintsQuery = `\n SELECT \n tc.table_schema,\n tc.table_name,\n tc.constraint_name,\n cc.check_clause,\n ccu.column_name\n FROM information_schema.table_constraints tc\n JOIN information_schema.check_constraints cc \n ON tc.constraint_name = cc.constraint_name \n AND tc.constraint_schema = cc.constraint_schema\n LEFT JOIN information_schema.constraint_column_usage ccu\n ON tc.constraint_name = ccu.constraint_name\n AND tc.constraint_schema = ccu.constraint_schema\n WHERE tc.constraint_type = 'CHECK'\n AND tc.table_schema IN (${schemaFilter})\n `;\n\n const constraintsResult = await pool.query(constraintsQuery, schemas);\n\n // Get primary keys\n const primaryKeysQuery = `\n SELECT \n tc.table_schema,\n tc.table_name,\n kcu.column_name\n FROM information_schema.table_constraints tc\n JOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n WHERE tc.constraint_type = 'PRIMARY KEY'\n AND tc.table_schema IN (${schemaFilter})\n ORDER BY kcu.ordinal_position\n `;\n\n const primaryKeysResult = await pool.query(primaryKeysQuery, schemas);\n\n // Get unique constraints\n const uniqueConstraintsQuery = `\n SELECT \n tc.table_schema,\n tc.table_name,\n tc.constraint_name,\n array_agg(kcu.column_name ORDER BY kcu.ordinal_position) as columns\n FROM information_schema.table_constraints tc\n JOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n WHERE tc.constraint_type = 'UNIQUE'\n AND tc.table_schema IN (${schemaFilter})\n GROUP BY tc.table_schema, tc.table_name, tc.constraint_name\n `;\n\n const uniqueConstraintsResult = await pool.query(uniqueConstraintsQuery, schemas);\n\n // Group by table\n const tableMap = new Map<string, TableMetadata>();\n\n for (const row of columnsResult.rows) {\n const tableKey = `${row.table_schema}.${row.table_name}`;\n\n if (!tableMap.has(tableKey)) {\n tableMap.set(tableKey, {\n tableName: row.table_name,\n schemaName: row.table_schema,\n columns: [],\n checkConstraints: [],\n primaryKeys: [],\n uniqueConstraints: [],\n });\n }\n\n const table = tableMap.get(tableKey)!;\n const isArray = row.data_type === 'ARRAY';\n\n table.columns.push({\n columnName: row.column_name,\n dataType: row.data_type,\n isNullable: row.is_nullable === 'YES',\n columnDefault: row.column_default,\n characterMaximumLength: row.character_maximum_length,\n numericPrecision: row.numeric_precision,\n numericScale: row.numeric_scale,\n datetimePrecision: row.datetime_precision,\n udtName: row.udt_name,\n domainName: row.domain_name,\n arrayDimensions: row.array_dimensions || 0,\n isArray,\n });\n }\n\n // Add check constraints\n for (const row of constraintsResult.rows) {\n const tableKey = `${row.table_schema}.${row.table_name}`;\n const table = tableMap.get(tableKey);\n if (table) {\n table.checkConstraints.push({\n constraintName: row.constraint_name,\n checkClause: row.check_clause,\n columnName: row.column_name,\n });\n }\n }\n\n // Add primary keys\n for (const row of primaryKeysResult.rows) {\n const tableKey = `${row.table_schema}.${row.table_name}`;\n const table = tableMap.get(tableKey);\n if (table) {\n table.primaryKeys.push(row.column_name);\n }\n }\n\n // Add unique constraints\n for (const row of uniqueConstraintsResult.rows) {\n const tableKey = `${row.table_schema}.${row.table_name}`;\n const table = tableMap.get(tableKey);\n if (table) {\n table.uniqueConstraints.push({\n constraintName: row.constraint_name,\n columns: row.columns,\n });\n }\n }\n\n // Filter tables based on options\n let tables = Array.from(tableMap.values());\n\n if (options.tables) {\n tables = tables.filter((t) => options.tables!.includes(t.tableName));\n }\n\n if (options.excludeTables) {\n tables = tables.filter((t) => !options.excludeTables!.includes(t.tableName));\n }\n\n return tables;\n}\n\n/**\n * Introspect enum types\n */\nasync function introspectEnums(\n pool: pg.Pool,\n schemas: string[]\n): Promise<EnumMetadata[]> {\n const schemaFilter = schemas.map((_, i) => `$${i + 1}`).join(', ');\n\n const query = `\n SELECT \n t.typname as enum_name,\n n.nspname as schema_name,\n array_agg(e.enumlabel ORDER BY e.enumsortorder) as enum_values\n FROM pg_type t\n JOIN pg_enum e ON t.oid = e.enumtypid\n JOIN pg_namespace n ON t.typnamespace = n.oid\n WHERE n.nspname IN (${schemaFilter})\n GROUP BY t.typname, n.nspname\n ORDER BY t.typname\n `;\n\n const result = await pool.query(query, schemas);\n\n return result.rows.map((row) => {\n // Handle PostgreSQL array format: {value1,value2,value3}\n let enumValues: string[];\n \n if (Array.isArray(row.enum_values)) {\n enumValues = row.enum_values;\n } else if (typeof row.enum_values === 'string') {\n // Parse PostgreSQL array format\n if (row.enum_values.startsWith('{') && row.enum_values.endsWith('}')) {\n enumValues = row.enum_values\n .slice(1, -1) // Remove { and }\n .split(',')\n .map((v: string) => v.trim());\n } else {\n enumValues = [row.enum_values];\n }\n } else {\n enumValues = [row.enum_values];\n }\n \n return {\n enumName: row.enum_name,\n enumValues,\n schemaName: row.schema_name,\n };\n });\n}\n\n/**\n * Introspect composite types\n */\nasync function introspectCompositeTypes(\n pool: pg.Pool,\n schemas: string[]\n): Promise<CompositeTypeMetadata[]> {\n const schemaFilter = schemas.map((_, i) => `$${i + 1}`).join(', ');\n\n const query = `\n SELECT \n t.typname as type_name,\n n.nspname as schema_name,\n a.attname as attribute_name,\n a.attnum as attribute_number,\n format_type(a.atttypid, a.atttypmod) as data_type\n FROM pg_type t\n JOIN pg_namespace n ON t.typnamespace = n.oid\n JOIN pg_class c ON t.typrelid = c.oid\n JOIN pg_attribute a ON c.oid = a.attrelid\n WHERE t.typtype = 'c'\n AND n.nspname IN (${schemaFilter})\n AND a.attnum > 0\n AND NOT a.attisdropped\n ORDER BY t.typname, a.attnum\n `;\n\n const result = await pool.query(query, schemas);\n\n const typeMap = new Map<string, CompositeTypeMetadata>();\n\n for (const row of result.rows) {\n const typeKey = `${row.schema_name}.${row.type_name}`;\n\n if (!typeMap.has(typeKey)) {\n typeMap.set(typeKey, {\n typeName: row.type_name,\n schemaName: row.schema_name,\n attributes: [],\n });\n }\n\n const type = typeMap.get(typeKey)!;\n type.attributes.push({\n attributeName: row.attribute_name,\n dataType: row.data_type,\n attributeNumber: row.attribute_number,\n });\n }\n\n return Array.from(typeMap.values());\n}\n\n/**\n * Introspect range types\n */\nasync function introspectRangeTypes(\n pool: pg.Pool,\n schemas: string[]\n): Promise<RangeTypeMetadata[]> {\n const schemaFilter = schemas.map((_, i) => `$${i + 1}`).join(', ');\n\n const query = `\n SELECT \n t.typname as range_name,\n n.nspname as schema_name,\n format_type(r.rngsubtype, NULL) as subtype\n FROM pg_type t\n JOIN pg_namespace n ON t.typnamespace = n.oid\n JOIN pg_range r ON t.oid = r.rngtypid\n WHERE n.nspname IN (${schemaFilter})\n ORDER BY t.typname\n `;\n\n const result = await pool.query(query, schemas);\n\n return result.rows.map((row) => ({\n rangeName: row.range_name,\n subtype: row.subtype,\n schemaName: row.schema_name,\n }));\n}\n\n/**\n * Introspect domain types\n */\nasync function introspectDomains(\n pool: pg.Pool,\n schemas: string[]\n): Promise<DomainMetadata[]> {\n const schemaFilter = schemas.map((_, i) => `$${i + 1}`).join(', ');\n\n // Get domain information\n const domainsQuery = `\n SELECT \n t.typname as domain_name,\n n.nspname as schema_name,\n format_type(t.typbasetype, t.typtypmod) as data_type,\n t.typnotnull as is_not_null,\n t.typdefault as domain_default,\n information_schema._pg_char_max_length(t.typbasetype, t.typtypmod) as character_maximum_length,\n information_schema._pg_numeric_precision(t.typbasetype, t.typtypmod) as numeric_precision,\n information_schema._pg_numeric_scale(t.typbasetype, t.typtypmod) as numeric_scale\n FROM pg_type t\n JOIN pg_namespace n ON t.typnamespace = n.oid\n WHERE t.typtype = 'd'\n AND n.nspname IN (${schemaFilter})\n ORDER BY t.typname\n `;\n\n const domainsResult = await pool.query(domainsQuery, schemas);\n\n // Get domain constraints\n const constraintsQuery = `\n SELECT \n t.typname as domain_name,\n n.nspname as schema_name,\n c.conname as constraint_name,\n pg_get_constraintdef(c.oid) as check_clause\n FROM pg_constraint c\n JOIN pg_type t ON c.contypid = t.oid\n JOIN pg_namespace n ON t.typnamespace = n.oid\n WHERE c.contype = 'c'\n AND n.nspname IN (${schemaFilter})\n `;\n\n const constraintsResult = await pool.query(constraintsQuery, schemas);\n\n const domains: DomainMetadata[] = domainsResult.rows.map((row) => ({\n domainName: row.domain_name,\n dataType: row.data_type,\n schemaName: row.schema_name,\n characterMaximumLength: row.character_maximum_length,\n numericPrecision: row.numeric_precision,\n numericScale: row.numeric_scale,\n isNullable: !row.is_not_null,\n domainDefault: row.domain_default,\n checkConstraints: [],\n }));\n\n // Add check constraints to domains\n for (const row of constraintsResult.rows) {\n const domain = domains.find(\n (d) => d.domainName === row.domain_name && d.schemaName === row.schema_name\n );\n if (domain) {\n domain.checkConstraints.push({\n constraintName: row.constraint_name,\n checkClause: row.check_clause,\n columnName: null,\n });\n }\n }\n\n return domains;\n}\n","import type {\n ColumnMetadata,\n DatabaseMetadata,\n SchemaGenerationOptions,\n CheckConstraintMetadata,\n} from './types.js';\n\n/**\n * Map PostgreSQL column to Zod schema string with strict validation\n */\nexport function mapColumnToZod(\n column: ColumnMetadata,\n metadata: DatabaseMetadata,\n options: SchemaGenerationOptions,\n warnings: string[]\n): string {\n // Handle domains first\n if (column.domainName) {\n const domain = metadata.domains.find((d) => d.domainName === column.domainName);\n if (domain) {\n const schemaPrefix = toPascalCase(domain.schemaName);\n const domainName = toPascalCase(domain.domainName);\n let schema = `${schemaPrefix}${domainName}Schema`;\n return column.isNullable ? `${schema}.nullable()` : schema;\n }\n }\n\n // Handle arrays\n if (column.isArray) {\n const baseType = mapBaseTypeToZod(column, metadata, options, warnings);\n let arraySchema = `z.array(${baseType})`;\n \n // Multi-dimensional arrays\n if (column.arrayDimensions > 1) {\n for (let i = 1; i < column.arrayDimensions; i++) {\n arraySchema = `z.array(${arraySchema})`;\n }\n }\n \n return column.isNullable ? `${arraySchema}.nullable()` : arraySchema;\n }\n\n // Handle base types\n const baseSchema = mapBaseTypeToZod(column, metadata, options, warnings);\n return column.isNullable ? `${baseSchema}.nullable()` : baseSchema;\n}\n\n/**\n * Map base PostgreSQL type to Zod\n */\nfunction mapBaseTypeToZod(\n column: ColumnMetadata,\n metadata: DatabaseMetadata,\n options: SchemaGenerationOptions,\n warnings: string[]\n): string {\n let udtName = column.udtName;\n const dataType = column.dataType.toLowerCase();\n\n // PostgreSQL array types have underscore prefix (e.g., _text for text[], _int4 for integer[])\n // Strip the underscore to get the actual base type name\n if (column.isArray && udtName.startsWith('_')) {\n udtName = udtName.substring(1);\n }\n\n // Custom type mappings\n if (options.customTypeMappings?.[udtName]) {\n return options.customTypeMappings[udtName];\n }\n\n // Check if it's an enum\n const enumType = metadata.enums.find((e) => e.enumName === udtName);\n if (enumType) {\n const schemaPrefix = toPascalCase(enumType.schemaName);\n const enumName = toPascalCase(enumType.enumName);\n return `${schemaPrefix}${enumName}Schema`;\n }\n\n // Check if it's a composite type\n const compositeType = metadata.compositeTypes.find((t) => t.typeName === udtName);\n if (compositeType) {\n const schemaPrefix = toPascalCase(compositeType.schemaName);\n const typeName = toPascalCase(compositeType.typeName);\n // Add 'Composite' suffix to match generator\n return `${schemaPrefix}${typeName}CompositeSchema`;\n }\n\n // Check if it's a range type\n const rangeType = metadata.rangeTypes.find((r) => r.rangeName === udtName);\n if (rangeType) {\n const schemaPrefix = toPascalCase(rangeType.schemaName);\n const rangeName = toPascalCase(rangeType.rangeName);\n return `${schemaPrefix}${rangeName}Schema`;\n }\n\n // Map by data type or by udtName for arrays\n // For arrays, dataType will be 'ARRAY' so we need to check the udtName\n const typeToCheck = dataType === 'array' ? udtName : dataType;\n \n switch (typeToCheck) {\n // Numeric types\n case 'smallint':\n case 'integer':\n case 'int':\n case 'int2':\n case 'int4':\n return 'z.number().int()';\n \n case 'bigint':\n case 'int8':\n return 'z.bigint()';\n \n case 'decimal':\n case 'numeric':\n if (column.numericPrecision !== null && column.numericScale !== null) {\n return `z.number() /* precision: ${column.numericPrecision}, scale: ${column.numericScale} */`;\n }\n return 'z.number()';\n \n case 'real':\n case 'float4':\n return 'z.number()';\n \n case 'double precision':\n case 'float8':\n return 'z.number()';\n \n case 'money':\n return 'z.string().regex(/^\\\\$?[0-9,]+(\\\\.\\\\d{2})?$/)';\n\n // Text types\n case 'character varying':\n case 'varchar':\n if (column.characterMaximumLength) {\n return `z.string().max(${column.characterMaximumLength})`;\n }\n return 'z.string()';\n \n case 'character':\n case 'char':\n if (column.characterMaximumLength) {\n return `z.string().length(${column.characterMaximumLength})`;\n }\n return 'z.string()';\n \n case 'text':\n return 'z.string()';\n \n case 'citext':\n return 'z.string()';\n\n // Boolean\n case 'boolean':\n case 'bool':\n return 'z.boolean()';\n\n // Date/Time types\n case 'timestamp':\n case 'timestamp without time zone':\n return 'z.date()';\n \n case 'timestamp with time zone':\n case 'timestamptz':\n return 'z.date()';\n \n case 'date':\n return 'z.date()';\n \n case 'time':\n case 'time without time zone':\n return 'z.iso.time()';\n \n case 'time with time zone':\n case 'timetz':\n // PostgreSQL time with timezone, no direct Zod v4 equivalent\n return 'z.string().regex(/^\\\\d{2}:\\\\d{2}:\\\\d{2}(\\\\.\\\\d+)?[+-]\\\\d{2}:\\\\d{2}$/)';\n \n case 'interval':\n return 'z.iso.duration()';\n\n // UUID\n case 'uuid':\n return 'z.uuid()';\n\n // JSON types\n case 'json':\n return 'z.record(z.string(), z.unknown())';\n \n case 'jsonb':\n return 'z.record(z.string(), z.unknown())';\n\n // Network types\n case 'inet':\n // In Zod v4, use z.ipv4() or z.ipv6() but inet accepts both, so we use a union\n return 'z.union([z.ipv4(), z.ipv6()])';\n \n case 'cidr':\n // PostgreSQL cidr accepts both IPv4 and IPv6 CIDR notation\n return 'z.union([z.cidrv4(), z.cidrv6()])';\n \n case 'macaddr':\n return 'z.mac()';\n \n case 'macaddr8':\n // macaddr8 is 64-bit (8 bytes), standard z.mac() is 48-bit, use regex\n return 'z.string().regex(/^([0-9A-Fa-f]{2}[:-]){7}([0-9A-Fa-f]{2})$/)';\n\n // Bit string types\n case 'bit':\n if (column.characterMaximumLength) {\n return `z.string().regex(/^[01]{${column.characterMaximumLength}}$/)`;\n }\n return 'z.string().regex(/^[01]+$/)';\n \n case 'bit varying':\n case 'varbit':\n if (column.characterMaximumLength) {\n return `z.string().regex(/^[01]{0,${column.characterMaximumLength}}$/)`;\n }\n return 'z.string().regex(/^[01]*$/)';\n\n // Geometric types\n case 'point':\n return 'z.tuple([z.number(), z.number()])';\n \n case 'line':\n return 'z.object({ a: z.number(), b: z.number(), c: z.number() })';\n \n case 'lseg':\n return 'z.tuple([z.tuple([z.number(), z.number()]), z.tuple([z.number(), z.number()])])';\n \n case 'box':\n return 'z.tuple([z.tuple([z.number(), z.number()]), z.tuple([z.number(), z.number()])])';\n \n case 'path':\n return 'z.array(z.tuple([z.number(), z.number()]))';\n \n case 'polygon':\n return 'z.array(z.tuple([z.number(), z.number()]))';\n \n case 'circle':\n return 'z.object({ center: z.tuple([z.number(), z.number()]), radius: z.number() })';\n\n // Text search types\n case 'tsvector':\n return 'z.string() /* tsvector */';\n \n case 'tsquery':\n return 'z.string() /* tsquery */';\n\n // XML\n case 'xml':\n return 'z.string() /* XML */';\n\n // Binary data\n case 'bytea':\n return 'z.instanceof(Buffer)';\n\n // Other types\n case 'oid':\n return 'z.number().int().positive()';\n \n case 'regproc':\n case 'regprocedure':\n case 'regoper':\n case 'regoperator':\n case 'regclass':\n case 'regtype':\n case 'regrole':\n case 'regnamespace':\n case 'regconfig':\n case 'regdictionary':\n return 'z.string() /* PostgreSQL OID reference */';\n\n // pg_lsn\n case 'pg_lsn':\n return 'z.string().regex(/^[0-9A-F]+\\\\/[0-9A-F]+$/)';\n\n // User-defined base types or unknown\n default:\n const warning = `Unknown type: ${dataType} (udt: ${udtName}) in column ${column.columnName}`;\n warnings.push(warning);\n \n if (options.strictMode) {\n throw new Error(warning);\n }\n \n return 'z.unknown() /* unmapped type */';\n }\n}\n\n/**\n * Apply check constraints as Zod refinements\n */\nexport function applyCheckConstraints(\n columnName: string,\n baseSchema: string,\n constraints: CheckConstraintMetadata[]\n): string {\n let schema = baseSchema;\n\n for (const constraint of constraints) {\n // Try to parse simple check constraints\n const checkClause = constraint.checkClause.toLowerCase();\n\n // >= pattern\n const geMatch = checkClause.match(new RegExp(`${columnName}\\\\s*>=\\\\s*([\\\\d.]+)`));\n if (geMatch) {\n const value = geMatch[1];\n if (schema.includes('z.number()')) {\n schema = schema.replace('z.number()', `z.number().min(${value})`);\n } else if (schema.includes('z.bigint()')) {\n schema = schema.replace('z.bigint()', `z.bigint().min(${value}n)`);\n }\n continue;\n }\n\n // > pattern\n const gtMatch = checkClause.match(new RegExp(`${columnName}\\\\s*>\\\\s*([\\\\d.]+)`));\n if (gtMatch) {\n const value = parseFloat(gtMatch[1]);\n if (schema.includes('z.number()')) {\n schema = schema.replace('z.number()', `z.number().min(${value + Number.EPSILON})`);\n }\n continue;\n }\n\n // <= pattern\n const leMatch = checkClause.match(new RegExp(`${columnName}\\\\s*<=\\\\s*([\\\\d.]+)`));\n if (leMatch) {\n const value = leMatch[1];\n if (schema.includes('z.number()')) {\n schema = schema.replace('z.number()', `z.number().max(${value})`);\n } else if (schema.includes('z.bigint()')) {\n schema = schema.replace('z.bigint()', `z.bigint().max(${value}n)`);\n }\n continue;\n }\n\n // < pattern\n const ltMatch = checkClause.match(new RegExp(`${columnName}\\\\s*<\\\\s*([\\\\d.]+)`));\n if (ltMatch) {\n const value = parseFloat(ltMatch[1]);\n if (schema.includes('z.number()')) {\n schema = schema.replace('z.number()', `z.number().max(${value - Number.EPSILON})`);\n }\n continue;\n }\n\n // BETWEEN pattern\n const betweenMatch = checkClause.match(\n new RegExp(`${columnName}\\\\s*between\\\\s*([\\\\d.]+)\\\\s*and\\\\s*([\\\\d.]+)`)\n );\n if (betweenMatch) {\n const [, min, max] = betweenMatch;\n if (schema.includes('z.number()')) {\n schema = schema.replace('z.number()', `z.number().min(${min}).max(${max})`);\n }\n continue;\n }\n\n // IN pattern (standard SQL)\n const inMatch = checkClause.match(\n new RegExp(`${columnName}\\\\s*in\\\\s*\\\\(([^)]+)\\\\)`)\n );\n if (inMatch) {\n const values = inMatch[1].split(',').map((v: string) => v.trim().replace(/'/g, ''));\n if (schema.includes('z.string()')) {\n const enumValues = values.map((v: string) => `'${v}'`).join(', ');\n schema = `z.enum([${enumValues}])`;\n }\n continue;\n }\n\n // PostgreSQL ANY (ARRAY[...]) pattern\n const anyArrayMatch = checkClause.match(\n new RegExp(`\\\\(?${columnName}\\\\s*=\\\\s*any\\\\s*\\\\(array\\\\[([^\\\\]]+)\\\\]`)\n );\n if (anyArrayMatch) {\n // Extract values from ARRAY['val1'::text, 'val2'::text]\n const valuesStr = anyArrayMatch[1];\n const values = valuesStr\n .split(',')\n .map((v: string) => {\n const match = v.trim().match(/'([^']+)'/);\n return match ? match[1] : null;\n })\n .filter((v: string | null): v is string => v !== null);\n \n if (values.length > 0 && schema.includes('z.string()')) {\n const enumValues = values.map((v: string) => `'${v}'`).join(', ');\n schema = `z.enum([${enumValues}])`;\n continue;\n }\n }\n\n // REGEX/~ pattern\n const regexMatch = checkClause.match(\n new RegExp(`${columnName}\\\\s*~\\\\s*'([^']+)'`)\n );\n if (regexMatch) {\n const pattern = regexMatch[1];\n if (schema.includes('z.string()')) {\n schema = schema.replace('z.string()', `z.string().regex(/${pattern}/)`);\n }\n continue;\n }\n\n // LENGTH pattern\n const lengthMatch = checkClause.match(\n new RegExp(`length\\\\(${columnName}\\\\)\\\\s*([><=]+)\\\\s*([\\\\d]+)`)\n );\n if (lengthMatch) {\n const [, operator, value] = lengthMatch;\n if (schema.includes('z.string()')) {\n if (operator === '>=' || operator === '>') {\n schema = schema.replace('z.string()', `z.string().min(${value})`);\n } else if (operator === '<=' || operator === '<') {\n schema = schema.replace('z.string()', `z.string().max(${value})`);\n }\n }\n continue;\n }\n\n // If we can't parse it, add as a comment\n schema += ` /* CHECK: ${constraint.checkClause} */`;\n }\n\n return schema;\n}\n\n/**\n * Convert snake_case to PascalCase\n */\nexport function toPascalCase(str: string): string {\n return str\n .split('_')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join('');\n}\n\n/**\n * Convert snake_case to camelCase\n */\nexport function toCamelCase(str: string): string {\n const pascal = toPascalCase(str);\n return pascal.charAt(0).toLowerCase() + pascal.slice(1);\n}\n","import type {\n ColumnMetadata,\n DatabaseMetadata,\n GeneratedSchema,\n GenerationResult,\n SchemaGenerationOptions,\n TableMetadata,\n} from './types.js';\nimport {applyCheckConstraints, mapColumnToZod, toCamelCase, toPascalCase,} from './type-mapper.js';\n\n/**\n * Generate Zod schemas from database metadata\n */\nexport function generateSchemas(\n metadata: DatabaseMetadata,\n options: SchemaGenerationOptions = {}\n): GenerationResult {\n const warnings: string[] = [];\n const schemas: GeneratedSchema[] = [];\n\n // Generate enum schemas\n const enums = metadata.enums.map((enumType) => ({\n name: toPascalCase(enumType.schemaName) + toPascalCase(enumType.enumName),\n code: generateEnumSchema(enumType.enumName, enumType.enumValues, options, enumType.schemaName),\n }));\n\n // Generate range type schemas\n const ranges = metadata.rangeTypes.map((rangeType) => ({\n name: toPascalCase(rangeType.schemaName) + toPascalCase(rangeType.rangeName),\n code: generateRangeSchema(rangeType.rangeName, rangeType.subtype, metadata, options, warnings, rangeType.schemaName),\n }));\n\n // Generate composite type schemas (only if flag is set)\n const compositeTypes = options.includeCompositeTypes\n ? metadata.compositeTypes.map((compositeType) => ({\n name: toPascalCase(compositeType.schemaName) + toPascalCase(compositeType.typeName) + 'Composite',\n code: generateCompositeTypeSchema(compositeType, metadata, options, warnings),\n }))\n : [];\n\n // Generate domain schemas\n const domains = metadata.domains.map((domain) => ({\n name: toPascalCase(domain.schemaName) + toPascalCase(domain.domainName),\n code: generateDomainSchema(domain, metadata, options, warnings),\n }));\n\n // Generate table schemas\n for (const table of metadata.tables) {\n const schema = generateTableSchema(table, metadata, options, warnings);\n schemas.push(schema);\n }\n\n return {\n schemas,\n enums,\n compositeTypes,\n domains,\n ranges,\n warnings,\n };\n}\n\n/**\n * Generate enum schema\n */\nfunction generateEnumSchema(\n enumName: string,\n values: string[],\n options: SchemaGenerationOptions,\n schemaPrefix?: string\n): string {\n const baseName = toPascalCase(enumName);\n const fullName = schemaPrefix ? `${toPascalCase(schemaPrefix)}${baseName}` : baseName;\n const schemaName = `${fullName}Schema`;\n const typeName = fullName;\n\n const valuesStr = values.map((v) => `'${v}'`).join(', ');\n\n let code = '';\n\n if (options.includeComments) {\n code += `/** PostgreSQL enum: ${enumName} */\\n`;\n }\n\n code += `export const ${schemaName} = z.enum([${valuesStr}]);\\n`;\n code += `export type ${typeName} = z.infer<typeof ${schemaName}>;\\n`;\n\n return code;\n}\n\n/**\n * Generate range type schema\n */\nfunction generateRangeSchema(\n rangeName: string,\n subtype: string,\n _metadata: DatabaseMetadata,\n options: SchemaGenerationOptions,\n _warnings: string[],\n schemaPrefix?: string\n): string {\n const baseName = toPascalCase(rangeName);\n const fullName = schemaPrefix ? `${toPascalCase(schemaPrefix)}${baseName}` : baseName;\n const schemaName = `${fullName}Schema`;\n const typeName = fullName;\n\n // Map subtype to Zod schema\n const subtypeSchema = mapSubtypeToZod(subtype, _metadata);\n\n let code = '';\n\n if (options.includeComments) {\n code += `/** PostgreSQL range type: ${rangeName}<${subtype}> */\\n`;\n }\n\n // Ranges represented as [lower, upper] tuple with nullable bounds\n code += `export const ${schemaName} = z.tuple([${subtypeSchema}.nullable(), ${subtypeSchema}.nullable()]);\\n`;\n code += `export type ${typeName} = z.infer<typeof ${schemaName}>;\\n`;\n\n return code;\n}\n\n/**\n * Map PostgreSQL subtype to Zod for range types\n */\nfunction mapSubtypeToZod(subtype: string, _metadata: DatabaseMetadata): string {\n const normalized = subtype.toLowerCase();\n\n switch (normalized) {\n case 'integer':\n case 'int':\n case 'int4':\n return 'z.number().int()';\n case 'bigint':\n case 'int8':\n return 'z.bigint()';\n case 'numeric':\n case 'decimal':\n return 'z.number()';\n case 'date':\n return 'z.date()';\n case 'timestamp':\n case 'timestamp without time zone':\n case 'timestamp with time zone':\n case 'timestamptz':\n return 'z.date()';\n default:\n return 'z.unknown()';\n }\n}\n\n/**\n * Generate composite type schema\n */\nfunction generateCompositeTypeSchema(\n compositeType: any,\n metadata: DatabaseMetadata,\n options: SchemaGenerationOptions,\n warnings: string[]\n): string {\n const baseName = toPascalCase(compositeType.typeName);\n const schemaPrefix = toPascalCase(compositeType.schemaName);\n // Add 'Composite' suffix to distinguish from tables with same name\n const fullName = `${schemaPrefix}${baseName}Composite`;\n const schemaName = `${fullName}Schema`;\n const typeName = fullName;\n\n let code = '';\n\n if (options.includeComments) {\n code += `/** PostgreSQL composite type: ${compositeType.typeName} */\\n`;\n }\n\n code += `export const ${schemaName} = z.object({\\n`;\n\n for (const attr of compositeType.attributes) {\n const fieldName = options.useCamelCase ? toCamelCase(attr.attributeName) : attr.attributeName;\n\n // Create a mock column for type mapping\n const mockColumn: ColumnMetadata = {\n columnName: attr.attributeName,\n dataType: attr.dataType,\n isNullable: true, // Composite type attributes can be null\n columnDefault: null,\n characterMaximumLength: null,\n numericPrecision: null,\n numericScale: null,\n datetimePrecision: null,\n udtName: attr.dataType,\n domainName: null,\n arrayDimensions: 0,\n isArray: false,\n };\n\n const zodType = mapColumnToZod(mockColumn, metadata, options, warnings);\n\n if (options.includeComments) {\n code += ` /** ${attr.dataType} */\\n`;\n }\n code += ` ${fieldName}: ${zodType},\\n`;\n }\n\n code += `});\\n`;\n code += `export type ${typeName} = z.infer<typeof ${schemaName}>;\\n`;\n\n return code;\n}\n\n/**\n * Generate domain schema\n */\nfunction generateDomainSchema(\n domain: any,\n metadata: DatabaseMetadata,\n options: SchemaGenerationOptions,\n warnings: string[]\n): string {\n const baseName = toPascalCase(domain.domainName);\n const schemaPrefix = toPascalCase(domain.schemaName);\n const fullName = `${schemaPrefix}${baseName}`;\n const schemaName = `${fullName}Schema`;\n const typeName = fullName;\n\n // Create a mock column for type mapping\n const mockColumn: ColumnMetadata = {\n columnName: domain.domainName,\n dataType: domain.dataType,\n isNullable: domain.isNullable,\n columnDefault: domain.domainDefault,\n characterMaximumLength: domain.characterMaximumLength,\n numericPrecision: domain.numericPrecision,\n numericScale: domain.numericScale,\n datetimePrecision: null,\n udtName: domain.dataType,\n domainName: null,\n arrayDimensions: 0,\n isArray: false,\n };\n\n let zodType = mapColumnToZod(mockColumn, metadata, options, warnings);\n\n // Apply domain check constraints\n if (domain.checkConstraints.length > 0) {\n zodType = applyCheckConstraints(domain.domainName, zodType, domain.checkConstraints);\n }\n\n let code = '';\n\n if (options.includeComments) {\n code += `/** PostgreSQL domain: ${domain.domainName} (base: ${domain.dataType}) */\\n`;\n }\n\n code += `export const ${schemaName} = ${zodType};\\n`;\n code += `export type ${typeName} = z.infer<typeof ${schemaName}>;\\n`;\n\n return code;\n}\n\n/**\n * Generate table schema\n */\nfunction generateTableSchema(\n table: TableMetadata,\n metadata: DatabaseMetadata,\n options: SchemaGenerationOptions,\n warnings: string[]\n): GeneratedSchema {\n // Include schema name to avoid collisions (e.g., PublicCommentThreadsSchema)\n const schemaPrefix = toPascalCase(table.schemaName);\n const tableName = toPascalCase(table.tableName);\n const schemaName = `${schemaPrefix}${tableName}`;\n const readSchemaName = `${schemaName}Schema`;\n const insertSchemaName = `${schemaName}InsertSchema`;\n const updateSchemaName = `${schemaName}UpdateSchema`;\n const typeName = schemaName;\n const insertTypeName = `${schemaName}Insert`;\n const updateTypeName = `${schemaName}Update`;\n\n // Generate read schema (complete)\n let readCode = '';\n\n if (options.includeComments) {\n readCode += `/** Table: ${table.schemaName}.${table.tableName} */\\n`;\n }\n\n readCode += `export const ${readSchemaName} = z.object({\\n`;\n\n for (const column of table.columns) {\n const fieldName = options.useCamelCase ? toCamelCase(column.columnName) : column.columnName;\n\n let zodType = mapColumnToZod(column, metadata, options, warnings);\n\n // Apply column-specific check constraints\n const columnConstraints = table.checkConstraints.filter(\n (c) => c.columnName === column.columnName\n );\n if (columnConstraints.length > 0) {\n zodType = applyCheckConstraints(column.columnName, zodType, columnConstraints);\n }\n\n if (options.includeComments) {\n const commentParts = [column.dataType];\n if (column.columnDefault) {\n commentParts.push(`default: ${column.columnDefault}`);\n }\n readCode += ` /** ${commentParts.join(', ')} */\\n`;\n }\n\n readCode += ` ${fieldName}: ${zodType},\\n`;\n }\n\n readCode += `});\\n`;\n readCode += `export type ${typeName} = z.infer<typeof ${readSchemaName}>;\\n`;\n\n // Generate insert and update schemas\n // Default to true if not specified\n let insertCode: string | undefined;\n let updateCode: string | undefined;\n\n if (options.generateInputSchemas !== false) {\n // Collect fields that should be optional for insert\n const optionalFields: Array<{ fieldName: string; zodType: string; comment?: string }> = [];\n\n for (const column of table.columns) {\n const fieldName = options.useCamelCase ? toCamelCase(column.columnName) : column.columnName;\n\n // Determine if field should be optional in insert\n const hasDefault = column.columnDefault !== null;\n const isSerial = column.columnDefault?.includes('nextval') ?? false;\n const isAutoGenerated = isSerial || column.columnDefault?.includes('gen_random_uuid()') || false;\n\n if (isAutoGenerated || hasDefault) {\n // Get the base type\n let zodType = mapColumnToZod(column, metadata, options, warnings);\n\n // Apply column-specific check constraints\n const columnConstraints = table.checkConstraints.filter(\n (c) => c.columnName === column.columnName\n );\n if (columnConstraints.length > 0) {\n zodType = applyCheckConstraints(column.columnName, zodType, columnConstraints);\n }\n\n // Make it optional\n zodType = `${zodType}.optional()`;\n\n let comment: string | undefined;\n if (options.includeComments) {\n const commentParts = [column.dataType];\n if (hasDefault) {\n commentParts.push(`default: ${column.columnDefault}`);\n }\n if (isSerial) {\n commentParts.push('auto-generated');\n }\n comment = commentParts.join(', ');\n }\n\n optionalFields.push({fieldName, zodType, comment});\n }\n }\n\n // Generate INSERT schema using .extend() if there are optional fields\n insertCode = '';\n\n if (options.includeComments) {\n insertCode += `/** Insert schema for ${table.tableName} */\\n`;\n }\n\n if (optionalFields.length === 0) {\n // No optional fields - just use the read schema directly\n insertCode += `export const ${insertSchemaName} = ${readSchemaName};\\n`;\n } else {\n // Use .extend() to override optional fields\n insertCode += `export const ${insertSchemaName} = ${readSchemaName}.extend({\\n`;\n\n for (const field of optionalFields) {\n if (field.comment) {\n insertCode += ` /** ${field.comment} */\\n`;\n }\n insertCode += ` ${field.fieldName}: ${field.zodType},\\n`;\n }\n\n insertCode += `});\\n`;\n }\n\n insertCode += `export type ${insertTypeName} = z.infer<typeof ${insertSchemaName}>;\\n`;\n\n // Generate UPDATE schema using .partial() - all fields optional\n updateCode = '';\n\n if (options.includeComments) {\n updateCode += `/** Update schema for ${table.tableName} (all fields optional) */\\n`;\n }\n\n updateCode += `export const ${updateSchemaName} = ${readSchemaName}.partial();\\n`;\n updateCode += `export type ${updateTypeName} = z.infer<typeof ${updateSchemaName}>;\\n`;\n }\n\n return {\n tableName: table.tableName,\n schemaName: table.schemaName,\n readSchema: readCode,\n inputSchema: insertCode,\n typeDefinitions: `${readCode}${insertCode ? '\\n' + insertCode : ''}${updateCode ? '\\n' + updateCode : ''}`,\n };\n}\n\n/**\n * Format the complete output file\n */\nexport function formatOutput(result: GenerationResult): string {\n let output = `/**\\n`;\n output += ` * ==========================================\\n`;\n output += ` * | GENERATED BY PG-TO-ZOD (TBP) |\\n`;\n output += ` * ==========================================\\n`;\n output += ` *\\n`;\n output += ` * ⚠️ DO NOT EDIT THIS FILE MANUALLY!\\n`;\n output += ` *\\n`;\n output += ` * This file was automatically generated from\\n`;\n output += ` * your PostgreSQL database schema.\\n`;\n output += ` *\\n`;\n output += ` * To regenerate, run:\\n`;\n output += ` * pg-to-zod --url <connection-url> -o <file>\\n`;\n output += ` *\\n`;\n output += ` * Any manual changes will be overwritten when\\n`;\n output += ` * the code is regenerated.\\n`;\n output += ` * ==========================================\\n`;\n output += ` */\\n\\n`;\n output += `import { z } from 'zod';\\n\\n`;\n\n // Enums\n if (result.enums.length > 0) {\n output += `// ============================================\\n`;\n output += `// Enums\\n`;\n output += `// ============================================\\n\\n`;\n\n for (const enumSchema of result.enums) {\n output += enumSchema.code + '\\n';\n }\n }\n\n // Domains\n if (result.domains.length > 0) {\n output += `// ============================================\\n`;\n output += `// Domains\\n`;\n output += `// ============================================\\n\\n`;\n\n for (const domain of result.domains) {\n output += domain.code + '\\n';\n }\n }\n\n // Ranges\n if (result.ranges.length > 0) {\n output += `// ============================================\\n`;\n output += `// Range Types\\n`;\n output += `// ============================================\\n\\n`;\n\n for (const range of result.ranges) {\n output += range.code + '\\n';\n }\n }\n\n // Composite types\n if (result.compositeTypes.length > 0) {\n output += `// ============================================\\n`;\n output += `// Composite Types\\n`;\n output += `// ============================================\\n\\n`;\n\n for (const compositeType of result.compositeTypes) {\n output += compositeType.code + '\\n';\n }\n }\n\n // Tables\n if (result.schemas.length > 0) {\n output += `// ============================================\\n`;\n output += `// Tables\\n`;\n output += `// ============================================\\n\\n`;\n\n for (const schema of result.schemas) {\n output += schema.typeDefinitions + '\\n';\n }\n }\n\n // Warnings\n if (result.warnings.length > 0) {\n output += `// ============================================\\n`;\n output += `// Warnings\\n`;\n output += `// ============================================\\n`;\n output += `// The following warnings were generated:\\n`;\n\n for (const warning of result.warnings) {\n output += `// - ${warning}\\n`;\n }\n }\n\n return output;\n}\n","import {introspectDatabase} from './introspect.js';\nimport {formatOutput, generateSchemas} from './generator.js';\nimport type {DatabaseConfig, GenerationResult, SchemaGenerationOptions,} from './types.js';\n\nexport type {\n DatabaseConfig,\n SchemaGenerationOptions,\n GenerationResult,\n DatabaseMetadata,\n TableMetadata,\n ColumnMetadata,\n EnumMetadata,\n CompositeTypeMetadata,\n RangeTypeMetadata,\n DomainMetadata,\n CheckConstraintMetadata,\n GeneratedSchema,\n} from './types.js';\n\nexport {introspectDatabase} from './introspect.js';\nexport {generateSchemas, formatOutput} from './generator.js';\nexport {mapColumnToZod, toPascalCase, toCamelCase} from './type-mapper.js';\n\n/**\n * Main function: introspect database and generate Zod schemas\n */\nexport async function generateZodSchemas(\n config: DatabaseConfig,\n options: SchemaGenerationOptions = {}\n): Promise<GenerationResult> {\n const metadata = await introspectDatabase(config, options);\n return generateSchemas(metadata, options);\n}\n\n/**\n * Convenience function: generate schemas and return formatted output string\n */\nexport async function generateZodSchemasString(\n config: DatabaseConfig,\n options: SchemaGenerationOptions = {}\n): Promise<string> {\n const result = await generateZodSchemas(config, options);\n return formatOutput(result);\n}\n\n/**\n * Default export\n */\nexport default {\n generateZodSchemas,\n generateZodSchemasString,\n introspectDatabase,\n generateSchemas,\n formatOutput,\n};\n"],"mappings":"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"}
|