hekireki 0.7.6 → 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/generator/drizzle/index.js +50 -53
- package/package.json +1 -1
|
@@ -5,6 +5,14 @@ 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);
|
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",
|