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.
@@ -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
- var ImportTracker = class {
101
- coreFns = /* @__PURE__ */ new Set();
102
- ormFns = /* @__PURE__ */ new Set();
103
- extPkgs = /* @__PURE__ */ new Map();
104
- provider;
105
- constructor(provider) {
106
- this.provider = provider;
107
- }
108
- addCore(fn) {
109
- this.coreFns.add(fn);
110
- }
111
- addOrm(fn) {
112
- this.ormFns.add(fn);
113
- }
114
- addExternal(pkg, fn) {
115
- const fns = this.extPkgs.get(pkg) ?? /* @__PURE__ */ new Set();
116
- fns.add(fn);
117
- this.extPkgs.set(pkg, fns);
118
- }
119
- generate() {
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.addCore("pgEnum");
149
+ imports.core.add("pgEnum");
150
150
  return `pgEnum('${enumDef?.dbName ?? field.type}', [${enumValues}])('${colName}')`;
151
151
  }
152
152
  if (provider === "mysql") {
153
- imports.addCore("mysqlEnum");
153
+ imports.core.add("mysqlEnum");
154
154
  return `mysqlEnum('${colName}', [${enumValues}])`;
155
155
  }
156
- imports.addCore("text");
156
+ imports.core.add("text");
157
157
  return `text('${colName}', { enum: [${enumValues}] })`;
158
158
  }
159
159
  if (isAutoincrement && provider === "postgresql") {
160
- imports.addCore("serial");
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.addCore(fnName);
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.addOrm("sql");
265
- if (result.needsCuid) imports.addExternal("@paralleldrive/cuid2", "createId");
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.addOrm("sql");
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.addCore("primaryKey");
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.addCore("unique");
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.addCore("index");
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.addCore(tableFunc);
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.addOrm("relations");
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
- switch (provider) {
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.generate(),
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.6",
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",