mutano 3.0.0 → 3.0.1

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.
Files changed (2) hide show
  1. package/README.md +116 -732
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,182 +1,24 @@
1
1
  # Mutano
2
2
 
3
- Converts Prisma/MySQL/PostgreSQL/SQLite schemas to Zod schemas, TypeScript interfaces, or Kysely type definitions
3
+ Convert database schemas to TypeScript types, Zod schemas, or Kysely definitions.
4
4
 
5
- ## Features
6
-
7
- - Generates Zod schemas, Typescript interfaces or Kysely type definitions for MySQL, PostgreSQL, SQLite, and Prisma schemas
8
- - **NEW: Database Views Support** - Extract and generate types for database views (read-only)
9
- - Supports camelCase conversion
10
- - Handles nullable, default, auto-increment and enum fields
11
- - Supports custom type overrides via configuration or database comments
12
- - Intelligently handles field nullability based on operation type (table, insertable, updateable, selectable)
13
- - All fields in updateable schemas are automatically made optional
14
- - Views are treated as read-only entities (no insertable/updateable schemas generated)
5
+ **Supports:** MySQL, PostgreSQL, SQLite, Prisma • **Features:** Views, Magic Comments, Type Overrides, Multiple Outputs
15
6
 
16
7
  ## Installation
17
8
 
18
- Install `mutano` with npm
19
-
20
9
  ```bash
21
10
  npm install mutano
22
11
  ```
23
12
 
24
- ## Usage/Examples
25
-
26
- Create user table:
27
-
28
- ```sql
29
- CREATE TABLE `user` (
30
- `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
31
- `name` varchar(255) NOT NULL COMMENT '@zod(z.string().min(10).max(255))', -- this will override the Zod type
32
- `username` varchar(255) NOT NULL,
33
- `password` varchar(255) NOT NULL,
34
- `profile_picture` varchar(255) DEFAULT NULL,
35
- `metadata` json NOT NULL COMMENT '@ts(Record<string, unknown>) @kysely(Record<string, string>)', -- this will override the TypeScript and Kysely type
36
- `role` enum('admin','user') NOT NULL,
37
- PRIMARY KEY (`id`)
38
- );
39
- ```
40
- Use the mutano API:
41
-
42
- ### MySQL Example with Zod Schemas
13
+ ## Quick Start
43
14
 
44
15
  ```typescript
45
16
  import { generate } from 'mutano'
46
17
 
