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
@@ -1,53 +1,99 @@
1
1
  #!/usr/bin/env node
2
- import fsp from 'node:fs/promises';
3
- import path from 'node:path';
4
- import pkg from '@prisma/generator-helper';
5
- import { fmt } from '../../shared/format/index.js';
6
- import { collectRelationProps } from '../../shared/helper/relations.js';
7
- import { buildValibotRelations } from './generator/schema.js';
8
- import { valibot } from './generator/valibot.js';
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 { t as collectRelationProps } from "../../relations-CxeKj9KD.js";
5
+ import path from "node:path";
6
+ import pkg from "@prisma/generator-helper";
7
+ import { makePropertiesGenerator, makeValibotInfer, makeValidationExtractor } from "utils-lab";
8
+
9
+ //#region src/generator/valibot/generator/schema.ts
10
+ function buildValibotRelations(model, relProps, options) {
11
+ if (relProps.length === 0) return null;
12
+ const fields = `${` ...${model.name}Schema.entries,`}\n${relProps.map((r) => ` ${r.key}: ${r.isMany ? `v.array(${r.targetModel}Schema)` : `${r.targetModel}Schema`},`).join("\n")}`;
13
+ const typeLine = options?.includeType ? `\n\nexport type ${model.name}Relations = v.InferInput<typeof ${model.name}RelationsSchema>` : "";
14
+ return `export const ${model.name}RelationsSchema = v.object({\n${fields}\n})${typeLine}`;
15
+ }
16
+ /**
17
+ * Generate Valibot schema
18
+ * @param modelName - The name of the model
19
+ * @param fields - The fields of the model
20
+ * @returns The generated Valibot schema
21
+ */
22
+ function schema(modelName, fields) {
23
+ return `export const ${modelName}Schema = v.object({\n${fields}\n})`;
24
+ }
25
+
26
+ //#endregion
27
+ //#region src/generator/valibot/generator/schemas.ts
28
+ /**
29
+ * Creates Valibot schemas from model fields.
30
+ *
31
+ * @param modelFields - The fields of the model
32
+ * @param comment - Whether to include comments in the generated code
33
+ * @returns The generated Valibot schemas
34
+ */
35
+ function schemas(modelFields, comment) {
36
+ return schemaFromFields(modelFields, comment, schema, makePropertiesGenerator("v"));
37
+ }
38
+
39
+ //#endregion
40
+ //#region src/generator/valibot/generator/valibot.ts
41
+ /**
42
+ * Creates Valibot schemas and types from models.
43
+ *
44
+ * @param models - The models to generate the Valibot schemas and types for
45
+ * @param type - Whether to generate types
46
+ * @param comment - Whether to include comments in the generated code
47
+ * @returns The generated Valibot schemas and types
48
+ */
49
+ function valibot(models, type, comment) {
50
+ return validationSchemas(models, type, comment, {
51
+ importStatement: `import * as v from 'valibot'`,
52
+ annotationPrefix: "@v.",
53
+ parseDocument: parseDocumentWithoutAnnotations,
54
+ extractValidation: makeValidationExtractor("@v."),
55
+ inferType: makeValibotInfer,
56
+ schemas
57
+ });
58
+ }
59
+
60
+ //#endregion
61
+ //#region src/generator/valibot/index.ts
9
62
  const { generatorHandler } = pkg;
10
63
  const buildRelationsOnly = (dmmf, includeType) => {
11
- const models = dmmf.datamodel.models;
12
- const relIndex = collectRelationProps(models);
13
- const relByModel = relIndex.reduce((acc, r) => {
14
- if (!acc[r.model])
15
- acc[r.model] = [];
16
- acc[r.model].push(r);
17
- return acc;
18
- }, {});
19
- return models
20
- .map((model) => buildValibotRelations(model, (relByModel[model.name] ?? []).map(({ key, targetModel, isMany }) => ({
21
- key,
22
- targetModel,
23
- isMany,
24
- })), { includeType }))
25
- .filter((code) => Boolean(code))
26
- .join('\n\n');
64
+ const models = dmmf.datamodel.models;
65
+ const relIndex = collectRelationProps(models);
66
+ const relByModel = {};
67
+ for (const r of relIndex) {
68
+ const existing = relByModel[r.model] ?? [];
69
+ relByModel[r.model] = [...existing, r];
70
+ }
71
+ return models.map((model) => buildValibotRelations(model, (relByModel[model.name] ?? []).map(({ key, targetModel, isMany }) => ({
72
+ key,
73
+ targetModel,
74
+ isMany
75
+ })), { includeType })).filter((code) => Boolean(code)).join("\n\n");
27
76
  };
