pg2zod 2.1.1 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/README.md +251 -143
- package/dist/cli.js +12 -12
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/{src-D1Dl6T_2.js → src-DrIY9N_Y.js} +261 -16
- package/dist/src-DrIY9N_Y.js.map +1 -0
- package/package.json +3 -2
- package/dist/src-D1Dl6T_2.js.map +0 -1
package/README.md
CHANGED
|
@@ -2,11 +2,14 @@
|
|
|
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,16 +30,19 @@ 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)
|
|
32
37
|
- TypeScript type inference support with `z.infer<>`
|
|
38
|
+
- **Database type interface** (organizes all types by schema, similar to Supabase)
|
|
33
39
|
- Schema-prefixed naming to avoid collisions (e.g., `PublicUsersSchema`)
|
|
34
40
|
- Optional camelCase conversion
|
|
35
41
|
- CHECK constraint parsing and implementation
|
|
36
42
|
- Comprehensive comments
|
|
37
43
|
|
|
38
44
|
🚀 **Modern Stack**
|
|
45
|
+
|
|
39
46
|
- ESM-first
|
|
40
47
|
- TypeScript with strict mode
|
|
41
48
|
- Zod v4 (latest beta)
|
|
@@ -56,26 +63,21 @@ yarn add pg2zod
|
|
|
56
63
|
### CLI Usage
|
|
57
64
|
|
|
58
65
|
```bash
|
|
59
|
-
# Generate schemas from a local database
|
|
66
|
+
# Generate schemas from a local database
|
|
67
|
+
# By default includes: tables, views, functions, composite types, and Database interface
|
|
60
68
|
pg2zod --database mydb --output src/db/schema.ts
|
|
61
69
|
|
|
62
70
|
# Use a connection URL
|
|
63
71
|
pg2zod --url postgresql://user:pass@localhost:5432/mydb -o schema.ts
|
|
64
72
|
|
|
65
|
-
# Skip
|
|
66
|
-
pg2zod --database mydb --no-
|
|
67
|
-
|
|
68
|
-
# Include composite types (skipped by default)
|
|
69
|
-
pg2zod --database mydb --composite-types --output schema.ts
|
|
73
|
+
# Skip views, routines, or composite types if you don't need them
|
|
74
|
+
pg2zod --database mydb --no-views --no-routines --output schema.ts
|
|
70
75
|
|
|
71
|
-
# Include
|
|
72
|
-
pg2zod --database mydb --
|
|
76
|
+
# Include SECURITY INVOKER functions (only SECURITY DEFINER by default)
|
|
77
|
+
pg2zod --database mydb --security-invoker --output schema.ts
|
|
73
78
|
|
|
74
|
-
#
|
|
75
|
-
pg2zod --database mydb --
|
|
76
|
-
|
|
77
|
-
# Include all functions including SECURITY INVOKER
|
|
78
|
-
pg2zod --database mydb --routines --security-invoker --output schema.ts
|
|
79
|
+
# Skip input schemas if you only need read schemas
|
|
80
|
+
pg2zod --database mydb --no-input-schemas --output schema.ts
|
|
79
81
|
|
|
80
82
|
# Use camelCase for field names
|
|
81
83
|
pg2zod --database mydb --camel-case -o schema.ts
|
|
@@ -90,22 +92,25 @@ pg2zod --database mydb --schemas public,auth,api -o schema.ts
|
|
|
90
92
|
### Programmatic API
|
|
91
93
|
|
|
92
94
|
```typescript
|
|
93
|
-
import {
|
|
95
|
+
import {generateZodSchemasString} from 'pg2zod';
|
|
94
96
|
|
|
95
97
|
const schemas = await generateZodSchemasString(
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
98
|
+
{
|
|
99
|
+
host: 'localhost',
|
|
100
|
+
port: 5432,
|
|
101
|
+
database: 'mydb',
|
|
102
|
+
user: 'postgres',
|
|
103
|
+
password: 'password',
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
schemas: ['public'],
|
|
107
|
+
generateInputSchemas: true,
|
|
108
|
+
includeViews: true, // Default: true
|
|
109
|
+
includeRoutines: true, // Default: true
|
|
110
|
+
includeCompositeTypes: true, // Default: true
|
|
111
|
+
includeComments: true,
|
|
112
|
+
strictMode: false,
|
|
113
|
+
}
|
|
109
114
|
);
|
|
110
115
|
|
|
111
116
|
console.log(schemas);
|
|
@@ -115,120 +120,143 @@ console.log(schemas);
|
|
|
115
120
|
|
|
116
121
|
### Built-in Types
|
|
117
122
|
|
|
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
|
|
123
|
+
| PostgreSQL Type | Zod Schema |
|
|
124
|
+
|----------------------------|-----------------------------------------------|
|
|
125
|
+
| `smallint`, `integer` | `z.number().int()` |
|
|
126
|
+
| `bigint` | `z.bigint()` |
|
|
127
|
+
| `numeric(p,s)`, `decimal` | `z.number()` with precision/scale comment |
|
|
128
|
+
| `real`, `double precision` | `z.number()` |
|
|
129
|
+
| `varchar(n)` | `z.string().max(n)` |
|
|
130
|
+
| `char(n)` | `z.string().length(n)` |
|
|
131
|
+
| `text` | `z.string()` |
|
|
132
|
+
| `boolean` | `z.boolean()` |
|
|
133
|
+
| `date`, `timestamp` | `z.date()` |
|
|
134
|
+
| `time` | `z.iso.time()` |
|
|
135
|
+
| `interval` | `z.iso.duration()` |
|
|
136
|
+
| `uuid` | `z.uuid()` |
|
|
137
|
+
| `json`, `jsonb` | `z.record(z.string(), z.unknown())` |
|
|
138
|
+
| `inet` | `z.union([z.ipv4(), z.ipv6()])` |
|
|
139
|
+
| `cidr` | `z.union([z.cidrv4(), z.cidrv6()])` |
|
|
140
|
+
| `macaddr` | `z.mac()` |
|
|
141
|
+
| `point` | `z.tuple([z.number(), z.number()])` |
|
|
142
|
+
| `circle` | `z.object({ center: ..., radius: ... })` |
|
|
143
|
+
| `polygon` | `z.array(z.tuple([z.number(), z.number()]))` |
|
|
144
|
+
| Arrays | `z.array(...)` (nested for multi-dimensional) |
|
|
140
145
|
|
|
141
146
|
### Custom Types
|
|
142
147
|
|
|
143
148
|
**Enums:**
|
|
149
|
+
|
|
144
150
|
```sql
|
|
145
151
|
CREATE TYPE status AS ENUM ('pending', 'active', 'inactive');
|
|
146
152
|
```
|
|
153
|
+
|
|
147
154
|
→
|
|
155
|
+
|
|
148
156
|
```typescript
|
|
149
157
|
export const StatusSchema = z.enum(['pending', 'active', 'inactive']);
|
|
150
158
|
export type Status = z.infer<typeof StatusSchema>;
|
|
151
159
|
```
|
|
152
160
|
|
|
153
161
|
**Domains:**
|
|
162
|
+
|
|
154
163
|
```sql
|
|
155
164
|
CREATE DOMAIN email AS TEXT CHECK (VALUE ~ '^[^@]+@[^@]+$');
|
|
156
165
|
```
|
|
166
|
+
|
|
157
167
|
→
|
|
168
|
+
|
|
158
169
|
```typescript
|
|
159
170
|
export const EmailSchema = z.string().regex(/^[^@]+@[^@]+$/);
|
|
160
171
|
export type Email = z.infer<typeof EmailSchema>;
|
|
161
172
|
```
|
|
162
173
|
|
|
163
174
|
**Composite Types:**
|
|
175
|
+
|
|
164
176
|
```sql
|
|
165
177
|
CREATE TYPE address AS (street TEXT, city TEXT, zip VARCHAR(10));
|
|
166
178
|
```
|
|
179
|
+
|
|
167
180
|
→
|
|
181
|
+
|
|
168
182
|
```typescript
|
|
169
183
|
export const AddressSchema = z.object({
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
184
|
+
street: z.string(),
|
|
185
|
+
city: z.string(),
|
|
186
|
+
zip: z.string().max(10),
|
|
173
187
|
});
|
|
174
188
|
export type Address = z.infer<typeof AddressSchema>;
|
|
175
189
|
```
|
|
176
190
|
|
|
177
191
|
**Range Types:**
|
|
192
|
+
|
|
178
193
|
```sql
|
|
179
194
|
-- int4range, daterange, tstzrange, etc.
|
|
180
195
|
```
|
|
196
|
+
|
|
181
197
|
→
|
|
198
|
+
|
|
182
199
|
```typescript
|
|
183
200
|
export const Int4rangeSchema = z.tuple([z.number().int().nullable(), z.number().int().nullable()]);
|
|
184
201
|
export type Int4range = z.infer<typeof Int4rangeSchema>;
|
|
185
202
|
```
|
|
186
203
|
|
|
187
204
|
**Views:**
|
|
205
|
+
|
|
188
206
|
```sql
|
|
189
207
|
CREATE VIEW user_stats AS
|
|
190
|
-
SELECT
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
COUNT(o.id) as order_count
|
|
208
|
+
SELECT u.id,
|
|
209
|
+
u.username,
|
|
210
|
+
COUNT(o.id) as order_count
|
|
194
211
|
FROM users u
|
|
195
|
-
LEFT JOIN orders o ON u.id = o.user_id
|
|
212
|
+
LEFT JOIN orders o ON u.id = o.user_id
|
|
196
213
|
GROUP BY u.id, u.username;
|
|
197
214
|
```
|
|
215
|
+
|
|
198
216
|
→
|
|
217
|
+
|
|
199
218
|
```typescript
|
|
200
219
|
/** View: public.user_stats (read-only) */
|
|
201
220
|
export const PublicUserStatsSchema = z.object({
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
});
|
|
221
|
+
id: z.number().int(),
|
|
222
|
+
username: z.string(),
|
|
223
|
+
order_count: z.number().int(),
|
|
224
|
+
});
|
|
206
225
|
export type PublicUserStats = z.infer<typeof PublicUserStatsSchema>;
|
|
207
226
|
```
|
|
208
227
|
|
|
209
228
|
**Functions/Procedures:**
|
|
229
|
+
|
|
210
230
|
```sql
|
|
211
231
|
CREATE FUNCTION get_user_by_id(user_id INTEGER)
|
|
212
|
-
RETURNS TABLE
|
|
232
|
+
RETURNS TABLE
|
|
233
|
+
(
|
|
234
|
+
id INTEGER,
|
|
235
|
+
username VARCHAR,
|
|
236
|
+
email VARCHAR
|
|
237
|
+
) AS $$
|
|
213
238
|
BEGIN
|
|
214
|
-
|
|
239
|
+
RETURN QUERY SELECT u.id, u.username, u.email FROM users u WHERE u.id = user_id;
|
|
215
240
|
END;
|
|
216
|
-
$$
|
|
241
|
+
$$
|
|
242
|
+
LANGUAGE plpgsql SECURITY DEFINER;
|
|
217
243
|
```
|
|
244
|
+
|
|
218
245
|
→
|
|
246
|
+
|
|
219
247
|
```typescript
|
|
220
248
|
/** FUNCTION: public.get_user_by_id */
|
|
221
249
|
export const PublicGetUserByIdParamsSchema = z.object({
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
});
|
|
250
|
+
/** integer (IN) */
|
|
251
|
+
user_id: z.number().int(),
|
|
252
|
+
});
|
|
225
253
|
export type PublicGetUserByIdParams = z.infer<typeof PublicGetUserByIdParamsSchema>;
|
|
226
254
|
|
|
227
255
|
/** Returns: record */
|
|
228
256
|
export const PublicGetUserByIdReturnSchema = z.array(z.object({
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
257
|
+
id: z.number().int(),
|
|
258
|
+
username: z.string(),
|
|
259
|
+
email: z.string(),
|
|
232
260
|
}));
|
|
233
261
|
export type PublicGetUserByIdReturn = z.infer<typeof PublicGetUserByIdReturnSchema>;
|
|
234
262
|
```
|
|
@@ -238,33 +266,109 @@ export type PublicGetUserByIdReturn = z.infer<typeof PublicGetUserByIdReturnSche
|
|
|
238
266
|
CHECK constraints are automatically parsed and translated to Zod validations:
|
|
239
267
|
|
|
240
268
|
```sql
|
|
241
|
-
CREATE TABLE products
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
269
|
+
CREATE TABLE products
|
|
270
|
+
(
|
|
271
|
+
price NUMERIC CHECK (price > 0),
|
|
272
|
+
quantity INTEGER CHECK (quantity >= 0 AND quantity <= 1000),
|
|
273
|
+
code VARCHAR(20) CHECK (code ~ '^[A-Z]{3}-\d{4}$'
|
|
274
|
+
) ,
|
|
245
275
|
status TEXT CHECK (status = ANY (ARRAY['draft', 'published', 'archived']))
|
|
246
276
|
);
|
|
247
277
|
```
|
|
278
|
+
|
|
248
279
|
→
|
|
280
|
+
|
|
249
281
|
```typescript
|
|
250
282
|
export const PublicProductsSchema = z.object({
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
283
|
+
price: z.number().min(0.00000000000001),
|
|
284
|
+
quantity: z.number().int().min(0).max(1000),
|
|
285
|
+
code: z.string().regex(/^[A-Z]{3}-\d{4}$/),
|
|
286
|
+
status: z.enum(['draft', 'published', 'archived']),
|
|
255
287
|
});
|
|
256
288
|
```
|
|
257
289
|
|
|
258
290
|
**Supported CHECK constraint patterns:**
|
|
291
|
+
|
|
259
292
|
- Numeric comparisons: `>, <, >=, <=`
|
|
260
293
|
- BETWEEN: `value BETWEEN min AND max`
|
|
261
294
|
- IN/ANY(ARRAY): `value = ANY (ARRAY['a', 'b'])` → `z.enum(['a', 'b'])`
|
|
262
295
|
- Regex: `value ~ 'pattern'` → `z.string().regex(/pattern/)`
|
|
263
296
|
- Length: `length(value) >= n` → `z.string().min(n)`
|
|
264
297
|
|
|
298
|
+
## Database Type Interface
|
|
299
|
+
|
|
300
|
+
pg2zod generates a `Database` TypeScript interface that organizes all your database types by schema, similar to Supabase's type generator. This provides a structured way to access all your types:
|
|
301
|
+
|
|
302
|
+
```typescript
|
|
303
|
+
export interface Database {
|
|
304
|
+
public: {
|
|
305
|
+
Tables: {
|
|
306
|
+
users: {
|
|
307
|
+
Row: PublicUsers;
|
|
308
|
+
Insert: PublicUsersInsert;
|
|
309
|
+
Update: PublicUsersUpdate;
|
|
310
|
+
};
|
|
311
|
+
posts: {
|
|
312
|
+
Row: PublicPosts;
|
|
313
|
+
Insert: PublicPostsInsert;
|
|
314
|
+
Update: PublicPostsUpdate;
|
|
315
|
+
};
|
|
316
|
+
};
|
|
317
|
+
Views: {
|
|
318
|
+
user_stats: {
|
|
319
|
+
Row: PublicUserStatsView;
|
|
320
|
+
};
|
|
321
|
+
};
|
|
322
|
+
Functions: {
|
|
323
|
+
get_user_by_id: {
|
|
324
|
+
Args: PublicGetUserByIdParams;
|
|
325
|
+
Returns: PublicGetUserByIdReturn;
|
|
326
|
+
};
|
|
327
|
+
log_action: {
|
|
328
|
+
Args: Record<string, never>; // No parameters
|
|
329
|
+
Returns: void; // No return value
|
|
330
|
+
};
|
|
331
|
+
};
|
|
332
|
+
Enums: {
|
|
333
|
+
user_role: PublicUserRole;
|
|
334
|
+
status: PublicStatus;
|
|
335
|
+
};
|
|
336
|
+
CompositeTypes: {
|
|
337
|
+
address: PublicAddressComposite;
|
|
338
|
+
};
|
|
339
|
+
};
|
|
340
|
+
auth: {
|
|
341
|
+
Tables: {
|
|
342
|
+
// auth schema tables...
|
|
343
|
+
};
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
**Usage:**
|
|
349
|
+
|
|
350
|
+
```typescript
|
|
351
|
+
import { Database } from './schema';
|
|
352
|
+
|
|
353
|
+
// Access table types
|
|
354
|
+
type User = Database['public']['Tables']['users']['Row'];
|
|
355
|
+
type UserInsert = Database['public']['Tables']['users']['Insert'];
|
|
356
|
+
|
|
357
|
+
// Access view types
|
|
358
|
+
type UserStats = Database['public']['Views']['user_stats']['Row'];
|
|
359
|
+
|
|
360
|
+
// Access function types
|
|
361
|
+
type GetUserByIdArgs = Database['public']['Functions']['get_user_by_id']['Args'];
|
|
362
|
+
type GetUserByIdReturn = Database['public']['Functions']['get_user_by_id']['Returns'];
|
|
363
|
+
|
|
364
|
+
// Access enums
|
|
365
|
+
type UserRole = Database['public']['Enums']['user_role'];
|
|
366
|
+
```
|
|
367
|
+
|
|
265
368
|
## CLI Options
|
|
266
369
|
|
|
267
370
|
### Connection Options
|
|
371
|
+
|
|
268
372
|
```
|
|
269
373
|
--url <url> PostgreSQL connection URL
|
|
270
374
|
--host <host> Database host (default: localhost)
|
|
@@ -276,14 +380,15 @@ export const PublicProductsSchema = z.object({
|
|
|
276
380
|
```
|
|
277
381
|
|
|
278
382
|
### Generation Options
|
|
383
|
+
|
|
279
384
|
```
|
|
280
385
|
--schemas <schemas> Comma-separated list of schemas (default: public)
|
|
281
386
|
--tables <tables> Include only these tables
|
|
282
387
|
--exclude-tables <tables> Exclude these tables
|
|
283
388
|
--no-input-schemas Skip input schemas (generated by default)
|
|
284
|
-
--composite-types
|
|
285
|
-
--views
|
|
286
|
-
--routines
|
|
389
|
+
--no-composite-types Skip composite types (generated by default)
|
|
390
|
+
--no-views Skip database views (generated by default)
|
|
391
|
+
--no-routines Skip functions/procedures (generated by default)
|
|
287
392
|
--security-invoker Include SECURITY INVOKER routines (default: DEFINER only)
|
|
288
393
|
--branded-types Use branded types for IDs (future)
|
|
289
394
|
--strict Fail on unmapped types
|
|
@@ -292,6 +397,7 @@ export const PublicProductsSchema = z.object({
|
|
|
292
397
|
```
|
|
293
398
|
|
|
294
399
|
### Output Options
|
|
400
|
+
|
|
295
401
|
```
|
|
296
402
|
--output <file> Output file path (default: schema.ts)
|
|
297
403
|
-o <file> Short form of --output
|
|
@@ -303,11 +409,11 @@ export const PublicProductsSchema = z.object({
|
|
|
303
409
|
|
|
304
410
|
```typescript
|
|
305
411
|
import {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
412
|
+
generateZodSchemas,
|
|
413
|
+
generateZodSchemasString,
|
|
414
|
+
introspectDatabase,
|
|
415
|
+
generateSchemas,
|
|
416
|
+
formatOutput,
|
|
311
417
|
} from 'pg2zod';
|
|
312
418
|
|
|
313
419
|
// Complete flow: introspect + generate + format
|
|
@@ -318,36 +424,36 @@ const schemaString = await generateZodSchemasString(config, options);
|
|
|
318
424
|
|
|
319
425
|
// Step-by-step
|
|
320
426
|
const metadata = await introspectDatabase(config, options);
|
|
321
|
-
const
|
|
322
|
-
const output = formatOutput(
|
|
427
|
+
const result2 = generateSchemas(metadata, options);
|
|
428
|
+
const output = formatOutput(result2);
|
|
323
429
|
```
|
|
324
430
|
|
|
325
431
|
### Types
|
|
326
432
|
|
|
327
433
|
```typescript
|
|
328
434
|
interface DatabaseConfig {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
435
|
+
host: string;
|
|
436
|
+
port: number;
|
|
437
|
+
database: string;
|
|
438
|
+
user: string;
|
|
439
|
+
password: string;
|
|
440
|
+
ssl?: boolean | { rejectUnauthorized: boolean };
|
|
335
441
|
}
|
|
336
442
|
|
|
337
443
|
interface SchemaGenerationOptions {
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
444
|
+
schemas?: string[]; // Default: ['public']
|
|
445
|
+
tables?: string[]; // Include only these
|
|
446
|
+
excludeTables?: string[]; // Exclude these
|
|
447
|
+
generateInputSchemas?: boolean; // Generate Insert/Update schemas (default: true)
|
|
448
|
+
includeCompositeTypes?: boolean; // Include composite types (default: true)
|
|
449
|
+
includeViews?: boolean; // Include database views (default: true)
|
|
450
|
+
includeRoutines?: boolean; // Include functions/procedures (default: true)
|
|
451
|
+
includeSecurityInvoker?: boolean; // Include SECURITY INVOKER routines (default: false)
|
|
452
|
+
useBrandedTypes?: boolean; // Use branded types (future)
|
|
453
|
+
strictMode?: boolean; // Fail on unknown types
|
|
454
|
+
includeComments?: boolean; // Include comments (default: true)
|
|
455
|
+
useCamelCase?: boolean; // Convert to camelCase
|
|
456
|
+
customTypeMappings?: Record<string, string>; // Custom mappings
|
|
351
457
|
}
|
|
352
458
|
```
|
|
353
459
|
|
|
@@ -360,19 +466,20 @@ interface SchemaGenerationOptions {
|
|
|
360
466
|
CREATE TYPE user_role AS ENUM ('admin', 'user', 'guest');
|
|
361
467
|
|
|
362
468
|
-- Create domain
|
|
363
|
-
CREATE DOMAIN email AS VARCHAR(255)
|
|
364
|
-
|
|
469
|
+
CREATE DOMAIN email AS VARCHAR(255)
|
|
470
|
+
CHECK (VALUE ~ '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$');
|
|
365
471
|
|
|
366
472
|
-- Create table
|
|
367
|
-
CREATE TABLE users
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
473
|
+
CREATE TABLE users
|
|
474
|
+
(
|
|
475
|
+
id SERIAL PRIMARY KEY,
|
|
476
|
+
username VARCHAR(50) NOT NULL UNIQUE,
|
|
477
|
+
email email NOT NULL,
|
|
478
|
+
role user_role DEFAULT 'user',
|
|
479
|
+
age INTEGER CHECK (age >= 18 AND age <= 120),
|
|
480
|
+
tags TEXT[],
|
|
481
|
+
metadata JSONB,
|
|
482
|
+
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
376
483
|
);
|
|
377
484
|
```
|
|
378
485
|
|
|
@@ -382,7 +489,7 @@ CREATE TABLE users (
|
|
|
382
489
|
// Generated by pg2zod
|
|
383
490
|
// Do not edit manually
|
|
384
491
|
|
|
385
|
-
import {
|
|
492
|
+
import {z} from 'zod';
|
|
386
493
|
|
|
387
494
|
// ============================================
|
|
388
495
|
// Enums
|
|
@@ -406,39 +513,39 @@ export type PublicEmail = z.infer<typeof PublicEmailSchema>;
|
|
|
406
513
|
|
|
407
514
|
/** Table: public.users - Read schema */
|
|
408
515
|
export const PublicUsersSchema = z.object({
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
516
|
+
id: z.number().int(),
|
|
517
|
+
username: z.string().max(50),
|
|
518
|
+
email: PublicEmailSchema,
|
|
519
|
+
role: PublicUserRoleSchema,
|
|
520
|
+
age: z.number().int().min(18).max(120).nullable(),
|
|
521
|
+
tags: z.array(z.string()).nullable(),
|
|
522
|
+
metadata: z.record(z.string(), z.unknown()).nullable(),
|
|
523
|
+
created_at: z.date(),
|
|
417
524
|
});
|
|
418
525
|
export type PublicUsers = z.infer<typeof PublicUsersSchema>;
|
|
419
526
|
|
|
420
527
|
/** Insert schema for users - only auto-generated fields and fields with defaults are optional */
|
|
421
528
|
export const PublicUsersInsertSchema = z.object({
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
529
|
+
id: z.number().int().optional(), // auto-generated: SERIAL/identity
|
|
530
|
+
username: z.string().max(50), // required: no default
|
|
531
|
+
email: PublicEmailSchema, // required: no default
|
|
532
|
+
role: PublicUserRoleSchema.optional(), // optional: has DEFAULT 'user'
|
|
533
|
+
age: z.number().int().min(18).max(120).nullable(), // nullable but no default, so required
|
|
534
|
+
tags: z.array(z.string()).nullable(), // nullable but no default, so required
|
|
535
|
+
metadata: z.record(z.string(), z.unknown()).nullable(), // nullable but no default, so required
|
|
536
|
+
created_at: z.date().optional(), // optional: has DEFAULT NOW()
|
|
430
537
|
});
|
|
431
538
|
export type PublicUsersInsert = z.infer<typeof PublicUsersInsertSchema>;
|
|
432
539
|
|
|
433
540
|
/** Update schema for users - all fields optional, primary keys excluded, validation preserved */
|
|
434
541
|
export const PublicUsersUpdateSchema = z.object({
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
542
|
+
username: z.string().max(50).optional(),
|
|
543
|
+
email: PublicEmailSchema.optional(),
|
|
544
|
+
role: PublicUserRoleSchema.optional(),
|
|
545
|
+
age: z.number().int().min(18).max(120).optional().nullable(),
|
|
546
|
+
tags: z.array(z.string()).optional().nullable(),
|
|
547
|
+
metadata: z.record(z.string(), z.unknown()).optional().nullable(),
|
|
548
|
+
created_at: z.date().optional(),
|
|
442
549
|
});
|
|
443
550
|
export type PublicUsersUpdate = z.infer<typeof PublicUsersUpdateSchema>;
|
|
444
551
|
```
|
|
@@ -466,5 +573,6 @@ MIT
|
|
|
466
573
|
## Credits
|
|
467
574
|
|
|
468
575
|
Built with:
|
|
576
|
+
|
|
469
577
|
- [pg](https://github.com/brianc/node-postgres) - PostgreSQL client
|
|
470
578
|
- [zod](https://github.com/colinhacks/zod) - TypeScript-first schema validation
|