18
+ // Basic usage
47
19
  await generate({
48
20
  origin: {
49
- type: 'mysql',
50
- host: '127.0.0.1',
51
- port: 3306,
52
- user: 'root',
53
- password: 'secret',
54
- database: 'myapp',
55
- overrideTypes: {
56
- json: 'z.record(z.string())'
57
- }
58
- },
59
- destinations: [{
60
- type: 'zod',
61
- useDateType: true,
62
- useTrim: false,
63
- nullish: false, // When true, nullable fields use nullish() instead of nullable()
64
- folder: './generated',
65
- suffix: 'schema'
66
- }]
67
- })
68
- ```
69
-
70
- ### MySQL Example with TypeScript Type Aliases (Instead of Interfaces)
71
-
72
- ```typescript
73
- import { generate } from 'mutano'
74
-
75
- await generate({
76
- origin: {
77
- type: 'mysql',
78
- host: '127.0.0.1',
79
- port: 3306,
80
- user: 'root',
81
- password: 'secret',
82
- database: 'myapp',
83
- overrideTypes: {
84
- json: 'z.record(z.string())'
85
- }
86
- },
87
- destinations: [{
88
- type: 'ts',
89
- modelType: 'type', // Generate TypeScript type aliases instead of interfaces
90
- folder: './types',
91
- suffix: 'types'
92
- }]
93
- })
94
- ```
95
-
96
- ### MySQL Example with Custom Header for TypeScript
97
-
98
- ```typescript
99
- import { generate } from 'mutano'
100
-
101
- await generate({
102
- origin: {
103
- type: 'mysql',
104
- host: '127.0.0.1',
105
- port: 3306,
106
- user: 'root',
107
- password: 'secret',
108
- database: 'myapp',
109
- overrideTypes: {
110
- json: 'z.record(z.string())'
111
- }
112
- },
113
- destinations: [{
114
- type: 'ts',
115
- header: "import type { CustomType } from './types';\nimport type { BaseModel } from './models';"
116
- }]
117
- })
118
- ```
119
-
120
- ### MySQL Example with Custom Header for Zod
121
-
122
- ```typescript
123
- import { generate } from 'mutano'
124
-
125
- await generate({
126
- origin: {
127
- type: 'mysql',
128
- host: '127.0.0.1',
129
- port: 3306,
130
- user: 'root',
131
- password: 'secret',
132
- database: 'myapp',
133
- overrideTypes: {
134
- json: 'z.record(z.string())'
135
- }
136
- },
137
- destinations: [{
138
- type: 'zod',
139
- header: "import { z } from 'zod';\nimport { CustomValidator } from './validators';"
140
- }]
141
- })
142
- ```
143
-
144
- ### MySQL Example with Kysely Type Definitions (Custom Schema Name)
145
-
146
- ```typescript
147
- import { generate } from 'mutano'
148
-
149
- await generate({
150
- origin: {
151
- type: 'mysql',
152
- host: '127.0.0.1',
153
- port: 3306,
154
- user: 'root',
155
- password: 'secret',
156
- database: 'myapp',
157
- overrideTypes: {
158
- json: 'z.record(z.string())'
159
- }
160
- },
161
- destinations: [{
162
- type: 'kysely',
163
- schemaName: 'Database', // Default is 'DB'
164
- header: "import { Generated, ColumnType } from 'kysely';\nimport { CustomTypes } from './types';",
165
- folder: './db/types',
166
- suffix: 'db'
167
- }]
168
- })
169
- ```
170
-
171
- ### Example with Dry Run Option
172
-
173
- ```typescript
174
- import { generate } from 'mutano'
175
-
176
- // Generate without writing to disk
177
- const output = await generate({
178
- origin: {
179
- type: 'mysql',
21
+ type: 'mysql', // or 'postgres', 'sqlite', 'prisma'
180
22
  host: '127.0.0.1',
181
23
  port: 3306,
182
24
  user: 'root',
@@ -184,656 +26,198 @@ const output = await generate({
184
26
  database: 'myapp'
185
27
  },
186
28
  destinations: [{
187
- type: 'zod'
188
- }],
189
- dryRun: true // Return content and don't write to files
190
- })
191
-
192
- // Output is an object where keys are filenames and values are file content
193
- console.log(Object.keys(output)) // ['user.ts', 'product.ts', ...]
194
-
195
- // You can access the content for a specific file
196
- console.log(output['user.ts'])
197
- ```
198
-
199
- ### PostgreSQL Example
200
-
201
- ```typescript
202
- import { generate } from 'mutano'
203
-
204
- await generate({
205
- origin: {
206
- type: 'postgres',
207
- host: '127.0.0.1',
208
- port: 5432,
209
- user: 'postgres',
210
- password: 'secret',
211
- database: 'myapp',
212
- schema: 'public', // optional, defaults to 'public'
213
- overrideTypes: {
214
- jsonb: 'z.record(z.string())'
215
- }
216
- },
217
- destinations: [{
218
- type: 'zod',
219
- useDateType: true
220
- }]
221
- })
222
- ```
223
-
224
- ### SQLite Example
225
-
226
- ```typescript
227
- import { generate } from 'mutano'
228
-
229
- await generate({
230
- origin: {
231
- type: 'sqlite',
232
- path: './myapp.db',
233
- overrideTypes: {
234
- json: 'z.record(z.string())'
235
- }
236
- },
237
- destinations: [{
238
- type: 'ts'
29
+ type: 'zod', // or 'ts', 'kysely'
30
+ folder: './generated'
239
31
  }]
240
32
  })
241
- ```
242
-
243
- ### Example with Multiple Destinations
244
-
245
- ```typescript
246
- import { generate } from 'mutano'
247
33
 
34
+ // Multiple outputs
248
35
  await generate({
249
- origin: {
250
- type: 'mysql',
251
- host: '127.0.0.1',
252
- port: 3306,
253
- user: 'root',
254
- password: 'secret',
255
- database: 'myapp',
256
- overrideTypes: {
257
- json: 'z.record(z.string())'
258
- }
259
- },
36
+ origin: { /* ... */ },
260
37
  destinations: [
261
- {
262
- type: 'zod',
263
- useDateType: true,
264
- folder: './generated/zod',
265
- suffix: 'schema'
266
- },
267
- {
268
- type: 'ts',
269
- folder: './generated/types',
270
- suffix: 'type'
271
- },
272
- {
273
- type: 'kysely',
274
- folder: './generated/kysely',
275
- suffix: 'db'
276
- }
38
+ { type: 'zod', folder: './zod' },
39
+ { type: 'ts', folder: './types' },
40
+ { type: 'kysely', outFile: './db.ts' }
277
41
  ]
278
42
  })
279
- ```
280
-
281
- This will generate all three types of output files for each table in your database, placing them in separate folders with appropriate suffixes.
282
-
283
- ### Database Views Example
284
-
285
- ```typescript
286
- import { generate } from 'mutano'
287
43
 
44
+ // With views support
288
45
  await generate({
289
- origin: {
290
- type: 'mysql',
291
- host: '127.0.0.1',
292
- port: 3306,
293
- user: 'root',
294
- password: 'secret',
295
- database: 'myapp'
296
- },
297
- destinations: [{
298
- type: 'zod',
299
- folder: './generated/schemas',
300
- suffix: 'schema'
301
- }],
302
- includeViews: true, // Enable views processing
303
- views: ['user_profile_view', 'order_summary_view'], // Optional: specify which views to include
304
- ignoreViews: ['temp_view'] // Optional: specify which views to ignore
305
- })
306
- ```
307
-
308
- **Database Views Features:**
309
- - **Read-only**: Views generate only selectable schemas (no insertable/updateable)
310
- - **All database types**: Supports MySQL, PostgreSQL, SQLite, and Prisma views
311
- - **Filtering**: Use `views` and `ignoreViews` options to control which views are processed
312
- - **Type safety**: Full TypeScript/Zod/Kysely type generation for view columns
313
- - **Prisma integration**: Automatically detects `view` blocks in Prisma schema files
314
-
315
- ### Prisma Views Integration
316
-
317
- Mutano automatically detects and processes `view` blocks in your Prisma schema:
318
-
319
- ```prisma
320
- // schema.prisma
321
- generator client {
322
- provider = "prisma-client-js"
323
- previewFeatures = ["views"]
324
- }
325
-
326
- model User {
327
- id Int @id @default(autoincrement())
328
- email String @unique
329
- name String?
330
- profile Profile?
331
- }
332
-
333
- model Profile {
334
- id Int @id @default(autoincrement())
335
- bio String
336
- user User @relation(fields: [userId], references: [id])
337
- userId Int @unique
338
- }
339
-
340
- // This view will be automatically processed by Mutano
341
- view UserInfo {
342
- id Int
343
- email String
344
- name String?
345
- bio String?
346
- }
347
- ```
348
-
349
- ```typescript
350
- // Generate types from Prisma schema with views
351
- await generate({
352
- origin: {
353
- type: 'prisma',
354
- path: './schema.prisma'
355
- },
356
- destinations: [{
357
- type: 'zod',
358
- useDateType: true
359
- }],
360
- includeViews: true
46
+ origin: { /* ... */ },
47
+ destinations: [{ type: 'zod' }],
48
+ includeViews: true,
49
+ views: ['user_profile_view'], // optional filter
50
+ ignoreViews: ['temp_view'] // optional exclude
361
51
  })
362
52
  ```
363
53
 
364
- The generator will create `user.type.ts`, `user.schema.ts`, and `user.db.ts` files with the following contents:
54
+ ## Database Support
365
55
 
366
- ### Database View Output Examples
56
+ | Database | Connection | Views | Magic Comments |
57
+ |----------|------------|-------|----------------|
58
+ | **MySQL** | Host/Port | ✅ | ✅ |
59
+ | **PostgreSQL** | Host/Port | ✅ | ✅ |
60
+ | **SQLite** | File Path | ✅ | ❌ |
61
+ | **Prisma** | Schema File | ✅ | ❌ |
367
62
 
368
- For a database view like:
369
- ```sql
370
- CREATE VIEW user_profile_view AS
371
- SELECT
372
- u.id,
373
- u.name,
374
- u.email,
375
- p.bio,
376
- p.avatar_url
377
- FROM users u
378
- LEFT JOIN profiles p ON u.id = p.user_id;
379
- ```
380
-
381
- ### Zod Schema Output Example with Custom Header
63
+ ## Output Examples
382
64
 
65
+ **Zod Schema:**
383
66
  ```typescript
384
- import { z } from 'zod';
385
- import { CustomValidator } from './validators';
386
-
387
67
  export const user = z.object({
388
68
  id: z.number().nonnegative(),
389
- name: z.string().min(10).max(255),
390
- username: z.string(),
391
- password: z.string(),
392
- profile_picture: z.string().nullable(),
69
+ name: z.string().min(1),
70
+ email: z.string().email(),
393
71
  role: z.enum(['admin', 'user']),
394
72
  })
395
73
 
396
74
  export const insertable_user = z.object({
397
- name: z.string().min(10).max(255),
398
- username: z.string(),
399
- password: z.string(),
400
- profile_picture: z.string().nullable(),
401
- role: z.enum(['admin', 'user']),
402
- })
403
-
404
- export const updateable_user = z.object({
405
- name: z.string().min(10).max(255).optional(),
406
- username: z.string().optional(),
407
- password: z.string().optional(),
408
- profile_picture: z.string().nullable().optional(),
409
- role: z.enum(['admin', 'user']).optional(),
410
- })
411
-
412
- export const selectable_user = z.object({
413
- id: z.number().nonnegative(),
414
- name: z.string(),
415
- username: z.string(),
416
- password: z.string(),
417
- profile_picture: z.string().nullable(),
75
+ name: z.string().min(1),
76
+ email: z.string().email(),
418
77
  role: z.enum(['admin', 'user']),
419
78
  })
420
79
 
421
- export type userType = z.infer<typeof user>
422
- export type InsertableUserType = z.infer<typeof insertable_user>
423
- export type UpdateableUserType = z.infer<typeof updateable_user>
424
- export type SelectableUserType = z.infer<typeof selectable_user>
80
+ export type UserType = z.infer<typeof user>
425
81
  ```
426
82
 
427
- ### TypeScript Interface Output Example with Custom Header
428
-
83
+ **TypeScript Interface:**
429
84
  ```typescript
430
- import { CustomType } from './types';
431
- import { BaseModel } from './models';
432
-
433
- // TypeScript interfaces for user
434
-
435
85
  export interface User {
436
86
  id: number;
437
87
  name: string;
438
- username: string;
439
- password: string;
440
- profile_picture: string | null;
441
- metadata: Record<string, unknown>; // Custom type from @ts comment
88
+ email: string;
442
89
  role: 'admin' | 'user';
443
90
  }
444
91
 
445
92
  export interface InsertableUser {
446
- name: string | null; // Optional because it has a default value
447
- username: string;
448
- password: string;
449
- profile_picture: string | null;
450
- metadata: Record<string, unknown>; // Custom type from @ts comment
451
- role: 'admin' | 'user';
452
- }
453
-
454
- export interface UpdateableUser {
455
- name: string | null; // Optional for updates
456
- username: string | null; // Optional for updates
457
- password: string | null; // Optional for updates
458
- profile_picture: string | null;
459
- metadata: Record<string, unknown> | null; // Custom type from @ts comment, optional for updates
460
- role: 'admin' | 'user' | null; // Optional for updates
461
- }
462
-
463
- export interface SelectableUser {
464
- id: number;
465
93
  name: string;
466
- username: string;
467
- password: string;
468
- profile_picture: string | null;
469
- metadata: Record<string, unknown>; // Custom type from @ts comment
94
+ email: string;
470
95
  role: 'admin' | 'user';
471
96
  }
472
97
  ```
473
98
 
474
- ### Kysely Type Definitions Output Example
475
-
99
+ **Kysely Types:**
476
100
  ```typescript
477
- import { Generated, ColumnType, Selectable, Insertable, Updateable } from 'kysely';
478
-
479
- // JSON type definitions
480
- export type Json = ColumnType<JsonValue, string, string>;
481
-
482
- export type JsonArray = JsonValue[];
483
-
484
- export type JsonObject = {
485
- [x: string]: JsonValue | undefined;
486
- };
487
-
488
- export type JsonPrimitive = boolean | number | string | null;
489
-
490
- export type JsonValue = JsonArray | JsonObject | JsonPrimitive;
491
-
492
- // Kysely type definitions for user
493
-
494
- // This interface defines the structure of the 'user' table
495
101
  export interface UserTable {
496
102
  id: Generated<number>;
497
103
  name: string;
498
- username: string;
499
- password: string;
500
- profile_picture: string | null;
501
- metadata: Record<string, unknown>; // Custom type from @kysely comment
104
+ email: string;
502
105
  role: 'admin' | 'user';
503
106
  }
504
107
 
505
- // Define the database interface
506
- export interface DB {
507
- user: UserTable;
508
- }
509
-
510
- // Use these types for inserting, selecting and updating the table
511
108
  export type User = Selectable<UserTable>;
512
109
  export type NewUser = Insertable<UserTable>;
513
110
  export type UserUpdate = Updateable<UserTable>;
514
111
  ```
515
112
 
516
- ### View Output Examples
517
-
518
- #### Zod Schema for Views (Read-only)
519
-
520
- ```typescript
521
- import { z } from 'zod';
522
-
523
- // View schema (read-only)
524
- export const user_profile_view = z.object({
525
- id: z.number().nonnegative(),
526
- name: z.string(),
527
- email: z.string(),
528
- bio: z.string().nullable(),
529
- avatar_url: z.string().nullable(),
530
- })
531
-
532
- export type UserProfileViewType = z.infer<typeof user_profile_view>
533
- ```
534
-
535
- #### TypeScript Interface for Views (Read-only)
536
-
537
- ```typescript
538
- // TypeScript interface for user_profile_view (view - read-only)
539
- export interface UserProfileView {
540
- id: number;
541
- name: string;
542
- email: string;
543
- bio: string | null;
544
- avatar_url: string | null;
545
- }
546
- ```
547
-
548
- #### Kysely Type Definitions for Views (Read-only)
113
+ ## Configuration
549
114
 
115
+ ### Origin Options
550
116
  ```typescript
551
- // Kysely type definitions for user_profile_view (view)
552
-
553
- // This interface defines the structure of the 'user_profile_view' view (read-only)
554
- export interface UserProfileView {
555
- id: number;
556
- name: string;
557
- email: string;
558
- bio: string | null;
559
- avatar_url: string | null;
560
- }
561
-
562
- // Helper types for user_profile_view (view - read-only)
563
- export type SelectableUserProfileView = Selectable<UserProfileView>;
564
- ```
565
-
566
- ## Config
567
-
568
- ```json
569
- {
570
- "origin": {
571
- "type": "mysql",
572
- "host": "127.0.0.1",
573
- "port": 3306,
574
- "user": "root",
575
- "password": "secret",
576
- "database": "myapp",
577
- "overrideTypes": {
578
- "json": "z.record(z.string())"
579
- },
580
- "ssl": {
581
- "ca": "path/to/ca.pem",
582
- "cert": "path/to/cert.pem",
583
- "key": "path/to/key.pem"
584
- },
585
- } | {
586
- "type": "postgres",
587
- "host": "127.0.0.1",
588
- "port": 5432,
589
- "user": "postgres",
590
- "password": "secret",
591
- "database": "myapp",
592
- "schema": "public",
593
- "overrideTypes": {
594
- "jsonb": "z.record(z.string())"
595
- },
596
- "ssl": {
597
- "ca": "path/to/ca.pem",
598
- "cert": "path/to/cert.pem",
599
- "key": "path/to/key.pem"
600
- },
601
- } | {
602
- "type": "sqlite",
603
- "path": "path/to/database.db",
604
- "overrideTypes": {
605
- "json": "z.record(z.string())"
606
- }
607
- } | {
608
- "type": "prisma",
609
- "path": "path/to/schema.prisma",
610
- "overrideTypes": {
611
- "Json": "z.record(z.string())"
612
- }
613
- },
614
- "destinations": [
615
- {
616
- "type": "zod",
617
- "useDateType": true,
618
- "useTrim": false,
619
- "nullish": false, // When true, nullable fields use nullish() instead of nullable()
620
- "requiredString": false, // When true, adds min(1) validation to non-nullable string fields
621
- "header": "import { z } from 'zod';\nimport { CustomValidator } from './validators';",
622
- "folder": "@zod",
623
- "suffix": "table"
624
- },
625
- {
626
- "type": "ts",
627
- "enumType": "union",
628
- "modelType": "interface",
629
- "header": "import { CustomType } from './types';\nimport { BaseModel } from './models';",
630
- "folder": "types",
631
- "suffix": "type"
632
- },
633
- {
634
- "type": "kysely",
635
- "schemaName": "Database",
636
- "header": "import { Generated, ColumnType } from 'kysely';\nimport { CustomTypes } from './types';",
637
- "outFile": "db.ts"
638
- }
639
- ],
640
- "tables": ["user", "log"],
641
- "views": ["user_profile_view", "order_summary"],
642
- "ignore": ["log", "/^temp/"],
643
- "ignoreViews": ["temp_view", "/^debug_/"],
644
- "includeViews": true,
645
- "camelCase": false,
646
- "silent": false,
647
- "dryRun": false,
648
- "magicComments": true
649
- }
650
- ```
651
-
652
- | Option | Description |
653
- | ------ | ----------- |
654
- | destinations | An array of destination configurations to generate multiple output formats from a single origin |
655
- | destinations[].type | The type of output to generate: "zod", "ts", or "kysely" |
656
- | destinations[].useDateType | (Zod only) Use a specialized Zod type for date-like fields instead of string |
657
- | destinations[].useTrim | (Zod only) Use `z.string().trim()` instead of `z.string()` |
658
- | destinations[].nullish | (Zod only) Use `nullish()` instead of `nullable()` for nullable fields. In updateable schemas, fields that were already nullable will become nullish |
659
- | destinations[].version | (Zod only) Zod version to use. Defaults to 3. Set to 4 to use Zod v4 |
660
- | destinations[].requiredString | (Zod only) Add `min(1)` for non-nullable string fields |
661
- | destinations[].enumType | (TypeScript only) How to represent enum types: "union" (default) or "enum" |
662
- | destinations[].modelType | (TypeScript only) How to represent models: "interface" (default) or "type" |
663
- | destinations[].schemaName | (Kysely only) Name of the database interface (default: "DB") |
664
- | destinations[].header | Custom header to include at the beginning of generated files (e.g., custom imports) |
665
- | destinations[].folder | Specify the output directory for the generated files |
666
- | destinations[].suffix | Suffix to the name of a generated file (eg: `user.table.ts`) |
667
- | destinations[].outFile | (Kysely only) Specify the output file for the generated content. All tables will be written to this file |
668
- | tables | Filter the tables to include only those specified |
669
- | views | Filter the views to include only those specified (requires `includeViews: true`) |
670
- | ignore | Filter the tables to exclude those specified. If a table name begins and ends with "/", it will be processed as a regular expression |
671
- | ignoreViews | Filter the views to exclude those specified. If a view name begins and ends with "/", it will be processed as a regular expression |
672
- | includeViews | When true, database views will be processed and included in the output. Views are read-only (no insertable/updateable schemas) |
673
- | camelCase | Convert all table names and their properties to camelcase. (eg: `profile_picture` becomes `profilePicture`) |
674
- | silent | Don't log anything to the console |
675
- | dryRun | When true, doesn't write files to disk but returns an object with filenames as keys and generated content as values |
676
- | magicComments | Use @zod and @ts comments to override types (unsupported by SQLite) |
677
-
678
- ## overrideTypes
679
-
680
- You can override the default type for a specific column type. This is specific to each database type and is placed inside the origin object. Each database type has its own set of valid types that can be overridden:
681
-
682
- ### MySQL overrideTypes
683
-
684
- ```json
117
+ // MySQL/PostgreSQL
685
118
  {
686
- "origin": {
687
- "type": "mysql",
688
- "host": "127.0.0.1",
689
- "port": 3306,
690
- "user": "root",
691
- "password": "secret",
692
- "database": "myapp",
693
- "overrideTypes": {
694
- "json": "z.record(z.string())",
695
- "text": "z.string().max(1000)"
696
- }
697
- }
698
- }
699
- ```
700
-
701
- ### PostgreSQL overrideTypes
702
-
703
- ```json
119
+ type: 'mysql' | 'postgres',
120
+ host: string,
121
+ port: number,
122
+ user: string,
123
+ password: string,
124
+ database: string,
125
+ schema?: string, // PostgreSQL only
126
+ ssl?: { ca, cert, key },
127
+ overrideTypes?: Record<string, string>
128
+ }
129
+
130
+ // SQLite
704
131
  {
705
- "origin": {
706
- "type": "postgres",
707
- "host": "127.0.0.1",
708
- "port": 5432,
709
- "user": "postgres",
710
- "password": "secret",
711
- "database": "myapp",
712
- "schema": "public",
713
- "overrideTypes": {
714
- "jsonb": "z.record(z.string())",
715
- "uuid": "z.string().uuid()"
716
- }
717
- }
132
+ type: 'sqlite',
133
+ path: string,
134
+ overrideTypes?: Record<string, string>
718
135
  }
719
- ```
720
136
 
721
- ### SQLite overrideTypes
722
-
723
- ```json
137
+ // Prisma
724
138
  {
725
- "origin": {
726
- "type": "sqlite",
727
- "path": "./myapp.db",
728
- "overrideTypes": {
729
- "json": "z.record(z.string())",
730
- "text": "z.string().max(1000)"
731
- }
732
- }
139
+ type: 'prisma',
140
+ path: string,
141
+ overrideTypes?: Record<string, string>
733
142
  }
734
143
  ```
735
144
 
736
- ### Prisma overrideTypes
737
-
738
- ```json
145
+ ### Destination Options
146
+ ```typescript
739
147
  {
740
- "origin": {
741
- "type": "prisma",
742
- "path": "./schema.prisma",
743
- "overrideTypes": {
744
- "Json": "z.record(z.string())",
745
- "String": "z.string().min(1)"
746
- }
747
- }
748
- }
749
- ```
148
+ type: 'zod' | 'ts' | 'kysely',
149
+ folder?: string,
150
+ suffix?: string,
151
+ outFile?: string, // Kysely only
152
+ header?: string, // Custom imports
750
153
 
751
- ## Magic Comments
154
+ // Zod specific
155
+ useDateType?: boolean,
156
+ useTrim?: boolean,
157
+ nullish?: boolean,
158
+ requiredString?: boolean,
159
+ version?: 3 | 4,
752
160
 
753
- ### @zod Comments
161
+ // TypeScript specific
162
+ enumType?: 'union' | 'enum',
163
+ modelType?: 'interface' | 'type',
754
164
 
755
- You can use the `@zod` comment to override the Zod type for a specific column. This is useful when you want to add custom validation or transformation to a field.
756
-
757
- ```sql
758
- CREATE TABLE `user` (
759
- `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
760
- `name` varchar(255) NOT NULL COMMENT '@zod(z.string().min(10).max(255))',
761
- `email` varchar(255) NOT NULL COMMENT '@zod(z.string().email())',
762
- PRIMARY KEY (`id`)
763
- );
165
+ // Kysely specific
166
+ schemaName?: string // Default: 'DB'
167
+ }
764
168
  ```
765
169
 
766
- This will generate:
767
-
768
- ```typescript
769
- export const user = z.object({
770
- id: z.number().nonnegative(),
771
- name: z.string().min(10).max(255),
772
- email: z.string().email(),
773
- })
774
- ```
170
+ ### Global Options
171
+ | Option | Description |
172
+ |--------|-------------|
173
+ | `tables` | Include only specified tables |
174
+ | `views` | Include only specified views |
175
+ | `ignore` | Exclude specified tables (supports regex) |
176
+ | `ignoreViews` | Exclude specified views (supports regex) |
177
+ | `includeViews` | Process database views |
178
+ | `camelCase` | Convert to camelCase |
179
+ | `dryRun` | Return content without writing files |
180
+ | `magicComments` | Enable @zod/@ts/@kysely comments |
775
181
 
776
- ### @ts Comments
182
+ ## Magic Comments
777
183
 
778
- You can use the `@ts` comment to override the TypeScript type for a specific column. This is useful when you want to specify a more precise type for a field.
184
+ Override types for specific columns using database comments (MySQL/PostgreSQL only):
779
185
 
780
186
  ```sql