28
- const getString = (v, fallback) => typeof v === 'string' ? v : Array.isArray(v) ? (v[0] ?? fallback) : fallback;
29
- const getBool = (v, fallback = false) => v === true || v === 'true' || (Array.isArray(v) && v[0] === 'true') ? true : fallback;
30
77
  const emit = async (options, enableRelation) => {
31
- const outDir = options.generator.output?.value ?? './valibot';
32
- const file = getString(options.generator.config?.file, 'index.ts') ?? 'index.ts';
33
- const base = valibot(options.dmmf.datamodel.models, getBool(options.generator.config?.type), getBool(options.generator.config?.comment));
34
- const relations = enableRelation
35
- ? buildRelationsOnly(options.dmmf, getBool(options.generator.config?.type))
36
- : '';
37
- const full = [base, relations].filter(Boolean).join('\n\n');
38
- const code = await fmt(full);
39
- await fsp.mkdir(outDir, { recursive: true });
40
- await fsp.writeFile(path.join(outDir, file), code, 'utf8');
78
+ const outDir = options.generator.output?.value ?? "./valibot";
79
+ const file = getString(options.generator.config?.file, "index.ts") ?? "index.ts";
80
+ const fmtResult = await fmt([valibot(options.dmmf.datamodel.models, getBool(options.generator.config?.type), getBool(options.generator.config?.comment)), enableRelation ? buildRelationsOnly(options.dmmf, getBool(options.generator.config?.type)) : ""].filter(Boolean).join("\n\n"));
81
+ if (!fmtResult.ok) throw new Error(`Format error: ${fmtResult.error}`);
82
+ const mkdirResult = await mkdir(outDir);
83
+ if (!mkdirResult.ok) throw new Error(`Failed to create directory: ${mkdirResult.error}`);
84
+ const writeResult = await writeFile(path.join(outDir, file), fmtResult.value);
85
+ if (!writeResult.ok) throw new Error(`Failed to write file: ${writeResult.error}`);
41
86
  };
42
- export const onGenerate = (options) => emit(options, options.generator.config?.relation === 'true' ||
43
- (Array.isArray(options.generator.config?.relation) &&
44
- options.generator.config?.relation[0] === 'true'));
87
+ const onGenerate = (options) => emit(options, options.generator.config?.relation === "true" || Array.isArray(options.generator.config?.relation) && options.generator.config?.relation[0] === "true");
45
88
  generatorHandler({
46
- onManifest() {
47
- return {
48
- defaultOutput: './valibot/',
49
- prettyName: 'Hekireki-Valibot',
50
- };
51
- },
52
- onGenerate,
89
+ onManifest() {
90
+ return {
91
+ defaultOutput: "./valibot/",
92
+ prettyName: "Hekireki-Valibot"
93
+ };
94
+ },
95
+ onGenerate
53
96
  });
97
+
98
+ //#endregion
99
+ export { onGenerate };
@@ -1,3 +1,6 @@
1
- #!/usr/bin/env node
2
- import type { GeneratorOptions } from '@prisma/generator-helper';
3
- export declare const onGenerate: (options: GeneratorOptions) => Promise<void>;
1
+ import { GeneratorOptions } from "@prisma/generator-helper";
2
+
3
+ //#region src/generator/zod/index.d.ts
4
+ declare const onGenerate: (options: GeneratorOptions) => Promise<void>;
5
+ //#endregion
6
+ export { onGenerate };
@@ -1,64 +1,106 @@
1
1
  #!/usr/bin/env node
