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
@@ -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 };
@@ -1,3 +1,6 @@
1
- #!/usr/bin/env node
2
- import type { GeneratorOptions } from '@prisma/generator-helper';
3
- export declare function main(options: GeneratorOptions): Promise<void>;
1
+ import { GeneratorOptions } from "@prisma/generator-helper";
2
+
3
+ //#region src/generator/ecto/index.d.ts
4
+ declare function main(options: GeneratorOptions): Promise<void>;
5
+ //#endregion
6
+ export { main };
@@ -1,18 +1,155 @@
1
1
  #!/usr/bin/env node
2
- import pkg from '@prisma/generator-helper';
3
- import { writeEctoSchemasToFiles } from './generator/ecto.js';
2
+ import { n as writeFile, t as mkdir } from "../../fsp-DYtOxLN_.js";
3
+ import { join } from "node:path";
4
+ import pkg from "@prisma/generator-helper";
5
+ import { makeSnakeCase } from "utils-lab";
6
+
7
+ //#region src/generator/ecto/utils/prisma-type-to-ecto-type.ts
8
+ function prismaTypeToEctoType(type) {
9
+ if (type === "Int") return "integer";
10
+ if (type === "String") return "string";
11
+ if (type === "Boolean") return "boolean";
12
+ if (type === "DateTime") return "utc_datetime";
13
+ return "string";
14
+ }
15
+
16
+ //#endregion
17
+ //#region src/generator/ecto/generator/ecto.ts
18
+ function getPrimaryKeyConfig(field) {
19
+ if (field.type === "String" && field.default && typeof field.default === "object" && "name" in field.default && field.default.name === "uuid") return {
20
+ line: "@primary_key {:id, :binary_id, autogenerate: true}",
21
+ typeSpec: "Ecto.UUID.t()",
22
+ omitIdFieldInSchema: true
23
+ };
24
+ return {
25
+ line: "@primary_key false",
26
+ typeSpec: "String.t()",
27
+ omitIdFieldInSchema: false
28
+ };
29
+ }
30
+ function getFieldDefaultOption(field) {
31
+ const def = field.default;
32
+ if (def === void 0 || def === null) return null;
33
+ if (typeof def === "string") return `default: "${def}"`;
34
+ if (typeof def === "number" || typeof def === "boolean") return `default: ${def}`;
35
+ return null;
36
+ }
37
+ function ectoTypeToTypespec(type) {
38
+ switch (type) {
39
+ case "string": return "String.t()";
40
+ case "integer": return "integer()";
41
+ case "float": return "float()";
42
+ case "boolean": return "boolean()";
43
+ case "binary_id": return "Ecto.UUID.t()";
44
+ case "naive_datetime": return "NaiveDateTime.t()";
45
+ case "utc_datetime": return "DateTime.t()";
46
+ default: return "term()";
47
+ }
48
+ }
49
+ function buildTimestampsLine(fields) {
50
+ const insertedAliases = [
51
+ "inserted_at",
52
+ "created_at",
53
+ "createdAt"
54
+ ];
55
+ const updatedAliases = [
56
+ "updated_at",
57
+ "modified_at",
58
+ "updatedAt",
59
+ "modifiedAt"
60
+ ];
61
+ const inserted = fields.find((f) => insertedAliases.includes(f.name));
62
+ const updated = fields.find((f) => updatedAliases.includes(f.name));
63
+ const exclude = /* @__PURE__ */ new Set();
64
+ if (inserted) exclude.add(inserted.name);
65
+ if (updated) exclude.add(updated.name);
66
+ if (!(inserted || updated)) return {
67
+ line: null,
68
+ exclude
69
+ };
70
+ if (inserted?.name === "inserted_at" && updated?.name === "updated_at") return {
71
+ line: " timestamps()",
72
+ exclude
73
+ };
74
+ return {
75
+ line: ` timestamps(inserted_at: :${inserted?.name ?? "inserted_at"}, updated_at: :${updated?.name ?? "updated_at"})`,
76
+ exclude
77
+ };
78
+ }
79
+ function ectoSchemas(models, app) {
80
+ return models.map((model) => {
81
+ const idField = model.fields.find((f) => f.isId);
82
+ if (!idField) return "";
83
+ const pk = getPrimaryKeyConfig(idField);
84
+ const fields = model.fields.map((f) => ({ ...f }));
85
+ const { line: timestampsLine, exclude: timestampsExclude } = buildTimestampsLine(fields);
86
+ const schemaFieldsRaw = fields.filter((f) => !(f.relationName || f.isId && pk.omitIdFieldInSchema || timestampsExclude.has(f.name)));
87
+ const typeSpecFields = [`id: ${pk.typeSpec}`, ...schemaFieldsRaw.map((f) => `${f.name}: ${ectoTypeToTypespec(prismaTypeToEctoType(f.type))}`)];
88
+ const typeSpecLines = [
89
+ " @type t :: %__MODULE__{",
90
+ ...typeSpecFields.map((line, i) => {
91
+ return ` ${line}${i === typeSpecFields.length - 1 ? "" : ","}`;
92
+ }),
93
+ " }"
94
+ ];
95
+ const schemaFields = schemaFieldsRaw.map((f) => {
96
+ const type = f.isId ? "binary_id" : prismaTypeToEctoType(f.type);
97
+ const primary = f.isId && !pk.omitIdFieldInSchema ? ", primary_key: true" : "";
98
+ const defaultOpt = getFieldDefaultOption(f);
99
+ const defaultClause = defaultOpt ? `, ${defaultOpt}` : "";
100
+ return ` field(:${f.name}, :${type}${primary}${defaultClause})`;
101
+ });
102
+ return [
103
+ `defmodule ${app}.${model.name} do`,
104
+ " use Ecto.Schema",
105
+ "",
106
+ ` ${pk.line}`,
107
+ "",
108
+ ...typeSpecLines,
109
+ "",
110
+ ` schema "${makeSnakeCase(model.name)}" do`,
111
+ ...schemaFields,
112
+ ...timestampsLine ? [timestampsLine] : [],
113
+ " end",
114
+ "end"
115
+ ].join("\n");
116
+ }).filter(Boolean).join("\n\n");
117
+ }
118
+ async function writeEctoSchemasToFiles(models, app, outDir) {
119
+ const mkdirResult = await mkdir(outDir);
120
+ if (!mkdirResult.ok) return mkdirResult;
121
+ for (const model of models) {
122
+ const code = ectoSchemas([model], app);
123
+ if (!code.trim()) continue;
124
+ const filePath = join(outDir, `${makeSnakeCase(model.name)}.ex`);
125
+ const writeResult = await writeFile(filePath, code);
126
+ if (!writeResult.ok) return writeResult;
127
+ console.log(`✅ wrote ${filePath}`);
128
+ }
129
+ return {
130
+ ok: true,
131
+ value: void 0
132
+ };
133
+ }
134
+
135
+ //#endregion
136
+ //#region src/generator/ecto/index.ts
4
137
  const { generatorHandler } = pkg;