781
187
  CREATE TABLE `user` (
782
- `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
783
- `metadata` json NOT NULL COMMENT '@ts(Record<string, unknown>)',
784
- `settings` json NOT NULL COMMENT '@ts(UserSettings)',
188
+ `id` int(11) NOT NULL AUTO_INCREMENT,
189
+ `name` varchar(255) COMMENT '@zod(z.string().min(2).max(50))',
190
+ `email` varchar(255) COMMENT '@ts(EmailAddress) @kysely(string)',
191
+ `metadata` json COMMENT '@ts(UserMetadata)',
785
192
  PRIMARY KEY (`id`)
786
193
  );
787
194
  ```
788
195
 
789
- This will generate:
790
-
791
- ```typescript
792
- export interface User {
793
- id: number;
794
- metadata: Record<string, unknown>;
795
- settings: UserSettings;
796
- }
797
- ```
798
-
799
- ### @kysely Comments
196
+ **Supported Comments:**
197
+ - `@zod(...)` - Override Zod schema
198
+ - `@ts(...)` - Override TypeScript type
199
+ - `@kysely(...)` - Override Kysely type
800
200
 
801
- You can use the `@kysely` comment to override the Kysely type for a specific column. This is useful when you want to specify a more precise type for a field.
802
-
803
- ```sql
804
- CREATE TABLE `user` (
805
- `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
806
- `metadata` json NOT NULL COMMENT '@kysely(Record<string, string>)',
807
- PRIMARY KEY (`id`)
808
- );
809
- ```
201
+ ## Type Overrides
810
202
 
811
- This will generate:
203
+ Override default types globally in your origin config:
812
204
 
813
205
  ```typescript