2
- import fsp from 'node:fs/promises';
3
- import path from 'node:path';
4
- import pkg from '@prisma/generator-helper';
5
- import { fmt } from '../../shared/format/index.js';
6
- import { collectRelationProps } from '../../shared/helper/relations.js';
7
- import { buildZodRelations } from './generator/schema.js';
8
- import { zod } from './generator/zod.js';
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 { t as collectRelationProps } from "../../relations-CxeKj9KD.js";
5
+ import path from "node:path";
6
+ import pkg from "@prisma/generator-helper";
7
+ import { makePropertiesGenerator, makeValidationExtractor, makeZodInfer } from "utils-lab";
8
+
9
+ //#region src/generator/zod/generator/schema.ts
10
+ function buildZodRelations(model, relProps, options) {
11
+ if (relProps.length === 0) return null;
12
+ const fields = `${` ...${model.name}Schema.shape,`}\n${relProps.map((r) => ` ${r.key}: ${r.isMany ? `z.array(${r.targetModel}Schema)` : `${r.targetModel}Schema`},`).join("\n")}`;
13
+ const typeLine = options?.includeType ? `\n\nexport type ${model.name}Relations = z.infer<typeof ${model.name}RelationsSchema>` : "";
14
+ return `export const ${model.name}RelationsSchema = z.object({\n${fields}\n})${typeLine}`;
15
+ }
16
+ /**
17
+ * Generate Zod schema
18
+ * @param modelName - The name of the model
19
+ * @param fields - The fields of the model
20
+ * @param config - The configuration for the generator
21
+ * @returns The generated Zod schema
22
+ */
23
+ function schema(modelName, fields) {
24
+ return `export const ${modelName}Schema = z.object({\n${fields}\n})`;
25
+ }
26
+
27
+ //#endregion
28
+ //#region src/generator/zod/generator/schemas.ts
29
+ /**
30
+ * Creates Zod 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 Zod schemas
35
+ */
36
+ function schemas(modelFields, comment) {
37
+ return schemaFromFields(modelFields, comment, schema, makePropertiesGenerator("z"));
38
+ }
39
+
40
+ //#endregion
41
+ //#region src/generator/zod/generator/zod.ts
42
+ /**
43
+ * Creates Zod schemas and types from models.
44
+ *
45
+ * @param models - The models to generate the Zod schemas and types for
46
+ * @param type - Whether to generate types
47
+ * @param comment - Whether to include comments in the generated code
48
+ * @param zodVersion - The Zod version/variant to use
49
+ * @returns The generated Zod schemas and types
50
+ */
51
+ function zod(models, type, comment, zodVersion) {
52
+ return validationSchemas(models, type, comment, {
53
+ importStatement: zodVersion === "mini" ? `import * as z from 'zod/mini'` : zodVersion === "@hono/zod-openapi" ? `import { z } from '@hono/zod-openapi'` : `import * as z from 'zod'`,
54
+ annotationPrefix: "@z.",
55
+ parseDocument: parseDocumentWithoutAnnotations,
56
+ extractValidation: makeValidationExtractor("@z."),
57
+ inferType: makeZodInfer,
58
+ schemas
59
+ });
60
+ }
61
+
62
+ //#endregion
63
+ //#region src/generator/zod/index.ts
9
64
  const { generatorHandler } = pkg;
10
65
  const buildRelationsOnly = (dmmf, includeType) => {
11
- const models = dmmf.datamodel.models;
12
- const relIndex = collectRelationProps(models);
13
- const relByModel = relIndex.reduce((acc, r) => {
14
- if (!acc[r.model])
15
- acc[r.model] = [];
16
- acc[r.model].push(r);
17
- return acc;
18
- }, {});
19
- const blocks = models
20
- .map((model) => {
21
- const relProps = (relByModel[model.name] ?? []).map(({ key, targetModel, isMany }) => ({
22
- key,
23
- targetModel,
24
- isMany,
25
- }));
26
- if (relProps.length === 0)
27
- return '';
28
- const schema = buildZodRelations(model, relProps);
29
- const typeLine = includeType
30
- ? `\n\nexport type ${model.name}Relations = z.infer<typeof ${model.name}RelationsSchema>`
31
- : '';
32
- return `${schema}${typeLine}`;
33
- })
34
- .filter(Boolean);
35
- return blocks.join('\n\n');
66
+ const models = dmmf.datamodel.models;
67
+ const relIndex = collectRelationProps(models);
68
+ const relByModel = {};
69
+ for (const r of relIndex) {
70
+ const existing = relByModel[r.model] ?? [];
71
+ relByModel[r.model] = [...existing, r];
72
+ }
73
+ return models.map((model) => {
74
+ const relProps = (relByModel[model.name] ?? []).map(({ key, targetModel, isMany }) => ({
75
+ key,
76
+ targetModel,
77
+ isMany
78
+ }));
79
+ if (relProps.length === 0) return "";
80
+ return `${buildZodRelations(model, relProps)}${includeType ? `\n\nexport type ${model.name}Relations = z.infer<typeof ${model.name}RelationsSchema>` : ""}`;
81
+ }).filter(Boolean).join("\n\n");
36
82
  };
