hekireki 0.7.5 → 0.7.7
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/dist/cli/index.d.ts +48 -5
- package/dist/cli/index.js +9 -4
- package/dist/generator/ajv/index.js +4 -4
- package/dist/generator/arktype/index.js +6 -6
- package/dist/generator/dbml/index.js +1 -1
- package/dist/generator/drizzle/index.js +51 -54
- package/dist/generator/ecto/index.js +1 -1
- package/dist/generator/effect/index.js +2 -2
- package/dist/generator/gorm/index.js +1 -1
- package/dist/generator/mermaid-er/index.js +1 -1
- package/dist/generator/sea-orm/index.js +1 -1
- package/dist/generator/sqlalchemy/index.js +1 -1
- package/dist/generator/typebox/index.js +7 -6
- package/dist/generator/valibot/index.js +6 -6
- package/dist/generator/zod/index.js +6 -6
- package/dist/{prisma-CfcdmYJs.js → prisma-o4IvnEUh.js} +8 -5
- package/dist/{utils-BGe939v0.js → utils-3ot3YB3D.js} +15 -3
- package/package.json +1 -1
package/dist/cli/index.d.ts
CHANGED
|
@@ -1,14 +1,57 @@
|
|
|
1
1
|
//#region src/cli/index.d.ts
|
|
2
|
-
|
|
2
|
+
declare const HELP_TEXT = "\u26A1\uFE0F hekireki - Prisma schema tools\n\nUsage:\n hekireki <command> [options]\n\nCommands:\n docs serve Start a local server to view the documentation\n\nOptions:\n -p, --port <port> Specify the port (default: 5858)\n -h, --help Show help\n\nExamples:\n hekireki docs serve\n hekireki docs serve -p 3000";
|
|
3
|
+
declare const DOCS_HELP_TEXT = "\u26A1\uFE0F hekireki docs - Documentation tools\n\nUsage:\n hekireki docs serve [options]\n\nCommands:\n serve Start a local server to view the documentation\n\nOptions:\n -p, --port <port> Specify the port (default: 5858)\n -h, --help Show help\n\nExamples:\n hekireki docs serve\n hekireki docs serve -p 3000";
|
|
4
|
+
/**
|
|
5
|
+
* Parse port from CLI arguments.
|
|
6
|
+
*/
|
|
7
|
+
declare const parsePort: (args: readonly string[]) => {
|
|
8
|
+
readonly ok: true;
|
|
9
|
+
readonly value: number;
|
|
10
|
+
} | {
|
|
11
|
+
readonly ok: false;
|
|
12
|
+
readonly error: string;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Parse CLI arguments for docs serve command.
|
|
16
|
+
*/
|
|
17
|
+
declare const parseDocsServeArgs: (args: readonly string[]) => {
|
|
18
|
+
readonly ok: true;
|
|
19
|
+
readonly value: {
|
|
20
|
+
readonly port: number;
|
|
21
|
+
};
|
|
22
|
+
} | {
|
|
23
|
+
readonly ok: false;
|
|
24
|
+
readonly error: string;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Handle docs subcommand.
|
|
28
|
+
*/
|
|
29
|
+
declare const handleDocs: (args: readonly string[]) => {
|
|
30
|
+
readonly ok: true;
|
|
31
|
+
readonly value: string;
|
|
32
|
+
} | {
|
|
33
|
+
readonly ok: false;
|
|
34
|
+
readonly error: string;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Main CLI dispatcher (pure — takes args, returns Result).
|
|
38
|
+
*/
|
|
39
|
+
declare const hekirekiCli: (args: readonly string[]) => {
|
|
3
40
|
readonly ok: true;
|
|
4
|
-
readonly value:
|
|
41
|
+
readonly value: string;
|
|
5
42
|
} | {
|
|
6
43
|
readonly ok: false;
|
|
7
44
|
readonly error: string;
|
|
8
45
|
};
|
|
9
46
|
/**
|
|
10
|
-
* Main CLI entry point for hekireki.
|
|
47
|
+
* Main CLI entry point for hekireki (reads process.argv).
|
|
11
48
|
*/
|
|
12
|
-
declare const hekireki: () =>
|
|
49
|
+
declare const hekireki: () => {
|
|
50
|
+
readonly ok: true;
|
|
51
|
+
readonly value: string;
|
|
52
|
+
} | {
|
|
53
|
+
readonly ok: false;
|
|
54
|
+
readonly error: string;
|
|
55
|
+
};
|
|
13
56
|
//#endregion
|
|
14
|
-
export { hekireki };
|
|
57
|
+
export { DOCS_HELP_TEXT, HELP_TEXT, handleDocs, hekireki, hekirekiCli, parseDocsServeArgs, parsePort };
|
package/dist/cli/index.js
CHANGED
|
@@ -137,10 +137,9 @@ const handleDocs = (args) => {
|
|
|
137
137
|
*/
|
|
138
138
|
const commands = { docs: handleDocs };
|
|
139
139
|
/**
|
|
140
|
-
* Main CLI
|
|
140
|
+
* Main CLI dispatcher (pure — takes args, returns Result).
|
|
141
141
|
*/
|
|
142
|
-
const
|
|
143
|
-
const args = process.argv.slice(2);
|
|
142
|
+
const hekirekiCli = (args) => {
|
|
144
143
|
const command = args[0];
|
|
145
144
|
if (!command || command === "-h" || command === "--help") return {
|
|
146
145
|
ok: true,
|
|
@@ -153,6 +152,12 @@ const hekireki = () => {
|
|
|
153
152
|
};
|
|
154
153
|
return handler(args.slice(1));
|
|
155
154
|
};
|
|
155
|
+
/**
|
|
156
|
+
* Main CLI entry point for hekireki (reads process.argv).
|
|
157
|
+
*/
|
|
158
|
+
const hekireki = () => {
|
|
159
|
+
return hekirekiCli(process.argv.slice(2));
|
|
160
|
+
};
|
|
156
161
|
const result = hekireki();
|
|
157
162
|
if (result.ok) console.log(result.value);
|
|
158
163
|
else {
|
|
@@ -161,4 +166,4 @@ else {
|
|
|
161
166
|
}
|
|
162
167
|
|
|
163
168
|
//#endregion
|
|
164
|
-
export { hekireki };
|
|
169
|
+
export { DOCS_HELP_TEXT, HELP_TEXT, handleDocs, hekireki, hekirekiCli, parseDocsServeArgs, parsePort };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { t as fmt } from "../../format-DwiYldCm.js";
|
|
3
|
-
import {
|
|
4
|
-
import { n as validationSchemas, t as makeRelationsOnly } from "../../prisma-
|
|
3
|
+
import { l as makeValidationExtractor, m as writeFile, n as getBool, o as makeCommentBlock, p as mkdir, u as parseDocumentWithoutAnnotations } from "../../utils-3ot3YB3D.js";
|
|
4
|
+
import { n as validationSchemas, t as makeRelationsOnly } from "../../prisma-o4IvnEUh.js";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import pkg from "@prisma/generator-helper";
|
|
7
7
|
|
|
@@ -37,13 +37,13 @@ const PRISMA_TO_AJV = {
|
|
|
37
37
|
* @param modelFields - The fields of the model
|
|
38
38
|
* @param comment - Whether to include JSDoc comments in the generated code
|
|
39
39
|
*/
|
|
40
|
-
function makeAjvSchemas(modelFields, comment) {
|
|
40
|
+
function makeAjvSchemas(modelFields, comment, objectType) {
|
|
41
41
|
const modelName = modelFields[0].modelName;
|
|
42
42
|
const properties = modelFields.map((field) => {
|
|
43
43
|
return `${comment ? makeCommentBlock(field.comment, 4) : ""} ${field.fieldName}: ${field.validation ?? "{ type: 'unknown' as const }"},`;
|
|
44
44
|
}).join("\n");
|
|
45
45
|
const requiredFields = modelFields.filter((f) => f.isRequired).map((f) => f.fieldName);
|
|
46
|
-
return `export const ${modelName}Schema = {\n type: 'object' as const,\n properties: {\n${properties}\n },${requiredFields.length > 0 ? `\n required: [${requiredFields.map((f) => `'${f}'`).join(", ")}] as const,` : ""}\n additionalProperties: false,\n} as const`;
|
|
46
|
+
return `export const ${modelName}Schema = {\n type: 'object' as const,\n properties: {\n${properties}\n },${requiredFields.length > 0 ? `\n required: [${requiredFields.map((f) => `'${f}'`).join(", ")}] as const,` : ""}\n additionalProperties: ${objectType === "loose" ? "true" : "false"},\n} as const`;
|
|
47
47
|
}
|
|
48
48
|
/**
|
|
49
49
|
* Generate JSON Schema relation object definition
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { t as fmt } from "../../format-DwiYldCm.js";
|
|
3
|
-
import {
|
|
4
|
-
import { n as validationSchemas, t as makeRelationsOnly } from "../../prisma-
|
|
3
|
+
import { d as schemaFromFields, l as makeValidationExtractor, m as writeFile, n as getBool, o as makeCommentBlock, p as mkdir, u as parseDocumentWithoutAnnotations } from "../../utils-3ot3YB3D.js";
|
|
4
|
+
import { n as validationSchemas, t as makeRelationsOnly } from "../../prisma-o4IvnEUh.js";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import pkg from "@prisma/generator-helper";
|
|
7
7
|
|
|
@@ -18,8 +18,8 @@ function makeArktypeInfer(modelName) {
|
|
|
18
18
|
* @param modelName - The model name for the schema
|
|
19
19
|
* @param fields - The formatted field definitions string
|
|
20
20
|
*/
|
|
21
|
-
function makeArktypeSchema(modelName, fields) {
|
|
22
|
-
return `export const ${modelName}Schema = type({\n${fields}\n})`;
|
|
21
|
+
function makeArktypeSchema(modelName, fields, objectType) {
|
|
22
|
+
return `export const ${modelName}Schema = type({${objectType === "strict" ? "\n \"+\": \"reject\",\n" : objectType === "loose" ? "\n \"+\": \"ignore\",\n" : "\n"}${fields}\n})`;
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
25
25
|
* Generate ArkType property definitions
|
|
@@ -55,8 +55,8 @@ const PRISMA_TO_ARKTYPE = {
|
|
|
55
55
|
* @param modelFields - The fields of the model
|
|
56
56
|
* @param comment - Whether to include JSDoc comments in the generated code
|
|
57
57
|
*/
|
|
58
|
-
function makeArktypeSchemas(modelFields, comment) {
|
|
59
|
-
return schemaFromFields(modelFields, comment, makeArktypeSchema, makeArktypeProperties);
|
|
58
|
+
function makeArktypeSchemas(modelFields, comment, objectType) {
|
|
59
|
+
return schemaFromFields(modelFields, comment, makeArktypeSchema, makeArktypeProperties, objectType);
|
|
60
60
|
}
|
|
61
61
|
/**
|
|
62
62
|
* Generate ArkType relation schema definition
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { f as stripAnnotations, h as writeFileBinary, m as writeFile, p as mkdir, r as getString } from "../../utils-3ot3YB3D.js";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import pkg from "@prisma/generator-helper";
|
|
5
5
|
import { Resvg } from "@resvg/resvg-js";
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { t as fmt } from "../../format-DwiYldCm.js";
|
|
3
|
-
import {
|
|
3
|
+
import { c as makeSnakeCase, m as writeFile, p as mkdir } from "../../utils-3ot3YB3D.js";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import pkg from "@prisma/generator-helper";
|
|
6
6
|
|
|
7
7
|
//#region src/helper/drizzle.ts
|
|
8
|
+
function resolveDbProvider(provider) {
|
|
9
|
+
switch (provider) {
|
|
10
|
+
case "postgresql":
|
|
11
|
+
case "cockroachdb": return "postgresql";
|
|
12
|
+
case "mysql": return "mysql";
|
|
13
|
+
case "sqlite": return "sqlite";
|
|
14
|
+
}
|
|
15
|
+
}
|
|
8
16
|
const PG_SCALAR_MAP = {
|
|
9
17
|
String: "text()",
|
|
10
18
|
Int: "integer()",
|
|
@@ -97,34 +105,26 @@ function mysqlNativeType(name, args) {
|
|
|
97
105
|
default: return null;
|
|
98
106
|
}
|
|
99
107
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
const mod = this.provider === "postgresql" ? "drizzle-orm/pg-core" : this.provider === "mysql" ? "drizzle-orm/mysql-core" : "drizzle-orm/sqlite-core";
|
|
121
|
-
return [
|
|
122
|
-
this.coreFns.size > 0 ? `import { ${[...this.coreFns].sort().join(", ")} } from '${mod}'` : "",
|
|
123
|
-
this.ormFns.size > 0 ? `import { ${[...this.ormFns].sort().join(", ")} } from 'drizzle-orm'` : "",
|
|
124
|
-
...[...this.extPkgs.entries()].map(([pkg, fns]) => `import { ${[...fns].sort().join(", ")} } from '${pkg}'`)
|
|
125
|
-
].filter(Boolean).join("\n");
|
|
126
|
-
}
|
|
127
|
-
};
|
|
108
|
+
function createImports() {
|
|
109
|
+
return {
|
|
110
|
+
core: /* @__PURE__ */ new Set(),
|
|
111
|
+
orm: /* @__PURE__ */ new Set(),
|
|
112
|
+
ext: /* @__PURE__ */ new Map()
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function addExternal(imports, pkg, fn) {
|
|
116
|
+
const fns = imports.ext.get(pkg) ?? /* @__PURE__ */ new Set();
|
|
117
|
+
fns.add(fn);
|
|
118
|
+
imports.ext.set(pkg, fns);
|
|
119
|
+
}
|
|
120
|
+
function generateImports(imports, provider) {
|
|
121
|
+
const mod = provider === "postgresql" ? "drizzle-orm/pg-core" : provider === "mysql" ? "drizzle-orm/mysql-core" : "drizzle-orm/sqlite-core";
|
|
122
|
+
return [
|
|
123
|
+
imports.core.size > 0 ? `import { ${[...imports.core].sort().join(", ")} } from '${mod}'` : "",
|
|
124
|
+
imports.orm.size > 0 ? `import { ${[...imports.orm].sort().join(", ")} } from 'drizzle-orm'` : "",
|
|
125
|
+
...[...imports.ext.entries()].map(([pkg, fns]) => `import { ${[...fns].sort().join(", ")} } from '${pkg}'`)
|
|
126
|
+
].filter(Boolean).join("\n");
|
|
127
|
+
}
|
|
128
128
|
function toCamelCase(name) {
|
|
129
129
|
return name.charAt(0).toLowerCase() + name.slice(1);
|
|
130
130
|
}
|
|
@@ -146,23 +146,23 @@ function makeColumnExpr(field, provider, imports, enums) {
|
|
|
146
146
|
const enumDef = enums.find((e) => e.name === field.type);
|
|
147
147
|
const enumValues = enumDef ? enumDef.values.map((v) => `'${v.name}'`).join(", ") : "";
|
|
148
148
|
if (provider === "postgresql") {
|
|
149
|
-
imports.
|
|
149
|
+
imports.core.add("pgEnum");
|
|
150
150
|
return `pgEnum('${enumDef?.dbName ?? field.type}', [${enumValues}])('${colName}')`;
|
|
151
151
|
}
|
|
152
152
|
if (provider === "mysql") {
|
|
153
|
-
imports.
|
|
153
|
+
imports.core.add("mysqlEnum");
|
|
154
154
|
return `mysqlEnum('${colName}', [${enumValues}])`;
|
|
155
155
|
}
|
|
156
|
-
imports.
|
|
156
|
+
imports.core.add("text");
|
|
157
157
|
return `text('${colName}', { enum: [${enumValues}] })`;
|
|
158
158
|
}
|
|
159
159
|
if (isAutoincrement && provider === "postgresql") {
|
|
160
|
-
imports.
|
|
160
|
+
imports.core.add("serial");
|
|
161
161
|
return `serial('${colName}')`;
|
|
162
162
|
}
|
|
163
163
|
const baseExpr = resolveScalarType(field, provider);
|
|
164
164
|
const fnName = baseExpr.match(/^(\w+)/)?.[1];
|
|
165
|
-
if (fnName) imports.
|
|
165
|
+
if (fnName) imports.core.add(fnName);
|
|
166
166
|
const parenIdx = baseExpr.indexOf("(");
|
|
167
167
|
if (parenIdx === -1) return baseExpr;
|
|
168
168
|
const baseFnName = baseExpr.slice(0, parenIdx);
|
|
@@ -261,8 +261,8 @@ function resolveUpdatedAtDefault(provider) {
|
|
|
261
261
|
}
|
|
262
262
|
function makeDefaultChain(dflt, fieldType, provider, imports) {
|
|
263
263
|
const result = resolveDefaultValue(dflt, fieldType, provider);
|
|
264
|
-
if (result.needsSql) imports.
|
|
265
|
-
if (result.needsCuid)
|
|
264
|
+
if (result.needsSql) imports.orm.add("sql");
|
|
265
|
+
if (result.needsCuid) addExternal(imports, "@paralleldrive/cuid2", "createId");
|
|
266
266
|
return result.chain;
|
|
267
267
|
}
|
|
268
268
|
const PRISMA_ACTION_MAP = {
|
|
@@ -275,6 +275,7 @@ const PRISMA_ACTION_MAP = {
|
|
|
275
275
|
function makeFkReference(field, model) {
|
|
276
276
|
const relField = model.fields.find((f) => f.kind === "object" && f.relationFromFields && f.relationFromFields.includes(field.name));
|
|
277
277
|
if (!(relField?.relationFromFields && relField.relationToFields)) return "";
|
|
278
|
+
if (relField.type === model.name) return "";
|
|
278
279
|
const targetVar = toCamelCase(relField.type);
|
|
279
280
|
const toCol = relField.relationToFields[0] ?? "id";
|
|
280
281
|
const onDelete = relField.relationOnDelete;
|
|
@@ -294,7 +295,7 @@ function makeColumn(field, model, provider, imports, enums) {
|
|
|
294
295
|
makeFkReference(field, model),
|
|
295
296
|
isAutoincrement ? provider === "mysql" ? ".autoincrement()" : "" : field.isUpdatedAt && (field.default === void 0 || field.default === null) ? (() => {
|
|
296
297
|
const r = resolveUpdatedAtDefault(provider);
|
|
297
|
-
if (r.needsSql) imports.
|
|
298
|
+
if (r.needsSql) imports.orm.add("sql");
|
|
298
299
|
return r.chain;
|
|
299
300
|
})() : makeDefaultChain(field.default, field.type, provider, imports),
|
|
300
301
|
field.isUpdatedAt ? ".$onUpdate(() => new Date())" : "",
|
|
@@ -304,15 +305,15 @@ function makeColumn(field, model, provider, imports, enums) {
|
|
|
304
305
|
}
|
|
305
306
|
function makeCompositeConstraints(model, imports, indexes, tableName) {
|
|
306
307
|
const pkLine = model.primaryKey ? (() => {
|
|
307
|
-
imports.
|
|
308
|
+
imports.core.add("primaryKey");
|
|
308
309
|
return `primaryKey({ columns: [${model.primaryKey.fields.map((f) => `table.${f}`).join(", ")}] })`;
|
|
309
310
|
})() : null;
|
|
310
311
|
const uniqueLines = model.uniqueFields.filter((fields) => fields.length > 1).map((fields) => {
|
|
311
|
-
imports.
|
|
312
|
+
imports.core.add("unique");
|
|
312
313
|
return `unique().on(${fields.map((f) => `table.${f}`).join(", ")})`;
|
|
313
314
|
});
|
|
314
315
|
const indexLines = indexes.filter((idx) => idx.model === model.name && (idx.type === "normal" || idx.type === "fulltext")).map((idx) => {
|
|
315
|
-
imports.
|
|
316
|
+
imports.core.add("index");
|
|
316
317
|
return `index('${idx.dbName ?? idx.name ?? `idx_${tableName}_${idx.fields.map((f) => f.name).join("_")}`}').on(${idx.fields.map((f) => `table.${f.name}`).join(", ")})`;
|
|
317
318
|
});
|
|
318
319
|
const all = [
|
|
@@ -324,7 +325,7 @@ function makeCompositeConstraints(model, imports, indexes, tableName) {
|
|
|
324
325
|
}
|
|
325
326
|
function makeTable(model, provider, imports, enums, indexes) {
|
|
326
327
|
const tableFunc = provider === "postgresql" ? "pgTable" : provider === "mysql" ? "mysqlTable" : "sqliteTable";
|
|
327
|
-
imports.
|
|
328
|
+
imports.core.add(tableFunc);
|
|
328
329
|
const varName = toCamelCase(model.name);
|
|
329
330
|
const tableName = model.dbName ?? makeSnakeCase(model.name);
|
|
330
331
|
const columns = model.fields.map((field) => makeColumn(field, model, provider, imports, enums)).filter((c) => c !== null).join(", ");
|
|
@@ -351,7 +352,7 @@ function makeRelationField(field, model, _models, relFields) {
|
|
|
351
352
|
function makeRelations(models, imports) {
|
|
352
353
|
const modelsWithRels = models.filter((model) => model.fields.some((f) => f.kind === "object"));
|
|
353
354
|
if (modelsWithRels.length === 0) return [];
|
|
354
|
-
imports.
|
|
355
|
+
imports.orm.add("relations");
|
|
355
356
|
return modelsWithRels.map((model) => {
|
|
356
357
|
const relFields = model.fields.filter((f) => f.kind === "object");
|
|
357
358
|
const fieldLines = relFields.map((field) => makeRelationField(field, model, models, relFields)).join(", ");
|
|
@@ -362,22 +363,14 @@ function makeRelations(models, imports) {
|
|
|
362
363
|
});
|
|
363
364
|
}
|
|
364
365
|
function drizzleSchema(datamodel, provider, indexes) {
|
|
365
|
-
const db = (
|
|
366
|
-
|
|
367
|
-
case "postgresql":
|
|
368
|
-
case "cockroachdb": return "postgresql";
|
|
369
|
-
case "mysql": return "mysql";
|
|
370
|
-
case "sqlite": return "sqlite";
|
|
371
|
-
default: throw new Error(`Unsupported provider: ${provider}`);
|
|
372
|
-
}
|
|
373
|
-
})();
|
|
374
|
-
const imports = new ImportTracker(db);
|
|
366
|
+
const db = resolveDbProvider(provider);
|
|
367
|
+
const imports = createImports();
|
|
375
368
|
const tableLines = datamodel.models.map((model) => makeTable(model, db, imports, datamodel.enums, indexes));
|
|
376
369
|
const relationsLines = makeRelations(datamodel.models, imports);
|
|
377
370
|
const tableLinesWithGap = tableLines.flatMap((line, i) => i < tableLines.length - 1 ? [line, ""] : [line]);
|
|
378
371
|
const relationsLinesWithGap = relationsLines.flatMap((line, i) => i < relationsLines.length - 1 ? [line, ""] : [line]);
|
|
379
372
|
return [
|
|
380
|
-
imports
|
|
373
|
+
generateImports(imports, db),
|
|
381
374
|
"",
|
|
382
375
|
...tableLinesWithGap,
|
|
383
376
|
...relationsLinesWithGap.length > 0 ? ["", ...relationsLinesWithGap] : []
|
|
@@ -387,6 +380,10 @@ function drizzleSchema(datamodel, provider, indexes) {
|
|
|
387
380
|
//#endregion
|
|
388
381
|
//#region src/generator/drizzle/index.ts
|
|
389
382
|
const { generatorHandler } = pkg;
|
|
383
|
+
function parsePrismaProvider(raw) {
|
|
384
|
+
if (raw === "postgresql" || raw === "cockroachdb" || raw === "mysql" || raw === "sqlite") return raw;
|
|
385
|
+
throw new Error(`Unsupported provider: ${raw}`);
|
|
386
|
+
}
|
|
390
387
|
async function main(options) {
|
|
391
388
|
if (!(options.generator.isCustomOutput && options.generator.output?.value)) throw new Error("output is required for Hekireki-Drizzle. Please specify output in your generator config.");
|
|
392
389
|
const output = options.generator.output.value;
|
|
@@ -397,7 +394,7 @@ async function main(options) {
|
|
|
397
394
|
dir: output,
|
|
398
395
|
file: path.join(output, "schema.ts")
|
|
399
396
|
};
|
|
400
|
-
const provider = options.datasources[0]?.activeProvider ?? "postgresql";
|
|
397
|
+
const provider = parsePrismaProvider(options.datasources[0]?.activeProvider ?? "postgresql");
|
|
401
398
|
const formatted = await fmt(drizzleSchema(options.dmmf.datamodel, provider, options.dmmf.datamodel.indexes));
|
|
402
399
|
await mkdir(resolved.dir);
|
|
403
400
|
await writeFile(resolved.file, formatted);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { c as makeSnakeCase, m as writeFile, p as mkdir } from "../../utils-3ot3YB3D.js";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import pkg from "@prisma/generator-helper";
|
|
5
5
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { t as fmt } from "../../format-DwiYldCm.js";
|
|
3
|
-
import {
|
|
4
|
-
import { n as validationSchemas, t as makeRelationsOnly } from "../../prisma-
|
|
3
|
+
import { d as schemaFromFields, l as makeValidationExtractor, m as writeFile, n as getBool, o as makeCommentBlock, p as mkdir, u as parseDocumentWithoutAnnotations } from "../../utils-3ot3YB3D.js";
|
|
4
|
+
import { n as validationSchemas, t as makeRelationsOnly } from "../../prisma-o4IvnEUh.js";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import pkg from "@prisma/generator-helper";
|
|
7
7
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { c as makeSnakeCase, m as writeFile, p as mkdir, r as getString } from "../../utils-3ot3YB3D.js";
|
|
3
3
|
import path, { dirname } from "node:path";
|
|
4
4
|
import pkg from "@prisma/generator-helper";
|
|
5
5
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { f as stripAnnotations, m as writeFile, p as mkdir } from "../../utils-3ot3YB3D.js";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import pkg from "@prisma/generator-helper";
|
|
5
5
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { c as makeSnakeCase, m as writeFile, p as mkdir, r as getString } from "../../utils-3ot3YB3D.js";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import pkg from "@prisma/generator-helper";
|
|
5
5
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { c as makeSnakeCase, m as writeFile, p as mkdir } from "../../utils-3ot3YB3D.js";
|
|
3
3
|
import path, { dirname } from "node:path";
|
|
4
4
|
import pkg from "@prisma/generator-helper";
|
|
5
5
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { t as fmt } from "../../format-DwiYldCm.js";
|
|
3
|
-
import {
|
|
4
|
-
import { n as validationSchemas, t as makeRelationsOnly } from "../../prisma-
|
|
3
|
+
import { d as schemaFromFields, l as makeValidationExtractor, m as writeFile, n as getBool, o as makeCommentBlock, p as mkdir, u as parseDocumentWithoutAnnotations } from "../../utils-3ot3YB3D.js";
|
|
4
|
+
import { n as validationSchemas, t as makeRelationsOnly } from "../../prisma-o4IvnEUh.js";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import pkg from "@prisma/generator-helper";
|
|
7
7
|
|
|
@@ -18,8 +18,9 @@ function makeTypeBoxInfer(modelName) {
|
|
|
18
18
|
* @param modelName - The model name for the schema
|
|
19
19
|
* @param fields - The formatted field definitions string
|
|
20
20
|
*/
|
|
21
|
-
function makeTypeBoxSchema(modelName, fields) {
|
|
22
|
-
|
|
21
|
+
function makeTypeBoxSchema(modelName, fields, objectType) {
|
|
22
|
+
const obj = `Type.Object({\n${fields}\n})`;
|
|
23
|
+
return objectType === "strict" ? `export const ${modelName}Schema = Type.Strict(${obj})` : `export const ${modelName}Schema = ${obj}`;
|
|
23
24
|
}
|
|
24
25
|
/**
|
|
25
26
|
* Generate TypeBox property definitions with optional wrapping
|
|
@@ -58,8 +59,8 @@ const PRISMA_TO_TYPEBOX = {
|
|
|
58
59
|
* @param modelFields - The fields of the model
|
|
59
60
|
* @param comment - Whether to include JSDoc comments in the generated code
|
|
60
61
|
*/
|
|
61
|
-
function makeTypeBoxSchemas(modelFields, comment) {
|
|
62
|
-
return schemaFromFields(modelFields, comment, makeTypeBoxSchema, makeTypeBoxProperties);
|
|
62
|
+
function makeTypeBoxSchemas(modelFields, comment, objectType) {
|
|
63
|
+
return schemaFromFields(modelFields, comment, makeTypeBoxSchema, makeTypeBoxProperties, objectType);
|
|
63
64
|
}
|
|
64
65
|
/**
|
|
65
66
|
* Generate TypeBox relation schema definition
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { t as fmt } from "../../format-DwiYldCm.js";
|
|
3
|
-
import {
|
|
4
|
-
import { n as validationSchemas, t as makeRelationsOnly } from "../../prisma-
|
|
3
|
+
import { d as schemaFromFields, l as makeValidationExtractor, m as writeFile, n as getBool, p as mkdir, s as makePropertiesGenerator, u as parseDocumentWithoutAnnotations } from "../../utils-3ot3YB3D.js";
|
|
4
|
+
import { n as validationSchemas, t as makeRelationsOnly } from "../../prisma-o4IvnEUh.js";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import pkg from "@prisma/generator-helper";
|
|
7
7
|
|
|
@@ -9,8 +9,8 @@ import pkg from "@prisma/generator-helper";
|
|
|
9
9
|
function makeValibotInfer(modelName) {
|
|
10
10
|
return `export type ${modelName} = v.InferOutput<typeof ${modelName}Schema>`;
|
|
11
11
|
}
|
|
12
|
-
function makeValibotSchema(modelName, fields) {
|
|
13
|
-
return `export const ${modelName}Schema = v
|
|
12
|
+
function makeValibotSchema(modelName, fields, objectType) {
|
|
13
|
+
return `export const ${modelName}Schema = v.${objectType === "strict" ? "strictObject" : objectType === "loose" ? "looseObject" : "object"}({\n${fields}\n})`;
|
|
14
14
|
}
|
|
15
15
|
function makeValibotEnumExpression(values) {
|
|
16
16
|
return `picklist([${values.map((v) => `'${v}'`).join(", ")}])`;
|
|
@@ -26,8 +26,8 @@ const PRISMA_TO_VALIBOT = {
|
|
|
26
26
|
Json: "unknown()",
|
|
27
27
|
Bytes: "any()"
|
|
28
28
|
};
|
|
29
|
-
function makeValibotSchemas(modelFields, comment) {
|
|
30
|
-
return schemaFromFields(modelFields, comment, makeValibotSchema, makePropertiesGenerator("v", (expr, isRequired) => isRequired ? expr : `v.exactOptional(${expr})`));
|
|
29
|
+
function makeValibotSchemas(modelFields, comment, objectType) {
|
|
30
|
+
return schemaFromFields(modelFields, comment, makeValibotSchema, makePropertiesGenerator("v", (expr, isRequired) => isRequired ? expr : `v.exactOptional(${expr})`), objectType);
|
|
31
31
|
}
|
|
32
32
|
function makeValibotRelations(model, relProps, options) {
|
|
33
33
|
if (relProps.length === 0) return null;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { t as fmt } from "../../format-DwiYldCm.js";
|
|
3
|
-
import {
|
|
4
|
-
import { n as validationSchemas, t as makeRelationsOnly } from "../../prisma-
|
|
3
|
+
import { d as schemaFromFields, l as makeValidationExtractor, m as writeFile, n as getBool, p as mkdir, r as getString, s as makePropertiesGenerator, u as parseDocumentWithoutAnnotations } from "../../utils-3ot3YB3D.js";
|
|
4
|
+
import { n as validationSchemas, t as makeRelationsOnly } from "../../prisma-o4IvnEUh.js";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import pkg from "@prisma/generator-helper";
|
|
7
7
|
|
|
@@ -9,8 +9,8 @@ import pkg from "@prisma/generator-helper";
|
|
|
9
9
|
function makeZodInfer(modelName) {
|
|
10
10
|
return `export type ${modelName} = z.infer<typeof ${modelName}Schema>`;
|
|
11
11
|
}
|
|
12
|
-
function makeZodSchema(modelName, fields) {
|
|
13
|
-
return `export const ${modelName}Schema = z
|
|
12
|
+
function makeZodSchema(modelName, fields, objectType) {
|
|
13
|
+
return `export const ${modelName}Schema = z.${objectType === "strict" ? "strictObject" : objectType === "loose" ? "looseObject" : "object"}({\n${fields}\n})`;
|
|
14
14
|
}
|
|
15
15
|
function makeZodEnumExpression(values) {
|
|
16
16
|
return `enum([${values.map((v) => `'${v}'`).join(", ")}])`;
|
|
@@ -26,8 +26,8 @@ const PRISMA_TO_ZOD = {
|
|
|
26
26
|
Json: "unknown()",
|
|
27
27
|
Bytes: "any()"
|
|
28
28
|
};
|
|
29
|
-
function makeZodSchemas(modelFields, comment) {
|
|
30
|
-
return schemaFromFields(modelFields, comment, makeZodSchema, makePropertiesGenerator("z", (expr, isRequired) => isRequired ? expr : `${expr}.exactOptional()`));
|
|
29
|
+
function makeZodSchemas(modelFields, comment, objectType) {
|
|
30
|
+
return schemaFromFields(modelFields, comment, makeZodSchema, makePropertiesGenerator("z", (expr, isRequired) => isRequired ? expr : `${expr}.exactOptional()`), objectType);
|
|
31
31
|
}
|
|
32
32
|
function makeZodRelations(model, relProps, options) {
|
|
33
33
|
if (relProps.length === 0) return null;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as isFields, i as groupByModel, t as extractObjectType } from "./utils-3ot3YB3D.js";
|
|
2
2
|
|
|
3
3
|
//#region src/helper/prisma.ts
|
|
4
4
|
function collectRelationProps(models) {
|
|
@@ -61,10 +61,13 @@ function validationSchemas(models, type, comment, config) {
|
|
|
61
61
|
fieldName: f.name
|
|
62
62
|
})));
|
|
63
63
|
if (config.onWarning) for (const { modelName, fieldName } of missing) config.onWarning(`Warning: Field "${modelName}.${fieldName}" has no ${config.annotationPrefix} annotation and will be omitted from the schema`);
|
|
64
|
-
const schemas = Object.values(groupByModel(isFields(modelFields))).map((fields) =>
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
const schemas = Object.values(groupByModel(isFields(modelFields))).map((fields) => {
|
|
65
|
+
const objectType = extractObjectType(fields[0].documentation, config.annotationPrefix);
|
|
66
|
+
return {
|
|
67
|
+
schema: config.schemas(fields, comment, objectType),
|
|
68
|
+
inferType: type ? config.inferType(fields[0].modelName) : ""
|
|
69
|
+
};
|
|
70
|
+
}).flatMap(({ schema, inferType }) => [schema, inferType].filter(Boolean)).join("\n\n");
|
|
68
71
|
return config.importStatement ? [
|
|
69
72
|
config.importStatement,
|
|
70
73
|
"",
|
|
@@ -84,10 +84,22 @@ function groupByModel(validFields) {
|
|
|
84
84
|
function isFields(modelFields) {
|
|
85
85
|
return modelFields.flat().filter((field) => field.validation !== null);
|
|
86
86
|
}
|
|
87
|
-
|
|
87
|
+
/**
|
|
88
|
+
* Extract object type (strict/loose) from model documentation.
|
|
89
|
+
*/
|
|
90
|
+
function extractObjectType(documentation, prefix) {
|
|
91
|
+
if (!documentation) return void 0;
|
|
92
|
+
const lines = documentation.split("\n").map((l) => l.trim());
|
|
93
|
+
const prefixWithoutAt = prefix.slice(1);
|
|
94
|
+
const match = lines.find((line) => line.includes(`${prefixWithoutAt}strictObject`) || line.includes(`${prefixWithoutAt}looseObject`));
|
|
95
|
+
if (!match) return void 0;
|
|
96
|
+
if (match.includes("strictObject")) return "strict";
|
|
97
|
+
if (match.includes("looseObject")) return "loose";
|
|
98
|
+
}
|
|
99
|
+
function schemaFromFields(modelFields, comment, schemaBuilder, propertiesGenerator, objectType) {
|
|
88
100
|
const modelName = modelFields[0].modelName;
|
|
89
|
-
return schemaBuilder(modelName, propertiesGenerator(modelFields, comment));
|
|
101
|
+
return schemaBuilder(modelName, propertiesGenerator(modelFields, comment), objectType);
|
|
90
102
|
}
|
|
91
103
|
|
|
92
104
|
//#endregion
|
|
93
|
-
export {
|
|
105
|
+
export { isFields as a, makeSnakeCase as c, schemaFromFields as d, stripAnnotations as f, writeFileBinary as h, groupByModel as i, makeValidationExtractor as l, writeFile as m, getBool as n, makeCommentBlock as o, mkdir as p, getString as r, makePropertiesGenerator as s, extractObjectType as t, parseDocumentWithoutAnnotations as u };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hekireki",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.7",
|
|
4
4
|
"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.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ajv",
|