814
- export interface UserTable {
815
- id: Generated<number>;
816
- metadata: Record<string, string>;
206
+ {
207
+ origin: {
208
+ type: 'mysql',
209
+ // ... connection config
210
+ overrideTypes: {
211
+ json: 'z.record(z.string())',
212
+ text: 'z.string().max(1000)',
213
+ decimal: 'z.number().positive()'
214
+ }
215
+ }
817
216
  }
818
217
  ```
819
218
 
820
- ## Complex TypeScript Types
821
-
822
- You can use complex TypeScript types in the `@ts`(or `@kysely`) comment:
823
-
824
- ```sql
825
- CREATE TABLE `product` (
826
- `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
827
- `variants` json NOT NULL COMMENT '@ts(Array<{ id: string; price: number; stock: number }>)',
828
- PRIMARY KEY (`id`)
829
- );
830
- ```
831
-
832
- This will generate:
833
-
834
- ```typescript
835
- export interface Product {
836
- id: number;
837
- variants: Array<{ id: string; price: number; stock: number }>;
838
- }
839
- ```
219
+ **Common Overrides:**
220
+ - **MySQL**: `json`, `text`, `decimal`, `enum`
221
+ - **PostgreSQL**: `jsonb`, `uuid`, `text`, `numeric`
222
+ - **SQLite**: `json`, `text`, `real`
223
+ - **Prisma**: `Json`, `String`, `Decimal`
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mutano",
3
3
  "type": "module",
4
- "version": "3.0.0",
4
+ "version": "3.0.1",
5
5
  "description": "Converts Prisma/MySQL/PostgreSQL/SQLite schemas to Zod/TS/Kysely interfaces",
6
6
  "author": "Alisson Cavalcante Agiani <thelinuxlich@gmail.com>",
7
7
  "license": "MIT",