sizuku 0.5.0 → 0.6.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/README.md CHANGED
@@ -2,21 +2,19 @@
2
2
 
3
3
  # Sizuku
4
4
 
5
- **[Sizuku](https://www.npmjs.com/package/sizuku)** is a tool that generates validation schemas for Zod, Valibot, ArkType, and Effect Schema, as well as ER diagrams, from [Drizzle](https://orm.drizzle.team/) schemas.
5
+ **[Sizuku](https://www.npmjs.com/package/sizuku)** is a CLI tool that generates validation schemas for Zod, Valibot, ArkType, and Effect Schema, as well as ER diagrams, from [Drizzle](https://orm.drizzle.team/) schemas.
6
6
 
7
7
  ## Features
8
8
 
9
- - 💎 Automatically generates [Zod](https://zod.dev/) schemas from your Drizzle schema
10
- - 🤖 Automatically generates [Valibot](https://valibot.dev/) schemas from your Drizzle schema
11
- - 🏹 Automatically generates [ArkType](https://arktype.io/) schemas from your Drizzle schema
12
- - ⚡ Automatically generates [Effect Schema](https://effect.website/docs/schema/introduction/) from your Drizzle schema
9
+ - 💎 Generates [Zod](https://zod.dev/) schemas from your Drizzle schema
10
+ - 🤖 Generates [Valibot](https://valibot.dev/) schemas from your Drizzle schema
11
+ - 🏹 Generates [ArkType](https://arktype.io/) schemas from your Drizzle schema
12
+ - ⚡ Generates [Effect Schema](https://effect.website/docs/schema/introduction/) from your Drizzle schema
13
13
  - 📊 Creates [Mermaid](https://mermaid.js.org/) ER diagrams
14
14
  - 📝 Generates [DBML](https://dbml.dbdiagram.io/) (Database Markup Language) files
15
- - 🖼️ Outputs ER diagrams as **PNG** images using [dbml-renderer](https://github.com/softwaretechnik-berlin/dbml-renderer)
15
+ - 🖼️ Outputs ER diagrams as **PNG** images
16
16
 
17
- ## Getting Started
18
-
19
- ### Installation
17
+ ## Installation
20
18
 
21
19
  ```bash
22
20
  npm install -D sizuku
@@ -24,130 +22,111 @@ npm install -D sizuku
24
22
 
25
23
  ## Usage
26
24
 
27
- ### Example
25
+ ```
26
+ sizuku <input> -o <output> [options]
27
+ ```
28
+
29
+ ### Options
30
+
31
+ ```
32
+ -o <path> Output file path
33
+ --zod Generate Zod validation schema
34
+ --valibot Generate Valibot validation schema
35
+ --arktype Generate ArkType validation schema
36
+ --effect Generate Effect Schema validation schema
37
+ --zod-version <version> Zod variant: 'v4' | 'mini' | '@hono/zod-openapi'
38
+ --no-export-types Do not export inferred types
39
+ --no-with-comment Do not add JSDoc comments
40
+ --no-with-relation Do not generate relation schemas
41
+ -h, --help Display help message
42
+ ```
43
+
44
+ ### Quick Start
45
+
46
+ ```sh
47
+ # Generate Zod schema
48
+ npx sizuku db/schema.ts -o zod/index.ts --zod
49
+
50
+ # Generate Valibot schema
51
+ npx sizuku db/schema.ts -o valibot/index.ts --valibot
52
+
53
+ # Generate DBML
54
+ npx sizuku db/schema.ts -o docs/schema.dbml
55
+
56
+ # Generate ER diagram PNG
57
+ npx sizuku db/schema.ts -o docs/er.png
58
+
59
+ # Generate Mermaid ER diagram
60
+ npx sizuku db/schema.ts -o docs/ER.md
61
+ ```
28
62
 
29
- Prepare schema.ts:
63
+ ## Schema Annotations
64
+
65
+ Add `///` comments to your Drizzle schema fields with library-specific annotations:
30
66
 
31
67
  ```ts
32
- import { relations } from 'drizzle-orm'
33
- import { mysqlTable, varchar } from 'drizzle-orm/mysql-core'
68
+ import { relations } from "drizzle-orm";
69
+ import { mysqlTable, varchar } from "drizzle-orm/mysql-core";
34
70
 
35
- export const user = mysqlTable('user', {
71
+ export const user = mysqlTable("user", {
36
72
  /// Primary key
37
73
  /// @z.uuid()
38
74
  /// @v.pipe(v.string(), v.uuid())
39
75
  /// @a."string.uuid"
40
76
  /// @e.Schema.UUID
41
- id: varchar('id', { length: 36 }).primaryKey(),
77
+ id: varchar("id", { length: 36 }).primaryKey(),
42
78
  /// Display name
43
79
  /// @z.string().min(1).max(50)
44
80
  /// @v.pipe(v.string(), v.minLength(1), v.maxLength(50))
45
81
  /// @a."1 <= string <= 50"
46
82
  /// @e.Schema.String.pipe(Schema.minLength(1), Schema.maxLength(50))
47
- name: varchar('name', { length: 50 }).notNull(),
48
- })
83
+ name: varchar("name", { length: 50 }).notNull(),
84
+ });
49
85
 
50
- /// @relation user.id post.userId one-to-many
51
- export const post = mysqlTable('post', {
52
- /// Primary key
86
+ export const post = mysqlTable("post", {
53
87
  /// @z.uuid()
54
88
  /// @v.pipe(v.string(), v.uuid())
55
89
  /// @a."string.uuid"
56
90
  /// @e.Schema.UUID
57
- id: varchar('id', { length: 36 }).primaryKey(),
58
- /// Article title
91
+ id: varchar("id", { length: 36 }).primaryKey(),
59
92
  /// @z.string().min(1).max(100)
60
93
  /// @v.pipe(v.string(), v.minLength(1), v.maxLength(100))
61
94
  /// @a."1 <= string <= 100"
62
95
  /// @e.Schema.String.pipe(Schema.minLength(1), Schema.maxLength(100))
63
- title: varchar('title', { length: 100 }).notNull(),
64
- /// Body content (no length limit)
65
- /// @z.string().min(1).max(65535)
66
- /// @v.pipe(v.string(), v.minLength(1), v.maxLength(65535))
67
- /// @a."1 <= string <= 65535"
68
- /// @e.Schema.String.pipe(Schema.minLength(1), Schema.maxLength(65535))
69
- content: varchar('content', { length: 65535 }).notNull(),
70
- /// Foreign key referencing User.id
96
+ title: varchar("title", { length: 100 }).notNull(),
71
97
  /// @z.uuid()
72
98
  /// @v.pipe(v.string(), v.uuid())
73
99
  /// @a."string.uuid"
74
100
  /// @e.Schema.UUID
75
- userId: varchar('user_id', { length: 36 }).notNull(),
76
- })
101
+ userId: varchar("user_id", { length: 36 })
102
+ .notNull()
103
+ .references(() => user.id),
104
+ });
77
105
 
78
106
  export const userRelations = relations(user, ({ many }) => ({
79
107
  posts: many(post),
80
- }))
108
+ }));
81
109
 
82
110
  export const postRelations = relations(post, ({ one }) => ({
83
111
  user: one(user, {
84
112
  fields: [post.userId],
85
113
  references: [user.id],
86
114
  }),
87
- }))
115
+ }));
88
116
  ```
89
117
 
90
- Prepare sizuku.config.ts:
118
+ Annotations are optional. Generators work without them (DBML/Mermaid don't need annotations at all).
91
119
 
92
- ```ts
93
- import { defineConfig } from 'sizuku/config'
94
-
95
- export default defineConfig({
96
- input: 'db/schema.ts',
97
- zod: {
98
- output: 'zod/index.ts',
99
- comment: true,
100
- type: true,
101
- zod: 'v4',
102
- relation: true,
103
- },
104
- valibot: {
105
- output: 'valibot/index.ts',
106
- comment: true,
107
- type: true,
108
- relation: true,
109
- },
110
- arktype: {
111
- output: 'arktype/index.ts',
112
- comment: true,
113
- type: true,
114
- relation: true,
115
- },
116
- effect: {
117
- output: 'effect/index.ts',
118
- comment: true,
119
- type: true,
120
- relation: true,
121
- },
122
- mermaid: {
123
- output: 'mermaid-er/ER.md',
124
- },
125
- dbml: {
126
- output: 'docs/schema.dbml',
127
- },
128
- })
129
- ```
120
+ ## Output Examples
130
121
 
131
- Run Sizuku:
122
+ ### Zod
132
123
 
133
124
  ```sh
134
- npx sizuku
125
+ npx sizuku db/schema.ts -o zod/index.ts --zod
135
126
  ```
136
127
 
137
- Output:
138
- ```
139
- 💧 Generated Zod schema at: zod/index.ts
140
- 💧 Generated Valibot schema at: valibot/index.ts
141
- 💧 Generated ArkType schema at: arktype/index.ts
142
- 💧 Generated Effect schema at: effect/index.ts
143
- 💧 Generated Mermaid ER at: mermaid-er/ER.md
144
- 💧 Generated DBML at: docs/schema.dbml
145
- ```
146
-
147
- ### Zod
148
-
149
128
  ```ts
150
- import * as z from 'zod'
129
+ import * as z from "zod";
151
130
 
152
131
  export const UserSchema = z.object({
153
132
  /**
@@ -158,44 +137,26 @@ export const UserSchema = z.object({
158
137
  * Display name
159
138
  */
160
139
  name: z.string().min(1).max(50),
161
- })
162
-
163
- export type User = z.infer<typeof UserSchema>
164
-
165
- export const PostSchema = z.object({
166
- /**
167
- * Primary key
168
- */
169
- id: z.uuid(),
170
- /**
171
- * Article title
172
- */
173
- title: z.string().min(1).max(100),
174
- /**
175
- * Body content (no length limit)
176
- */
177
- content: z.string().min(1).max(65535),
178
- /**
179
- * Foreign key referencing User.id
180
- */
181
- userId: z.uuid(),
182
- })
183
-
184
- export type Post = z.infer<typeof PostSchema>
185
-
186
- export const UserRelationsSchema = z.object({ ...UserSchema.shape, posts: z.array(PostSchema) })
140
+ });
187
141
 
188
- export type UserRelations = z.infer<typeof UserRelationsSchema>
142
+ export type User = z.infer<typeof UserSchema>;
189
143
 
190
- export const PostRelationsSchema = z.object({ ...PostSchema.shape, user: UserSchema })
144
+ export const UserRelationsSchema = z.object({
145
+ ...UserSchema.shape,
146
+ posts: z.array(PostSchema),
147
+ });
191
148
 
192
- export type PostRelations = z.infer<typeof PostRelationsSchema>
149
+ export type UserRelations = z.infer<typeof UserRelationsSchema>;
193
150
  ```
194
151
 
195
152
  ### Valibot
196
153
 
154
+ ```sh
155
+ npx sizuku db/schema.ts -o valibot/index.ts --valibot
156
+ ```
157
+
197
158
  ```ts
198
- import * as v from 'valibot'
159
+ import * as v from "valibot";
199
160
 
200
161
  export const UserSchema = v.object({
201
162
  /**
@@ -206,195 +167,131 @@ export const UserSchema = v.object({
206
167
  * Display name
207
168
  */
208
169
  name: v.pipe(v.string(), v.minLength(1), v.maxLength(50)),
209
- })
210
-
211
- export type User = v.InferInput<typeof UserSchema>
212
-
213
- export const PostSchema = v.object({
214
- /**
215
- * Primary key
216
- */
217
- id: v.pipe(v.string(), v.uuid()),
218
- /**
219
- * Article title
220
- */
221
- title: v.pipe(v.string(), v.minLength(1), v.maxLength(100)),
222
- /**
223
- * Body content (no length limit)
224
- */
225
- content: v.pipe(v.string(), v.minLength(1), v.maxLength(65535)),
226
- /**
227
- * Foreign key referencing User.id
228
- */
229
- userId: v.pipe(v.string(), v.uuid()),
230
- })
231
-
232
- export type Post = v.InferInput<typeof PostSchema>
233
-
234
- export const UserRelationsSchema = v.object({ ...UserSchema.entries, posts: v.array(PostSchema) })
170
+ });
235
171
 
236
- export type UserRelations = v.InferInput<typeof UserRelationsSchema>
172
+ export type User = v.InferOutput<typeof UserSchema>;
237
173
 
238
- export const PostRelationsSchema = v.object({ ...PostSchema.entries, user: UserSchema })
174
+ export const UserRelationsSchema = v.object({
175
+ ...UserSchema.entries,
176
+ posts: v.array(PostSchema),
177
+ });
239
178
 
240
- export type PostRelations = v.InferInput<typeof PostRelationsSchema>
179
+ export type UserRelations = v.InferOutput<typeof UserRelationsSchema>;
241
180
  ```
242
181
 
243
182
  ### ArkType
244
183
 
184
+ ```sh
185
+ npx sizuku db/schema.ts -o arktype/index.ts --arktype
186
+ ```
187
+
245
188
  ```ts
246
- import { type } from 'arktype'
189
+ import { type } from "arktype";
247
190
 
248
191
  export const UserSchema = type({
249
- /** Primary key */
250
- id: 'string.uuid',
251
- /** Display name */
252
- name: '1 <= string <= 50',
253
- })
254
-
255
- export type User = typeof UserSchema.infer
256
-
257
- export const PostSchema = type({
258
- /** Primary key */
259
- id: 'string.uuid',
260
- /** Article title */
261
- title: '1 <= string <= 100',
262
- /** Body content (no length limit) */
263
- content: '1 <= string <= 65535',
264
- /** Foreign key referencing User.id */
265
- userId: 'string.uuid',
266
- })
267
-
268
- export type Post = typeof PostSchema.infer
192
+ /**
193
+ * Primary key
194
+ */
195
+ id: "string.uuid",
196
+ /**
197
+ * Display name
198
+ */
199
+ name: "1 <= string <= 50",
200
+ });
201
+
202
+ export type User = typeof UserSchema.infer;
269
203
  ```
270
204
 
271
205
  ### Effect Schema
272
206
 
207
+ ```sh
208
+ npx sizuku db/schema.ts -o effect/index.ts --effect
209
+ ```
210
+
273
211
  ```ts
274
- import { Schema } from 'effect'
212
+ import { Schema } from "effect";
275
213
 
276
214
  export const UserSchema = Schema.Struct({
277
- /** Primary key */
215
+ /**
216
+ * Primary key
217
+ */
278
218
  id: Schema.UUID,
279
- /** Display name */
219
+ /**
220
+ * Display name
221
+ */
280
222
  name: Schema.String.pipe(Schema.minLength(1), Schema.maxLength(50)),
281
- })
223
+ });
282
224
 
283
- export type User = Schema.Schema.Type<typeof UserSchema>
225
+ export type UserEncoded = typeof UserSchema.Encoded;
226
+ ```
284
227
 
285
- export const PostSchema = Schema.Struct({
286
- /** Primary key */
287
- id: Schema.UUID,
288
- /** Article title */
289
- title: Schema.String.pipe(Schema.minLength(1), Schema.maxLength(100)),
290
- /** Body content (no length limit) */
291
- content: Schema.String.pipe(Schema.minLength(1), Schema.maxLength(65535)),
292
- /** Foreign key referencing User.id */
293
- userId: Schema.UUID,
294
- })
295
-
296
- export type Post = Schema.Schema.Type<typeof PostSchema>
228
+ ### DBML
229
+
230
+ ```sh
231
+ npx sizuku db/schema.ts -o docs/schema.dbml
232
+ ```
233
+
234
+ ```dbml
235
+ Table user {
236
+ id varchar [pk, note: 'Primary key']
237
+ name varchar [note: 'Display name']
238
+ }
239
+
240
+ Table post {
241
+ id varchar [pk]
242
+ title varchar
243
+ userId varchar
244
+ }
245
+
246
+ Ref post_userId_user_id_fk: post.userId > user.id
297
247
  ```
298
248
 
299
249
  ### Mermaid ER
300
250
 
251
+ ```sh
252
+ npx sizuku db/schema.ts -o docs/ER.md
253
+ ```
254
+
301
255
  ```mermaid
302
256
  erDiagram
303
257
  user ||--}| post : "(id) - (userId)"
304
258
  user {
305
- varchar id "(PK) Primary key"
259
+ varchar id PK "Primary key"
306
260
  varchar name "Display name"
307
261
  }
308
262
  post {
309
- varchar id "(PK) Primary key"
310
- varchar title "Article title"
311
- varchar content "Body content (no length limit)"
312
- varchar userId "Foreign key referencing User.id"
263
+ varchar id PK
264
+ varchar title
265
+ varchar userId FK
313
266
  }
314
267
  ```
315
268
 
316
- ### DBML
269
+ ## Relation Detection
317
270
 
318
- The `dbml` generator outputs a DBML schema file or ER diagram PNG depending on the file extension:
271
+ Sizuku detects relations from three sources:
319
272
 
320
- - `.dbml` extension: outputs a DBML schema file
321
- - `.png` extension: outputs an ER diagram PNG image
273
+ ### 1. `.references()` chain
322
274
 
323
- ```dbml
324
- Table user {
325
- id varchar [pk, note: 'Primary key']
326
- name varchar [note: 'Display name']
327
- }
328
-
329
- Table post {
330
- id varchar [pk, note: 'Primary key']
331
- title varchar [note: 'Article title']
332
- content varchar [note: 'Body content (no length limit)']
333
- userId varchar [note: 'Foreign key referencing User.id']
334
- }
335
-
336
- Ref post_userId_user_id_fk: post.userId > user.id
275
+ ```ts
276
+ userId: varchar("user_id").references(() => user.id);
337
277
  ```
338
278
 
339
- ## Configuration
340
-
341
- ```typescript
342
- import { defineConfig } from 'sizuku/config'
343
-
344
- export default defineConfig({
345
- // Input: Path to Drizzle schema file (must end with .ts)
346
- input: 'db/schema.ts',
347
-
348
- // Zod Schema Generator
349
- zod: {
350
- output: 'zod/index.ts', // Output file path (must end with .ts)
351
- comment: true, // Include schema documentation (default: false)
352
- type: true, // Generate TypeScript types (default: false)
353
- zod: 'v4', // Zod import: 'v4' | 'mini' | '@hono/zod-openapi' (default: 'v4')
354
- relation: true, // Generate relation schemas (default: false)
355
- },
356
-
357
- // Valibot Schema Generator
358
- valibot: {
359
- output: 'valibot/index.ts',
360
- comment: true,
361
- type: true,
362
- relation: true,
363
- },
364
-
365
- // ArkType Schema Generator
366
- arktype: {
367
- output: 'arktype/index.ts',
368
- comment: true,
369
- type: true,
370
- relation: true, // Generate relation schemas (default: false)
371
- },
372
-
373
- // Effect Schema Generator
374
- effect: {
375
- output: 'effect/index.ts',
376
- comment: true,
377
- type: true,
378
- relation: true, // Generate relation schemas (default: false)
379
- },
380
-
381
- // Mermaid ER Diagram Generator
382
- mermaid: {
383
- output: 'mermaid-er/ER.md', // Output file path
384
- },
385
-
386
- // DBML / ER Diagram PNG Generator
387
- // Use .dbml extension for DBML text, .png extension for ER diagram image
388
- dbml: {
389
- output: 'docs/schema.dbml', // Output file path (must end with .dbml or .png)
390
- },
391
- })
279
+ ### 2. `foreignKey()` constraint
280
+
281
+ ```ts
282
+ export const post = pgTable('post', { ... }, (t) => ({
283
+ fk: foreignKey({ columns: [t.userId], foreignColumns: [user.id] }),
284
+ }))
392
285
  ```
393
286
 
394
- ### ⚠️ WARNING: Potential Breaking Changes Without Notice
287
+ ### 3. `relations()` block
395
288
 
396
- This package is in active development and may introduce breaking changes without prior notice.
289
+ ```ts
290
+ export const postRelations = relations(post, ({ one }) => ({
291
+ user: one(user, { fields: [post.userId], references: [user.id] }),
292
+ }));
293
+ ```
397
294
 
398
295
  ## License
399
296
 
400
- Distributed under the MIT License. See [LICENSE](https://github.com/nakita628/sizuku?tab=MIT-1-ov-file) for more information.
297
+ Distributed under the MIT License. See [LICENSE](https://github.com/nakita628/sizuku?tab=MIT-1-ov-file) for more information.