hekireki 0.4.1 โ†’ 0.5.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.
Files changed (72) hide show
  1. package/README.md +180 -24
  2. package/dist/dbml-content-D3ioOw2D.js +151 -0
  3. package/dist/fsp-DYtOxLN_.js +68 -0
  4. package/dist/generator/arktype/index.d.ts +6 -0
  5. package/dist/generator/arktype/index.js +94 -0
  6. package/dist/generator/dbml/index.d.ts +6 -0
  7. package/dist/generator/dbml/index.js +49 -0
  8. package/dist/generator/ecto/index.d.ts +6 -3
  9. package/dist/generator/ecto/index.js +150 -13
  10. package/dist/generator/effect/index.d.ts +6 -0
  11. package/dist/generator/effect/index.js +94 -0
  12. package/dist/generator/mermaid-er/index.d.ts +6 -3
  13. package/dist/generator/mermaid-er/index.js +136 -21
  14. package/dist/generator/svg/index.d.ts +6 -0
  15. package/dist/generator/svg/index.js +74 -0
  16. package/dist/generator/valibot/index.d.ts +6 -3
  17. package/dist/generator/valibot/index.js +91 -45
  18. package/dist/generator/zod/index.d.ts +6 -3
  19. package/dist/generator/zod/index.js +98 -56
  20. package/dist/relations-CxeKj9KD.js +12 -0
  21. package/dist/utils-CXBzdZih.js +134 -0
  22. package/package.json +29 -17
  23. package/dist/generator/ecto/generator/ecto.d.ts +0 -3
  24. package/dist/generator/ecto/generator/ecto.js +0 -131
  25. package/dist/generator/ecto/utils/index.d.ts +0 -1
  26. package/dist/generator/ecto/utils/index.js +0 -1
  27. package/dist/generator/ecto/utils/prisma-type-to-ecto-type.d.ts +0 -1
  28. package/dist/generator/ecto/utils/prisma-type-to-ecto-type.js +0 -11
  29. package/dist/generator/mermaid-er/generator/er-content.d.ts +0 -8
  30. package/dist/generator/mermaid-er/generator/er-content.js +0 -23
  31. package/dist/generator/mermaid-er/generator/index.d.ts +0 -4
  32. package/dist/generator/mermaid-er/generator/index.js +0 -4
  33. package/dist/generator/mermaid-er/generator/model-fields.d.ts +0 -8
  34. package/dist/generator/mermaid-er/generator/model-fields.js +0 -25
  35. package/dist/generator/mermaid-er/generator/model-info.d.ts +0 -8
  36. package/dist/generator/mermaid-er/generator/model-info.js +0 -10
  37. package/dist/generator/mermaid-er/generator/relation-line.d.ts +0 -13
  38. package/dist/generator/mermaid-er/generator/relation-line.js +0 -14
  39. package/dist/generator/mermaid-er/helper/build-relation-line.d.ts +0 -9
  40. package/dist/generator/mermaid-er/helper/build-relation-line.js +0 -37
  41. package/dist/generator/mermaid-er/helper/extract-relations.d.ts +0 -8
  42. package/dist/generator/mermaid-er/helper/extract-relations.js +0 -22
  43. package/dist/generator/mermaid-er/utils/index.d.ts +0 -34
  44. package/dist/generator/mermaid-er/utils/index.js +0 -48
  45. package/dist/generator/valibot/generator/index.d.ts +0 -3
  46. package/dist/generator/valibot/generator/index.js +0 -3
  47. package/dist/generator/valibot/generator/schema.d.ts +0 -16
  48. package/dist/generator/valibot/generator/schema.js +0 -51
  49. package/dist/generator/valibot/generator/schemas.d.ts +0 -13
  50. package/dist/generator/valibot/generator/schemas.js +0 -17
  51. package/dist/generator/valibot/generator/valibot.d.ts +0 -9
  52. package/dist/generator/valibot/generator/valibot.js +0 -42
  53. package/dist/generator/valibot/utils/index.d.ts +0 -44
  54. package/dist/generator/valibot/utils/index.js +0 -75
  55. package/dist/generator/zod/generator/index.d.ts +0 -3
  56. package/dist/generator/zod/generator/index.js +0 -3
  57. package/dist/generator/zod/generator/schema.d.ts +0 -17
  58. package/dist/generator/zod/generator/schema.js +0 -38
  59. package/dist/generator/zod/generator/schemas.d.ts +0 -13
  60. package/dist/generator/zod/generator/schemas.js +0 -17
  61. package/dist/generator/zod/generator/zod.d.ts +0 -9
  62. package/dist/generator/zod/generator/zod.js +0 -47
  63. package/dist/generator/zod/utils/index.d.ts +0 -46
  64. package/dist/generator/zod/utils/index.js +0 -75
  65. package/dist/shared/format/index.d.ts +0 -1
  66. package/dist/shared/format/index.js +0 -9
  67. package/dist/shared/generator/index.d.ts +0 -11
  68. package/dist/shared/generator/index.js +0 -23
  69. package/dist/shared/helper/relations.d.ts +0 -7
  70. package/dist/shared/helper/relations.js +0 -5
  71. package/dist/shared/utils/index.d.ts +0 -61
  72. package/dist/shared/utils/index.js +0 -63