5
- export async function main(options) {
6
- const output = options.generator.output?.value ?? './ecto';
7
- const app = options.generator.config?.app ?? 'MyApp';
8
- await writeEctoSchemasToFiles(options.dmmf.datamodel.models, app, output);
138
+ async function main(options) {
139
+ const output = options.generator.output?.value ?? "./ecto";
140
+ const app = options.generator.config?.app ?? "MyApp";
141
+ const result = await writeEctoSchemasToFiles(options.dmmf.datamodel.models, app, output);
142
+ if (!result.ok) throw new Error(`Failed to write Ecto schemas: ${result.error}`);
9
143
  }
10
144
  generatorHandler({
11
- onManifest() {
12
- return {
13
- defaultOutput: './ecto/',
14
- prettyName: 'Hekireki-Ecto',
15
- };
16
- },
17
- onGenerate: main,
145
+ onManifest() {
146
+ return {
147
+ defaultOutput: "./ecto/",
148
+ prettyName: "Hekireki-Ecto"
149
+ };
150
+ },
151
+ onGenerate: main
18
152
  });
153
+
154
+ //#endregion
155
+ export { main };
@@ -0,0 +1,6 @@
1
+ import { GeneratorOptions } from "@prisma/generator-helper";
2
+
3
+ //#region src/generator/effect/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/effect/generator/schema.ts
9
+ /**
10
+ * Generate Effect Schema
11
+ * @param modelName - The name of the model
12
+ * @param fields - The fields of the model
13
+ * @returns The generated Effect Schema
14
+ */
15
+ function schema(modelName, fields) {
16
+ return `export const ${modelName}Schema = Schema.Struct({\n${fields}\n})`;
17
+ }
18
+
19
+ //#endregion
20
+ //#region src/generator/effect/generator/schemas.ts
21
+ /**
22
+ * Generate properties for Effect Schema.
23
+ */
24
+ function effectPropertiesGenerator(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 ?? "Schema.Unknown"},`;
27
+ }).join("\n");
28
+ }
29
+ /**
30
+ * Creates Effect 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 Effect schemas
35
+ */
36
+ function schemas(modelFields, comment) {
37
+ return schemaFromFields(modelFields, comment, schema, effectPropertiesGenerator);
38
+ }
39
+
40
+ //#endregion
41
+ //#region src/generator/effect/generator/effect.ts
42
+ /**
43
+ * Generate Effect Schema infer type statement.
44
+ * @param modelName - The name of the model
45
+ * @returns The generated type inference statement
46
+ */
47
+ function makeEffectInfer(modelName) {
48
+ return `export type ${modelName} = Schema.Schema.Type<typeof ${modelName}Schema>`;
49
+ }
50
+ /**
51
+ * Creates Effect schemas and types from models.
52
+ *
53
+ * @param models - The models to generate the Effect 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 Effect schemas and types
57
+ */
58
+ function effect(models, type, comment) {
59
+ return validationSchemas(models, type, comment, {
60
+ importStatement: `import { Schema } from 'effect'`,
61
+ annotationPrefix: "@e.",
62
+ parseDocument: parseDocumentWithoutAnnotations,
63
+ extractValidation: makeValidationExtractor("@e."),
64
+ inferType: makeEffectInfer,
65
+ schemas
66
+ });
67
+ }
68
+
69
+ //#endregion
70
+ //#region src/generator/effect/index.ts
71
+ const { generatorHandler } = pkg;
72
+ const emit = async (options) => {
73
+ const outDir = options.generator.output?.value ?? "./effect";
74
+ const file = getString(options.generator.config?.file, "index.ts") ?? "index.ts";
75
+ const fmtResult = await fmt(effect(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: "./effect/",
87
+ prettyName: "Hekireki-Effect"
88
+ };
89
+ },
90
+ onGenerate
91
+ });
92
+
93
+ //#endregion
94
+ export { onGenerate };
@@ -1,3 +1,6 @@
1
- #!/usr/bin/env node
2
- import type { GeneratorOptions } from '@prisma/generator-helper';
3
- export declare function main(options: GeneratorOptions): Promise<void>;
1
+ import { GeneratorOptions } from "@prisma/generator-helper";
2
+
3
+ //#region src/generator/mermaid-er/index.d.ts
4
+ declare function main(options: GeneratorOptions): Promise<void>;
5
+ //#endregion
6
+ export { main };
@@ -1,26 +1,141 @@
1
1
  #!/usr/bin/env node
2
- import fsp from 'node:fs/promises';
3
- import pkg from '@prisma/generator-helper';
4
- import { erContent } from './generator/er-content.js';
2
+ import { n as writeFile, t as mkdir } from "../../fsp-DYtOxLN_.js";
3
+ import pkg from "@prisma/generator-helper";
4
+
5
+ //#region src/generator/mermaid-er/helper/extract-relations-from-dmmf.ts
6
+ const RELATIONSHIPS = {
7
+ "zero-one": "|o",
8
+ one: "||",
9
+ "zero-many": "}o",
10
+ many: "}|"
11
+ };
12
+ /**
13
+ * Extract Mermaid ER diagram relation lines from Prisma DMMF models.
14
+ * This function automatically detects relations from field definitions.
15
+ *
16
+ * @param models - The list of Prisma DMMF models.
17
+ * @returns An array of Mermaid ER diagram relation lines.
18
+ */
19
+ function extractRelationsFromDmmf(models) {
20
+ const relations = [];
21
+ for (const model of models) for (const field of model.fields) {
22
+ if (field.kind !== "object" || !field.relationFromFields || field.relationFromFields.length === 0) continue;
23
+ const toModel = model.name;
24
+ const fromModel = field.type;
25
+ const toField = field.relationFromFields[0];
26
+ const fromField = field.relationToFields?.[0] ?? "id";
27
+ const fromCardinality = "one";
28
+ const inverseField = models.find((m) => m.name === fromModel)?.fields.find((f) => f.relationName === field.relationName && f.name !== field.name);
29
+ let toCardinality;
30
+ if (inverseField?.isList) toCardinality = field.isRequired ? "many" : "zero-many";
31
+ else toCardinality = field.isRequired ? "one" : "zero-one";
32
+ const relationLine = ` ${fromModel} ${RELATIONSHIPS[fromCardinality]}--${RELATIONSHIPS[toCardinality]} ${toModel} : "(${fromField}) - (${toField})"`;
33
+ relations.push(relationLine);
34
+ }
35
+ return relations;
36
+ }
37
+
38
+ //#endregion
39
+ //#region src/generator/mermaid-er/utils/index.ts
40
+ /**
41
+ * Remove duplicate relation lines from an array of Mermaid ER diagram relations.
42
+ *
43
+ * @param relations - An array of relation lines (e.g., generated from `relationLine`).
44
+ * @returns A new array with duplicates removed, preserving insertion order.
45
+ */
46
+ function removeDuplicateRelations(relations) {
47
+ return [...new Set(relations)];
48
+ }
49
+
50
+ //#endregion
51
+ //#region src/generator/mermaid-er/generator/model-fields.ts
52
+ const ZOD_ANNOTATION = "@z.";
53
+ const VALIBOT_ANNOTATION = "@v.";
54
+ const RELATION_ANNOTATION = "@relation";
55
+ /**
56
+ * Convert Prisma type to lowercase Mermaid ER type.
57
+ */
58
+ function toMermaidType(prismaType) {
59
+ return prismaType.toLowerCase();
60
+ }
61
+ /**
62
+ * Generate Mermaid ER field lines from a Prisma model.
63
+ *
64
+ * @param model - A Prisma DMMF model definition.
65
+ * @returns An array of strings representing each field in Mermaid ER syntax, excluding relation fields and annotations.
66
+ */
67
+ function modelFields(model) {
68
+ const fkFields = new Set(model.fields.filter((f) => f.relationFromFields && f.relationFromFields.length > 0).flatMap((f) => f.relationFromFields ?? []));
69
+ return model.fields.map((field) => {
70
+ if (field.relationName) return null;
71
+ const commentPart = field.documentation ? field.documentation.split("\n").filter((line) => !(line.includes(ZOD_ANNOTATION) || line.includes(VALIBOT_ANNOTATION) || line.includes(RELATION_ANNOTATION))).join("\n").trim() : "";
72
+ const keyMarker = field.isId ? "PK" : fkFields.has(field.name) ? "FK" : "";
73
+ const keyPart = keyMarker ? ` ${keyMarker}` : "";
74
+ return ` ${toMermaidType(field.type)} ${field.name}${keyPart}${commentPart ? ` "${commentPart}"` : ""}`;
75
+ }).filter((field) => field !== null);
76
+ }
77
+
78
+ //#endregion
79
+ //#region src/generator/mermaid-er/generator/model-info.ts
80
+ /**
81
+ * Generate Mermaid ER diagram model block from a Prisma model.
82
+ *
83
+ * @param model - A Prisma DMMF model definition.
84
+ * @returns An array of strings representing the model block in Mermaid ER syntax.
85
+ */
86
+ function modelInfo(model) {
87
+ return [
88
+ ` ${model.name} {`,
89
+ ...modelFields(model),
90
+ " }"
91
+ ];
92
+ }
93
+
94
+ //#endregion
95
+ //#region src/generator/mermaid-er/generator/er-content.ts
96
+ const ER_HEADER = ["```mermaid", "erDiagram"];
97
+ const ER_FOOTER = ["```"];
98
+ /**
99
+ * Generate Mermaid ER diagram content from Prisma models.
100
+ *
101
+ * @param models - The list of Prisma DMMF models.
102
+ * @returns An array of Mermaid ER diagram lines.
103
+ */
104
+ function erContent(models) {
105
+ const uniqueRelations = removeDuplicateRelations(extractRelationsFromDmmf(models));
106
+ const modelInfos = models.flatMap(modelInfo);
107
+ return [
108
+ ...ER_HEADER,
109
+ ...uniqueRelations,
110
+ ...modelInfos,
111
+ ...ER_FOOTER
112
+ ];
113
+ }
114
+
115
+ //#endregion
116
+ //#region src/generator/mermaid-er/index.ts
5
117
  const { generatorHandler } = pkg;
6
- export async function main(options) {
7
- const content = erContent(options.dmmf.datamodel.models);
8
- const output = options.generator.output?.value ?? './mermaid-er';
9
- const file = options.generator.config?.file ?? 'ER.md';
10
- // Handle case where output is a file path (contains extension)
11
- const isOutputFile = output.includes('.');
12
- const outputDir = isOutputFile ? '.' : output;
13
- const outputFile = isOutputFile ? output : `${output}/${file}`;
14
- await fsp.mkdir(outputDir, { recursive: true });
15
- await fsp.writeFile(outputFile, content.join('\n'), { encoding: 'utf-8' });
118
+ async function main(options) {
119
+ const content = erContent(options.dmmf.datamodel.models);
120
+ const output = options.generator.output?.value ?? "./mermaid-er";
121
+ const file = options.generator.config?.file ?? "ER.md";
122
+ const isOutputFile = output.includes(".");
123
+ const outputDir = isOutputFile ? "." : output;
124
+ const outputFile = isOutputFile ? output : `${output}/${file}`;
125
+ const mkdirResult = await mkdir(outputDir);
126
+ if (!mkdirResult.ok) throw new Error(`Failed to create directory: ${mkdirResult.error}`);
127
+ const writeResult = await writeFile(outputFile, content.join("\n"));
128
+ if (!writeResult.ok) throw new Error(`Failed to write file: ${writeResult.error}`);
16
129
  }
17
- // prisma generator handler
18
130
  generatorHandler({
19
- onManifest() {
20
- return {
21
- defaultOutput: './mermaid-er',
22
- prettyName: 'Hekireki-ER',
23
- };
24
- },
25
- onGenerate: main,
131
+ onManifest() {
132
+ return {
133
+ defaultOutput: "./mermaid-er",
134
+ prettyName: "Hekireki-ER"
135
+ };
136
+ },
137
+ onGenerate: main
26
138
  });
139
+
140
+ //#endregion
141
+ export { main };
@@ -0,0 +1,6 @@
1
+ import { GeneratorOptions } from "@prisma/generator-helper";
2
+
3
+ //#region src/generator/svg/index.d.ts
4
+ declare function main(options: GeneratorOptions): Promise<void>;
5
+ //#endregion
6
+ export { main };
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env node
2
+ import { n as writeFile, r as writeFileBinary, 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
+ import { Resvg } from "@resvg/resvg-js";
6
+ import { run } from "@softwaretechnik/dbml-renderer";
7
+
8
+ //#region src/generator/svg/index.ts
9
+ const { generatorHandler } = pkg;
10
+ /**
11
+ * Get string value from config
12
+ */
13
+ function getStringValue(value) {
14
+ if (value === void 0) return void 0;
15
+ return Array.isArray(value) ? value[0] : value;
16
+ }
17
+ /**
18
+ * Get boolean option from config
19
+ */
20
+ function getBoolOption(config, key, defaultValue) {
21
+ const value = getStringValue(config[key]);
22
+ if (value === void 0) return defaultValue;
23
+ return value.toLowerCase() !== "false";
24
+ }
25
+ /**
26
+ * Get file extension for format
27
+ */
28
+ function getExtension(format) {
29
+ switch (format) {
30
+ case "png": return "png";
31
+ case "dot": return "dot";
32
+ default: return "svg";
33
+ }
34
+ }
35
+ async function main(options) {
36
+ const { config } = options.generator;
37
+ const mapToDbSchema = getBoolOption(config, "mapToDbSchema", false);
38
+ const includeRelationFields = getBoolOption(config, "includeRelationFields", false);
39
+ const format = getStringValue(config.format)?.toLowerCase() || "png";
40
+ const dbml = dbmlContent(options.dmmf.datamodel, mapToDbSchema, includeRelationFields);
41
+ const output = options.generator.output?.value ?? "./docs";
42
+ const defaultFile = `er-diagram.${getExtension(format)}`;
43
+ const file = getStringValue(config.file) ?? defaultFile;
44
+ const isOutputFile = output.includes(".");
45
+ const outputDir = isOutputFile ? "." : output;
46
+ const outputFile = isOutputFile ? output : `${output}/${file}`;
47
+ const mkdirResult = await mkdir(outputDir);
48
+ if (!mkdirResult.ok) throw new Error(`Failed to create directory: ${mkdirResult.error}`);
49
+ if (format === "dot") {
50
+ const writeResult = await writeFile(outputFile, run(dbml, "dot"));
51
+ if (!writeResult.ok) throw new Error(`Failed to write file: ${writeResult.error}`);
52
+ } else {
53
+ const svg = run(dbml, "svg");
54
+ if (format === "png") {
55
+ const writeResult = await writeFileBinary(outputFile, new Resvg(svg, { font: { loadSystemFonts: true } }).render().asPng());
56
+ if (!writeResult.ok) throw new Error(`Failed to write file: ${writeResult.error}`);
57
+ } else {
58
+ const writeResult = await writeFile(outputFile, svg);
59
+ if (!writeResult.ok) throw new Error(`Failed to write file: ${writeResult.error}`);
60
+ }
61
+ }
62
+ }
63
+ generatorHandler({
64
+ onManifest() {
65
+ return {
66
+ defaultOutput: "./docs",
67
+ prettyName: "Hekireki-SVG"
68
+ };
69
+ },
70
+ onGenerate: main
71
+ });
72
+
73
+ //#endregion
74
+ export { main };
@@ -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/valibot/index.d.ts
4
+ declare const onGenerate: (options: GeneratorOptions) => Promise<void>;
5
+ //#endregion
6
+ export { onGenerate };