hekireki 0.5.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import { GeneratorOptions } from "@prisma/generator-helper";
2
2
 
3
3
  //#region src/generator/arktype/index.d.ts
4
- declare const onGenerate: (options: GeneratorOptions) => Promise<void>;
4
+ declare function main(options: GeneratorOptions): Promise<void>;
5
5
  //#endregion
6
- export { onGenerate };
6
+ export { main };
@@ -1,73 +1,16 @@
1
1
  #!/usr/bin/env node
2
- import { a as getBool, i as collectRelationProps, n as validationSchemas, o as getString, r as parseDocumentWithoutAnnotations, s as fmt, t as schemaFromFields } from "../../utils-BHGDO4qk.js";
3
- import { n as writeFile, t as mkdir } from "../../fsp-FOfmtPYd.js";
2
+ import { n as validationSchemas, r as fmt, t as makeRelationsOnly } from "../../prisma-vPHUnYiY.js";
3
+ import { C as parseDocumentWithoutAnnotations, O as mkdir, b as makeValidationExtractor, k as writeFile, l as getBool, m as makeArktypeSchemas, p as makeArktypeInfer, u as getString } from "../../utils-0nIzqFtt.js";
4
4
  import path from "node:path";
5
5
  import pkg from "@prisma/generator-helper";
6
- import { makeValidationExtractor } from "utils-lab";
7
6
 
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
- * Make ArkType relations schema for a model.
20
- * @param model - The DMMF model
21
- * @param relProps - The relation properties
22
- * @param options - Options for the relation generation
23
- * @returns The generated ArkType relations schema or null if no relations
24
- */
7
+ //#region src/helper/arktype.ts
25
8
  function makeArktypeRelations(model, relProps, options) {
26
9
  if (relProps.length === 0) return null;
27
10
  const fields = `${`...${model.name}Schema.t,`}${relProps.map((r) => `${r.key}:${r.isMany ? `${r.targetModel}Schema.array()` : `${r.targetModel}Schema`},`).join("")}`;
28
11
  const typeLine = options?.includeType ? `\n\nexport type ${model.name}Relations = typeof ${model.name}RelationsSchema.infer` : "";
29
12
  return `export const ${model.name}RelationsSchema = type({${fields}})${typeLine}`;
30
13
  }
