hekireki 0.8.0 → 0.8.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 +19 -0
- package/dist/bin/ajv.js +2 -4
- package/dist/bin/arktype.js +2 -4
- package/dist/bin/dbml.js +2 -4
- package/dist/bin/docs.js +2 -4
- package/dist/bin/drizzle.js +2 -4
- package/dist/bin/ecto.js +2 -4
- package/dist/bin/effect.js +2 -4
- package/dist/bin/gorm.js +2 -4
- package/dist/bin/mermaid-er.js +2 -4
- package/dist/bin/sea-orm.js +2 -4
- package/dist/bin/sqlalchemy.js +2 -4
- package/dist/bin/typebox.js +2 -4
- package/dist/bin/valibot.js +2 -4
- package/dist/bin/zod.js +2 -4
- package/dist/{bin-BDZ9aq7E.js → bin-B_9WDdSx.js} +202 -90
- package/dist/cli/index.js +1 -3
- package/package.json +21 -21
package/README.md
CHANGED
|
@@ -712,6 +712,25 @@ generator Hekireki-PNG {
|
|
|
712
712
|
}
|
|
713
713
|
```
|
|
714
714
|
|
|
715
|
+
### Logical Relations (without a Foreign Key)
|
|
716
|
+
|
|
717
|
+
To draw a relation that has **no physical foreign key**, add a `/// @relation <Parent>.<field> <Child>.<field> <cardinality>` doc-comment on the model:
|
|
718
|
+
|
|
719
|
+
```prisma
|
|
720
|
+
model User {
|
|
721
|
+
id String @id @default(uuid())
|
|
722
|
+
name String
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
/// @relation User.id Post.userId one-to-many
|
|
726
|
+
model Post {
|
|
727
|
+
id String @id @default(uuid())
|
|
728
|
+
userId String
|
|
729
|
+
}
|
|
730
|
+
```
|
|
731
|
+
|
|
732
|
+
The relation is drawn in both the Mermaid and DBML output even though `Post.userId` has no `@relation(...)` foreign key. When a physical FK and an annotation describe the same pair, the annotation's cardinality wins in the Mermaid diagram.
|
|
733
|
+
|
|
715
734
|
### Docs
|
|
716
735
|
|
|
717
736
|
The `hekireki-docs` generator creates an HTML documentation page from your Prisma schema. Serve it locally with `hekireki docs serve`:
|
package/dist/bin/ajv.js
CHANGED
package/dist/bin/arktype.js
CHANGED
package/dist/bin/dbml.js
CHANGED
package/dist/bin/docs.js
CHANGED
package/dist/bin/drizzle.js
CHANGED
package/dist/bin/ecto.js
CHANGED
package/dist/bin/effect.js
CHANGED
package/dist/bin/gorm.js
CHANGED
package/dist/bin/mermaid-er.js
CHANGED
package/dist/bin/sea-orm.js
CHANGED
package/dist/bin/sqlalchemy.js
CHANGED
package/dist/bin/typebox.js
CHANGED
package/dist/bin/valibot.js
CHANGED
package/dist/bin/zod.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import pkg from "@prisma/generator-helper";
|
|
4
4
|
import { format } from "oxfmt";
|
|
@@ -8,7 +8,6 @@ import { run } from "@softwaretechnik/dbml-renderer";
|
|
|
8
8
|
import { Style, css } from "hono/css";
|
|
9
9
|
import { raw } from "hono/html";
|
|
10
10
|
import { Fragment, jsx, jsxs } from "hono/jsx/jsx-runtime";
|
|
11
|
-
|
|
12
11
|
//#region src/format/index.ts
|
|
13
12
|
async function fmt(input) {
|
|
14
13
|
const { code, errors } = await format("<stdin>.ts", input, {
|
|
@@ -25,7 +24,6 @@ async function fmt(input) {
|
|
|
25
24
|
value: code
|
|
26
25
|
};
|
|
27
26
|
}
|
|
28
|
-
|
|
29
27
|
//#endregion
|
|
30
28
|
//#region src/fsp/index.ts
|
|
31
29
|
async function mkdir(dir) {
|
|
@@ -70,7 +68,6 @@ async function writeFileBinary(path, data) {
|
|
|
70
68
|
};
|
|
71
69
|
}
|
|
72
70
|
}
|
|
73
|
-
|
|
74
71
|
//#endregion
|
|
75
72
|
//#region src/emit/index.ts
|
|
76
73
|
async function emit(code, dir, output) {
|
|
@@ -125,30 +122,20 @@ async function emitMany(files, dir) {
|
|
|
125
122
|
value: void 0
|
|
126
123
|
};
|
|
127
124
|
}
|
|
128
|
-
|
|
129
|
-
//#endregion
|
|
130
|
-
//#region src/helper/extract-relations.ts
|
|
131
|
-
function collectRelationProps(models) {
|
|
132
|
-
return models.flatMap((m) => m.fields.filter((f) => f.kind === "object").map((f) => ({
|
|
133
|
-
model: m.name,
|
|
134
|
-
key: f.name,
|
|
135
|
-
targetModel: f.type,
|
|
136
|
-
isMany: f.isList
|
|
137
|
-
})));
|
|
138
|
-
}
|
|
139
|
-
function makeRelationsOnly(dmmf, includeType, makeRelations) {
|
|
140
|
-
const models = dmmf.datamodel.models;
|
|
141
|
-
const relIndex = collectRelationProps(models);
|
|
142
|
-
const relByModel = Object.groupBy(relIndex, (r) => r.model);
|
|
143
|
-
return models.map((model) => makeRelations(model, (relByModel[model.name] ?? []).map(({ key, targetModel, isMany }) => ({
|
|
144
|
-
key,
|
|
145
|
-
targetModel,
|
|
146
|
-
isMany
|
|
147
|
-
})), { includeType })).filter((code) => Boolean(code)).join("\n\n");
|
|
148
|
-
}
|
|
149
|
-
|
|
150
125
|
//#endregion
|
|
151
126
|
//#region src/utils/index.ts
|
|
127
|
+
function parseRelation(line) {
|
|
128
|
+
const match = line.trim().match(/^@relation\s+(\w+)\.(\w+)\s+(\w+)\.(\w+)\s+(\w+-to-\w+)$/);
|
|
129
|
+
if (!match) return null;
|
|
130
|
+
const [, fromModel, fromField, toModel, toField, type] = match;
|
|
131
|
+
return {
|
|
132
|
+
fromModel,
|
|
133
|
+
fromField,
|
|
134
|
+
toModel,
|
|
135
|
+
toField,
|
|
136
|
+
type
|
|
137
|
+
};
|
|
138
|
+
}
|
|
152
139
|
function getString(v, fallback) {
|
|
153
140
|
return typeof v === "string" ? v : Array.isArray(v) ? v[0] ?? fallback : fallback;
|
|
154
141
|
}
|
|
@@ -245,7 +232,6 @@ function schemaFromFields(modelFields, comment, schemaBuilder, propertiesGenerat
|
|
|
245
232
|
const modelName = modelFields[0].modelName;
|
|
246
233
|
return schemaBuilder(modelName, propertiesGenerator(modelFields, comment), objectType);
|
|
247
234
|
}
|
|
248
|
-
|
|
249
235
|
//#endregion
|
|
250
236
|
//#region src/helper/validation-schema.ts
|
|
251
237
|
function validationSchemas(models, type, comment, config) {
|
|
@@ -300,9 +286,8 @@ function validationSchemas(models, type, comment, config) {
|
|
|
300
286
|
schemas
|
|
301
287
|
].join("\n") : schemas;
|
|
302
288
|
}
|
|
303
|
-
|
|
304
289
|
//#endregion
|
|
305
|
-
//#region src/
|
|
290
|
+
//#region src/helper/ajv.ts
|
|
306
291
|
function makeAjvInfer(modelName) {
|
|
307
292
|
return `export type ${modelName} = FromSchema<typeof ${modelName}Schema>`;
|
|
308
293
|
}
|
|
@@ -348,9 +333,33 @@ function ajvSchemaCode(models, type, comment, enums) {
|
|
|
348
333
|
formatEnum: makeAjvEnumExpression
|
|
349
334
|
});
|
|
350
335
|
}
|
|
336
|
+
//#endregion
|
|
337
|
+
//#region src/helper/extract-relations.ts
|
|
338
|
+
function collectRelationProps(models) {
|
|
339
|
+
return models.flatMap((m) => m.fields.filter((f) => f.kind === "object").map((f) => ({
|
|
340
|
+
model: m.name,
|
|
341
|
+
key: f.name,
|
|
342
|
+
targetModel: f.type,
|
|
343
|
+
isMany: f.isList
|
|
344
|
+
})));
|
|
345
|
+
}
|
|
346
|
+
function makeRelationsOnly(dmmf, includeType, makeRelations) {
|
|
347
|
+
const models = dmmf.datamodel.models;
|
|
348
|
+
const relIndex = collectRelationProps(models);
|
|
349
|
+
const relByModel = Object.groupBy(relIndex, (r) => r.model);
|
|
350
|
+
return models.map((model) => makeRelations(model, (relByModel[model.name] ?? []).map(({ key, targetModel, isMany }) => ({
|
|
351
|
+
key,
|
|
352
|
+
targetModel,
|
|
353
|
+
isMany
|
|
354
|
+
})), { includeType })).filter((code) => Boolean(code)).join("\n\n");
|
|
355
|
+
}
|
|
356
|
+
//#endregion
|
|
357
|
+
//#region src/generator/ajv.ts
|
|
351
358
|
function ajvCode(dmmf, type, comment, relation) {
|
|
352
359
|
return [ajvSchemaCode(dmmf.datamodel.models, type, comment, dmmf.datamodel.enums), relation ? makeRelationsOnly(dmmf, type, makeAjvRelations) : ""].filter(Boolean).join("\n\n");
|
|
353
360
|
}
|
|
361
|
+
//#endregion
|
|
362
|
+
//#region src/core/ajv.ts
|
|
354
363
|
async function ajv(options) {
|
|
355
364
|
if (!(options.generator.isCustomOutput && options.generator.output?.value)) return {
|
|
356
365
|
ok: false,
|
|
@@ -366,9 +375,8 @@ async function ajv(options) {
|
|
|
366
375
|
};
|
|
367
376
|
return emit(ajvCode(options.dmmf, getBool(options.generator.config?.type), getBool(options.generator.config?.comment), getBool(options.generator.config?.relation)), resolved.dir, resolved.file);
|
|
368
377
|
}
|
|
369
|
-
|
|
370
378
|
//#endregion
|
|
371
|
-
//#region src/
|
|
379
|
+
//#region src/helper/arktype.ts
|
|
372
380
|
function makeArktypeInfer(modelName) {
|
|
373
381
|
return `export type ${modelName} = typeof ${modelName}Schema.infer`;
|
|
374
382
|
}
|
|
@@ -417,9 +425,13 @@ function arktypeSchemaCode(models, type, comment, enums) {
|
|
|
417
425
|
formatEnum: makeArktypeEnumExpression
|
|
418
426
|
});
|
|
419
427
|
}
|
|
428
|
+
//#endregion
|
|
429
|
+
//#region src/generator/arktype.ts
|
|
420
430
|
function arktypeCode(dmmf, type, comment, relation) {
|
|
421
431
|
return [arktypeSchemaCode(dmmf.datamodel.models, type, comment, dmmf.datamodel.enums), relation ? makeRelationsOnly(dmmf, type, makeArktypeRelations) : ""].filter(Boolean).join("\n\n");
|
|
422
432
|
}
|
|
433
|
+
//#endregion
|
|
434
|
+
//#region src/core/arktype.ts
|
|
423
435
|
async function arktype(options) {
|
|
424
436
|
if (!(options.generator.isCustomOutput && options.generator.output?.value)) return {
|
|
425
437
|
ok: false,
|
|
@@ -435,9 +447,70 @@ async function arktype(options) {
|
|
|
435
447
|
};
|
|
436
448
|
return emit(arktypeCode(options.dmmf, getBool(options.generator.config?.type), getBool(options.generator.config?.comment), getBool(options.generator.config?.relation)), resolved.dir, resolved.file);
|
|
437
449
|
}
|
|
438
|
-
|
|
439
450
|
//#endregion
|
|
440
|
-
//#region src/
|
|
451
|
+
//#region src/helper/relation.ts
|
|
452
|
+
function isCardinality(value) {
|
|
453
|
+
return value === "zero-one" || value === "one" || value === "zero-many" || value === "many";
|
|
454
|
+
}
|
|
455
|
+
function erKey(relation) {
|
|
456
|
+
return `${relation.from.model}.${relation.from.field}->${relation.to.model}.${relation.to.field}`;
|
|
457
|
+
}
|
|
458
|
+
function inferredERRelations(models) {
|
|
459
|
+
return models.flatMap((model) => model.fields.filter((field) => field.kind === "object" && field.relationFromFields && field.relationFromFields.length > 0).map((field) => {
|
|
460
|
+
const toModel = model.name;
|
|
461
|
+
const fromModel = field.type;
|
|
462
|
+
const toField = field.relationFromFields?.[0] ?? "";
|
|
463
|
+
const fromField = field.relationToFields?.[0] ?? "id";
|
|
464
|
+
const toCardinality = (models.find((m) => m.name === fromModel)?.fields.find((f) => f.relationName === field.relationName && f.name !== field.name))?.isList ? field.isRequired ? "many" : "zero-many" : field.isRequired ? "one" : "zero-one";
|
|
465
|
+
return {
|
|
466
|
+
from: {
|
|
467
|
+
model: fromModel,
|
|
468
|
+
field: fromField,
|
|
469
|
+
cardinality: "one"
|
|
470
|
+
},
|
|
471
|
+
to: {
|
|
472
|
+
model: toModel,
|
|
473
|
+
field: toField,
|
|
474
|
+
cardinality: toCardinality
|
|
475
|
+
},
|
|
476
|
+
identifying: true,
|
|
477
|
+
origin: "inferred"
|
|
478
|
+
};
|
|
479
|
+
}));
|
|
480
|
+
}
|
|
481
|
+
function annotatedERRelations(models) {
|
|
482
|
+
return models.flatMap((model) => (model.documentation ?? "").split("\n").flatMap((line) => {
|
|
483
|
+
const relation = parseRelation(line);
|
|
484
|
+
if (relation === null) return [];
|
|
485
|
+
const [fromCard, toCard] = relation.type.split("-to-");
|
|
486
|
+
if (!isCardinality(fromCard) || !isCardinality(toCard)) return [];
|
|
487
|
+
return [{
|
|
488
|
+
from: {
|
|
489
|
+
model: relation.fromModel,
|
|
490
|
+
field: relation.fromField,
|
|
491
|
+
cardinality: fromCard
|
|
492
|
+
},
|
|
493
|
+
to: {
|
|
494
|
+
model: relation.toModel,
|
|
495
|
+
field: relation.toField,
|
|
496
|
+
cardinality: toCard
|
|
497
|
+
},
|
|
498
|
+
identifying: true,
|
|
499
|
+
origin: "annotated"
|
|
500
|
+
}];
|
|
501
|
+
}));
|
|
502
|
+
}
|
|
503
|
+
function mergeERRelations(models) {
|
|
504
|
+
const inferred = inferredERRelations(models);
|
|
505
|
+
const annotated = annotatedERRelations(models);
|
|
506
|
+
const inferredKeys = new Set(inferred.map(erKey));
|
|
507
|
+
return [...new Map([...inferred.map((r) => [erKey(r), r]), ...annotated.map((r) => [erKey(r), inferredKeys.has(erKey(r)) ? {
|
|
508
|
+
...r,
|
|
509
|
+
origin: "inferred"
|
|
510
|
+
} : r])]).values()];
|
|
511
|
+
}
|
|
512
|
+
//#endregion
|
|
513
|
+
//#region src/helper/dbml.ts
|
|
441
514
|
function escapeNote(str) {
|
|
442
515
|
return str.replace(/'/g, "\\'");
|
|
443
516
|
}
|
|
@@ -553,19 +626,43 @@ function makeRelations$1(models, mapToDbSchema = false) {
|
|
|
553
626
|
});
|
|
554
627
|
}));
|
|
555
628
|
}
|
|
629
|
+
function isMany(cardinality) {
|
|
630
|
+
return cardinality === "many" || cardinality === "zero-many";
|
|
631
|
+
}
|
|
632
|
+
function dbmlOperator(leftMany, rightMany) {
|
|
633
|
+
if (leftMany && !rightMany) return ">";
|
|
634
|
+
if (!leftMany && rightMany) return "<";
|
|
635
|
+
if (leftMany && rightMany) return "<>";
|
|
636
|
+
return "-";
|
|
637
|
+
}
|
|
638
|
+
function annotatedDbmlRefs(models) {
|
|
639
|
+
const inferredKeys = new Set(inferredERRelations(models).map(erKey));
|
|
640
|
+
return annotatedERRelations(models).filter((relation) => !inferredKeys.has(erKey(relation))).map((relation) => {
|
|
641
|
+
const left = `${relation.to.model}.${relation.to.field}`;
|
|
642
|
+
const right = `${relation.from.model}.${relation.from.field}`;
|
|
643
|
+
const operator = dbmlOperator(isMany(relation.to.cardinality), isMany(relation.from.cardinality));
|
|
644
|
+
return `Ref ${`${relation.to.model}_${relation.to.field}_${relation.from.model}_${relation.from.field}`}: ${left} ${operator} ${right}`;
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
//#endregion
|
|
648
|
+
//#region src/generator/dbml.ts
|
|
556
649
|
function dbmlContent(datamodel, mapToDbSchema = false) {
|
|
557
650
|
const tables = makeTables(datamodel.models, mapToDbSchema);
|
|
558
651
|
const enums = makeEnums(datamodel.enums);
|
|
559
652
|
const refs = makeRelations$1(datamodel.models, mapToDbSchema);
|
|
653
|
+
const logicalRefs = annotatedDbmlRefs(datamodel.models);
|
|
560
654
|
return [
|
|
561
655
|
...enums,
|
|
562
656
|
...tables,
|
|
563
|
-
...refs
|
|
657
|
+
...refs,
|
|
658
|
+
...logicalRefs
|
|
564
659
|
].join("\n\n");
|
|
565
660
|
}
|
|
566
661
|
function dbmlToPng(dbml) {
|
|
567
662
|
return new Resvg(run(dbml, "svg"), { font: { loadSystemFonts: true } }).render().asPng();
|
|
568
663
|
}
|
|
664
|
+
//#endregion
|
|
665
|
+
//#region src/core/dbml.ts
|
|
569
666
|
function resolveOutPath(output) {
|
|
570
667
|
if (path.extname(output)) return output;
|
|
571
668
|
return path.join(output, "schema.dbml");
|
|
@@ -581,9 +678,8 @@ async function dbml(options) {
|
|
|
581
678
|
const outPath = resolveOutPath(output);
|
|
582
679
|
return emitRaw(outPath.endsWith(".png") ? dbmlToPng(content) : content, path.dirname(outPath), outPath);
|
|
583
680
|
}
|
|
584
|
-
|
|
585
681
|
//#endregion
|
|
586
|
-
//#region src/
|
|
682
|
+
//#region src/helper/docs/generator/transformDMMF.ts
|
|
587
683
|
const getMappings = (mappings, datamodel) => {
|
|
588
684
|
return mappings.modelOperations.filter((mapping) => {
|
|
589
685
|
const model = datamodel.models.find((m) => m.name === mapping.model);
|
|
@@ -609,9 +705,8 @@ const transformDMMF = (dmmf) => {
|
|
|
609
705
|
mappings: getMappings(dmmf.mappings, dmmf.datamodel)
|
|
610
706
|
};
|
|
611
707
|
};
|
|
612
|
-
|
|
613
708
|
//#endregion
|
|
614
|
-
//#region src/
|
|
709
|
+
//#region src/helper/docs/styles.ts
|
|
615
710
|
const globalCss = css`
|
|
616
711
|
:-hono-global {
|
|
617
712
|
:root {
|
|
@@ -831,9 +926,8 @@ const mb2Class = css`
|
|
|
831
926
|
const ml4Class = css`
|
|
832
927
|
margin-left: 1rem;
|
|
833
928
|
`;
|
|
834
|
-
|
|
835
929
|
//#endregion
|
|
836
|
-
//#region src/
|
|
930
|
+
//#region src/helper/docs/generator/helpers.ts
|
|
837
931
|
const capitalize = (str) => str[0].toUpperCase() + str.slice(1);
|
|
838
932
|
const lowerCase = (name) => name.substring(0, 1).toLowerCase() + name.substring(1);
|
|
839
933
|
const primitiveTypes = [
|
|
@@ -846,9 +940,8 @@ const primitiveTypes = [
|
|
|
846
940
|
"Null"
|
|
847
941
|
];
|
|
848
942
|
const isScalarType = (type) => primitiveTypes.includes(type);
|
|
849
|
-
|
|
850
943
|
//#endregion
|
|
851
|
-
//#region src/
|
|
944
|
+
//#region src/helper/docs/generator/apitypes.tsx
|
|
852
945
|
const TypeRefLink = ({ typeRef, kind }) => {
|
|
853
946
|
const typeName = typeRef.type;
|
|
854
947
|
if (isScalarType(typeName)) return /* @__PURE__ */ jsx(Fragment, { children: typeName });
|
|
@@ -946,9 +1039,8 @@ const getTypesData = (d) => {
|
|
|
946
1039
|
const createTypes = (d) => {
|
|
947
1040
|
return /* @__PURE__ */ jsx(TypesSection, { data: getTypesData(d) });
|
|
948
1041
|
};
|
|
949
|
-
|
|
950
1042
|
//#endregion
|
|
951
|
-
//#region src/
|
|
1043
|
+
//#region src/helper/docs/generator/model.tsx
|
|
952
1044
|
const ModelAction = {
|
|
953
1045
|
create: "create",
|
|
954
1046
|
deleteMany: "deleteMany",
|
|
@@ -1312,9 +1404,8 @@ const getModelData = (d) => ({ models: getModels$1(d) });
|
|
|
1312
1404
|
const createModels = (d) => {
|
|
1313
1405
|
return /* @__PURE__ */ jsx(ModelsSection, { data: getModelData(d) });
|
|
1314
1406
|
};
|
|
1315
|
-
|
|
1316
1407
|
//#endregion
|
|
1317
|
-
//#region src/
|
|
1408
|
+
//#region src/helper/docs/generator/toc.tsx
|
|
1318
1409
|
const TOCSubHeader = ({ name }) => /* @__PURE__ */ jsx("div", {
|
|
1319
1410
|
class: tocSubHeaderClass,
|
|
1320
1411
|
children: /* @__PURE__ */ jsx("a", {
|
|
@@ -1442,9 +1533,8 @@ const getTOCData = (d) => ({
|
|
|
1442
1533
|
const createTOC = (d) => {
|
|
1443
1534
|
return /* @__PURE__ */ jsx(TOCComponent, { data: getTOCData(d) });
|
|
1444
1535
|
};
|
|
1445
|
-
|
|
1446
1536
|
//#endregion
|
|
1447
|
-
//#region src/
|
|
1537
|
+
//#region src/helper/docs/printer/index.tsx
|
|
1448
1538
|
const HekirekiLogo = () => /* @__PURE__ */ jsxs("svg", {
|
|
1449
1539
|
width: "40",
|
|
1450
1540
|
height: "40",
|
|
@@ -1535,7 +1625,11 @@ const generateHTML = (data) => {
|
|
|
1535
1625
|
})]
|
|
1536
1626
|
}) })).toString()}`;
|
|
1537
1627
|
};
|
|
1538
|
-
|
|
1628
|
+
//#endregion
|
|
1629
|
+
//#region src/generator/docs.ts
|
|
1630
|
+
function docsHTML(dmmf) {
|
|
1631
|
+
return generateHTML(transformDMMF(dmmf));
|
|
1632
|
+
}
|
|
1539
1633
|
//#endregion
|
|
1540
1634
|
//#region src/core/docs.ts
|
|
1541
1635
|
async function docs(options) {
|
|
@@ -1544,11 +1638,10 @@ async function docs(options) {
|
|
|
1544
1638
|
error: "output is required for Hekireki-Docs. Please specify output in your generator config."
|
|
1545
1639
|
};
|
|
1546
1640
|
const output = options.generator.output.value;
|
|
1547
|
-
return emitRaw(
|
|
1641
|
+
return emitRaw(docsHTML(options.dmmf), output, path.join(output, "index.html"));
|
|
1548
1642
|
}
|
|
1549
|
-
|
|
1550
1643
|
//#endregion
|
|
1551
|
-
//#region src/
|
|
1644
|
+
//#region src/helper/drizzle.ts
|
|
1552
1645
|
function resolveDbProvider(provider) {
|
|
1553
1646
|
switch (provider) {
|
|
1554
1647
|
case "postgresql":
|
|
@@ -1906,6 +1999,8 @@ function makeRelations(models, imports) {
|
|
|
1906
1999
|
return `export const ${modelVar}Relations = relations(${modelVar}, ({ ${[needsOne ? "one" : "", needsMany ? "many" : ""].filter(Boolean).join(", ")} }) => ({ ${fieldLines} }))`;
|
|
1907
2000
|
});
|
|
1908
2001
|
}
|
|
2002
|
+
//#endregion
|
|
2003
|
+
//#region src/generator/drizzle.ts
|
|
1909
2004
|
function drizzleSchema(datamodel, provider, indexes) {
|
|
1910
2005
|
const db = resolveDbProvider(provider);
|
|
1911
2006
|
const imports = createImports();
|
|
@@ -1930,6 +2025,8 @@ function parsePrismaProvider(raw) {
|
|
|
1930
2025
|
error: `Unsupported provider: ${raw}`
|
|
1931
2026
|
};
|
|
1932
2027
|
}
|
|
2028
|
+
//#endregion
|
|
2029
|
+
//#region src/core/drizzle.ts
|
|
1933
2030
|
async function drizzle(options) {
|
|
1934
2031
|
if (!(options.generator.isCustomOutput && options.generator.output?.value)) return {
|
|
1935
2032
|
ok: false,
|
|
@@ -1947,9 +2044,8 @@ async function drizzle(options) {
|
|
|
1947
2044
|
};
|
|
1948
2045
|
return emit(drizzleSchema(options.dmmf.datamodel, providerResult.value, options.dmmf.datamodel.indexes), resolved.dir, resolved.file);
|
|
1949
2046
|
}
|
|
1950
|
-
|
|
1951
2047
|
//#endregion
|
|
1952
|
-
//#region src/
|
|
2048
|
+
//#region src/helper/ecto.ts
|
|
1953
2049
|
function prismaTypeToEctoType(type) {
|
|
1954
2050
|
if (type === "Int") return "integer";
|
|
1955
2051
|
if (type === "BigInt") return "integer";
|
|
@@ -2210,12 +2306,16 @@ function ectoSchemas(models, app, allModels, enums) {
|
|
|
2210
2306
|
].join("\n");
|
|
2211
2307
|
}).filter(Boolean).join("\n\n");
|
|
2212
2308
|
}
|
|
2309
|
+
//#endregion
|
|
2310
|
+
//#region src/generator/ecto.ts
|
|
2213
2311
|
function ectoSchemaFiles(models, app, enums) {
|
|
2214
2312
|
return models.map((model) => ({
|
|
2215
2313
|
fileName: `${makeSnakeCase(model.name)}.ex`,
|
|
2216
2314
|
code: ectoSchemas([model], app, models, enums)
|
|
2217
2315
|
})).filter((entry) => entry.code.trim().length > 0);
|
|
2218
2316
|
}
|
|
2317
|
+
//#endregion
|
|
2318
|
+
//#region src/core/ecto.ts
|
|
2219
2319
|
async function ecto(options) {
|
|
2220
2320
|
if (!(options.generator.isCustomOutput && options.generator.output?.value)) return {
|
|
2221
2321
|
ok: false,
|
|
@@ -2226,11 +2326,10 @@ async function ecto(options) {
|
|
|
2226
2326
|
const enums = options.dmmf.datamodel.enums;
|
|
2227
2327
|
return emitMany(ectoSchemaFiles(options.dmmf.datamodel.models, app, enums), outDir);
|
|
2228
2328
|
}
|
|
2229
|
-
|
|
2230
2329
|
//#endregion
|
|
2231
|
-
//#region src/
|
|
2330
|
+
//#region src/helper/effect.ts
|
|
2232
2331
|
function makeEffectInfer(modelName) {
|
|
2233
|
-
return `export type ${modelName}
|
|
2332
|
+
return `export type ${modelName} = typeof ${modelName}Schema.Type`;
|
|
2234
2333
|
}
|
|
2235
2334
|
function makeEffectSchema(modelName, fields) {
|
|
2236
2335
|
return `export const ${modelName}Schema = Schema.Struct({\n${fields}\n})`;
|
|
@@ -2261,7 +2360,7 @@ function makeEffectRelations(model, relProps, options) {
|
|
|
2261
2360
|
if (relProps.length === 0) return null;
|
|
2262
2361
|
const base = `...${model.name}Schema.fields,`;
|
|
2263
2362
|
const rels = relProps.map((r) => `${r.key}:${r.isMany ? `Schema.Array(${r.targetModel}Schema)` : `${r.targetModel}Schema`},`).join("");
|
|
2264
|
-
const typeLine = options?.includeType ? `\n\nexport type ${model.name}
|
|
2363
|
+
const typeLine = options?.includeType ? `\n\nexport type ${model.name}Relations = typeof ${model.name}RelationsSchema.Type` : "";
|
|
2265
2364
|
return `export const ${model.name}RelationsSchema = Schema.Struct({${base}${rels}})${typeLine}`;
|
|
2266
2365
|
}
|
|
2267
2366
|
function effectSchemaCode(models, type, comment, enums) {
|
|
@@ -2277,9 +2376,13 @@ function effectSchemaCode(models, type, comment, enums) {
|
|
|
2277
2376
|
formatEnum: makeEffectEnumExpression
|
|
2278
2377
|
});
|
|
2279
2378
|
}
|
|
2379
|
+
//#endregion
|
|
2380
|
+
//#region src/generator/effect.ts
|
|
2280
2381
|
function effectCode(dmmf, type, comment, relation) {
|
|
2281
2382
|
return [effectSchemaCode(dmmf.datamodel.models, type, comment, dmmf.datamodel.enums), relation ? makeRelationsOnly(dmmf, type, makeEffectRelations) : ""].filter(Boolean).join("\n\n");
|
|
2282
2383
|
}
|
|
2384
|
+
//#endregion
|
|
2385
|
+
//#region src/core/effect.ts
|
|
2283
2386
|
async function effect(options) {
|
|
2284
2387
|
if (!(options.generator.isCustomOutput && options.generator.output?.value)) return {
|
|
2285
2388
|
ok: false,
|
|
@@ -2295,9 +2398,8 @@ async function effect(options) {
|
|
|
2295
2398
|
};
|
|
2296
2399
|
return emit(effectCode(options.dmmf, getBool(options.generator.config?.type), getBool(options.generator.config?.comment), getBool(options.generator.config?.relation)), resolved.dir, resolved.file);
|
|
2297
2400
|
}
|
|
2298
|
-
|
|
2299
2401
|
//#endregion
|
|
2300
|
-
//#region src/
|
|
2402
|
+
//#region src/helper/gorm.ts
|
|
2301
2403
|
const PRISMA_TO_GO = {
|
|
2302
2404
|
String: "string",
|
|
2303
2405
|
Int: "int",
|
|
@@ -2586,6 +2688,8 @@ function formatImports(imports) {
|
|
|
2586
2688
|
")"
|
|
2587
2689
|
];
|
|
2588
2690
|
}
|
|
2691
|
+
//#endregion
|
|
2692
|
+
//#region src/generator/gorm.ts
|
|
2589
2693
|
function generateGormModels(models, enums, indexes, packageName = "model") {
|
|
2590
2694
|
const idx = indexes ?? [];
|
|
2591
2695
|
const modelBodies = models.map((model) => generateModelStruct(model, models, enums, idx)).filter((body) => body !== null);
|
|
@@ -2597,6 +2701,8 @@ function generateGormModels(models, enums, indexes, packageName = "model") {
|
|
|
2597
2701
|
""
|
|
2598
2702
|
].join("\n");
|
|
2599
2703
|
}
|
|
2704
|
+
//#endregion
|
|
2705
|
+
//#region src/core/gorm.ts
|
|
2600
2706
|
async function gorm(options) {
|
|
2601
2707
|
if (!(options.generator.isCustomOutput && options.generator.output?.value)) return {
|
|
2602
2708
|
ok: false,
|
|
@@ -2609,18 +2715,17 @@ async function gorm(options) {
|
|
|
2609
2715
|
const indexes = options.dmmf.datamodel.indexes;
|
|
2610
2716
|
return emitRaw(generateGormModels(options.dmmf.datamodel.models, enums, indexes, packageName), path.dirname(outPath), outPath);
|
|
2611
2717
|
}
|
|
2612
|
-
|
|
2613
2718
|
//#endregion
|
|
2614
|
-
//#region src/
|
|
2615
|
-
function removeDuplicateRelations(relations) {
|
|
2616
|
-
return [...new Set(relations)];
|
|
2617
|
-
}
|
|
2719
|
+
//#region src/helper/mermaid-er.ts
|
|
2618
2720
|
const RELATIONSHIPS = {
|
|
2619
2721
|
"zero-one": "|o",
|
|
2620
2722
|
one: "||",
|
|
2621
2723
|
"zero-many": "}o",
|
|
2622
2724
|
many: "}|"
|
|
2623
2725
|
};
|
|
2726
|
+
function erRelationLine(relation) {
|
|
2727
|
+
return ` ${relation.from.model} ${RELATIONSHIPS[relation.from.cardinality]}--${RELATIONSHIPS[relation.to.cardinality]} ${relation.to.model} : "(${relation.from.field}) - (${relation.to.field})"`;
|
|
2728
|
+
}
|
|
2624
2729
|
function modelFields(model) {
|
|
2625
2730
|
const fkFields = new Set(model.fields.filter((f) => f.relationFromFields && f.relationFromFields.length > 0).flatMap((f) => f.relationFromFields ?? []));
|
|
2626
2731
|
return model.fields.map((field) => {
|
|
@@ -2638,28 +2743,22 @@ function modelInfo(model) {
|
|
|
2638
2743
|
" }"
|
|
2639
2744
|
];
|
|
2640
2745
|
}
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
const toModel = model.name;
|
|
2644
|
-
const fromModel = field.type;
|
|
2645
|
-
const toField = field.relationFromFields?.[0];
|
|
2646
|
-
const fromField = field.relationToFields?.[0] ?? "id";
|
|
2647
|
-
const toCardinality = (models.find((m) => m.name === fromModel)?.fields.find((f) => f.relationName === field.relationName && f.name !== field.name))?.isList ? field.isRequired ? "many" : "zero-many" : field.isRequired ? "one" : "zero-one";
|
|
2648
|
-
return ` ${fromModel} ${RELATIONSHIPS.one}--${RELATIONSHIPS[toCardinality]} ${toModel} : "(${fromField}) - (${toField})"`;
|
|
2649
|
-
}));
|
|
2650
|
-
}
|
|
2746
|
+
//#endregion
|
|
2747
|
+
//#region src/generator/mermaid-er.ts
|
|
2651
2748
|
const ER_HEADER = ["```mermaid", "erDiagram"];
|
|
2652
2749
|
const ER_FOOTER = ["```"];
|
|
2653
2750
|
function erContent(models) {
|
|
2654
|
-
const
|
|
2751
|
+
const relations = mergeERRelations(models).map(erRelationLine);
|
|
2655
2752
|
const modelInfos = models.flatMap(modelInfo);
|
|
2656
2753
|
return [
|
|
2657
2754
|
...ER_HEADER,
|
|
2658
|
-
...
|
|
2755
|
+
...relations,
|
|
2659
2756
|
...modelInfos,
|
|
2660
2757
|
...ER_FOOTER
|
|
2661
2758
|
];
|
|
2662
2759
|
}
|
|
2760
|
+
//#endregion
|
|
2761
|
+
//#region src/core/mermaid-er.ts
|
|
2663
2762
|
async function mermaidEr(options) {
|
|
2664
2763
|
if (!(options.generator.isCustomOutput && options.generator.output?.value)) return {
|
|
2665
2764
|
ok: false,
|
|
@@ -2676,9 +2775,8 @@ async function mermaidEr(options) {
|
|
|
2676
2775
|
};
|
|
2677
2776
|
return emitRaw(content.join("\n"), resolved.dir, resolved.file);
|
|
2678
2777
|
}
|
|
2679
|
-
|
|
2680
2778
|
//#endregion
|
|
2681
|
-
//#region src/
|
|
2779
|
+
//#region src/helper/sea-orm.ts
|
|
2682
2780
|
const PRISMA_TO_RUST = {
|
|
2683
2781
|
String: "String",
|
|
2684
2782
|
Int: "i32",
|
|
@@ -3034,6 +3132,8 @@ function collectM2MPairs(models) {
|
|
|
3034
3132
|
return true;
|
|
3035
3133
|
});
|
|
3036
3134
|
}
|
|
3135
|
+
//#endregion
|
|
3136
|
+
//#region src/generator/sea-orm.ts
|
|
3037
3137
|
function seaOrmFiles(models, enums, serde = {}) {
|
|
3038
3138
|
const useLines = ["use sea_orm::entity::prelude::*;", "use serde::{Deserialize, Serialize};"];
|
|
3039
3139
|
const enumFiles = enums.map((e) => ({
|
|
@@ -3079,6 +3179,8 @@ function seaOrmFiles(models, enums, serde = {}) {
|
|
|
3079
3179
|
code
|
|
3080
3180
|
})), modEntry];
|
|
3081
3181
|
}
|
|
3182
|
+
//#endregion
|
|
3183
|
+
//#region src/core/sea-orm.ts
|
|
3082
3184
|
async function seaOrm(options) {
|
|
3083
3185
|
if (!(options.generator.isCustomOutput && options.generator.output?.value)) return {
|
|
3084
3186
|
ok: false,
|
|
@@ -3089,9 +3191,8 @@ async function seaOrm(options) {
|
|
|
3089
3191
|
const enums = options.dmmf.datamodel.enums;
|
|
3090
3192
|
return emitMany(seaOrmFiles(options.dmmf.datamodel.models, enums, serde), outDir);
|
|
3091
3193
|
}
|
|
3092
|
-
|
|
3093
3194
|
//#endregion
|
|
3094
|
-
//#region src/
|
|
3195
|
+
//#region src/helper/sqlalchemy.ts
|
|
3095
3196
|
const PRISMA_TO_PYTHON = {
|
|
3096
3197
|
String: "str",
|
|
3097
3198
|
Int: "int",
|
|
@@ -3491,6 +3592,8 @@ function collectGlobalImports(models, _enums, indexes, m2mTables) {
|
|
|
3491
3592
|
if (needsUuid) lines.push("import uuid as uuid_mod");
|
|
3492
3593
|
return lines;
|
|
3493
3594
|
}
|
|
3595
|
+
//#endregion
|
|
3596
|
+
//#region src/generator/sqlalchemy.ts
|
|
3494
3597
|
function generateSingleFile(models, enums, indexes) {
|
|
3495
3598
|
const idx = indexes ?? [];
|
|
3496
3599
|
const m2mTables = collectManyToManyTables(models);
|
|
@@ -3510,6 +3613,8 @@ function generateSingleFile(models, enums, indexes) {
|
|
|
3510
3613
|
""
|
|
3511
3614
|
].join("\n");
|
|
3512
3615
|
}
|
|
3616
|
+
//#endregion
|
|
3617
|
+
//#region src/core/sqlalchemy.ts
|
|
3513
3618
|
async function sqlalchemy(options) {
|
|
3514
3619
|
if (!(options.generator.isCustomOutput && options.generator.output?.value)) return {
|
|
3515
3620
|
ok: false,
|
|
@@ -3521,9 +3626,8 @@ async function sqlalchemy(options) {
|
|
|
3521
3626
|
const indexes = options.dmmf.datamodel.indexes;
|
|
3522
3627
|
return emitRaw(generateSingleFile(options.dmmf.datamodel.models, enums, indexes), path.dirname(outPath), outPath);
|
|
3523
3628
|
}
|
|
3524
|
-
|
|
3525
3629
|
//#endregion
|
|
3526
|
-
//#region src/
|
|
3630
|
+
//#region src/helper/typebox.ts
|
|
3527
3631
|
function makeTypeBoxInfer(modelName) {
|
|
3528
3632
|
return `export type ${modelName} = Static<typeof ${modelName}Schema>`;
|
|
3529
3633
|
}
|
|
@@ -3576,9 +3680,13 @@ function typeboxSchemaCode(models, type, comment, enums) {
|
|
|
3576
3680
|
formatEnum: makeTypeBoxEnumExpression
|
|
3577
3681
|
});
|
|
3578
3682
|
}
|
|
3683
|
+
//#endregion
|
|
3684
|
+
//#region src/generator/typebox.ts
|
|
3579
3685
|
function typeboxCode(dmmf, type, comment, relation) {
|
|
3580
3686
|
return [typeboxSchemaCode(dmmf.datamodel.models, type, comment, dmmf.datamodel.enums), relation ? makeRelationsOnly(dmmf, type, makeTypeBoxRelations) : ""].filter(Boolean).join("\n\n");
|
|
3581
3687
|
}
|
|
3688
|
+
//#endregion
|
|
3689
|
+
//#region src/core/typebox.ts
|
|
3582
3690
|
async function typebox(options) {
|
|
3583
3691
|
if (!(options.generator.isCustomOutput && options.generator.output?.value)) return {
|
|
3584
3692
|
ok: false,
|
|
@@ -3594,9 +3702,8 @@ async function typebox(options) {
|
|
|
3594
3702
|
};
|
|
3595
3703
|
return emit(typeboxCode(options.dmmf, getBool(options.generator.config?.type), getBool(options.generator.config?.comment), getBool(options.generator.config?.relation)), resolved.dir, resolved.file);
|
|
3596
3704
|
}
|
|
3597
|
-
|
|
3598
3705
|
//#endregion
|
|
3599
|
-
//#region src/
|
|
3706
|
+
//#region src/helper/valibot.ts
|
|
3600
3707
|
function makeValibotInfer(modelName) {
|
|
3601
3708
|
return `export type ${modelName} = v.InferOutput<typeof ${modelName}Schema>`;
|
|
3602
3709
|
}
|
|
@@ -3640,9 +3747,13 @@ function valibotSchemaCode(models, type, comment, enums) {
|
|
|
3640
3747
|
formatEnum: makeValibotEnumExpression
|
|
3641
3748
|
});
|
|
3642
3749
|
}
|
|
3750
|
+
//#endregion
|
|
3751
|
+
//#region src/generator/valibot.ts
|
|
3643
3752
|
function valibotCode(dmmf, type, comment, relation) {
|
|
3644
3753
|
return [valibotSchemaCode(dmmf.datamodel.models, type, comment, dmmf.datamodel.enums), relation ? makeRelationsOnly(dmmf, type, makeValibotRelations) : ""].filter(Boolean).join("\n\n");
|
|
3645
3754
|
}
|
|
3755
|
+
//#endregion
|
|
3756
|
+
//#region src/core/valibot.ts
|
|
3646
3757
|
async function valibot(options) {
|
|
3647
3758
|
if (!(options.generator.isCustomOutput && options.generator.output?.value)) return {
|
|
3648
3759
|
ok: false,
|
|
@@ -3658,9 +3769,8 @@ async function valibot(options) {
|
|
|
3658
3769
|
};
|
|
3659
3770
|
return emit(valibotCode(options.dmmf, getBool(options.generator.config?.type), getBool(options.generator.config?.comment), getBool(options.generator.config?.relation)), resolved.dir, resolved.file);
|
|
3660
3771
|
}
|
|
3661
|
-
|
|
3662
3772
|
//#endregion
|
|
3663
|
-
//#region src/
|
|
3773
|
+
//#region src/helper/zod.ts
|
|
3664
3774
|
function makeZodInfer(modelName) {
|
|
3665
3775
|
return `export type ${modelName} = z.infer<typeof ${modelName}Schema>`;
|
|
3666
3776
|
}
|
|
@@ -3704,9 +3814,13 @@ function zodSchemaCode(models, type, comment, zodVersion, enums) {
|
|
|
3704
3814
|
formatEnum: makeZodEnumExpression
|
|
3705
3815
|
});
|
|
3706
3816
|
}
|
|
3817
|
+
//#endregion
|
|
3818
|
+
//#region src/generator/zod.ts
|
|
3707
3819
|
function zodCode(dmmf, type, comment, relation, version) {
|
|
3708
3820
|
return [zodSchemaCode(dmmf.datamodel.models, type, comment, version, dmmf.datamodel.enums), relation ? makeRelationsOnly(dmmf, type, makeZodRelations) : ""].filter(Boolean).join("\n\n");
|
|
3709
3821
|
}
|
|
3822
|
+
//#endregion
|
|
3823
|
+
//#region src/core/zod.ts
|
|
3710
3824
|
async function zod(options) {
|
|
3711
3825
|
if (!(options.generator.isCustomOutput && options.generator.output?.value)) return {
|
|
3712
3826
|
ok: false,
|
|
@@ -3722,7 +3836,6 @@ async function zod(options) {
|
|
|
3722
3836
|
};
|
|
3723
3837
|
return emit(zodCode(options.dmmf, getBool(options.generator.config?.type), getBool(options.generator.config?.comment), getBool(options.generator.config?.relation), getString(options.generator.config?.zod, "v4")), resolved.dir, resolved.file);
|
|
3724
3838
|
}
|
|
3725
|
-
|
|
3726
3839
|
//#endregion
|
|
3727
3840
|
//#region src/bin/index.ts
|
|
3728
3841
|
const GENERATORS = {
|
|
@@ -3798,6 +3911,5 @@ function registerGenerator(name) {
|
|
|
3798
3911
|
}
|
|
3799
3912
|
});
|
|
3800
3913
|
}
|
|
3801
|
-
|
|
3802
3914
|
//#endregion
|
|
3803
|
-
export { registerGenerator as t };
|
|
3915
|
+
export { registerGenerator as t };
|
package/dist/cli/index.js
CHANGED
|
@@ -4,7 +4,6 @@ import path from "node:path";
|
|
|
4
4
|
import { serve } from "@hono/node-server";
|
|
5
5
|
import { serveStatic } from "@hono/node-server/serve-static";
|
|
6
6
|
import { Hono } from "hono";
|
|
7
|
-
|
|
8
7
|
//#region src/cli/index.ts
|
|
9
8
|
const HELP_TEXT = `⚡️ hekireki - Prisma schema tools
|
|
10
9
|
|
|
@@ -131,6 +130,5 @@ else {
|
|
|
131
130
|
console.error(result.error);
|
|
132
131
|
process.exit(1);
|
|
133
132
|
}
|
|
134
|
-
|
|
135
133
|
//#endregion
|
|
136
|
-
export { DOCS_HELP_TEXT, HELP_TEXT, handleDocs, hekireki, parsePort };
|
|
134
|
+
export { DOCS_HELP_TEXT, HELP_TEXT, handleDocs, hekireki, parsePort };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hekireki",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.2",
|
|
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",
|
|
@@ -61,31 +61,31 @@
|
|
|
61
61
|
"release": "npm pkg fix && pnpm build && npm publish"
|
|
62
62
|
},
|
|
63
63
|
"dependencies": {
|
|
64
|
-
"@hono/node-server": "^
|
|
65
|
-
"@prisma/generator-helper": "^7.
|
|
64
|
+
"@hono/node-server": "^2.0.1",
|
|
65
|
+
"@prisma/generator-helper": "^7.8.0",
|
|
66
66
|
"@resvg/resvg-js": "^2.6.2",
|
|
67
67
|
"@softwaretechnik/dbml-renderer": "^1.0.31",
|
|
68
|
-
"hono": "^4.
|
|
69
|
-
"oxfmt": "^0.
|
|
68
|
+
"hono": "^4.12.16",
|
|
69
|
+
"oxfmt": "^0.47.0"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
|
-
"@paralleldrive/cuid2": "^
|
|
73
|
-
"@prisma/client": "^7.
|
|
74
|
-
"@sinclair/typebox": "^0.34.
|
|
75
|
-
"@types/node": "^25.
|
|
76
|
-
"@typescript/native-preview": "7.0.0-dev.
|
|
77
|
-
"ajv": "^8.
|
|
78
|
-
"arktype": "^2.
|
|
79
|
-
"better-auth": "^1.
|
|
80
|
-
"drizzle-kit": "^0.31.
|
|
81
|
-
"drizzle-orm": "^0.45.
|
|
82
|
-
"effect": "^3.
|
|
72
|
+
"@paralleldrive/cuid2": "^3.3.0",
|
|
73
|
+
"@prisma/client": "^7.8.0",
|
|
74
|
+
"@sinclair/typebox": "^0.34.49",
|
|
75
|
+
"@types/node": "^25.6.0",
|
|
76
|
+
"@typescript/native-preview": "7.0.0-dev.20260504.1",
|
|
77
|
+
"ajv": "^8.20.0",
|
|
78
|
+
"arktype": "^2.2.0",
|
|
79
|
+
"better-auth": "^1.6.9",
|
|
80
|
+
"drizzle-kit": "^0.31.10",
|
|
81
|
+
"drizzle-orm": "^0.45.2",
|
|
82
|
+
"effect": "^3.21.2",
|
|
83
83
|
"json-schema-to-ts": "^3.1.1",
|
|
84
|
-
"prisma": "^7.
|
|
85
|
-
"tsdown": "^0.
|
|
84
|
+
"prisma": "^7.8.0",
|
|
85
|
+
"tsdown": "^0.21.10",
|
|
86
86
|
"tsx": "^4.21.0",
|
|
87
|
-
"typescript": "^
|
|
88
|
-
"valibot": "1.
|
|
89
|
-
"zod": "^4.3
|
|
87
|
+
"typescript": "^6.0.3",
|
|
88
|
+
"valibot": "1.3.1",
|
|
89
|
+
"zod": "^4.4.3"
|
|
90
90
|
}
|
|
91
91
|
}
|