Skip to content

Commit 9cfe0e8

Browse files
committed
BREAKING CHANGE: relation support
1 parent aa5fa03 commit 9cfe0e8

File tree

4 files changed

+85
-23
lines changed

4 files changed

+85
-23
lines changed

prisma/typebox/Post.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,22 @@
1-
import { Type, Static } from '@sinclair/typebox';
1+
import { Type, Static } from "@sinclair/typebox";
2+
import { Role } from "./Role";
23

34
export const Post = Type.Object({
4-
id: Type.Number(),
5+
id: Type.Optional(Type.Number()),
6+
user: Type.Optional(
7+
Type.Object({
8+
id: Type.Optional(Type.Number()),
9+
createdAt: Type.Optional(Type.String()),
10+
email: Type.String(),
11+
weight: Type.Optional(Type.Number()),
12+
is18: Type.Optional(Type.Boolean()),
13+
name: Type.Optional(Type.String()),
14+
successorId: Type.Optional(Type.Number()),
15+
role: Type.Optional(Role),
16+
keywords: Type.Array(Type.String()),
17+
biography: Type.String(),
18+
})
19+
),
520
userId: Type.Optional(Type.Number()),
621
});
722

prisma/typebox/Role.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { Type, Static } from '@sinclair/typebox';
1+
import { Type, Static } from "@sinclair/typebox";
22

33
export const RoleConst = {
4-
USER: Type.Literal('USER'),
5-
ADMIN: Type.Literal('ADMIN'),
4+
USER: Type.Literal("USER"),
5+
ADMIN: Type.Literal("ADMIN"),
66
};
77

88
export const Role = Type.KeyOf(Type.Object(RoleConst));

prisma/typebox/User.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
1-
import { Type, Static } from '@sinclair/typebox';
1+
import { Type, Static } from "@sinclair/typebox";
2+
import { Role } from "./Role";
23

34
export const User = Type.Object({
4-
id: Type.Number(),
5-
createdAt: Type.String(),
5+
id: Type.Optional(Type.Number()),
6+
createdAt: Type.Optional(Type.String()),
67
email: Type.String(),
78
weight: Type.Optional(Type.Number()),
89
is18: Type.Optional(Type.Boolean()),
910
name: Type.Optional(Type.String()),
1011
successorId: Type.Optional(Type.Number()),
12+
role: Type.Optional(Role),
13+
posts: Type.Array(
14+
Type.Object({
15+
id: Type.Optional(Type.Number()),
16+
userId: Type.Optional(Type.Number()),
17+
})
18+
),
1119
keywords: Type.Array(Type.String()),
1220
biography: Type.String(),
1321
});

src/generator/transformDMMF.ts

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { DMMF } from '@prisma/generator-helper';
22

33
const transformField = (field: DMMF.Field) => {
44
const tokens = [field.name + ':'];
5+
const deps = new Set();
56

67
if (['Int', 'Float'].includes(field.type)) {
78
tokens.push('Type.Number()');
@@ -10,28 +11,32 @@ const transformField = (field: DMMF.Field) => {
1011
} else if (field.type === 'Boolean') {
1112
tokens.push('Type.Boolean()');
1213
} else {
13-
return '';
14+
tokens.push(`::${field.type}::`);
15+
deps.add(field.type);
1416
}
1517

1618
if (field.isList) {
1719
tokens.splice(1, 0, 'Type.Array(');
1820
tokens.splice(tokens.length, 0, ')');
1921
}
2022

21-
if (!field.isRequired) {
23+
if (!field.isRequired || field.hasDefaultValue) {
2224
tokens.splice(1, 0, 'Type.Optional(');
2325
tokens.splice(tokens.length, 0, ')');
2426
}
2527

26-
return tokens.join(' ').concat('\n');
28+
return { str: tokens.join(' ').concat('\n'), deps };
2729
};
2830

2931
const transformFields = (fields: DMMF.Field[]) => {
3032
let dependencies = new Set();
3133
const _fields: string[] = [];
3234

3335
fields.map(transformField).forEach((field) => {
34-
_fields.push(field);
36+
_fields.push(field.str);
37+
[...field.deps].forEach((d) => {
38+
dependencies.add(d);
39+
});
3540
});
3641

3742
return {
@@ -40,16 +45,23 @@ const transformFields = (fields: DMMF.Field[]) => {
4045
};
4146
};
4247

43-
const transformModel = (model: DMMF.Model) => {
48+
const transformModel = (model: DMMF.Model, dependant: string | null = null) => {
4449
const fields = transformFields(model.fields);
45-
46-
return [
47-
`import {Type, Static} from '@sinclair/typebox'\n`,
48-
`\nexport const ${model.name} = Type.Object({\n\t`,
50+
let raw = [
51+
`${dependant ? '' : `export const ${model.name} = `}Type.Object({\n\t`,
4952
fields.rawString,
50-
'})\n',
51-
`\nexport type ${model.name}Type = Static<typeof ${model.name}>`,
52-
].join('');
53+
'})',
54+
].join('\n');
55+
56+
if (typeof dependant === 'string') {
57+
const re = new RegExp(`.+::${dependant}.+\n`);
58+
raw = raw.replace(re, '');
59+
}
60+
61+
return {
62+
raw,
63+
deps: fields.dependencies,
64+
};
5365
};
5466

5567
export const transformEnum = (enm: DMMF.DatamodelEnum) => {
@@ -58,7 +70,6 @@ export const transformEnum = (enm: DMMF.DatamodelEnum) => {
5870
.join('');
5971

6072
return [
61-
"import {Type, Static} from '@sinclair/typebox'\n",
6273
`export const ${enm.name}Const = {`,
6374
values,
6475
'}\n',
@@ -69,18 +80,46 @@ export const transformEnum = (enm: DMMF.DatamodelEnum) => {
6980

7081
export function transformDMMF(dmmf: DMMF.Document) {
7182
const { models, enums } = dmmf.datamodel;
83+
const importStatements = new Set([
84+
'import {Type, Static} from "@sinclair/typebox"',
85+
]);
7286

7387
return [
7488
...models.map((model) => {
89+
let { raw, deps } = transformModel(model);
90+
91+
[...deps].forEach((d) => {
92+
const depsModel = models.find((m) => m.name === d) as DMMF.Model;
93+
if (depsModel) {
94+
const replacer = transformModel(depsModel, model.name);
95+
const re = new RegExp(`::${d}::`, 'gm');
96+
raw = raw.replace(re, replacer.raw);
97+
}
98+
});
99+
100+
enums.forEach((enm) => {
101+
const re = new RegExp(`::${enm.name}::`, 'gm');
102+
if (raw.match(re)) {
103+
raw = raw.replace(re, enm.name);
104+
importStatements.add(`import { ${enm.name} } from './${enm.name}'`);
105+
}
106+
});
107+
75108
return {
76109
name: model.name,
77-
rawString: transformModel(model),
110+
rawString: [
111+
[...importStatements].join('\n'),
112+
raw,
113+
`export type ${model.name}Type = Static<typeof ${model.name}>`,
114+
].join('\n\n'),
78115
};
79116
}),
80117
...enums.map((enm) => {
81118
return {
82119
name: enm.name,
83-
rawString: transformEnum(enm),
120+
rawString:
121+
'import {Type, Static} from "@sinclair/typebox"\n\n' +
122+
transformEnum(enm),
84123
};
85124
}),
86125
];

0 commit comments

Comments
 (0)