hekireki 0.4.2 โ†’ 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 -20
  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,12 +1,16 @@
1
1
  # Hekireki
2
2
 
3
- **[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.
4
4
 
5
5
  ## Features
6
6
 
7
7
  - ๐Ÿ’Ž Automatically generates [Zod](https://zod.dev/) schemas from your Prisma schema
8
8
  - ๐Ÿค– Automatically generates [Valibot](https://valibot.dev/) schemas from your Prisma schema
9
- - ๐Ÿ“Š 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)
10
14
  - ๐Ÿงช Generates [Ecto](https://hexdocs.pm/ecto/Ecto.Schema.html) schemas for Elixir projects
11
15
  โš ๏ธ Foreign key constraints are **not** included โ€” manage relationships in your application logic
12
16
 
@@ -21,13 +25,8 @@ npm install -D hekireki
21
25
  Prepare `schema.prisma`:
22
26
 
23
27
  ```prisma
24
- generator client {
25
- provider = "prisma-client-js"
26
- }
27
-
28
28
  datasource db {
29
29
  provider = "sqlite"
30
- url = env("DATABASE_URL")
31
30
  }
32
31
 
33
32
  generator Hekireki-ER {
@@ -48,42 +47,75 @@ generator Hekireki-Valibot {
48
47
  relation = true
49
48
  }
50
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
+
51
62
  generator Hekireki-Ecto {
52
63
  provider = "hekireki-ecto"
53
64
  output = "schema"
54
65
  app = "DBSchema"
55
66
  }
56
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
+
57
78
  model User {
58
79
  /// Primary key
59
80
  /// @z.uuid()
60
81
  /// @v.pipe(v.string(), v.uuid())
82
+ /// @a."string.uuid"
83
+ /// @e.Schema.UUID
61
84
  id String @id @default(uuid())
62
85
  /// Display name
63
86
  /// @z.string().min(1).max(50)
64
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))
65
90
  name String
66
91
  /// One-to-many relation to Post
67
92
  posts Post[]
68
93
  }
69
94
 
70
- /// @relation User.id Post.userId one-to-many
71
95
  model Post {
72
96
  /// Primary key
73
97
  /// @z.uuid()
74
98
  /// @v.pipe(v.string(), v.uuid())
99
+ /// @a."string.uuid"
100
+ /// @e.Schema.UUID
75
101
  id String @id @default(uuid())
76
102
  /// Article title
77
103
  /// @z.string().min(1).max(100)
78
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))
79
107
  title String
80
108
  /// Body content (no length limit)
81
109
  /// @z.string()
82
110
  /// @v.string()
111
+ /// @a."string"
112
+ /// @e.Schema.String
83
113
  content String
84
114
  /// Foreign key referencing User.id
85
115
  /// @z.uuid()
86
116
  /// @v.pipe(v.string(), v.uuid())
117
+ /// @a."string.uuid"
118
+ /// @e.Schema.UUID
87
119
  userId String
88
120
  /// Prisma relation definition
89
121
  user User @relation(fields: [userId], references: [id])
@@ -147,6 +179,7 @@ export type PostRelations = z.infer<typeof PostRelationsSchema>
147
179
  ```
148
180
 
149
181
  ## Valibot
182
+
150
183
  ```ts
151
184
  import * as v from 'valibot'
152
185
 
@@ -184,29 +217,91 @@ export const PostSchema = v.object({
184
217
 
185
218
  export type Post = v.InferInput<typeof PostSchema>
186
219
 
187
- 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
+ })
188
224
 
189
225
  export type UserRelations = v.InferInput<typeof UserRelationsSchema>
190
226
 
191
- export const PostRelationsSchema = v.object({ ...PostSchema.entries, user: UserSchema })
227
+ export const PostRelationsSchema = v.object({
228
+ ...PostSchema.entries,
229
+ user: UserSchema,
230
+ })
192
231
 
193
232
  export type PostRelations = v.InferInput<typeof PostRelationsSchema>
194
233
  ```
195
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
+
196
291
  ## Mermaid
197
292
 
198
293
  ```mermaid
199
294
  erDiagram
200
295
  User ||--}| Post : "(id) - (userId)"
201
296
  User {
202
- String id "Primary key"
203
- String name "Display name"
297
+ string id PK "Primary key"
298
+ string name "Display name"
204
299
  }
205
300
  Post {
206
- String id "Primary key"
207
- String title "Article title"
208
- String content "Body content (no length limit)"
209
- 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"
210
305
  }
211
306
  ```
212
307
 
@@ -250,6 +345,32 @@ defmodule DBSchema.Post do
250
345
  end
251
346
  ```
252
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
+
253
374
  ## Configuration
254
375
 
255
376
  ### Zod Generator Options
@@ -273,6 +394,24 @@ end
273
394
  | `comment` | `boolean` | `false` | Include schema documentation |
274
395
  | `relation` | `boolean` | `false` | Generate relation schemas |
275
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
+
276
415
  ### Mermaid ER Generator Options
277
416
 
278
417
  | Option | Type | Default | Description |
@@ -285,13 +424,34 @@ end
285
424
  | Option | Type | Default | Description |
286
425
  |--------------|-----------|-------------------------------------|--------------------------------------------------|
287
426
  | `output` | `string` | `./ecto` | Output directory |
288
- | `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`) |
289
443
 
290
- โš ๏ธ WARNING: Potential Breaking Changes Without Notice
444
+ ## Annotation Prefixes
291
445
 
292
- 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:
293
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` |
294
454
 
295
455
  ## License
296
456
 
297
- 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 };
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env node
2
+ import { n as writeFile, t as mkdir } from "../../fsp-DYtOxLN_.js";
3
+ import { t as dbmlContent } from "../../dbml-content-D3ioOw2D.js";
4
+ import pkg from "@prisma/generator-helper";
5
+
6
+ //#region src/generator/dbml/index.ts
7
+ const { generatorHandler } = pkg;
8
+ /**
9
+ * Get string value from config
10
+ */
11
+ function getStringValue(value) {
12
+ if (value === void 0) return void 0;
13
+ return Array.isArray(value) ? value[0] : value;
14
+ }
15
+ /**
16
+ * Get boolean option from config
17
+ */
18
+ function getBoolOption(config, key, defaultValue) {
19
+ const value = getStringValue(config[key]);
20
+ if (value === void 0) return defaultValue;
21
+ return value.toLowerCase() !== "false";
22
+ }
23
+ async function main(options) {
24
+ const { config } = options.generator;
25
+ const mapToDbSchema = getBoolOption(config, "mapToDbSchema", true);
26
+ const includeRelationFields = getBoolOption(config, "includeRelationFields", true);
27
+ const content = dbmlContent(options.dmmf.datamodel, mapToDbSchema, includeRelationFields);
28
+ const output = options.generator.output?.value ?? "./dbml";
29
+ const file = getStringValue(config.file) ?? "schema.dbml";
30
+ const isOutputFile = output.includes(".");
31
+ const outputDir = isOutputFile ? "." : output;
32
+ const outputFile = isOutputFile ? output : `${output}/${file}`;
33
+ const mkdirResult = await mkdir(outputDir);
34
+ if (!mkdirResult.ok) throw new Error(`Failed to create directory: ${mkdirResult.error}`);
35
+ const writeResult = await writeFile(outputFile, content);
36
+ if (!writeResult.ok) throw new Error(`Failed to write file: ${writeResult.error}`);
37
+ }
38
+ generatorHandler({
39
+ onManifest() {
40
+ return {
41
+ defaultOutput: "./dbml",
42
+ prettyName: "Hekireki-DBML"
43
+ };
44
+ },
45
+ onGenerate: main
46
+ });
47
+
48
+ //#endregion
49
+ export { main };