hekireki 0.7.0 → 0.7.2
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.
- package/README.md +282 -14
- package/dist/generator/ajv/index.d.ts +6 -0
- package/dist/generator/ajv/index.js +87 -0
- package/dist/generator/arktype/index.js +17 -3
- package/dist/generator/dbml/index.js +43 -33
- package/dist/generator/drizzle/index.js +15 -24
- package/dist/generator/ecto/index.js +34 -9
- package/dist/generator/effect/index.js +17 -3
- package/dist/generator/gorm/index.d.ts +6 -0
- package/dist/generator/gorm/index.js +370 -0
- package/dist/generator/mermaid-er/index.js +6 -12
- package/dist/generator/sea-orm/index.d.ts +6 -0
- package/dist/generator/sea-orm/index.js +444 -0
- package/dist/generator/sqlalchemy/index.d.ts +6 -0
- package/dist/generator/sqlalchemy/index.js +458 -0
- package/dist/generator/typebox/index.d.ts +6 -0
- package/dist/generator/typebox/index.js +93 -0
- package/dist/generator/valibot/index.js +15 -5
- package/dist/generator/zod/index.js +15 -5
- package/dist/{prisma-Cc0YxSiO.js → prisma-ChsFqlYX.js} +6 -6
- package/dist/utils-COHZyQue.js +116 -0
- package/package.json +18 -7
- package/dist/utils-DeZn2r_T.js +0 -287
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { i as isFields, r as groupByModel } from "./utils-COHZyQue.js";
|
|
2
2
|
|
|
3
3
|
//#region src/helper/prisma.ts
|
|
4
4
|
function collectRelationProps(models) {
|
|
@@ -61,15 +61,15 @@ function validationSchemas(models, type, comment, config) {
|
|
|
61
61
|
fieldName: f.name
|
|
62
62
|
})));
|
|
63
63
|
for (const { modelName, fieldName } of missing) console.warn(`Warning: Field "${modelName}.${fieldName}" has no ${config.annotationPrefix} annotation and will be omitted from the schema`);
|
|
64
|
-
const
|
|
64
|
+
const schemas = Object.values(groupByModel(isFields(modelFields))).map((fields) => ({
|
|
65
65
|
schema: config.schemas(fields, comment),
|
|
66
66
|
inferType: type ? config.inferType(fields[0].modelName) : ""
|
|
67
|
-
}));
|
|
68
|
-
return [
|
|
67
|
+
})).flatMap(({ schema, inferType }) => [schema, inferType].filter(Boolean)).join("\n\n");
|
|
68
|
+
return config.importStatement ? [
|
|
69
69
|
config.importStatement,
|
|
70
70
|
"",
|
|
71
|
-
|
|
72
|
-
].join("\n");
|
|
71
|
+
schemas
|
|
72
|
+
].join("\n") : schemas;
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
//#endregion
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
|
|
3
|
+
//#region src/fsp/index.ts
|
|
4
|
+
async function mkdir(dir) {
|
|
5
|
+
try {
|
|
6
|
+
await fs.mkdir(dir, { recursive: true });
|
|
7
|
+
return {
|
|
8
|
+
ok: true,
|
|
9
|
+
value: void 0
|
|
10
|
+
};
|
|
11
|
+
} catch (e) {
|
|
12
|
+
return {
|
|
13
|
+
ok: false,
|
|
14
|
+
error: e instanceof Error ? e.message : String(e)
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
async function writeFile(path, data) {
|
|
19
|
+
try {
|
|
20
|
+
await fs.writeFile(path, data, "utf-8");
|
|
21
|
+
return {
|
|
22
|
+
ok: true,
|
|
23
|
+
value: void 0
|
|
24
|
+
};
|
|
25
|
+
} catch (e) {
|
|
26
|
+
return {
|
|
27
|
+
ok: false,
|
|
28
|
+
error: e instanceof Error ? e.message : String(e)
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async function writeFileBinary(path, data) {
|
|
33
|
+
try {
|
|
34
|
+
await fs.writeFile(path, data);
|
|
35
|
+
return {
|
|
36
|
+
ok: true,
|
|
37
|
+
value: void 0
|
|
38
|
+
};
|
|
39
|
+
} catch (e) {
|
|
40
|
+
return {
|
|
41
|
+
ok: false,
|
|
42
|
+
error: e instanceof Error ? e.message : String(e)
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
//#endregion
|
|
48
|
+
//#region src/utils/index.ts
|
|
49
|
+
function getString(v, fallback) {
|
|
50
|
+
return typeof v === "string" ? v : Array.isArray(v) ? v[0] ?? fallback : fallback;
|
|
51
|
+
}
|
|
52
|
+
function getBool(v, fallback = false) {
|
|
53
|
+
return v === true || v === "true" || Array.isArray(v) && v[0] === "true" ? true : fallback;
|
|
54
|
+
}
|
|
55
|
+
function makeSnakeCase(name) {
|
|
56
|
+
return name.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase();
|
|
57
|
+
}
|
|
58
|
+
function makeValidationExtractor(annotationPrefix) {
|
|
59
|
+
const escaped = annotationPrefix.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
60
|
+
const regex = new RegExp(`${escaped}(.+?)(?:\\n|$)`);
|
|
61
|
+
return function extractValidation(documentation) {
|
|
62
|
+
if (!documentation) return null;
|
|
63
|
+
return documentation.match(regex)?.[1]?.trim() ?? null;
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function parseDocumentWithoutAnnotations(documentation) {
|
|
67
|
+
if (!documentation) return [];
|
|
68
|
+
return documentation.split("\n").map((line) => line.trim()).filter((line) => ![
|
|
69
|
+
"@z.",
|
|
70
|
+
"@v.",
|
|
71
|
+
"@a.",
|
|
72
|
+
"@e.",
|
|
73
|
+
"@t.",
|
|
74
|
+
"@j."
|
|
75
|
+
].some((prefix) => line.startsWith(prefix))).filter((line) => ![
|
|
76
|
+
"@z",
|
|
77
|
+
"@v",
|
|
78
|
+
"@a",
|
|
79
|
+
"@e",
|
|
80
|
+
"@t",
|
|
81
|
+
"@j"
|
|
82
|
+
].includes(line)).filter((line) => line.length > 0);
|
|
83
|
+
}
|
|
84
|
+
function stripAnnotations(doc) {
|
|
85
|
+
if (!doc) return void 0;
|
|
86
|
+
const result = doc.split("\n").filter((line) => {
|
|
87
|
+
const trimmed = line.trim();
|
|
88
|
+
return !(trimmed.startsWith("@z.") || trimmed.startsWith("@v.") || trimmed.startsWith("@a.") || trimmed.startsWith("@e.") || trimmed.startsWith("@t.") || trimmed.startsWith("@j.") || trimmed.startsWith("@relation") || trimmed === "@z" || trimmed === "@v" || trimmed === "@a" || trimmed === "@e" || trimmed === "@t" || trimmed === "@j");
|
|
89
|
+
}).join("\n").trim();
|
|
90
|
+
return result.length > 0 ? result : void 0;
|
|
91
|
+
}
|
|
92
|
+
function makePropertiesGenerator(libraryPrefix, wrapCardinality) {
|
|
93
|
+
return function makeProperties(modelFields, includeComments) {
|
|
94
|
+
return modelFields.filter((field) => field.validation).map((field) => {
|
|
95
|
+
const cleanLines = field.comment.filter((line) => !(line.includes("@relation") || line.includes("@z") || line.includes("@v") || line.includes("@a") || line.includes("@e") || line.includes("@t") || line.includes("@j")));
|
|
96
|
+
const docComment = includeComments && cleanLines.length > 0 ? ` /**\n${cleanLines.map((line) => ` * ${line}`).join("\n")}\n */\n` : "";
|
|
97
|
+
const base = `${libraryPrefix}.${field.validation}`;
|
|
98
|
+
const wrapped = wrapCardinality ? wrapCardinality(base, field.isRequired) : base;
|
|
99
|
+
return `${docComment} ${field.fieldName}: ${wrapped}`;
|
|
100
|
+
}).join(",\n");
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
function groupByModel(validFields) {
|
|
104
|
+
const raw = Object.groupBy(validFields, (f) => f.modelName);
|
|
105
|
+
return Object.fromEntries(Object.entries(raw).filter((entry) => entry[1] != null));
|
|
106
|
+
}
|
|
107
|
+
function isFields(modelFields) {
|
|
108
|
+
return modelFields.flat().filter((field) => field.validation !== null);
|
|
109
|
+
}
|
|
110
|
+
function schemaFromFields(modelFields, comment, schemaBuilder, propertiesGenerator) {
|
|
111
|
+
const modelName = modelFields[0].modelName;
|
|
112
|
+
return schemaBuilder(modelName, propertiesGenerator(modelFields, comment));
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
//#endregion
|
|
116
|
+
export { makePropertiesGenerator as a, parseDocumentWithoutAnnotations as c, mkdir as d, writeFile as f, isFields as i, schemaFromFields as l, getString as n, makeSnakeCase as o, writeFileBinary as p, groupByModel as r, makeValidationExtractor as s, getBool as t, stripAnnotations as u };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hekireki",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.7.
|
|
4
|
+
"version": "0.7.2",
|
|
5
5
|
"license": "MIT",
|
|
6
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": [
|
|
@@ -13,8 +13,15 @@
|
|
|
13
13
|
"mermaid",
|
|
14
14
|
"ecto",
|
|
15
15
|
"dbml",
|
|
16
|
+
"typebox",
|
|
17
|
+
"ajv",
|
|
18
|
+
"json-schema",
|
|
16
19
|
"docs",
|
|
17
|
-
"documentation"
|
|
20
|
+
"documentation",
|
|
21
|
+
"gorm",
|
|
22
|
+
"go",
|
|
23
|
+
"sea-orm",
|
|
24
|
+
"rust"
|
|
18
25
|
],
|
|
19
26
|
"homepage": "https://github.com/nakita628/hekireki",
|
|
20
27
|
"publishConfig": {
|
|
@@ -40,15 +47,18 @@
|
|
|
40
47
|
"hekireki-effect": "dist/generator/effect/index.js",
|
|
41
48
|
"hekireki-dbml": "dist/generator/dbml/index.js",
|
|
42
49
|
"hekireki-docs": "dist/generator/docs/index.js",
|
|
43
|
-
"hekireki-drizzle": "dist/generator/drizzle/index.js"
|
|
50
|
+
"hekireki-drizzle": "dist/generator/drizzle/index.js",
|
|
51
|
+
"hekireki-typebox": "dist/generator/typebox/index.js",
|
|
52
|
+
"hekireki-ajv": "dist/generator/ajv/index.js",
|
|
53
|
+
"hekireki-sqlalchemy": "dist/generator/sqlalchemy/index.js",
|
|
54
|
+
"hekireki-gorm": "dist/generator/gorm/index.js",
|
|
55
|
+
"hekireki-sea-orm": "dist/generator/sea-orm/index.js"
|
|
44
56
|
},
|
|
45
57
|
"scripts": {
|
|
46
58
|
"generate": "prisma generate",
|
|
47
59
|
"deps": "rm -rf node_modules && pnpm install",
|
|
48
60
|
"build": "tsdown",
|
|
49
61
|
"typecheck": "tsc --noEmit",
|
|
50
|
-
"test": "vitest run",
|
|
51
|
-
"coverage": "vitest run --coverage",
|
|
52
62
|
"release": "npm pkg fix && pnpm build && npm publish"
|
|
53
63
|
},
|
|
54
64
|
"dependencies": {
|
|
@@ -63,7 +73,6 @@
|
|
|
63
73
|
"@prisma/client": "^7.4.0",
|
|
64
74
|
"@types/node": "^25.2.3",
|
|
65
75
|
"@typescript/native-preview": "7.0.0-dev.20260218.1",
|
|
66
|
-
"@vitest/coverage-v8": "^4.0.18",
|
|
67
76
|
"arktype": "^2.1.29",
|
|
68
77
|
"effect": "^3.19.18",
|
|
69
78
|
"prisma": "^7.4.0",
|
|
@@ -71,7 +80,9 @@
|
|
|
71
80
|
"tsx": "^4.21.0",
|
|
72
81
|
"typescript": "^5.9.3",
|
|
73
82
|
"valibot": "1.2.0",
|
|
74
|
-
"
|
|
83
|
+
"@sinclair/typebox": "^0.34.33",
|
|
84
|
+
"ajv": "^8.17.1",
|
|
85
|
+
"json-schema-to-ts": "^3.1.1",
|
|
75
86
|
"zod": "^4.3.6"
|
|
76
87
|
}
|
|
77
88
|
}
|
package/dist/utils-DeZn2r_T.js
DELETED
|
@@ -1,287 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs/promises";
|
|
2
|
-
|
|
3
|
-
//#region src/fsp/index.ts
|
|
4
|
-
async function mkdir(dir) {
|
|
5
|
-
try {
|
|
6
|
-
await fs.mkdir(dir, { recursive: true });
|
|
7
|
-
return {
|
|
8
|
-
ok: true,
|
|
9
|
-
value: void 0
|
|
10
|
-
};
|
|
11
|
-
} catch (e) {
|
|
12
|
-
return {
|
|
13
|
-
ok: false,
|
|
14
|
-
error: e instanceof Error ? e.message : String(e)
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
async function writeFile(path, data) {
|
|
19
|
-
try {
|
|
20
|
-
await fs.writeFile(path, data, "utf-8");
|
|
21
|
-
return {
|
|
22
|
-
ok: true,
|
|
23
|
-
value: void 0
|
|
24
|
-
};
|
|
25
|
-
} catch (e) {
|
|
26
|
-
return {
|
|
27
|
-
ok: false,
|
|
28
|
-
error: e instanceof Error ? e.message : String(e)
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
async function writeFileBinary(path, data) {
|
|
33
|
-
try {
|
|
34
|
-
await fs.writeFile(path, data);
|
|
35
|
-
return {
|
|
36
|
-
ok: true,
|
|
37
|
-
value: void 0
|
|
38
|
-
};
|
|
39
|
-
} catch (e) {
|
|
40
|
-
return {
|
|
41
|
-
ok: false,
|
|
42
|
-
error: e instanceof Error ? e.message : String(e)
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
//#endregion
|
|
48
|
-
//#region src/utils/index.ts
|
|
49
|
-
/**
|
|
50
|
-
* Extract a string value from generator config.
|
|
51
|
-
*/
|
|
52
|
-
const getString = (v, fallback) => typeof v === "string" ? v : Array.isArray(v) ? v[0] ?? fallback : fallback;
|
|
53
|
-
/**
|
|
54
|
-
* Extract a boolean value from generator config.
|
|
55
|
-
*/
|
|
56
|
-
const getBool = (v, fallback = false) => v === true || v === "true" || Array.isArray(v) && v[0] === "true" ? true : fallback;
|
|
57
|
-
/**
|
|
58
|
-
* Convert camelCase/PascalCase to snake_case
|
|
59
|
-
*/
|
|
60
|
-
function makeSnakeCase(name) {
|
|
61
|
-
return name.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase();
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Create a validation extractor for a specific annotation prefix
|
|
65
|
-
*/
|
|
66
|
-
function makeValidationExtractor(annotationPrefix) {
|
|
67
|
-
const escaped = annotationPrefix.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
68
|
-
const regex = new RegExp(`${escaped}(.+?)(?:\\n|$)`);
|
|
69
|
-
return function extractValidation(documentation) {
|
|
70
|
-
if (!documentation) return null;
|
|
71
|
-
return documentation.match(regex)?.[1]?.trim() ?? null;
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Parse documentation and filter out all annotation lines.
|
|
76
|
-
*/
|
|
77
|
-
function parseDocumentWithoutAnnotations(documentation) {
|
|
78
|
-
if (!documentation) return [];
|
|
79
|
-
return documentation.split("\n").map((line) => line.trim()).filter((line) => ![
|
|
80
|
-
"@z.",
|
|
81
|
-
"@v.",
|
|
82
|
-
"@a.",
|
|
83
|
-
"@e."
|
|
84
|
-
].some((prefix) => line.startsWith(prefix))).filter((line) => ![
|
|
85
|
-
"@z",
|
|
86
|
-
"@v",
|
|
87
|
-
"@a",
|
|
88
|
-
"@e"
|
|
89
|
-
].includes(line)).filter((line) => line.length > 0);
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Format enum values as Zod enum expression
|
|
93
|
-
*/
|
|
94
|
-
function makeZodEnumExpression(values) {
|
|
95
|
-
return `enum([${values.map((v) => `'${v}'`).join(", ")}])`;
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Format enum values as Valibot picklist expression
|
|
99
|
-
*/
|
|
100
|
-
function makeValibotEnumExpression(values) {
|
|
101
|
-
return `picklist([${values.map((v) => `'${v}'`).join(", ")}])`;
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Format enum values as ArkType union expression
|
|
105
|
-
*/
|
|
106
|
-
function makeArktypeEnumExpression(values) {
|
|
107
|
-
return `"${values.map((v) => `'${v}'`).join(" | ")}"`;
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Format enum values as Effect Schema.Literal expression
|
|
111
|
-
*/
|
|
112
|
-
function makeEffectEnumExpression(values) {
|
|
113
|
-
return `Schema.Literal(${values.map((v) => `'${v}'`).join(", ")})`;
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Create a properties generator for a specific validation library
|
|
117
|
-
*/
|
|
118
|
-
function makePropertiesGenerator(libraryPrefix, wrapCardinality) {
|
|
119
|
-
return function makeProperties(modelFields, includeComments) {
|
|
120
|
-
return modelFields.filter((field) => field.validation).map((field) => {
|
|
121
|
-
const cleanLines = field.comment.filter((line) => !(line.includes("@relation") || line.includes("@v") || line.includes("@z")));
|
|
122
|
-
const docComment = includeComments && cleanLines.length > 0 ? ` /**\n${cleanLines.map((line) => ` * ${line}`).join("\n")}\n */\n` : "";
|
|
123
|
-
const base = `${libraryPrefix}.${field.validation}`;
|
|
124
|
-
const wrapped = wrapCardinality ? wrapCardinality(base, field.isRequired) : base;
|
|
125
|
-
return `${docComment} ${field.fieldName}: ${wrapped}`;
|
|
126
|
-
}).join(",\n");
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* Create Zod type inference line
|
|
131
|
-
*/
|
|
132
|
-
function makeZodInfer(modelName) {
|
|
133
|
-
return `export type ${modelName} = z.infer<typeof ${modelName}Schema>`;
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Generate Zod schema
|
|
137
|
-
*/
|
|
138
|
-
function makeZodSchema(modelName, fields) {
|
|
139
|
-
return `export const ${modelName}Schema = z.object({\n${fields}\n})`;
|
|
140
|
-
}
|
|
141
|
-
/**
|
|
142
|
-
* Create Valibot type inference line
|
|
143
|
-
*/
|
|
144
|
-
function makeValibotInfer(modelName) {
|
|
145
|
-
return `export type ${modelName} = v.InferInput<typeof ${modelName}Schema>`;
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* Generate Valibot schema
|
|
149
|
-
*/
|
|
150
|
-
function makeValibotSchema(modelName, fields) {
|
|
151
|
-
return `export const ${modelName}Schema = v.object({\n${fields}\n})`;
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* Generate ArkType infer type statement.
|
|
155
|
-
*/
|
|
156
|
-
function makeArktypeInfer(modelName) {
|
|
157
|
-
return `export type ${modelName} = typeof ${modelName}Schema.infer`;
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* Generate ArkType schema
|
|
161
|
-
*/
|
|
162
|
-
function makeArktypeSchema(modelName, fields) {
|
|
163
|
-
return `export const ${modelName}Schema = type({\n${fields}\n})`;
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* Generate properties for ArkType schema.
|
|
167
|
-
*/
|
|
168
|
-
function makeArktypeProperties(fields, comment) {
|
|
169
|
-
return fields.map((field) => {
|
|
170
|
-
return `${comment && field.comment.length > 0 ? `${field.comment.map((c) => ` /** ${c} */`).join("\n")}\n` : ""} ${field.fieldName}: ${field.validation ?? "\"unknown\""},`;
|
|
171
|
-
}).join("\n");
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
* Generate Effect Schema infer type statement.
|
|
175
|
-
*/
|
|
176
|
-
function makeEffectInfer(modelName) {
|
|
177
|
-
return `export type ${modelName} = Schema.Schema.Type<typeof ${modelName}Schema>`;
|
|
178
|
-
}
|
|
179
|
-
/**
|
|
180
|
-
* Generate Effect Schema
|
|
181
|
-
*/
|
|
182
|
-
function makeEffectSchema(modelName, fields) {
|
|
183
|
-
return `export const ${modelName}Schema = Schema.Struct({\n${fields}\n})`;
|
|
184
|
-
}
|
|
185
|
-
/**
|
|
186
|
-
* Generate properties for Effect Schema.
|
|
187
|
-
*/
|
|
188
|
-
function makeEffectProperties(fields, comment) {
|
|
189
|
-
return fields.map((field) => {
|
|
190
|
-
return `${comment && field.comment.length > 0 ? `${field.comment.map((c) => ` /** ${c} */`).join("\n")}\n` : ""} ${field.fieldName}: ${field.validation ?? "Schema.Unknown"},`;
|
|
191
|
-
}).join("\n");
|
|
192
|
-
}
|
|
193
|
-
/**
|
|
194
|
-
* Remove duplicate relation lines from an array of Mermaid ER diagram relations.
|
|
195
|
-
*/
|
|
196
|
-
function removeDuplicateRelations(relations) {
|
|
197
|
-
return [...new Set(relations)];
|
|
198
|
-
}
|
|
199
|
-
function escapeNote(str) {
|
|
200
|
-
return str.replace(/'/g, "\\'");
|
|
201
|
-
}
|
|
202
|
-
function formatConstraints(constraints) {
|
|
203
|
-
return constraints.length > 0 ? ` [${constraints.join(", ")}]` : "";
|
|
204
|
-
}
|
|
205
|
-
function makeEnum(enumDef) {
|
|
206
|
-
return [
|
|
207
|
-
`Enum ${enumDef.name} {`,
|
|
208
|
-
...enumDef.values.map((v) => ` ${v}`),
|
|
209
|
-
"}"
|
|
210
|
-
].join("\n");
|
|
211
|
-
}
|
|
212
|
-
function makeRefName(ref) {
|
|
213
|
-
return ref.name ?? `${ref.fromTable}_${ref.fromColumn}_${ref.toTable}_${ref.toColumn}_fk`;
|
|
214
|
-
}
|
|
215
|
-
/**
|
|
216
|
-
* Strip validation annotations (@z.*, @v.*, @a.*, @e.*) and relation annotations (@relation) from documentation
|
|
217
|
-
*/
|
|
218
|
-
function stripAnnotations(doc) {
|
|
219
|
-
if (!doc) return void 0;
|
|
220
|
-
const result = doc.split("\n").filter((line) => {
|
|
221
|
-
const trimmed = line.trim();
|
|
222
|
-
return !(trimmed.startsWith("@z.") || trimmed.startsWith("@v.") || trimmed.startsWith("@a.") || trimmed.startsWith("@e.") || trimmed.startsWith("@relation") || trimmed === "@z" || trimmed === "@v" || trimmed === "@a" || trimmed === "@e");
|
|
223
|
-
}).join("\n").trim();
|
|
224
|
-
return result.length > 0 ? result : void 0;
|
|
225
|
-
}
|
|
226
|
-
/**
|
|
227
|
-
* Combine keys for composite foreign keys
|
|
228
|
-
*/
|
|
229
|
-
function combineKeys(keys) {
|
|
230
|
-
return keys.length > 1 ? `(${keys.join(", ")})` : keys[0];
|
|
231
|
-
}
|
|
232
|
-
/**
|
|
233
|
-
* Convert Prisma type to Ecto type
|
|
234
|
-
*/
|
|
235
|
-
function prismaTypeToEctoType(type) {
|
|
236
|
-
if (type === "Int") return "integer";
|
|
237
|
-
if (type === "BigInt") return "integer";
|
|
238
|
-
if (type === "Float") return "float";
|
|
239
|
-
if (type === "Decimal") return "decimal";
|
|
240
|
-
if (type === "String") return "string";
|
|
241
|
-
if (type === "Boolean") return "boolean";
|
|
242
|
-
if (type === "DateTime") return "utc_datetime";
|
|
243
|
-
if (type === "Json") return "map";
|
|
244
|
-
if (type === "Bytes") return "binary";
|
|
245
|
-
return "string";
|
|
246
|
-
}
|
|
247
|
-
/**
|
|
248
|
-
* Convert Ecto type to Elixir typespec
|
|
249
|
-
*/
|
|
250
|
-
function ectoTypeToTypespec(type) {
|
|
251
|
-
switch (type) {
|
|
252
|
-
case "string": return "String.t()";
|
|
253
|
-
case "integer": return "integer()";
|
|
254
|
-
case "float": return "float()";
|
|
255
|
-
case "boolean": return "boolean()";
|
|
256
|
-
case "binary_id": return "Ecto.UUID.t()";
|
|
257
|
-
case "naive_datetime": return "NaiveDateTime.t()";
|
|
258
|
-
case "utc_datetime": return "DateTime.t()";
|
|
259
|
-
case "decimal": return "Decimal.t()";
|
|
260
|
-
case "map": return "map()";
|
|
261
|
-
case "binary": return "binary()";
|
|
262
|
-
default: return "term()";
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
/**
|
|
266
|
-
* Group valid fields by their model name.
|
|
267
|
-
*/
|
|
268
|
-
function groupByModel(validFields) {
|
|
269
|
-
const raw = Object.groupBy(validFields, (f) => f.modelName);
|
|
270
|
-
return Object.fromEntries(Object.entries(raw).filter((entry) => entry[1] != null));
|
|
271
|
-
}
|
|
272
|
-
/**
|
|
273
|
-
* Extract fields with validation from a nested array of model fields.
|
|
274
|
-
*/
|
|
275
|
-
function isFields(modelFields) {
|
|
276
|
-
return modelFields.flat().filter((field) => field.validation !== null);
|
|
277
|
-
}
|
|
278
|
-
/**
|
|
279
|
-
* Creates schema from model fields.
|
|
280
|
-
*/
|
|
281
|
-
function schemaFromFields(modelFields, comment, schemaBuilder, propertiesGenerator) {
|
|
282
|
-
const modelName = modelFields[0].modelName;
|
|
283
|
-
return schemaBuilder(modelName, propertiesGenerator(modelFields, comment));
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
//#endregion
|
|
287
|
-
export { removeDuplicateRelations as A, makeValibotSchema as C, makeZodSchema as D, makeZodInfer as E, writeFileBinary as F, stripAnnotations as M, mkdir as N, parseDocumentWithoutAnnotations as O, writeFile as P, makeValibotInfer as S, makeZodEnumExpression as T, makeEnum as _, getBool as a, makeSnakeCase as b, isFields as c, makeArktypeProperties as d, makeArktypeSchema as f, makeEffectSchema as g, makeEffectProperties as h, formatConstraints as i, schemaFromFields as j, prismaTypeToEctoType as k, makeArktypeEnumExpression as l, makeEffectInfer as m, ectoTypeToTypespec as n, getString as o, makeEffectEnumExpression as p, escapeNote as r, groupByModel as s, combineKeys as t, makeArktypeInfer as u, makePropertiesGenerator as v, makeValidationExtractor as w, makeValibotEnumExpression as x, makeRefName as y };
|