package/README.md CHANGED
@@ -1,16 +1,16 @@
1
1
  # Hekireki
2
2
 
3
- <p align="center">
4
- <img src="https://raw.githubusercontent.com/nakita628/hekireki/refs/heads/main/assets/img/hekireki.png"/>
5
- </p>
6
-
7
- **[Hekireki](https://www.npmjs.com/package/hekireki)** is a tool that generates validation schemas for Zod and Valibot, as well as ER diagrams, from [Prisma](https://www.prisma.io/) schemas annotated with comments.
3
+ **[Hekireki](https://www.npmjs.com/package/hekireki)** is a tool that generates validation schemas for Zod, Valibot, ArkType, and Effect Schema, as well as ER diagrams, from [Prisma](https://www.prisma.io/) schemas annotated with comments.
8
4
 
9
5
  ## Features
10
6
 
11
7
  - ๐Ÿ’Ž Automatically generates [Zod](https://zod.dev/) schemas from your Prisma schema
12
8
  - ๐Ÿค– Automatically generates [Valibot](https://valibot.dev/) schemas from your Prisma schema
13
- - ๐Ÿ“Š Creates [Mermaid](https://mermaid.js.org/) ER diagrams
9
+ - ๐Ÿน Automatically generates [ArkType](https://arktype.io/) schemas from your Prisma schema
10
+ - โšก Automatically generates [Effect Schema](https://effect.website/docs/schema/introduction/) from your Prisma schema
11
+ - ๐Ÿ“Š Creates [Mermaid](https://mermaid.js.org/) ER diagrams with PK/FK markers
12
+ - ๐Ÿ“ Generates [DBML](https://dbml.dbdiagram.io/) (Database Markup Language) files
13
+ - ๐Ÿ–ผ๏ธ Outputs ER diagrams as **PNG/SVG** images using [dbml-renderer](https://github.com/softwaretechnik-berlin/dbml-renderer)
14
14
  - ๐Ÿงช Generates [Ecto](https://hexdocs.pm/ecto/Ecto.Schema.html) schemas for Elixir projects
15
15
  โš ๏ธ Foreign key constraints are **not** included โ€” manage relationships in your application logic
16
16
 
@@ -25,13 +25,8 @@ npm install -D hekireki
25
25
  Prepare `schema.prisma`:
26
26
 
27
27
  ```prisma
28
- generator client {
29
- provider = "prisma-client-js"
30
- }
31
-
32
28
  datasource db {
33
29
  provider = "sqlite"
34
- url = env("DATABASE_URL")
35
30
  }
36
31
 
37
32
  generator Hekireki-ER {
@@ -52,42 +47,75 @@ generator Hekireki-Valibot {
52
47
  relation = true
53
48
  }
54
49
 
50
+ generator Hekireki-ArkType {
51
+ provider = "hekireki-arktype"
52
+ type = true
53
+ comment = true
54
+ }
55
+
56
+ generator Hekireki-Effect {
57
+ provider = "hekireki-effect"
58
+ type = true
59
+ comment = true
60
+ }
61
+
55
62
  generator Hekireki-Ecto {
56
63
  provider = "hekireki-ecto"
57
64
  output = "schema"
58
65
  app = "DBSchema"
59
66
  }
60
67
 
68
+ generator Hekireki-DBML {
69
+ provider = "hekireki-dbml"
70
+ }
71
+
72
+ generator Hekireki-SVG {
73
+ provider = "hekireki-svg"
74
+ output = "docs"
75
+ format = "png"
76
+ }
77
+
61
78
  model User {
62
79
  /// Primary key
63
80
  /// @z.uuid()
64
81
  /// @v.pipe(v.string(), v.uuid())
82
+ /// @a."string.uuid"
83
+ /// @e.Schema.UUID
65
84
  id String @id @default(uuid())
66
85
  /// Display name
67
86
  /// @z.string().min(1).max(50)
68
87
  /// @v.pipe(v.string(), v.minLength(1), v.maxLength(50))
88
+ /// @a."1 <= string <= 50"
89
+ /// @e.Schema.String.pipe(Schema.minLength(1), Schema.maxLength(50))
69
90
  name String
70
91
  /// One-to-many relation to Post
71
92
  posts Post[]
72
93
  }
73
94
 
74
- /// @relation User.id Post.userId one-to-many
75
95
  model Post {
76
96
  /// Primary key
77
97
  /// @z.uuid()
78
98
  /// @v.pipe(v.string(), v.uuid())
99
+ /// @a."string.uuid"
100
+ /// @e.Schema.UUID
79
101
  id String @id @default(uuid())
80
102
  /// Article title
81
103
  /// @z.string().min(1).max(100)
82
104
  /// @v.pipe(v.string(), v.minLength(1), v.maxLength(100))
105
+ /// @a."1 <= string <= 100"
106
+ /// @e.Schema.String.pipe(Schema.minLength(1), Schema.maxLength(100))
83
107
  title String
84
108
  /// Body content (no length limit)
85
109
  /// @z.string()
86
110
  /// @v.string()
111
+ /// @a."string"
112
+ /// @e.Schema.String
87
113
  content String
88
114
  /// Foreign key referencing User.id
89
115
  /// @z.uuid()
90
116
  /// @v.pipe(v.string(), v.uuid())
117
+ /// @a."string.uuid"
118
+ /// @e.Schema.UUID
91
119
  userId String
92
120
  /// Prisma relation definition
93
121
  user User @relation(fields: [userId], references: [id])
@@ -151,6 +179,7 @@ export type PostRelations = z.infer<typeof PostRelationsSchema>
151
179
  ```
152
180
 
153
181
  ## Valibot
182
+
154
183
  ```ts
155
184
  import * as v from 'valibot'
156
185
 
@@ -188,29 +217,91 @@ export const PostSchema = v.object({
188
217
 
189
218
  export type Post = v.InferInput<typeof PostSchema>
190
219
 
191
- export const UserRelationsSchema = v.object({ ...UserSchema.entries, posts: v.array(PostSchema) })
220
+ export const UserRelationsSchema = v.object({
221
+ ...UserSchema.entries,
222
+ posts: v.array(PostSchema),
223
+ })
192
224
 
193
225
  export type UserRelations = v.InferInput<typeof UserRelationsSchema>
194
226
 
195
- export const PostRelationsSchema = v.object({ ...PostSchema.entries, user: UserSchema })
227
+ export const PostRelationsSchema = v.object({
228
+ ...PostSchema.entries,
229
+ user: UserSchema,
230
+ })
196
231
 
197
232
  export type PostRelations = v.InferInput<typeof PostRelationsSchema>
198
233
  ```
199
234
 
235
+ ## ArkType
236
+
237
+ ```ts
238
+ import { type } from 'arktype'
239
+
240
+ export const UserSchema = type({
241
+ /** Primary key */
242
+ id: 'string.uuid',
243
+ /** Display name */
244
+ name: '1 <= string <= 50',
245
+ })
246
+
247
+ export type User = typeof UserSchema.infer
248
+
249
+ export const PostSchema = type({
250
+ /** Primary key */
251
+ id: 'string.uuid',
252
+ /** Article title */
253
+ title: '1 <= string <= 100',
254
+ /** Body content (no length limit) */
255
+ content: 'string',
256
+ /** Foreign key referencing User.id */
257
+ userId: 'string.uuid',
258
+ })
259
+
260
+ export type Post = typeof PostSchema.infer
261
+ ```
262
+
263
+ ## Effect Schema
264
+
265
+ ```ts
266
+ import { Schema } from 'effect'
267
+
268
+ export const UserSchema = Schema.Struct({
269
+ /** Primary key */
270
+ id: Schema.UUID,
271
+ /** Display name */
272
+ name: Schema.String.pipe(Schema.minLength(1), Schema.maxLength(50)),
273
+ })
274
+
275
+ export type User = Schema.Schema.Type<typeof UserSchema>
276
+
277
+ export const PostSchema = Schema.Struct({
278
+ /** Primary key */
279
+ id: Schema.UUID,
280
+ /** Article title */
281
+ title: Schema.String.pipe(Schema.minLength(1), Schema.maxLength(100)),
282
+ /** Body content (no length limit) */
283
+ content: Schema.String,
284
+ /** Foreign key referencing User.id */
285
+ userId: Schema.UUID,
286
+ })
287
+
288
+ export type Post = Schema.Schema.Type<typeof PostSchema>
289
+ ```
290
+
200
291
  ## Mermaid
201
292
 
202
293
  ```mermaid
203
294
  erDiagram
204
295
  User ||--}| Post : "(id) - (userId)"
205
296
  User {
206
- String id "Primary key"
207
- String name "Display name"
297
+ string id PK "Primary key"
298
+ string name "Display name"
208
299
  }
209
300
  Post {
210
- String id "Primary key"
211
- String title "Article title"
212
- String content "Body content (no length limit)"
213
- String userId "Foreign key referencing User.id"
301
+ string id PK "Primary key"
302
+ string title "Article title"
303
+ string content "Body content (no length limit)"
304
+ string userId FK "Foreign key referencing User.id"
214
305
  }
215
306
  ```
216
307
 
@@ -254,6 +345,32 @@ defmodule DBSchema.Post do
254
345
  end
255
346
  ```
256
347
 
348
+ ## DBML
349
+
350
+ ```dbml
351
+ Table User {
352
+ id String [pk, note: 'Primary key']
353
+ name String [not null, note: 'Display name']
354
+ posts Post [not null, note: 'One-to-many relation to Post']
355
+ }
356
+
357
+ Table Post {
358
+ id String [pk, note: 'Primary key']
359
+ title String [not null, note: 'Article title']
360
+ content String [not null, note: 'Body content (no length limit)']
361
+ userId String [not null, note: 'Foreign key referencing User.id']
362
+ user User [not null, note: 'Prisma relation definition']
363
+ }
364
+
365
+ Ref Post_userId_fk: Post.userId > User.id
366
+ ```
367
+
368
+ ## PNG/SVG
369
+
370
+ The `hekireki-svg` generator outputs ER diagrams as PNG or SVG images using [dbml-renderer](https://github.com/softwaretechnik-berlin/dbml-renderer).
371
+
372
+ Output: `docs/er-diagram.png`
373
+
257
374
  ## Configuration
258
375
 
259
376
  ### Zod Generator Options
@@ -277,6 +394,24 @@ end
277
394
  | `comment` | `boolean` | `false` | Include schema documentation |
278
395
  | `relation` | `boolean` | `false` | Generate relation schemas |
279
396
 
397
+ ### ArkType Generator Options
398
+
399
+ | Option | Type | Default | Description |
400
+ |--------------|-----------|-------------------------------------|--------------------------------------------------|
401
+ | `output` | `string` | `./arktype` | Output directory |
402
+ | `file` | `string` | `index.ts` | File Name |
403
+ | `type` | `boolean` | `false` | Generate TypeScript types |
404
+ | `comment` | `boolean` | `false` | Include schema documentation |
405
+
406
+ ### Effect Schema Generator Options
407
+
408
+ | Option | Type | Default | Description |
409
+ |--------------|-----------|-------------------------------------|--------------------------------------------------|
410
+ | `output` | `string` | `./effect` | Output directory |
411
+ | `file` | `string` | `index.ts` | File Name |
412
+ | `type` | `boolean` | `false` | Generate TypeScript types |
413
+ | `comment` | `boolean` | `false` | Include schema documentation |
414
+
280
415
  ### Mermaid ER Generator Options
281
416
 
282
417
  | Option | Type | Default | Description |
@@ -289,13 +424,34 @@ end
289
424
  | Option | Type | Default | Description |
290
425
  |--------------|-----------|-------------------------------------|--------------------------------------------------|
291
426
  | `output` | `string` | `./ecto` | Output directory |
292
- | `app` | `string` | `MyApp` | App Name |
427
+ | `app` | `string` | `MyApp` | App Name |
428
+
429
+ ### DBML Generator Options
430
+
431
+ | Option | Type | Default | Description |
432
+ |--------------|-----------|-------------------------------------|--------------------------------------------------|
433
+ | `output` | `string` | `./dbml` | Output directory |
434
+ | `file` | `string` | `schema.dbml` | File Name |
435
+
436
+ ### SVG Generator Options
437
+
438
+ | Option | Type | Default | Description |
439
+ |--------------|-----------|-------------------------------------|--------------------------------------------------|
440
+ | `output` | `string` | `./docs` | Output directory |
441
+ | `file` | `string` | `er-diagram` | File Name (without extension) |
442
+ | `format` | `string` | `png` | Output format (`png`, `svg`, or `dot`) |
293
443
 
294
- โš ๏ธ WARNING: Potential Breaking Changes Without Notice
444
+ ## Annotation Prefixes
295
445
 
296
- This project is in **early development** and being maintained by a developer with about 2 years of experience. While I'm doing my best to create a useful tool:
446
+ Each generator uses a specific annotation prefix in Prisma schema comments:
297
447
 
448
+ | Generator | Prefix | Example |
449
+ |----------------|--------|------------------------------------------------------------|
450
+ | Zod | `@z.` | `/// @z.uuid()` |
451
+ | Valibot | `@v.` | `/// @v.pipe(v.string(), v.uuid())` |
452
+ | ArkType | `@a.` | `/// @a."string.uuid"` |
453
+ | Effect Schema | `@e.` | `/// @e.Schema.UUID` |
298
454
 
299
455
  ## License
300
456
 
301
- Distributed under the MIT License. See [LICENSE](https://github.com/nakita628/hekireki?tab=MIT-1-ov-file) for more information.
457
+ Distributed under the MIT License. See [LICENSE](https://github.com/nakita628/hekireki?tab=MIT-1-ov-file) for more information.
@@ -0,0 +1,151 @@
1
+ import { escapeNote, formatConstraints, generateEnum, generateIndex, generateRef, quote } from "utils-lab";
2
+
3
+ //#region src/generator/dbml/generator/dbml-content.ts
4
+ /**
5
+ * Strip validation annotations (@z.*, @v.*, @a.*, @e.*) and relation annotations (@relation) from documentation
6
+ */
7
+ function stripAnnotations(doc) {
8
+ if (!doc) return void 0;
9
+ const result = doc.split("\n").filter((line) => {
10
+ const trimmed = line.trim();
11
+ return !trimmed.startsWith("@z.") && !trimmed.startsWith("@v.") && !trimmed.startsWith("@a.") && !trimmed.startsWith("@e.") && !trimmed.startsWith("@relation");
12
+ }).join("\n").trim();
13
+ return result.length > 0 ? result : void 0;
14
+ }
15
+ /**
16
+ * Convert Prisma field to DBMLColumn
17
+ */
18
+ function toDBMLColumn(field, models, mapToDbSchema) {
19
+ let fieldType = field.type;
20
+ if (mapToDbSchema) {
21
+ const relatedModel = models.find((m) => m.name === field.type);
22
+ if (relatedModel?.dbName) fieldType = relatedModel.dbName;
23
+ }
24
+ if (field.isList && !field.relationName) fieldType = `${fieldType}[]`;
25
+ let defaultValue;
26
+ const defaultDef = field.default;
27
+ if (defaultDef?.name === "autoincrement") {} else if (defaultDef?.name === "now") defaultValue = "`now()`";
28
+ else if (field.hasDefaultValue && typeof field.default !== "object") if (field.type === "String" || field.type === "Json" || field.kind === "enum") defaultValue = `'${field.default}'`;
29
+ else defaultValue = String(field.default);
30
+ return {
31
+ name: field.name,
32
+ type: fieldType,
33
+ isPrimaryKey: field.isId,
34
+ isIncrement: defaultDef?.name === "autoincrement",
35
+ isUnique: field.isUnique,
36
+ isNotNull: field.isRequired && !field.isId,
37
+ defaultValue,
38
+ note: stripAnnotations(field.documentation)
39
+ };
40
+ }
41
+ /**
42
+ * Generate custom column line with Prisma-specific formatting
43
+ */
44
+ function generatePrismaColumn(column) {
45
+ const constraints = [];
46
+ if (column.isPrimaryKey) constraints.push("pk");
47
+ if (column.isIncrement) constraints.push("increment");
48
+ if (column.defaultValue !== void 0) constraints.push(`default: ${column.defaultValue}`);
49
+ if (column.isUnique) constraints.push("unique");
50
+ if (column.isNotNull) constraints.push("not null");
51
+ if (column.note) constraints.push(`note: ${quote(column.note)}`);
52
+ return ` ${column.name} ${column.type}${formatConstraints(constraints)}`;
53
+ }
54
+ /**
55
+ * Generate table indexes block
56
+ */
57
+ function generateTableIndexes(model) {
58
+ const indexes = [];
59
+ const primaryFields = model.primaryKey?.fields;
60
+ if (primaryFields && primaryFields.length > 0) indexes.push({
61
+ columns: primaryFields,
62
+ isPrimaryKey: true
63
+ });
64
+ for (const composite of model.uniqueFields) if (composite.length > 1) indexes.push({
65
+ columns: composite,
66
+ isUnique: true
67
+ });
68
+ return indexes;
69
+ }
70
+ /**
71
+ * Generate table definitions
72
+ */
73
+ function generateTables(models, mapToDbSchema = false, includeRelationFields = true) {
74
+ return models.map((model) => {
75
+ const modelName = mapToDbSchema && model.dbName ? model.dbName : model.name;
76
+ const columnLines = (includeRelationFields ? model.fields : model.fields.filter((field) => !field.relationName)).map((field) => toDBMLColumn(field, models, mapToDbSchema)).map(generatePrismaColumn).join("\n");
77
+ const indexes = generateTableIndexes(model);
78
+ const indexBlock = indexes.length > 0 ? `\n\n indexes {\n${indexes.map(generateIndex).join("\n")}\n }` : "";
79
+ const strippedNote = stripAnnotations(model.documentation);
80
+ return `Table ${modelName} {\n${columnLines}${indexBlock}${strippedNote ? `\n\n Note: ${quote(escapeNote(strippedNote))}` : ""}\n}`;
81
+ });
82
+ }
83
+ /**
84
+ * Generate enum definitions
85
+ */
86
+ function generateEnums(enums) {
87
+ return enums.map((e) => {
88
+ return generateEnum({
89
+ name: e.name,
90
+ values: e.values.map((v) => v.name)
91
+ });
92
+ });
93
+ }
94
+ /**
95
+ * Get relation operator based on cardinality
96
+ */
97
+ function getRelationOperator(models, from, to) {
98
+ return (models.find((m) => m.name === to)?.fields.find((f) => f.type === from))?.isList ? ">" : "-";
99
+ }
100
+ /**
101
+ * Combine keys for composite foreign keys
102
+ */
103
+ function combineKeys(keys) {
104
+ return keys.length > 1 ? `(${keys.join(", ")})` : keys[0];
105
+ }
106
+ /**
107
+ * Generate foreign key references
108
+ */
109
+ function generateRelations(models, mapToDbSchema = false) {
110
+ const refs = [];
111
+ for (const model of models) {
112
+ const relFields = model.fields.filter((field) => field.relationName && field.relationToFields?.length && field.relationFromFields?.length);
113
+ for (const field of relFields) {
114
+ const relationFrom = model.name;
115
+ const relationTo = field.type;
116
+ const operator = getRelationOperator(models, relationFrom, relationTo);
117
+ const relationFromName = mapToDbSchema && model.dbName ? model.dbName : model.name;
118
+ const relatedModel = models.find((m) => m.name === relationTo);
119
+ const relationToName = mapToDbSchema && relatedModel?.dbName ? relatedModel.dbName : relationTo;
120
+ const fromColumn = combineKeys(field.relationFromFields ?? []);
121
+ const toColumn = combineKeys(field.relationToFields ?? []);
122
+ const ref = {
123
+ name: `${relationFromName}_${fromColumn}_fk`,
124
+ fromTable: relationFromName,
125
+ fromColumn,
126
+ toTable: relationToName,
127
+ toColumn,
128
+ type: operator,
129
+ onDelete: field.relationOnDelete
130
+ };
131
+ refs.push(generateRef(ref));
132
+ }
133
+ }
134
+ return refs;
135
+ }
136
+ /**
137
+ * Generate complete DBML content from Prisma DMMF
138
+ */
139
+ function dbmlContent(datamodel, mapToDbSchema = false, includeRelationFields = true) {
140
+ const tables = generateTables(datamodel.models, mapToDbSchema, includeRelationFields);
141
+ const enums = generateEnums(datamodel.enums);
142
+ const refs = generateRelations(datamodel.models, mapToDbSchema);
143
+ return [
144
+ ...enums,
145
+ ...tables,
146
+ ...refs
147
+ ].join("\n\n");
148
+ }
149
+
150
+ //#endregion
151
+ export { dbmlContent as t };
@@ -0,0 +1,68 @@
1
+ import fsp from "node:fs/promises";
2
+
3
+ //#region src/shared/fsp/index.ts
4
+ /**
5
+ * Creates a directory if it does not already exist.
6
+ *
7
+ * @param dir - Directory path to create.
8
+ * @returns A `Result` that is `ok` on success, otherwise an error message.
9
+ */
10
+ async function mkdir(dir) {
11
+ try {
12
+ await fsp.mkdir(dir, { recursive: true });
13
+ return {
14
+ ok: true,
15
+ value: void 0
16
+ };
17
+ } catch (e) {
18
+ return {
19
+ ok: false,
20
+ error: e instanceof Error ? e.message : String(e)
21
+ };
22
+ }
23
+ }
24
+ /**
25
+ * Writes UTF-8 text to a file, creating it if necessary.
26
+ *
27
+ * @param path - File path to write.
28
+ * @param data - Text data to write.
29
+ * @returns A `Result` that is `ok` on success, otherwise an error message.
30
+ */
31
+ async function writeFile(path, data) {
32
+ try {
33
+ await fsp.writeFile(path, data, "utf-8");
34
+ return {
35
+ ok: true,
36
+ value: void 0
37
+ };
38
+ } catch (e) {
39
+ return {
40
+ ok: false,
41
+ error: e instanceof Error ? e.message : String(e)
42
+ };
43
+ }
44
+ }
45
+ /**
46
+ * Writes binary data to a file, creating it if necessary.
47
+ *
48
+ * @param path - File path to write.
49
+ * @param data - Binary data to write.
50
+ * @returns A `Result` that is `ok` on success, otherwise an error message.
51
+ */
52
+ async function writeFileBinary(path, data) {
53
+ try {
54
+ await fsp.writeFile(path, data);
55
+ return {
56
+ ok: true,
57
+ value: void 0
58
+ };
59
+ } catch (e) {
60
+ return {
61
+ ok: false,
62
+ error: e instanceof Error ? e.message : String(e)
63
+ };
64
+ }
65
+ }
66
+
67
+ //#endregion
68
+ export { writeFile as n, writeFileBinary as r, mkdir as t };
@@ -0,0 +1,6 @@
1
+ import { GeneratorOptions } from "@prisma/generator-helper";
2
+
3
+ //#region src/generator/arktype/index.d.ts
4
+ declare const onGenerate: (options: GeneratorOptions) => Promise<void>;
5
+ //#endregion
6
+ export { onGenerate };
@@ -0,0 +1,94 @@
1
+ #!/usr/bin/env node
2
+ import { a as getString, i as getBool, n as validationSchemas, o as fmt, r as parseDocumentWithoutAnnotations, t as schemaFromFields } from "../../utils-CXBzdZih.js";
3
+ import { n as writeFile, t as mkdir } from "../../fsp-DYtOxLN_.js";
4
+ import path from "node:path";
5
+ import pkg from "@prisma/generator-helper";
6
+ import { makeValidationExtractor } from "utils-lab";
7
+
8
+ //#region src/generator/arktype/generator/schema.ts
9
+ /**
10
+ * Generate ArkType schema
11
+ * @param modelName - The name of the model
12
+ * @param fields - The fields of the model
13
+ * @returns The generated ArkType schema
14
+ */
15
+ function schema(modelName, fields) {
16
+ return `export const ${modelName}Schema = type({\n${fields}\n})`;
17
+ }
18
+
19
+ //#endregion
20
+ //#region src/generator/arktype/generator/schemas.ts
21
+ /**
22
+ * Generate properties for ArkType schema.
23
+ */
24
+ function arktypePropertiesGenerator(fields, comment) {
25
+ return fields.map((field) => {
26
+ return `${comment && field.comment.length > 0 ? `${field.comment.map((c) => ` /** ${c} */`).join("\n")}\n` : ""} ${field.fieldName}: ${field.validation ?? "\"unknown\""},`;
27
+ }).join("\n");
28
+ }
29
+ /**
30
+ * Creates ArkType schemas from model fields.
31
+ *
32
+ * @param modelFields - The fields of the model
33
+ * @param comment - Whether to include comments in the generated code
34
+ * @returns The generated ArkType schemas
35
+ */
36
+ function schemas(modelFields, comment) {
37
+ return schemaFromFields(modelFields, comment, schema, arktypePropertiesGenerator);
38
+ }
39
+
40
+ //#endregion
41
+ //#region src/generator/arktype/generator/arktype.ts
42
+ /**
43
+ * Generate ArkType infer type statement.
44
+ * @param modelName - The name of the model
45
+ * @returns The generated type inference statement
46
+ */
47
+ function makeArktypeInfer(modelName) {
48
+ return `export type ${modelName} = typeof ${modelName}Schema.infer`;
49
+ }
50
+ /**
51
+ * Creates ArkType schemas and types from models.
52
+ *
53
+ * @param models - The models to generate the ArkType schemas and types for
54
+ * @param type - Whether to generate types
55
+ * @param comment - Whether to include comments in the generated code
56
+ * @returns The generated ArkType schemas and types
57
+ */
58
+ function arktype(models, type, comment) {
59
+ return validationSchemas(models, type, comment, {
60
+ importStatement: `import { type } from 'arktype'`,
61
+ annotationPrefix: "@a.",
62
+ parseDocument: parseDocumentWithoutAnnotations,
63
+ extractValidation: makeValidationExtractor("@a."),
64
+ inferType: makeArktypeInfer,
65
+ schemas
66
+ });
67
+ }
68
+
69
+ //#endregion
70
+ //#region src/generator/arktype/index.ts
71
+ const { generatorHandler } = pkg;
72
+ const emit = async (options) => {
73
+ const outDir = options.generator.output?.value ?? "./arktype";
74
+ const file = getString(options.generator.config?.file, "index.ts") ?? "index.ts";
75
+ const fmtResult = await fmt(arktype(options.dmmf.datamodel.models, getBool(options.generator.config?.type), getBool(options.generator.config?.comment)));
76
+ if (!fmtResult.ok) throw new Error(`Format error: ${fmtResult.error}`);
77
+ const mkdirResult = await mkdir(outDir);
78
+ if (!mkdirResult.ok) throw new Error(`Failed to create directory: ${mkdirResult.error}`);
79
+ const writeResult = await writeFile(path.join(outDir, file), fmtResult.value);
80
+ if (!writeResult.ok) throw new Error(`Failed to write file: ${writeResult.error}`);
81
+ };
82
+ const onGenerate = (options) => emit(options);
83
+ generatorHandler({
84
+ onManifest() {
85
+ return {
86
+ defaultOutput: "./arktype/",
87
+ prettyName: "Hekireki-ArkType"
88
+ };
89
+ },
90
+ onGenerate
91
+ });
92
+
93
+ //#endregion
94
+ export { onGenerate };
@@ -0,0 +1,6 @@
1
+ import { GeneratorOptions } from "@prisma/generator-helper";
2
+
3
+ //#region src/generator/dbml/index.d.ts
4
+ declare function main(options: GeneratorOptions): Promise<void>;
5
+ //#endregion
6
+ export { main };