37
- const getString = (v, fallback) => typeof v === 'string' ? v : Array.isArray(v) ? (v[0] ?? fallback) : fallback;
38
- const getBool = (v, fallback = false) => v === true || v === 'true' || (Array.isArray(v) && v[0] === 'true') ? true : fallback;
39
83
  const emit = async (options, enableRelation) => {
40
- const outDir = options.generator.output?.value ?? './zod';
41
- const file = getString(options.generator.config?.file, 'index.ts') ?? 'index.ts';
42
- const zodVersion = getString(options.generator.config?.zod, 'v4');
43
- const base = zod(options.dmmf.datamodel.models, getBool(options.generator.config?.type), getBool(options.generator.config?.comment), zodVersion);
44
- // Respect the `type` flag when generating relation schemas
45
- const relations = enableRelation
46
- ? buildRelationsOnly(options.dmmf, getBool(options.generator.config?.type))
47
- : '';
48
- const full = [base, relations].filter(Boolean).join('\n\n');
49
- const code = await fmt(full);
50
- await fsp.mkdir(outDir, { recursive: true });
51
- await fsp.writeFile(path.join(outDir, file), code, 'utf8');
84
+ const outDir = options.generator.output?.value ?? "./zod";
85
+ const file = getString(options.generator.config?.file, "index.ts") ?? "index.ts";
86
+ const zodVersion = getString(options.generator.config?.zod, "v4");
87
+ const fmtResult = await fmt([zod(options.dmmf.datamodel.models, getBool(options.generator.config?.type), getBool(options.generator.config?.comment), zodVersion), enableRelation ? buildRelationsOnly(options.dmmf, getBool(options.generator.config?.type)) : ""].filter(Boolean).join("\n\n"));
88
+ if (!fmtResult.ok) throw new Error(`Format error: ${fmtResult.error}`);
89
+ const mkdirResult = await mkdir(outDir);
90
+ if (!mkdirResult.ok) throw new Error(`Failed to create directory: ${mkdirResult.error}`);
91
+ const writeResult = await writeFile(path.join(outDir, file), fmtResult.value);
92
+ if (!writeResult.ok) throw new Error(`Failed to write file: ${writeResult.error}`);
52
93
  };
53
- export const onGenerate = (options) => emit(options, options.generator.config?.relation === 'true' ||
54
- (Array.isArray(options.generator.config?.relation) &&
55
- options.generator.config?.relation[0] === 'true'));
94
+ const onGenerate = (options) => emit(options, options.generator.config?.relation === "true" || Array.isArray(options.generator.config?.relation) && options.generator.config?.relation[0] === "true");
56
95
  generatorHandler({
57
- onManifest() {
58
- return {
59
- defaultOutput: './zod/',
60
- prettyName: 'Hekireki-Zod',
61
- };
62
- },
63
- onGenerate,
96
+ onManifest() {
97
+ return {
98
+ defaultOutput: "./zod/",
99
+ prettyName: "Hekireki-Zod"
100
+ };
101
+ },
102
+ onGenerate
64
103
  });