31
-
32
- //#endregion
33
- //#region src/generator/arktype/generator/schemas.ts
34
- /**
35
- * Generate properties for ArkType schema.
36
- */
37
- function arktypePropertiesGenerator(fields, comment) {
38
- return fields.map((field) => {
39
- return `${comment && field.comment.length > 0 ? `${field.comment.map((c) => ` /** ${c} */`).join("\n")}\n` : ""} ${field.fieldName}: ${field.validation ?? "\"unknown\""},`;
40
- }).join("\n");
41
- }
42
- /**
43
- * Creates ArkType schemas from model fields.
44
- *
45
- * @param modelFields - The fields of the model
46
- * @param comment - Whether to include comments in the generated code
47
- * @returns The generated ArkType schemas
48
- */
49
- function schemas(modelFields, comment) {
50
- return schemaFromFields(modelFields, comment, schema, arktypePropertiesGenerator);
51
- }
52
-
53
- //#endregion
54
- //#region src/generator/arktype/generator/arktype.ts
55
- /**
56
- * Generate ArkType infer type statement.
57
- * @param modelName - The name of the model
58
- * @returns The generated type inference statement
59
- */
60
- function makeArktypeInfer(modelName) {
61
- return `export type ${modelName} = typeof ${modelName}Schema.infer`;
62
- }
63
- /**
64
- * Creates ArkType schemas and types from models.
65
- *
66
- * @param models - The models to generate the ArkType schemas and types for
67
- * @param type - Whether to generate types
68
- * @param comment - Whether to include comments in the generated code
69
- * @returns The generated ArkType schemas and types
70
- */
71
14
  function arktype(models, type, comment) {
72
15
  return validationSchemas(models, type, comment, {
73
16
  importStatement: `import { type } from 'arktype'`,
@@ -75,38 +18,24 @@ function arktype(models, type, comment) {
75
18
  parseDocument: parseDocumentWithoutAnnotations,
76
19
  extractValidation: makeValidationExtractor("@a."),
77
20
  inferType: makeArktypeInfer,
78
- schemas
21
+ schemas: makeArktypeSchemas
79
22
  });
80
23
  }
81
24
 
82
25
  //#endregion
83
26
  //#region src/generator/arktype/index.ts
84
27
  const { generatorHandler } = pkg;
85
- const buildRelationsOnly = (dmmf, includeType) => {
86
- const models = dmmf.datamodel.models;
87
- const relIndex = collectRelationProps(models);
88
- const relByModel = {};
89
- for (const r of relIndex) {
90
- const existing = relByModel[r.model] ?? [];
91
- relByModel[r.model] = [...existing, r];
92
- }
93
- return models.map((model) => makeArktypeRelations(model, (relByModel[model.name] ?? []).map(({ key, targetModel, isMany }) => ({
94
- key,
95
- targetModel,
96
- isMany
97
- })), { includeType })).filter((code) => Boolean(code)).join("\n\n");
98
- };
99
- const emit = async (options, enableRelation) => {
28
+ async function main(options) {
100
29
  const outDir = options.generator.output?.value ?? "./arktype";
101
30
  const file = getString(options.generator.config?.file, "index.ts") ?? "index.ts";
102
- const fmtResult = await fmt([arktype(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"));
31
+ const enableRelation = options.generator.config?.relation === "true" || Array.isArray(options.generator.config?.relation) && options.generator.config?.relation[0] === "true";
32
+ const fmtResult = await fmt([arktype(options.dmmf.datamodel.models, getBool(options.generator.config?.type), getBool(options.generator.config?.comment)), enableRelation ? makeRelationsOnly(options.dmmf, getBool(options.generator.config?.type), makeArktypeRelations) : ""].filter(Boolean).join("\n\n"));
103
33
  if (!fmtResult.ok) throw new Error(`Format error: ${fmtResult.error}`);
104
34
  const mkdirResult = await mkdir(outDir);
105
35
  if (!mkdirResult.ok) throw new Error(`Failed to create directory: ${mkdirResult.error}`);
106
36
  const writeResult = await writeFile(path.join(outDir, file), fmtResult.value);
107
37
  if (!writeResult.ok) throw new Error(`Failed to write file: ${writeResult.error}`);
108
- };
109
- const onGenerate = (options) => emit(options, options.generator.config?.relation === "true" || Array.isArray(options.generator.config?.relation) && options.generator.config?.relation[0] === "true");
38
+ }
110
39
  generatorHandler({
111
40
  onManifest() {
112
41
  return {
@@ -114,8 +43,8 @@ generatorHandler({
114
43
  prettyName: "Hekireki-ArkType"
115
44
  };
116
45
  },
117
- onGenerate
46
+ onGenerate: main
118
47
  });
119
48
 
120
49
  //#endregion
121
- export { onGenerate };
50
+ export { main };
@@ -1,9 +1,6 @@
1
1
  import { GeneratorOptions } from "@prisma/generator-helper";
2
2
 
3
3
  //#region src/generator/dbml/index.d.ts
4
- /**
5
- * Main generator function
6
- */
7
- declare const main: (options: GeneratorOptions) => Promise<void>;
4
+ declare function main(options: GeneratorOptions): Promise<void>;
8
5
  //#endregion
9
6
  export { main };
@@ -1,80 +1,42 @@
1
1
  #!/usr/bin/env node
2
- import { n as writeFile, r as writeFileBinary, t as mkdir } from "../../fsp-FOfmtPYd.js";
2
+ import { A as writeFileBinary, D as stripAnnotations, O as mkdir, T as quote, a as generateEnum, c as generateRef, k as writeFile, o as generateIndex, r as escapeNote, s as generatePrismaColumn, t as combineKeys, u as getString } from "../../utils-0nIzqFtt.js";
3
3
  import pkg from "@prisma/generator-helper";
4
- import { escapeNote, formatConstraints, generateEnum, generateIndex, generateRef, quote } from "utils-lab";
5
4
  import { Resvg } from "@resvg/resvg-js";
6
5
  import { run } from "@softwaretechnik/dbml-renderer";
7
6
 
8
- //#region src/generator/dbml/generator/dbml-content.ts
9
- /**
10
- * Strip validation annotations (@z.*, @v.*, @a.*, @e.*) and relation annotations (@relation) from documentation
11
- */
12
- function stripAnnotations(doc) {
13
- if (!doc) return void 0;
14
- const result = doc.split("\n").filter((line) => {
15
- const trimmed = line.trim();
16
- return !(trimmed.startsWith("@z.") || trimmed.startsWith("@v.") || trimmed.startsWith("@a.") || trimmed.startsWith("@e.") || trimmed.startsWith("@relation"));
17
- }).join("\n").trim();
18
- return result.length > 0 ? result : void 0;
7
+ //#region src/helper/dbml.ts
8
+ function resolveFieldType(field, models, mapToDbSchema) {
9
+ const baseType = mapToDbSchema ? models.find((m) => m.name === field.type)?.dbName ?? field.type : field.type;
10
+ return field.isList && !field.relationName ? `${baseType}[]` : baseType;
11
+ }
12
+ function resolveDefaultValue(field) {
13
+ const defaultDef = field.default;
14
+ if (defaultDef?.name === "autoincrement") return void 0;
15
+ if (defaultDef?.name === "now") return "`now()`";
16
+ if (field.hasDefaultValue && typeof field.default !== "object") return field.type === "String" || field.type === "Json" || field.kind === "enum" ? `'${field.default}'` : String(field.default);
19
17
  }
20
- /**
21
- * Convert Prisma field to DBMLColumn
22
- */
23
18
  function toDBMLColumn(field, models, mapToDbSchema) {
24
- let fieldType = field.type;
25
- if (mapToDbSchema) {
26
- const relatedModel = models.find((m) => m.name === field.type);
27
- if (relatedModel?.dbName) fieldType = relatedModel.dbName;
28
- }
29
- if (field.isList && !field.relationName) fieldType = `${fieldType}[]`;
30
- let defaultValue;
31
19
  const defaultDef = field.default;
32
- if (defaultDef?.name === "autoincrement") {} else if (defaultDef?.name === "now") defaultValue = "`now()`";
33
- else if (field.hasDefaultValue && typeof field.default !== "object") if (field.type === "String" || field.type === "Json" || field.kind === "enum") defaultValue = `'${field.default}'`;
34
- else defaultValue = String(field.default);
35
20
  return {
36
21
  name: field.name,
37
- type: fieldType,
22
+ type: resolveFieldType(field, models, mapToDbSchema),
38
23
  isPrimaryKey: field.isId,
39
24
  isIncrement: defaultDef?.name === "autoincrement",
40
25
  isUnique: field.isUnique,
41
26
  isNotNull: field.isRequired && !field.isId,
42
- defaultValue,
27
+ defaultValue: resolveDefaultValue(field),
43
28
  note: stripAnnotations(field.documentation)
44
29
  };
45
30
  }
46
- /**
47
- * Generate custom column line with Prisma-specific formatting
48
- */
49
- function generatePrismaColumn(column) {
50
- const constraints = [];
51
- if (column.isPrimaryKey) constraints.push("pk");
52
- if (column.isIncrement) constraints.push("increment");
53
- if (column.defaultValue !== void 0) constraints.push(`default: ${column.defaultValue}`);
54
- if (column.isUnique) constraints.push("unique");
55
- if (column.isNotNull) constraints.push("not null");
56
- if (column.note) constraints.push(`note: ${quote(column.note)}`);
57
- return ` ${column.name} ${column.type}${formatConstraints(constraints)}`;
58
- }
59
- /**
60
- * Generate table indexes block
61
- */
62
31
  function generateTableIndexes(model) {
63
- const indexes = [];
64
- const primaryFields = model.primaryKey?.fields;
65
- if (primaryFields && primaryFields.length > 0) indexes.push({
66
- columns: primaryFields,
32
+ return [...model.primaryKey?.fields && model.primaryKey.fields.length > 0 ? [{
33
+ columns: model.primaryKey.fields,
67
34
  isPrimaryKey: true
68
- });
69
- for (const composite of model.uniqueFields) if (composite.length > 1) indexes.push({
70
- columns: composite,
35
+ }] : [], ...model.uniqueFields.filter((c) => c.length > 1).map((c) => ({
36
+ columns: c,
71
37
  isUnique: true
72
- });
73
- return indexes;
38
+ }))];
74
39
  }
75
- /**
76
- * Generate table definitions
77
- */
78
40
  function generateTables(models, mapToDbSchema = false, includeRelationFields = true) {
79
41
  return models.map((model) => {
80
42
  const modelName = mapToDbSchema && model.dbName ? model.dbName : model.name;
@@ -85,9 +47,6 @@ function generateTables(models, mapToDbSchema = false, includeRelationFields = t
85
47
  return `Table ${modelName} {\n${columnLines}${indexBlock}${strippedNote ? `\n\n Note: ${quote(escapeNote(strippedNote))}` : ""}\n}`;
86
48
  });
87
49
  }
88
- /**
89
- * Generate enum definitions
90
- */
91
50
  function generateEnums(enums) {
92
51
  return enums.map((e) => {
93
52
  return generateEnum({
@@ -96,51 +55,30 @@ function generateEnums(enums) {
96
55
  });
97
56
  });
98
57
  }
99
- /**
100
- * Get relation operator based on cardinality
101
- */
102
58
  function getRelationOperator(models, from, to) {
103
59
  return (models.find((m) => m.name === to)?.fields.find((f) => f.type === from))?.isList ? ">" : "-";
104
60
  }
105
- /**
106
- * Combine keys for composite foreign keys
107
- */
108
- function combineKeys(keys) {
109
- return keys.length > 1 ? `(${keys.join(", ")})` : keys[0];
110
- }
111
- /**
112
- * Generate foreign key references
113
- */
114
61
  function generateRelations(models, mapToDbSchema = false) {
115
- const refs = [];
116
- for (const model of models) {
117
- const relFields = model.fields.filter((field) => field.relationName && field.relationToFields?.length && field.relationFromFields?.length);
118
- for (const field of relFields) {
119
- const relationFrom = model.name;
120
- const relationTo = field.type;
121
- const operator = getRelationOperator(models, relationFrom, relationTo);
122
- const relationFromName = mapToDbSchema && model.dbName ? model.dbName : model.name;
123
- const relatedModel = models.find((m) => m.name === relationTo);
124
- const relationToName = mapToDbSchema && relatedModel?.dbName ? relatedModel.dbName : relationTo;
125
- const fromColumn = combineKeys(field.relationFromFields ?? []);
126
- const toColumn = combineKeys(field.relationToFields ?? []);
127
- const ref = {
128
- name: `${relationFromName}_${fromColumn}_fk`,
129
- fromTable: relationFromName,
130
- fromColumn,
131
- toTable: relationToName,
132
- toColumn,
133
- type: operator,
134
- onDelete: field.relationOnDelete
135
- };
136
- refs.push(generateRef(ref));
137
- }
138
- }
139
- return refs;
62
+ return models.flatMap((model) => model.fields.filter((field) => field.relationName && field.relationToFields?.length && field.relationFromFields?.length).map((field) => {
63
+ const relationFrom = model.name;
64
+ const relationTo = field.type;
65
+ const operator = getRelationOperator(models, relationFrom, relationTo);
66
+ const relationFromName = mapToDbSchema && model.dbName ? model.dbName : model.name;
67
+ const relatedModel = models.find((m) => m.name === relationTo);
68
+ const relationToName = mapToDbSchema && relatedModel?.dbName ? relatedModel.dbName : relationTo;
69
+ const fromColumn = combineKeys(field.relationFromFields ?? []);
70
+ const toColumn = combineKeys(field.relationToFields ?? []);
71
+ return generateRef({
72
+ name: `${relationFromName}_${fromColumn}_fk`,
73
+ fromTable: relationFromName,
74
+ fromColumn,
75
+ toTable: relationToName,
76
+ toColumn,
77
+ type: operator,
78
+ onDelete: field.relationOnDelete
79
+ });
80
+ }));
140
81
  }
141
- /**
142
- * Generate complete DBML content from Prisma DMMF
143
- */
144
82
  function dbmlContent(datamodel, mapToDbSchema = false, includeRelationFields = true) {
145
83
  const tables = generateTables(datamodel.models, mapToDbSchema, includeRelationFields);
146
84
  const enums = generateEnums(datamodel.enums);
@@ -151,25 +89,7 @@ function dbmlContent(datamodel, mapToDbSchema = false, includeRelationFields = t
151
89
  ...refs
152
90
  ].join("\n\n");
153
91
  }
154
-
155
- //#endregion
156
- //#region src/generator/dbml/index.ts
157
- const { generatorHandler } = pkg;
158
- /**
159
- * Get string value from config
160
- */
161
- const getStringValue = (value) => value === void 0 ? void 0 : Array.isArray(value) ? value[0] : value;
162
- /**
163
- * Get boolean option from config
164
- */
165
- const getBoolOption = (config, key, defaultValue) => {
166
- const value = getStringValue(config[key]);
167
- return value === void 0 ? defaultValue : value.toLowerCase() !== "false";
168
- };
169
- /**
170
- * Generate DBML file
171
- */
172
- const generateDbml = async (outputDir, content, fileName) => {
92
+ const generateDbmlFile = async (outputDir, content, fileName) => {
173
93
  const writeResult = await writeFile(`${outputDir}/${fileName}`, content);
174
94
  if (!writeResult.ok) return {
175
95
  ok: false,
@@ -177,9 +97,6 @@ const generateDbml = async (outputDir, content, fileName) => {
177
97
  };
178
98
  return { ok: true };
179
99
  };
180
- /**
181
- * Generate PNG from DBML
182
- */
183
100
  const generatePng = async (outputDir, dbml, fileName) => {
184
101
  const pngBuffer = new Resvg(run(dbml, "svg"), { font: { loadSystemFonts: true } }).render().asPng();
185
102
  const writeResult = await writeFileBinary(`${outputDir}/${fileName}`, pngBuffer);
@@ -189,24 +106,25 @@ const generatePng = async (outputDir, dbml, fileName) => {
189
106
  };
190
107
  return { ok: true };
191
108
  };
192
- /**
193
- * Main generator function
194
- */
195
- const main = async (options) => {
109
+
110
+ //#endregion
111
+ //#region src/generator/dbml/index.ts
112
+ const { generatorHandler } = pkg;
113
+ async function main(options) {
196
114
  const { config } = options.generator;
197
- const mapToDbSchema = getBoolOption(config, "mapToDbSchema", true);
198
- const includeRelationFields = getBoolOption(config, "includeRelationFields", true);
115
+ const mapToDbSchema = getString(config?.mapToDbSchema) !== "false";
116
+ const includeRelationFields = getString(config?.includeRelationFields) !== "false";
199
117
  const content = dbmlContent(options.dmmf.datamodel, mapToDbSchema, includeRelationFields);
200
118
  const output = options.generator.output?.value ?? "./dbml";
201
- const dbmlFile = getStringValue(config.file) ?? "schema.dbml";
202
- const pngFile = getStringValue(config.pngFile) ?? "er-diagram.png";
119
+ const dbmlFile = getString(config?.file, "schema.dbml") ?? "schema.dbml";
120
+ const pngFile = getString(config?.pngFile, "er-diagram.png") ?? "er-diagram.png";
203
121
  const mkdirResult = await mkdir(output);
204
- if (!mkdirResult.ok) throw new Error(`❌ Failed to create directory: ${mkdirResult.error}`);
205
- const dbmlResult = await generateDbml(output, content, dbmlFile);
206
- if (!dbmlResult.ok) throw new Error(`❌ ${dbmlResult.error}`);
122
+ if (!mkdirResult.ok) throw new Error(`Failed to create directory: ${mkdirResult.error}`);
123
+ const dbmlResult = await generateDbmlFile(output, content, dbmlFile);
124
+ if (!dbmlResult.ok) throw new Error(dbmlResult.error);
207
125
  const pngResult = await generatePng(output, content, pngFile);
208
- if (!pngResult.ok) throw new Error(`❌ ${pngResult.error}`);
209
- };
126
+ if (!pngResult.ok) throw new Error(pngResult.error);
127
+ }
210
128
  generatorHandler({
211
129
  onManifest() {
212
130
  return {