pg2zod 2.1.0 → 2.1.2
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 +24 -0
- package/README.md +182 -143
- package/dist/cli.js +10 -10
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/{src-CEkWBxDB.js → src-BTbLgtTh.js} +38 -16
- package/dist/src-BTbLgtTh.js.map +1 -0
- package/package.json +4 -4
- package/dist/src-CEkWBxDB.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.1.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 9cd667c: Filter internal PostgreSQL functions and handle duplicates
|
|
8
|
+
|
|
9
|
+
**Bug Fixes:**
|
|
10
|
+
|
|
11
|
+
- Fixed type errors in view column metadata generation
|
|
12
|
+
- Removed invalid fields (ordinalPosition, isIdentity, etc.) from ColumnMetadata
|
|
13
|
+
|
|
14
|
+
**Improvements:**
|
|
15
|
+
|
|
16
|
+
- Filter out internal PostgreSQL system functions (functions using internal, trigger, cstring, "char", and other low-level types)
|
|
17
|
+
- Skip functions with duplicate parameter names that would cause invalid TypeScript
|
|
18
|
+
- Skip overloaded functions - only keep first occurrence to avoid naming conflicts
|
|
19
|
+
- Significantly reduces generated function count (from 261 to ~50-60 for typical databases)
|
|
20
|
+
- Generated schemas now compile without TypeScript errors
|
|
21
|
+
|
|
22
|
+
**Quality:**
|
|
23
|
+
|
|
24
|
+
- Ensures only user-facing, application-relevant functions are included in generated schemas
|
|
25
|
+
- Cleaner output with fewer warnings about unmapped internal types
|
|
26
|
+
|
|
3
27
|
## 2.1.0
|
|
4
28
|
|
|
5
29
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
#
|
|
1
|
+
# pg2zod
|
|
2
2
|
|
|
3
3
|
> **Introspect PostgreSQL databases and generate strict, comprehensive Zod v4 schemas**
|
|
4
4
|
|
|
5
|
-
A modern TypeScript package that automatically generates high-quality, strict Zod schemas from your PostgreSQL database
|
|
5
|
+
A modern TypeScript package that automatically generates high-quality, strict Zod schemas from your PostgreSQL database
|
|
6
|
+
schema. Supports all PostgreSQL types including advanced features like enums, composite types, domains, ranges, arrays,
|
|
7
|
+
and geometric types.
|
|
6
8
|
|
|
7
9
|
## Features
|
|
8
10
|
|
|
9
11
|
✨ **Comprehensive Type Coverage**
|
|
12
|
+
|
|
10
13
|
- All built-in PostgreSQL types (numeric, text, date/time, boolean, JSON, UUID, etc.)
|
|
11
14
|
- Custom types: enums, domains, composite types, range types
|
|
12
15
|
- Database views (read-only schemas)
|
|
@@ -18,6 +21,7 @@ A modern TypeScript package that automatically generates high-quality, strict Zo
|
|
|
18
21
|
- Bit strings, XML, and more
|
|
19
22
|
|
|
20
23
|
🔒 **Strict & Safe**
|
|
24
|
+
|
|
21
25
|
- Length constraints (`varchar(n)` → `.max(n)`)
|
|
22
26
|
- Precision/scale validation for numeric types
|
|
23
27
|
- Format validations (UUID, IP, MAC addresses, etc.)
|
|
@@ -26,6 +30,7 @@ A modern TypeScript package that automatically generates high-quality, strict Zo
|
|
|
26
30
|
- NOT NULL awareness
|
|
27
31
|
|
|
28
32
|
🎯 **Smart Code Generation**
|
|
33
|
+
|
|
29
34
|
- Read schemas (reflect actual DB structure)
|
|
30
35
|
- Insert schemas (intelligent optional field detection based on defaults/auto-generation)
|
|
31
36
|
- Update schemas (all fields optional but maintain validation)
|
|
@@ -36,6 +41,7 @@ A modern TypeScript package that automatically generates high-quality, strict Zo
|
|
|
36
41
|
- Comprehensive comments
|
|
37
42
|
|
|
38
43
|
🚀 **Modern Stack**
|
|
44
|
+
|
|
39
45
|
- ESM-first
|
|
40
46
|
- TypeScript with strict mode
|
|
41
47
|
- Zod v4 (latest beta)
|
|
@@ -44,11 +50,11 @@ A modern TypeScript package that automatically generates high-quality, strict Zo
|
|
|
44
50
|
## Installation
|
|
45
51
|
|
|
46
52
|
```bash
|
|
47
|
-
npm install
|
|
53
|
+
npm install pg2zod
|
|
48
54
|
# or
|
|
49
|
-
pnpm add
|
|
55
|
+
pnpm add pg2zod
|
|
50
56
|
# or
|
|
51
|
-
yarn add
|
|
57
|
+
yarn add pg2zod
|
|
52
58
|
```
|
|
53
59
|
|
|
54
60
|
## Quick Start
|
|
@@ -57,55 +63,55 @@ yarn add pg-to-zod
|
|
|
57
63
|
|
|
58
64
|
```bash
|
|
59
65
|
# Generate schemas from a local database (includes input schemas by default)
|
|
60
|
-
|
|
66
|
+
pg2zod --database mydb --output src/db/schema.ts
|
|
61
67
|
|
|
62
68
|
# Use a connection URL
|
|
63
|
-
|
|
69
|
+
pg2zod --url postgresql://user:pass@localhost:5432/mydb -o schema.ts
|
|
64
70
|
|
|
65
71
|
# Skip input schemas if you only need read schemas
|
|
66
|
-
|
|
72
|
+
pg2zod --database mydb --no-input-schemas --output schema.ts
|
|
67
73
|
|
|
68
74
|
# Include composite types (skipped by default)
|
|
69
|
-
|
|
75
|
+
pg2zod --database mydb --composite-types --output schema.ts
|
|
70
76
|
|
|
71
77
|
# Include database views
|
|
72
|
-
|
|
78
|
+
pg2zod --database mydb --views --output schema.ts
|
|
73
79
|
|
|
74
80
|
# Include functions/procedures (SECURITY DEFINER only by default)
|
|
75
|
-
|
|
81
|
+
pg2zod --database mydb --routines --output schema.ts
|
|
76
82
|
|
|
77
83
|
# Include all functions including SECURITY INVOKER
|
|
78
|
-
|
|
84
|
+
pg2zod --database mydb --routines --security-invoker --output schema.ts
|
|
79
85
|
|
|
80
86
|
# Use camelCase for field names
|
|
81
|
-
|
|
87
|
+
pg2zod --database mydb --camel-case -o schema.ts
|
|
82
88
|
|
|
83
89
|
# Include specific tables only
|
|
84
|
-
|
|
90
|
+
pg2zod --database mydb --tables users,posts,comments -o schema.ts
|
|
85
91
|
|
|
86
92
|
# Multiple schemas
|
|
87
|
-
|
|
93
|
+
pg2zod --database mydb --schemas public,auth,api -o schema.ts
|
|
88
94
|
```
|
|
89
95
|
|
|
90
96
|
### Programmatic API
|
|
91
97
|
|
|
92
98
|
```typescript
|
|
93
|
-
import {
|
|
99
|
+
import {generateZodSchemasString} from 'pg2zod';
|
|
94
100
|
|
|
95
101
|
const schemas = await generateZodSchemasString(
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
102
|
+
{
|
|
103
|
+
host: 'localhost',
|
|
104
|
+
port: 5432,
|
|
105
|
+
database: 'mydb',
|
|
106
|
+
user: 'postgres',
|
|
107
|
+
password: 'password',
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
schemas: ['public'],
|
|
111
|
+
generateInputSchemas: true,
|
|
112
|
+
includeComments: true,
|
|
113
|
+
strictMode: false,
|
|
114
|
+
}
|
|
109
115
|
);
|
|
110
116
|
|
|
111
117
|
console.log(schemas);
|
|
@@ -115,120 +121,143 @@ console.log(schemas);
|
|
|
115
121
|
|
|
116
122
|
### Built-in Types
|
|
117
123
|
|
|
118
|
-
| PostgreSQL Type
|
|
119
|
-
|
|
120
|
-
| `smallint`, `integer`
|
|
121
|
-
| `bigint`
|
|
122
|
-
| `numeric(p,s)`, `decimal`
|
|
123
|
-
| `real`, `double precision` | `z.number()`
|
|
124
|
-
| `varchar(n)`
|
|
125
|
-
| `char(n)`
|
|
126
|
-
| `text`
|
|
127
|
-
| `boolean`
|
|
128
|
-
| `date`, `timestamp`
|
|
129
|
-
| `time`
|
|
130
|
-
| `interval`
|
|
131
|
-
| `uuid`
|
|
132
|
-
| `json`, `jsonb`
|
|
133
|
-
| `inet`
|
|
134
|
-
| `cidr`
|
|
135
|
-
| `macaddr`
|
|
136
|
-
| `point`
|
|
137
|
-
| `circle`
|
|
138
|
-
| `polygon`
|
|
139
|
-
| Arrays
|
|
124
|
+
| PostgreSQL Type | Zod Schema |
|
|
125
|
+
|----------------------------|-----------------------------------------------|
|
|
126
|
+
| `smallint`, `integer` | `z.number().int()` |
|
|
127
|
+
| `bigint` | `z.bigint()` |
|
|
128
|
+
| `numeric(p,s)`, `decimal` | `z.number()` with precision/scale comment |
|
|
129
|
+
| `real`, `double precision` | `z.number()` |
|
|
130
|
+
| `varchar(n)` | `z.string().max(n)` |
|
|
131
|
+
| `char(n)` | `z.string().length(n)` |
|
|
132
|
+
| `text` | `z.string()` |
|
|
133
|
+
| `boolean` | `z.boolean()` |
|
|
134
|
+
| `date`, `timestamp` | `z.date()` |
|
|
135
|
+
| `time` | `z.iso.time()` |
|
|
136
|
+
| `interval` | `z.iso.duration()` |
|
|
137
|
+
| `uuid` | `z.uuid()` |
|
|
138
|
+
| `json`, `jsonb` | `z.record(z.string(), z.unknown())` |
|
|
139
|
+
| `inet` | `z.union([z.ipv4(), z.ipv6()])` |
|
|
140
|
+
| `cidr` | `z.union([z.cidrv4(), z.cidrv6()])` |
|
|
141
|
+
| `macaddr` | `z.mac()` |
|
|
142
|
+
| `point` | `z.tuple([z.number(), z.number()])` |
|
|
143
|
+
| `circle` | `z.object({ center: ..., radius: ... })` |
|
|
144
|
+
| `polygon` | `z.array(z.tuple([z.number(), z.number()]))` |
|
|
145
|
+
| Arrays | `z.array(...)` (nested for multi-dimensional) |
|
|
140
146
|
|
|
141
147
|
### Custom Types
|
|
142
148
|
|
|
143
149
|
**Enums:**
|
|
150
|
+
|
|
144
151
|
```sql
|
|
145
152
|
CREATE TYPE status AS ENUM ('pending', 'active', 'inactive');
|
|
146
153
|
```
|
|
154
|
+
|
|
147
155
|
→
|
|
156
|
+
|
|
148
157
|
```typescript
|
|
149
158
|
export const StatusSchema = z.enum(['pending', 'active', 'inactive']);
|
|
150
159
|
export type Status = z.infer<typeof StatusSchema>;
|
|
151
160
|
```
|
|
152
161
|
|
|
153
162
|
**Domains:**
|
|
163
|
+
|
|
154
164
|
```sql
|
|
155
165
|
CREATE DOMAIN email AS TEXT CHECK (VALUE ~ '^[^@]+@[^@]+$');
|
|
156
166
|
```
|
|
167
|
+
|
|
157
168
|
→
|
|
169
|
+
|
|
158
170
|
```typescript
|
|
159
171
|
export const EmailSchema = z.string().regex(/^[^@]+@[^@]+$/);
|
|
160
172
|
export type Email = z.infer<typeof EmailSchema>;
|
|
161
173
|
```
|
|
162
174
|
|
|
163
175
|
**Composite Types:**
|
|
176
|
+
|
|
164
177
|
```sql
|
|
165
178
|
CREATE TYPE address AS (street TEXT, city TEXT, zip VARCHAR(10));
|
|
166
179
|
```
|
|
180
|
+
|
|
167
181
|
→
|
|
182
|
+
|
|
168
183
|
```typescript
|
|
169
184
|
export const AddressSchema = z.object({
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
185
|
+
street: z.string(),
|
|
186
|
+
city: z.string(),
|
|
187
|
+
zip: z.string().max(10),
|
|
173
188
|
});
|
|
174
189
|
export type Address = z.infer<typeof AddressSchema>;
|
|
175
190
|
```
|
|
176
191
|
|
|
177
192
|
**Range Types:**
|
|
193
|
+
|
|
178
194
|
```sql
|
|
179
195
|
-- int4range, daterange, tstzrange, etc.
|
|
180
196
|
```
|
|
197
|
+
|
|
181
198
|
→
|
|
199
|
+
|
|
182
200
|
```typescript
|
|
183
201
|
export const Int4rangeSchema = z.tuple([z.number().int().nullable(), z.number().int().nullable()]);
|
|
184
202
|
export type Int4range = z.infer<typeof Int4rangeSchema>;
|
|
185
203
|
```
|
|
186
204
|
|
|
187
205
|
**Views:**
|
|
206
|
+
|
|
188
207
|
```sql
|
|
189
208
|
CREATE VIEW user_stats AS
|
|
190
|
-
SELECT
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
COUNT(o.id) as order_count
|
|
209
|
+
SELECT u.id,
|
|
210
|
+
u.username,
|
|
211
|
+
COUNT(o.id) as order_count
|
|
194
212
|
FROM users u
|
|
195
|
-
LEFT JOIN orders o ON u.id = o.user_id
|
|
213
|
+
LEFT JOIN orders o ON u.id = o.user_id
|
|
196
214
|
GROUP BY u.id, u.username;
|
|
197
215
|
```
|
|
216
|
+
|
|
198
217
|
→
|
|
218
|
+
|
|
199
219
|
```typescript
|
|
200
220
|
/** View: public.user_stats (read-only) */
|
|
201
221
|
export const PublicUserStatsSchema = z.object({
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
});
|
|
222
|
+
id: z.number().int(),
|
|
223
|
+
username: z.string(),
|
|
224
|
+
order_count: z.number().int(),
|
|
225
|
+
});
|
|
206
226
|
export type PublicUserStats = z.infer<typeof PublicUserStatsSchema>;
|
|
207
227
|
```
|
|
208
228
|
|
|
209
229
|
**Functions/Procedures:**
|
|
230
|
+
|
|
210
231
|
```sql
|
|
211
232
|
CREATE FUNCTION get_user_by_id(user_id INTEGER)
|
|
212
|
-
RETURNS TABLE
|
|
233
|
+
RETURNS TABLE
|
|
234
|
+
(
|
|
235
|
+
id INTEGER,
|
|
236
|
+
username VARCHAR,
|
|
237
|
+
email VARCHAR
|
|
238
|
+
) AS $$
|
|
213
239
|
BEGIN
|
|
214
|
-
|
|
240
|
+
RETURN QUERY SELECT u.id, u.username, u.email FROM users u WHERE u.id = user_id;
|
|
215
241
|
END;
|
|
216
|
-
$$
|
|
242
|
+
$$
|
|
243
|
+
LANGUAGE plpgsql SECURITY DEFINER;
|
|
217
244
|
```
|
|
245
|
+
|
|
218
246
|
→
|
|
247
|
+
|
|
219
248
|
```typescript
|
|
220
249
|
/** FUNCTION: public.get_user_by_id */
|
|
221
250
|
export const PublicGetUserByIdParamsSchema = z.object({
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
});
|
|
251
|
+
/** integer (IN) */
|
|
252
|
+
user_id: z.number().int(),
|
|
253
|
+
});
|
|
225
254
|
export type PublicGetUserByIdParams = z.infer<typeof PublicGetUserByIdParamsSchema>;
|
|
226
255
|
|
|
227
256
|
/** Returns: record */
|
|
228
257
|
export const PublicGetUserByIdReturnSchema = z.array(z.object({
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
258
|
+
id: z.number().int(),
|
|
259
|
+
username: z.string(),
|
|
260
|
+
email: z.string(),
|
|
232
261
|
}));
|
|
233
262
|
export type PublicGetUserByIdReturn = z.infer<typeof PublicGetUserByIdReturnSchema>;
|
|
234
263
|
```
|
|
@@ -238,24 +267,29 @@ export type PublicGetUserByIdReturn = z.infer<typeof PublicGetUserByIdReturnSche
|
|
|
238
267
|
CHECK constraints are automatically parsed and translated to Zod validations:
|
|
239
268
|
|
|
240
269
|
```sql
|
|
241
|
-
CREATE TABLE products
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
270
|
+
CREATE TABLE products
|
|
271
|
+
(
|
|
272
|
+
price NUMERIC CHECK (price > 0),
|
|
273
|
+
quantity INTEGER CHECK (quantity >= 0 AND quantity <= 1000),
|
|
274
|
+
code VARCHAR(20) CHECK (code ~ '^[A-Z]{3}-\d{4}$'
|
|
275
|
+
) ,
|
|
245
276
|
status TEXT CHECK (status = ANY (ARRAY['draft', 'published', 'archived']))
|
|
246
277
|
);
|
|
247
278
|
```
|
|
279
|
+
|
|
248
280
|
→
|
|
281
|
+
|
|
249
282
|
```typescript
|
|
250
283
|
export const PublicProductsSchema = z.object({
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
284
|
+
price: z.number().min(0.00000000000001),
|
|
285
|
+
quantity: z.number().int().min(0).max(1000),
|
|
286
|
+
code: z.string().regex(/^[A-Z]{3}-\d{4}$/),
|
|
287
|
+
status: z.enum(['draft', 'published', 'archived']),
|
|
255
288
|
});
|
|
256
289
|
```
|
|
257
290
|
|
|
258
291
|
**Supported CHECK constraint patterns:**
|
|
292
|
+
|
|
259
293
|
- Numeric comparisons: `>, <, >=, <=`
|
|
260
294
|
- BETWEEN: `value BETWEEN min AND max`
|
|
261
295
|
- IN/ANY(ARRAY): `value = ANY (ARRAY['a', 'b'])` → `z.enum(['a', 'b'])`
|
|
@@ -265,6 +299,7 @@ export const PublicProductsSchema = z.object({
|
|
|
265
299
|
## CLI Options
|
|
266
300
|
|
|
267
301
|
### Connection Options
|
|
302
|
+
|
|
268
303
|
```
|
|
269
304
|
--url <url> PostgreSQL connection URL
|
|
270
305
|
--host <host> Database host (default: localhost)
|
|
@@ -276,6 +311,7 @@ export const PublicProductsSchema = z.object({
|
|
|
276
311
|
```
|
|
277
312
|
|
|
278
313
|
### Generation Options
|
|
314
|
+
|
|
279
315
|
```
|
|
280
316
|
--schemas <schemas> Comma-separated list of schemas (default: public)
|
|
281
317
|
--tables <tables> Include only these tables
|
|
@@ -292,6 +328,7 @@ export const PublicProductsSchema = z.object({
|
|
|
292
328
|
```
|
|
293
329
|
|
|
294
330
|
### Output Options
|
|
331
|
+
|
|
295
332
|
```
|
|
296
333
|
--output <file> Output file path (default: schema.ts)
|
|
297
334
|
-o <file> Short form of --output
|
|
@@ -303,12 +340,12 @@ export const PublicProductsSchema = z.object({
|
|
|
303
340
|
|
|
304
341
|
```typescript
|
|
305
342
|
import {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
} from '
|
|
343
|
+
generateZodSchemas,
|
|
344
|
+
generateZodSchemasString,
|
|
345
|
+
introspectDatabase,
|
|
346
|
+
generateSchemas,
|
|
347
|
+
formatOutput,
|
|
348
|
+
} from 'pg2zod';
|
|
312
349
|
|
|
313
350
|
// Complete flow: introspect + generate + format
|
|
314
351
|
const result = await generateZodSchemas(config, options);
|
|
@@ -318,36 +355,36 @@ const schemaString = await generateZodSchemasString(config, options);
|
|
|
318
355
|
|
|
319
356
|
// Step-by-step
|
|
320
357
|
const metadata = await introspectDatabase(config, options);
|
|
321
|
-
const
|
|
322
|
-
const output = formatOutput(
|
|
358
|
+
const result2 = generateSchemas(metadata, options);
|
|
359
|
+
const output = formatOutput(result2);
|
|
323
360
|
```
|
|
324
361
|
|
|
325
362
|
### Types
|
|
326
363
|
|
|
327
364
|
```typescript
|
|
328
365
|
interface DatabaseConfig {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
366
|
+
host: string;
|
|
367
|
+
port: number;
|
|
368
|
+
database: string;
|
|
369
|
+
user: string;
|
|
370
|
+
password: string;
|
|
371
|
+
ssl?: boolean | { rejectUnauthorized: boolean };
|
|
335
372
|
}
|
|
336
373
|
|
|
337
374
|
interface SchemaGenerationOptions {
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
375
|
+
schemas?: string[]; // Default: ['public']
|
|
376
|
+
tables?: string[]; // Include only these
|
|
377
|
+
excludeTables?: string[]; // Exclude these
|
|
378
|
+
generateInputSchemas?: boolean; // Generate Insert/Update schemas (default: true)
|
|
379
|
+
includeCompositeTypes?: boolean; // Include composite types (default: false)
|
|
380
|
+
includeViews?: boolean; // Include database views (default: false)
|
|
381
|
+
includeRoutines?: boolean; // Include functions/procedures (default: false)
|
|
382
|
+
includeSecurityInvoker?: boolean; // Include SECURITY INVOKER routines (default: false)
|
|
383
|
+
useBrandedTypes?: boolean; // Use branded types (future)
|
|
384
|
+
strictMode?: boolean; // Fail on unknown types
|
|
385
|
+
includeComments?: boolean; // Include comments (default: true)
|
|
386
|
+
useCamelCase?: boolean; // Convert to camelCase
|
|
387
|
+
customTypeMappings?: Record<string, string>; // Custom mappings
|
|
351
388
|
}
|
|
352
389
|
```
|
|
353
390
|
|
|
@@ -360,29 +397,30 @@ interface SchemaGenerationOptions {
|
|
|
360
397
|
CREATE TYPE user_role AS ENUM ('admin', 'user', 'guest');
|
|
361
398
|
|
|
362
399
|
-- Create domain
|
|
363
|
-
CREATE DOMAIN email AS VARCHAR(255)
|
|
364
|
-
|
|
400
|
+
CREATE DOMAIN email AS VARCHAR(255)
|
|
401
|
+
CHECK (VALUE ~ '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$');
|
|
365
402
|
|
|
366
403
|
-- Create table
|
|
367
|
-
CREATE TABLE users
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
404
|
+
CREATE TABLE users
|
|
405
|
+
(
|
|
406
|
+
id SERIAL PRIMARY KEY,
|
|
407
|
+
username VARCHAR(50) NOT NULL UNIQUE,
|
|
408
|
+
email email NOT NULL,
|
|
409
|
+
role user_role DEFAULT 'user',
|
|
410
|
+
age INTEGER CHECK (age >= 18 AND age <= 120),
|
|
411
|
+
tags TEXT[],
|
|
412
|
+
metadata JSONB,
|
|
413
|
+
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
376
414
|
);
|
|
377
415
|
```
|
|
378
416
|
|
|
379
417
|
### Generated Output
|
|
380
418
|
|
|
381
419
|
```typescript
|
|
382
|
-
// Generated by
|
|
420
|
+
// Generated by pg2zod
|
|
383
421
|
// Do not edit manually
|
|
384
422
|
|
|
385
|
-
import {
|
|
423
|
+
import {z} from 'zod';
|
|
386
424
|
|
|
387
425
|
// ============================================
|
|
388
426
|
// Enums
|
|
@@ -406,39 +444,39 @@ export type PublicEmail = z.infer<typeof PublicEmailSchema>;
|
|
|
406
444
|
|
|
407
445
|
/** Table: public.users - Read schema */
|
|
408
446
|
export const PublicUsersSchema = z.object({
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
447
|
+
id: z.number().int(),
|
|
448
|
+
username: z.string().max(50),
|
|
449
|
+
email: PublicEmailSchema,
|
|
450
|
+
role: PublicUserRoleSchema,
|
|
451
|
+
age: z.number().int().min(18).max(120).nullable(),
|
|
452
|
+
tags: z.array(z.string()).nullable(),
|
|
453
|
+
metadata: z.record(z.string(), z.unknown()).nullable(),
|
|
454
|
+
created_at: z.date(),
|
|
417
455
|
});
|
|
418
456
|
export type PublicUsers = z.infer<typeof PublicUsersSchema>;
|
|
419
457
|
|
|
420
458
|
/** Insert schema for users - only auto-generated fields and fields with defaults are optional */
|
|
421
459
|
export const PublicUsersInsertSchema = z.object({
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
460
|
+
id: z.number().int().optional(), // auto-generated: SERIAL/identity
|
|
461
|
+
username: z.string().max(50), // required: no default
|
|
462
|
+
email: PublicEmailSchema, // required: no default
|
|
463
|
+
role: PublicUserRoleSchema.optional(), // optional: has DEFAULT 'user'
|
|
464
|
+
age: z.number().int().min(18).max(120).nullable(), // nullable but no default, so required
|
|
465
|
+
tags: z.array(z.string()).nullable(), // nullable but no default, so required
|
|
466
|
+
metadata: z.record(z.string(), z.unknown()).nullable(), // nullable but no default, so required
|
|
467
|
+
created_at: z.date().optional(), // optional: has DEFAULT NOW()
|
|
430
468
|
});
|
|
431
469
|
export type PublicUsersInsert = z.infer<typeof PublicUsersInsertSchema>;
|
|
432
470
|
|
|
433
471
|
/** Update schema for users - all fields optional, primary keys excluded, validation preserved */
|
|
434
472
|
export const PublicUsersUpdateSchema = z.object({
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
473
|
+
username: z.string().max(50).optional(),
|
|
474
|
+
email: PublicEmailSchema.optional(),
|
|
475
|
+
role: PublicUserRoleSchema.optional(),
|
|
476
|
+
age: z.number().int().min(18).max(120).optional().nullable(),
|
|
477
|
+
tags: z.array(z.string()).optional().nullable(),
|
|
478
|
+
metadata: z.record(z.string(), z.unknown()).optional().nullable(),
|
|
479
|
+
created_at: z.date().optional(),
|
|
442
480
|
});
|
|
443
481
|
export type PublicUsersUpdate = z.infer<typeof PublicUsersUpdateSchema>;
|
|
444
482
|
```
|
|
@@ -466,5 +504,6 @@ MIT
|
|
|
466
504
|
## Credits
|
|
467
505
|
|
|
468
506
|
Built with:
|
|
507
|
+
|
|
469
508
|
- [pg](https://github.com/brianc/node-postgres) - PostgreSQL client
|
|
470
509
|
- [zod](https://github.com/colinhacks/zod) - TypeScript-first schema validation
|
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-BTbLgtTh.js";
|
|
3
3
|
import * as fs from "node:fs/promises";
|
|
4
4
|
import * as path from "node:path";
|
|
5
5
|
|
|
@@ -15,7 +15,7 @@ function parseArgs() {
|
|
|
15
15
|
process.exit(0);
|
|
16
16
|
}
|
|
17
17
|
if (args.includes("--version") || args.includes("-v")) {
|
|
18
|
-
console.log("
|
|
18
|
+
console.log("pg2zod 2.1.0");
|
|
19
19
|
process.exit(0);
|
|
20
20
|
}
|
|
21
21
|
const connectionUrl = getArg(args, "--url");
|
|
@@ -85,10 +85,10 @@ function parseConnectionUrl(url) {
|
|
|
85
85
|
*/
|
|
86
86
|
function printHelp() {
|
|
87
87
|
console.log(`
|
|
88
|
-
|
|
88
|
+
pg2zod - Generate strict Zod v4 schemas from PostgreSQL database
|
|
89
89
|
|
|
90
90
|
USAGE:
|
|
91
|
-
|
|
91
|
+
pg2zod [OPTIONS]
|
|
92
92
|
|
|
93
93
|
CONNECTION OPTIONS:
|
|
94
94
|
--url <url> PostgreSQL connection URL
|
|
@@ -131,22 +131,22 @@ ENVIRONMENT VARIABLES:
|
|
|
131
131
|
|
|
132
132
|
EXAMPLES:
|
|
133
133
|
# Generate schemas from local database
|
|
134
|
-
|
|
134
|
+
pg2zod --database mydb --output src/schemas.ts
|
|
135
135
|
|
|
136
136
|
# Use connection URL
|
|
137
|
-
|
|
137
|
+
pg2zod --url postgresql://user:pass@localhost:5432/mydb
|
|
138
138
|
|
|
139
139
|
# Generate with input schemas and camelCase
|
|
140
|
-
|
|
140
|
+
pg2zod --database mydb --input-schemas --camel-case
|
|
141
141
|
|
|
142
142
|
# Include specific tables only
|
|
143
|
-
|
|
143
|
+
pg2zod --database mydb --tables users,posts,comments
|
|
144
144
|
|
|
145
145
|
# Exclude specific tables
|
|
146
|
-
|
|
146
|
+
pg2zod --database mydb --exclude-tables migrations,internal
|
|
147
147
|
|
|
148
148
|
# Multiple schemas
|
|
149
|
-
|
|
149
|
+
pg2zod --database mydb --schemas public,auth,api
|
|
150
150
|
`);
|
|
151
151
|
}
|
|
152
152
|
/**
|
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 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"}
|
|
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('pg2zod 2.1.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(`\npg2zod - Generate strict Zod v4 schemas from PostgreSQL database\n\nUSAGE:\n pg2zod [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 pg2zod --database mydb --output src/schemas.ts\n\n # Use connection URL\n pg2zod --url postgresql://user:pass@localhost:5432/mydb\n\n # Generate with input schemas and camelCase\n pg2zod --database mydb --input-schemas --camel-case\n\n # Include specific tables only\n pg2zod --database mydb --tables users,posts,comments\n\n # Exclude specific tables\n pg2zod --database mydb --exclude-tables migrations,internal\n\n # Multiple schemas\n pg2zod --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,eAAe;AAC3B,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.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;AAUA;AAYA;AAciB,UA5HA,cAAA,CA4HgB;EACvB,UAAA,EAAA,MAAA;EACD,QAAA,EAAA,MAAA;EACG,UAAA,EAAA,OAAA;EACH,aAAA,EAAA,MAAA,GAAA,IAAA;EACS,sBAAA,EAAA,MAAA,GAAA,IAAA;EACJ,gBAAA,EAAA,MAAA,GAAA,IAAA;EACH,YAAA,EAAA,MAAA,GAAA,IAAA;EAAc,iBAAA,EAAA,MAAA,GAAA,IAAA;EAMR,OAAA,EAAA,MAAA;EA4CA,UAAA,EAAA,MAAe,GAAA,IAAA;EAWf,eAAA,EAAA,MAAgB;EACtB,OAAA,EAAA,OAAA;;;;;AAKA,UApLM,uBAAA,CAoLN;EACD,cAAA,EAAA,MAAA;EAAK,WAAA,EAAA,MAAA;;;;ACnMf;;AAEW,UDqBM,YAAA,CCrBN;EACA,QAAA,EAAA,MAAA;EAAR,UAAA,EAAA,MAAA,EAAA;EAAO,UAAA,EAAA,MAAA;;;;ACPV;AACc,UFmCG,qBAAA,CEnCH;EACD,QAAA,EAAA,MAAA;EACV,UAAA,EAAA,MAAA;EAAgB,UAAA,EFoCL,KEpCK,CAAA;
|
|
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-BTbLgtTh.js";
|
|
2
2
|
|
|
3
3
|
export { src_default as default, formatOutput, generateSchemas, generateZodSchemas, generateZodSchemasString, introspectDatabase, mapColumnToZod, toCamelCase, toPascalCase };
|
|
@@ -372,17 +372,13 @@ async function introspectViews(pool, schemas) {
|
|
|
372
372
|
udtName: row.udt_name,
|
|
373
373
|
isNullable: row.is_nullable === "YES",
|
|
374
374
|
columnDefault: row.column_default,
|
|
375
|
-
ordinalPosition: row.ordinal_position,
|
|
376
375
|
characterMaximumLength: row.character_maximum_length,
|
|
377
376
|
numericPrecision: row.numeric_precision,
|
|
378
377
|
numericScale: row.numeric_scale,
|
|
379
378
|
datetimePrecision: row.datetime_precision,
|
|
380
379
|
arrayDimensions: row.array_dimensions,
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
isGenerated: false,
|
|
384
|
-
generationExpression: null,
|
|
385
|
-
checkConstraints: []
|
|
380
|
+
domainName: null,
|
|
381
|
+
isArray: row.array_dimensions > 0
|
|
386
382
|
});
|
|
387
383
|
}
|
|
388
384
|
return views;
|
|
@@ -696,20 +692,46 @@ function generateSchemas(metadata, options = {}) {
|
|
|
696
692
|
const schema = generateTableSchema(table, metadata, options, warnings);
|
|
697
693
|
schemas.push(schema);
|
|
698
694
|
}
|
|
695
|
+
const views = metadata.views?.map((view) => ({
|
|
696
|
+
name: toPascalCase(view.schemaName) + toPascalCase(view.viewName),
|
|
697
|
+
code: generateViewSchema(view, metadata, options, warnings)
|
|
698
|
+
})) || [];
|
|
699
|
+
const filteredRoutines = metadata.routines?.filter((routine) => {
|
|
700
|
+
if (routine.securityType === "INVOKER" && !options.includeSecurityInvoker) return false;
|
|
701
|
+
const internalTypes = [
|
|
702
|
+
"internal",
|
|
703
|
+
"trigger",
|
|
704
|
+
"event_trigger",
|
|
705
|
+
"cstring",
|
|
706
|
+
"opaque",
|
|
707
|
+
"\"char\"",
|
|
708
|
+
"language_handler",
|
|
709
|
+
"fdw_handler",
|
|
710
|
+
"index_am_handler",
|
|
711
|
+
"tsm_handler",
|
|
712
|
+
"table_am_handler"
|
|
713
|
+
];
|
|
714
|
+
const hasInternalParam = routine.parameters.some((param) => internalTypes.includes(param.dataType.toLowerCase()) || internalTypes.includes(param.udtName.toLowerCase()));
|
|
715
|
+
const hasInternalReturn = routine.returnType && (internalTypes.includes(routine.returnType.toLowerCase()) || routine.returnUdtName && internalTypes.includes(routine.returnUdtName.toLowerCase()));
|
|
716
|
+
if (hasInternalParam || hasInternalReturn) return false;
|
|
717
|
+
const paramNames = routine.parameters.map((p) => p.parameterName.toLowerCase());
|
|
718
|
+
if (new Set(paramNames).size !== paramNames.length) return false;
|
|
719
|
+
return true;
|
|
720
|
+
}) || [];
|
|
721
|
+
const seenRoutineNames = /* @__PURE__ */ new Set();
|
|
699
722
|
return {
|
|
700
723
|
schemas,
|
|
701
724
|
enums,
|
|
702
725
|
compositeTypes,
|
|
703
726
|
domains,
|
|
704
727
|
ranges,
|
|
705
|
-
views
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
if (routine.securityType === "INVOKER" && !options.includeSecurityInvoker) return false;
|
|
728
|
+
views,
|
|
729
|
+
routines: filteredRoutines.filter((routine) => {
|
|
730
|
+
const baseName = toPascalCase(routine.schemaName) + toPascalCase(routine.routineName);
|
|
731
|
+
if (seenRoutineNames.has(baseName)) return false;
|
|
732
|
+
seenRoutineNames.add(baseName);
|
|
711
733
|
return true;
|
|
712
|
-
})
|
|
734
|
+
}).map((routine) => ({
|
|
713
735
|
name: toPascalCase(routine.schemaName) + toPascalCase(routine.routineName),
|
|
714
736
|
code: generateRoutineSchema(routine, metadata, options, warnings)
|
|
715
737
|
})),
|
|
@@ -1043,7 +1065,7 @@ function generateTableSchema(table, metadata, options, warnings) {
|
|
|
1043
1065
|
function formatOutput(result) {
|
|
1044
1066
|
let output = `/**\n`;
|
|
1045
1067
|
output += ` * ==========================================\n`;
|
|
1046
|
-
output += ` * | GENERATED BY
|
|
1068
|
+
output += ` * | GENERATED BY PG2ZOD |\n`;
|
|
1047
1069
|
output += ` * ==========================================\n`;
|
|
1048
1070
|
output += ` *\n`;
|
|
1049
1071
|
output += ` * ⚠️ DO NOT EDIT THIS FILE MANUALLY!\n`;
|
|
@@ -1052,7 +1074,7 @@ function formatOutput(result) {
|
|
|
1052
1074
|
output += ` * your PostgreSQL database schema.\n`;
|
|
1053
1075
|
output += ` *\n`;
|
|
1054
1076
|
output += ` * To regenerate, run:\n`;
|
|
1055
|
-
output += ` *
|
|
1077
|
+
output += ` * pg2zod --url <connection-url> -o <file>\n`;
|
|
1056
1078
|
output += ` *\n`;
|
|
1057
1079
|
output += ` * Any manual changes will be overwritten when\n`;
|
|
1058
1080
|
output += ` * the code is regenerated.\n`;
|
|
@@ -1138,4 +1160,4 @@ var src_default = {
|
|
|
1138
1160
|
|
|
1139
1161
|
//#endregion
|
|
1140
1162
|
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 };
|
|
1141
|
-
//# sourceMappingURL=src-
|
|
1163
|
+
//# sourceMappingURL=src-BTbLgtTh.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"src-BTbLgtTh.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 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 domainName: null,\n isArray: row.array_dimensions > 0,\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 and internal types)\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 \n // Skip routines with internal PostgreSQL types\n // These are low-level system functions not meant for application use\n const internalTypes = ['internal', 'trigger', 'event_trigger', 'cstring', 'opaque', '\"char\"', 'language_handler', 'fdw_handler', 'index_am_handler', 'tsm_handler', 'table_am_handler'];\n \n // Check parameters for internal types\n const hasInternalParam = routine.parameters.some(param => \n internalTypes.includes(param.dataType.toLowerCase()) || \n internalTypes.includes(param.udtName.toLowerCase())\n );\n \n // Check return type for internal types\n const hasInternalReturn = routine.returnType && (\n internalTypes.includes(routine.returnType.toLowerCase()) ||\n (routine.returnUdtName && internalTypes.includes(routine.returnUdtName.toLowerCase()))\n );\n \n if (hasInternalParam || hasInternalReturn) {\n return false;\n }\n \n // Skip functions with duplicate parameter names (would cause invalid TypeScript)\n const paramNames = routine.parameters.map(p => p.parameterName.toLowerCase());\n const hasDuplicateParams = new Set(paramNames).size !== paramNames.length;\n if (hasDuplicateParams) {\n return false;\n }\n \n return true;\n }) || [];\n\n // Handle function overloading by skipping duplicates - only keep first occurrence\n const seenRoutineNames = new Set<string>();\n const uniqueRoutines = filteredRoutines.filter((routine) => {\n const baseName = toPascalCase(routine.schemaName) + toPascalCase(routine.routineName);\n \n if (seenRoutineNames.has(baseName)) {\n // Skip duplicates (overloaded functions)\n return false;\n }\n \n seenRoutineNames.add(baseName);\n return true;\n });\n \n const routines = uniqueRoutines.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 PG2ZOD |\\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 += ` * pg2zod --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.1.
|
|
3
|
+
"version": "2.1.2",
|
|
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",
|
|
@@ -38,12 +38,12 @@
|
|
|
38
38
|
"license": "MIT",
|
|
39
39
|
"repository": {
|
|
40
40
|
"type": "git",
|
|
41
|
-
"url": "https://github.com/theNkennaAmadi/
|
|
41
|
+
"url": "https://github.com/theNkennaAmadi/pg2zod.git"
|
|
42
42
|
},
|
|
43
43
|
"bugs": {
|
|
44
|
-
"url": "https://github.com/theNkennaAmadi/
|
|
44
|
+
"url": "https://github.com/theNkennaAmadi/pg2zod/issues"
|
|
45
45
|
},
|
|
46
|
-
"homepage": "https://github.com/theNkennaAmadi/
|
|
46
|
+
"homepage": "https://github.com/theNkennaAmadi/pg2zod#readme",
|
|
47
47
|
"publishConfig": {
|
|
48
48
|
"access": "public",
|
|
49
49
|
"registry": "https://registry.npmjs.org/"
|
package/dist/src-CEkWBxDB.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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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"}
|