104
+
105
+ //#endregion
106
+ export { onGenerate };
@@ -0,0 +1,12 @@
1
+ //#region src/shared/helper/relations.ts
2
+ function collectRelationProps(models) {
3
+ return models.flatMap((m) => m.fields.filter((f) => f.kind === "object").map((f) => ({
4
+ model: m.name,
5
+ key: f.name,
6
+ targetModel: f.type,
7
+ isMany: f.isList
8
+ })));
9
+ }
10
+
11
+ //#endregion
12
+ export { collectRelationProps as t };
@@ -0,0 +1,134 @@
1
+ import path from "node:path";
2
+ import { format } from "oxfmt";
3
+
4
+ //#region src/shared/format/index.ts
5
+ async function fmt(input) {
6
+ const { code, errors } = await format("<stdin>.ts", input, {
7
+ printWidth: 100,
8
+ singleQuote: true,
9
+ semi: false
10
+ });
11
+ if (errors.length > 0) return {
12
+ ok: false,
13
+ error: errors.map((e) => e.message).join("\n")
14
+ };
15
+ return {
16
+ ok: true,
17
+ value: code
18
+ };
19
+ }
20
+
21
+ //#endregion
22
+ //#region src/shared/generator/index.ts
23
+ /**
24
+ * Extract a string value from generator config.
25
+ * Handles both single string and array of strings.
26
+ */
27
+ const getString = (v, fallback) => typeof v === "string" ? v : Array.isArray(v) ? v[0] ?? fallback : fallback;
28
+ /**
29
+ * Extract a boolean value from generator config.
30
+ * Accepts true, 'true', or ['true'] as truthy values.
31
+ */
32
+ const getBool = (v, fallback = false) => v === true || v === "true" || Array.isArray(v) && v[0] === "true" ? true : fallback;
33
+
34
+ //#endregion
35
+ //#region src/shared/helper/document-parser.ts
36
+ /**
37
+ * All annotation prefixes used by hekireki generators.
38
+ */
39
+ const ANNOTATION_PREFIXES = [
40
+ "@z.",
41
+ "@v.",
42
+ "@a.",
43
+ "@e."
44
+ ];
45
+ /**
46
+ * Parse documentation and filter out all annotation lines.
47
+ * This ensures that annotations from other libraries don't appear in comments.
48
+ *
49
+ * @param documentation - The documentation string from Prisma field
50
+ * @returns Array of comment lines without any annotations
51
+ */
52
+ function parseDocumentWithoutAnnotations(documentation) {
53
+ if (!documentation) return [];
54
+ return documentation.split("\n").map((line) => line.trim()).filter((line) => {
55
+ return !ANNOTATION_PREFIXES.some((prefix) => line.startsWith(prefix));
56
+ }).filter((line) => line.length > 0);
57
+ }
58
+
59
+ //#endregion
60
+ //#region src/shared/utils/index.ts
61
+ /**
62
+ * Group valid fields by their model name.
63
+ *
64
+ * @param validFields - An array of field objects with validation metadata.
65
+ * @returns An object mapping each model name to its corresponding array of fields.
66
+ */
67
+ function groupByModel(validFields) {
68
+ const grouped = {};
69
+ for (const field of validFields) {
70
+ if (!grouped[field.modelName]) grouped[field.modelName] = [];
71
+ grouped[field.modelName] = [...grouped[field.modelName], field];
72
+ }
73
+ return grouped;
74
+ }
75
+ /**
76
+ * Extract fields with validation from a nested array of model fields.
77
+ *
78
+ * @param modelFields - A nested array of model field definitions.
79
+ * @returns A flat array of fields that include a non-null `validation` property.
80
+ */
81
+ function isFields(modelFields) {
82
+ return modelFields.flat().filter((field) => field.validation !== null);
83
+ }
84
+ /**
85
+ * Creates schema from model fields.
86
+ *
87
+ * @param modelFields - The list of model fields with metadata.
88
+ * @param comment - Whether to include documentation comments.
89
+ * @param schemaBuilder - Function to build the schema from modelName and fields.
90
+ * @returns The generated schema string.
91
+ */
92
+ function schemaFromFields(modelFields, comment, schemaBuilder, propertiesGenerator) {
93
+ const modelName = modelFields[0].modelName;
94
+ const modelDoc = modelFields[0].documentation || "";
95
+ const fields = propertiesGenerator(modelFields, comment);
96
+ if (!(modelDoc || !comment)) return schemaBuilder(modelName, fields);
97
+ return schemaBuilder(modelName, fields);
98
+ }
99
+ /**
100
+ * Creates validation schemas for models.
101
+ *
102
+ * @param models - The models to generate schemas for
103
+ * @param type - Whether to generate types
104
+ * @param comment - Whether to include comments
105
+ * @param config - Configuration for the specific library
106
+ * @returns The generated schemas and types
107
+ */
108
+ function validationSchemas(models, type, comment, config) {
109
+ const modelFields = models.map((model) => ({
110
+ documentation: model.documentation ?? "",
111
+ name: model.name,
112
+ fields: model.fields
113
+ })).map((model) => {
114
+ return model.fields.map((field) => ({
115
+ documentation: model.documentation,
116
+ modelName: model.name,
117
+ fieldName: field.name,
118
+ comment: config.parseDocument(field.documentation),
119
+ validation: config.extractValidation(field.documentation)
120
+ }));
121
+ });
122
+ const schemaResults = Object.values(groupByModel(isFields(modelFields))).map((fields) => ({
123
+ schema: config.schemas(fields, comment),
124
+ inferType: type ? config.inferType(fields[0].modelName) : ""
125
+ }));
126
+ return [
127
+ config.importStatement,
128
+ "",
129
+ schemaResults.flatMap(({ schema, inferType }) => [schema, inferType].filter(Boolean)).join("\n\n")
130
+ ].join("\n");
131
+ }
132
+
133
+ //#endregion
134
+ export { getString as a, getBool as i, validationSchemas as n, fmt as o, parseDocumentWithoutAnnotations as r, schemaFromFields as t };
package/package.json CHANGED
@@ -1,15 +1,18 @@
1
1
  {
2
2
  "name": "hekireki",
3
3
  "type": "module",
4
- "version": "0.4.1",
4
+ "version": "0.5.0",
5
5
  "license": "MIT",
6
- "description": "Hekireki is a tool that generates validation schemas for Zod and Valibot, as well as ER diagrams, from Prisma schemas annotated with comments.",
6
+ "description": "Hekireki is a tool that generates validation schemas for Zod, Valibot, ArkType, and Effect Schema, as well as ER diagrams and DBML, from Prisma schemas annotated with comments.",
7
7
  "keywords": [
8
8
  "prisma",
9
9
  "zod",
10
10
  "valibot",
11
+ "arktype",
12
+ "effect",
11
13
  "mermaid",
12
- "ecto"
14
+ "ecto",
15
+ "dbml"
13
16
  ],
14
17
  "homepage": "https://github.com/nakita628/hekireki",
15
18
  "publishConfig": {
@@ -22,8 +25,6 @@
22
25
  "bugs": {
23
26
  "url": "https://github.com/nakita628/hekireki/issues"
24
27
  },
25
- "main": "dist/index.js",
26
- "types": "dist/index.d.ts",
27
28
  "files": [
28
29
  "dist"
29
30
  ],
@@ -31,29 +32,40 @@
31
32
  "hekireki-zod": "dist/generator/zod/index.js",
32
33
  "hekireki-valibot": "dist/generator/valibot/index.js",
33
34
  "hekireki-mermaid-er": "dist/generator/mermaid-er/index.js",
34
- "hekireki-ecto": "dist/generator/ecto/index.js"
35
+ "hekireki-ecto": "dist/generator/ecto/index.js",
36
+ "hekireki-arktype": "dist/generator/arktype/index.js",
37
+ "hekireki-effect": "dist/generator/effect/index.js",
38
+ "hekireki-dbml": "dist/generator/dbml/index.js",
39
+ "hekireki-svg": "dist/generator/svg/index.js"
35
40
  },
36
41
  "scripts": {
37
42
  "generate": "prisma generate",
38
43
  "deps": "rm -rf node_modules && pnpm install",
39
- "build": "rm -rf ./dist/* && tsc",
44
+ "build": "tsdown",
40
45
  "typecheck": "tsc --noEmit",
41
46
  "test": "vitest run",
42
47
  "coverage": "vitest run --coverage",
43
48
  "release": "npm pkg fix && pnpm build && npm publish"
44
49
  },
45
50
  "dependencies": {
46
- "@prisma/generator-helper": "^6.10.1",
47
- "prettier": "^3.6.2"
51
+ "@prisma/generator-helper": "^7.0.1",
52
+ "@resvg/resvg-js": "^2.6.2",
53
+ "@softwaretechnik/dbml-renderer": "^1.0.31",
54
+ "oxfmt": "^0.27.0",
55
+ "utils-lab": "^0.0.2"
48
56
  },
49
57
  "devDependencies": {
50
- "@prisma/client": "^6.10.1",
51
- "@types/node": "^22.18.0",
52
- "@vitest/coverage-v8": "^3.2.4",
53
- "prisma": "^6.10.1",
54
- "tsx": "^4.20.3",
55
- "valibot": "1.1.0",
56
- "vitest": "^3.2.4",
57
- "zod": "^4.0.5"
58
+ "@prisma/client": "^7.0.1",
59
+ "@types/node": "^24.10.1",
60
+ "@typescript/native-preview": "7.0.0-dev.20260130.1",
61
+ "@vitest/coverage-v8": "^4.0.14",
62
+ "arktype": "^2.1.29",
63
+ "effect": "^3.19.15",
64
+ "prisma": "^7.0.1",
65
+ "tsdown": "^0.20.1",
66
+ "tsx": "^4.20.6",
67
+ "valibot": "1.2.0",
68
+ "vitest": "^4.0.14",
69
+ "zod": "^4.1.13"
58
70
  }
59
71
  }
@@ -1,3 +0,0 @@
1
- import type { DMMF } from '@prisma/generator-helper';
2
- export declare function ectoSchemas(models: readonly DMMF.Model[], app: string | string[]): string;
3
- export declare function writeEctoSchemasToFiles(models: readonly DMMF.Model[], app: string | string[], outDir: string): Promise<void>;