Skip to content

Commit 0702890

Browse files
committed
✨ feat: add type overwrites
1 parent 0e6fa5d commit 0702890

File tree

5 files changed

+118
-48
lines changed

5 files changed

+118
-48
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,11 @@ Prismabox offers annotations to adjust the output of models and fields.
3737
| @prismabox.hide | - | Hides the field or model from the output |
3838
| @prismabox.hidden | - | Alias for @prismabox.hide |
3939
| @prismabox.input.hide | - | Hides the field or model from the output only in the input model |
40-
|@prismabox.create.input.hide| - | Hides the field or model from the outputs only in the input create model|
41-
|@prismabox.update.input.hide| - | Hides the field or model from the outputs only in the input update model|
40+
| @prismabox.create.input.hide | - | Hides the field or model from the outputs only in the input create model|
41+
| @prismabox.update.input.hide | - | Hides the field or model from the outputs only in the input update model|
4242
| @prismabox.options | @prismabox.options{ min: 10, max: 20 } | Uses the provided options for the field or model in the generated schema. Be careful to use valid JS/TS syntax! |
43+
| @prismabox.typeOverwrite | @prismabox.typeOverwrite=Type.CustomName | Overwrite the type prismabox outputs for a field with a custom string. See [m1212e/prismabox#29](https://github.com/m1212e/prismabox/issues/29) for an extended usecase |
44+
4345
> For a more detailed list of available annotations, please see [annotations.ts](src/annotations/annotations.ts)
4446
4547
A schema using annotations could look like this:

prisma/schema.prisma

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ generator client {
88
}
99

1010
generator prismabox {
11-
provider = "node ./dist/cli.js"
12-
inputModel = true
13-
output = "./generated/schema"
11+
provider = "node ./dist/cli.js"
12+
inputModel = true
13+
output = "./generated/schema"
1414
additionalFieldsPlain = ["additional: Type.Optional(Type.String())"]
15-
useJsonTypes = true
16-
allowRecursion = false
15+
useJsonTypes = true
16+
allowRecursion = false
1717
}
1818

1919
model Password {
@@ -74,7 +74,9 @@ model User {
7474
id String @id @default(uuid())
7575
createdAt DateTime @default(now())
7676
updatedAt DateTime @updatedAt
77+
/// @prismabox.typeOverwrite=CustomName
7778
name String
79+
/// @prismabox.typeOverwrite=CustomConferenceMember
7880
conferenceMemberships ConferenceMember[]
7981
committeeMemberships CommitteeMember[]
8082
messages Message[]
@@ -319,11 +321,11 @@ model Message {
319321
}
320322

321323
model User2 {
322-
id String @id @default(uuid())
323-
createdAt DateTime @default(now())
324-
updatedAt DateTime @updatedAt
324+
id String @id @default(uuid())
325+
createdAt DateTime @default(now())
326+
updatedAt DateTime @updatedAt
325327
/// @prismabox.input.hide
326-
authProviderId String @unique
328+
authProviderId String @unique
327329
/// @prismabox.input.hide
328330
domainId String
329331
firstName String
@@ -333,7 +335,7 @@ model User2 {
333335
sponsor String
334336
company String
335337
/// custom user attributes from the auth provider are stored here. In most cases you can expect a Record<string, string> here.
336-
attributes Json @default("{}")
338+
attributes Json @default("{}")
337339
338340
@@unique([email, domainId])
339-
}
341+
}

src/annotations/annotations.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ export type Annotation =
55
| { type: "HIDDEN_INPUT" }
66
| { type: "HIDDEN_INPUT_CREATE" }
77
| { type: "HIDDEN_INPUT_UPDATE" }
8-
| { type: "OPTIONS"; value: string };
8+
| { type: "OPTIONS"; value: string }
9+
| { type: "TYPE_OVERWRITE"; value: string };
910

1011
export function isHiddenVariant(
1112
annotation: Annotation,
@@ -37,6 +38,12 @@ export function isOptionsVariant(
3738
return annotation.type === "OPTIONS";
3839
}
3940

41+
export function isTypeOverwriteVariant(
42+
annotation: Annotation,
43+
): annotation is { type: "TYPE_OVERWRITE"; value: string } {
44+
return annotation.type === "TYPE_OVERWRITE";
45+
}
46+
4047
const annotationKeys: { type: Annotation["type"]; keys: string[] }[] = [
4148
{
4249
type: "HIDDEN_INPUT_CREATE",
@@ -63,6 +70,10 @@ const annotationKeys: { type: Annotation["type"]; keys: string[] }[] = [
6370
type: "OPTIONS",
6471
keys: ["@prismabox.options"],
6572
},
73+
{
74+
type: "TYPE_OVERWRITE",
75+
keys: ["@prismabox.typeOverwrite"],
76+
},
6677
];
6778

6879
export function extractAnnotations(
@@ -108,6 +119,15 @@ export function extractAnnotations(
108119
line.length - 1,
109120
),
110121
});
122+
} else if (annotationKey.type === "TYPE_OVERWRITE") {
123+
if (!line.startsWith(`${annotationKey.keys[0]}=`)) {
124+
throw new Error("Invalid syntax, expected = after prismabox.type");
125+
}
126+
127+
annotations.push({
128+
type: "TYPE_OVERWRITE",
129+
value: line.split("=")[1],
130+
});
111131
} else {
112132
annotations.push({ type: annotationKey.type });
113133
}

src/generators/plain.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import type { DMMF } from "@prisma/generator-helper";
2-
import { extractAnnotations } from "../annotations/annotations";
2+
import {
3+
extractAnnotations,
4+
isTypeOverwriteVariant,
5+
} from "../annotations/annotations";
36
import { generateTypeboxOptions } from "../annotations/options";
47
import { getConfig } from "../config";
58
import type { ProcessedModel } from "../model";
@@ -93,10 +96,18 @@ export function stringifyPlain(
9396
let stringifiedType = "";
9497

9598
if (isPrimitivePrismaFieldType(field.type)) {
96-
stringifiedType = stringifyPrimitiveType({
97-
fieldType: field.type as PrimitivePrismaFieldType,
98-
options: generateTypeboxOptions({ input: annotations }),
99-
});
99+
const overwrittenType = annotations.annotations
100+
.filter(isTypeOverwriteVariant)
101+
.at(0)?.value;
102+
103+
if (overwrittenType) {
104+
stringifiedType = overwrittenType;
105+
} else {
106+
stringifiedType = stringifyPrimitiveType({
107+
fieldType: field.type as PrimitivePrismaFieldType,
108+
options: generateTypeboxOptions({ input: annotations }),
109+
});
110+
}
100111
} else if (processedEnums.find((e) => e.name === field.type)) {
101112
// biome-ignore lint/style/noNonNullAssertion: we checked this manually
102113
stringifiedType = processedEnums.find(

src/generators/where.ts

Lines changed: 64 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import type { DMMF } from "@prisma/generator-helper";
2-
import { extractAnnotations } from "../annotations/annotations";
2+
import {
3+
extractAnnotations,
4+
isTypeOverwriteVariant,
5+
} from "../annotations/annotations";
36
import { generateTypeboxOptions } from "../annotations/options";
47
import { getConfig } from "../config";
58
import type { ProcessedModel } from "../model";
@@ -40,13 +43,21 @@ export function stringifyWhere(data: DMMF.Model) {
4043
let stringifiedType = "";
4144

4245
if (isPrimitivePrismaFieldType(field.type)) {
43-
stringifiedType = stringifyPrimitiveType({
44-
fieldType: field.type as PrimitivePrismaFieldType,
45-
options: generateTypeboxOptions({
46-
exludeAdditionalProperties: true,
47-
input: annotations,
48-
}),
49-
});
46+
const overwrittenType = annotations.annotations
47+
.filter(isTypeOverwriteVariant)
48+
.at(0)?.value;
49+
50+
if (overwrittenType) {
51+
stringifiedType = overwrittenType;
52+
} else {
53+
stringifiedType = stringifyPrimitiveType({
54+
fieldType: field.type as PrimitivePrismaFieldType,
55+
options: generateTypeboxOptions({
56+
exludeAdditionalProperties: true,
57+
input: annotations,
58+
}),
59+
});
60+
}
5061
} else if (processedEnums.find((e) => e.name === field.type)) {
5162
// biome-ignore lint/style/noNonNullAssertion: we checked this manually
5263
stringifiedType = processedEnums.find(
@@ -115,13 +126,21 @@ export function stringifyWhereUnique(data: DMMF.Model) {
115126
let stringifiedType = "";
116127

117128
if (isPrimitivePrismaFieldType(f.type)) {
118-
stringifiedType = stringifyPrimitiveType({
119-
fieldType: f.type as PrimitivePrismaFieldType,
120-
options: generateTypeboxOptions({
121-
exludeAdditionalProperties: true,
122-
input: annotations,
123-
}),
124-
});
129+
const overwrittenType = annotations.annotations
130+
.filter(isTypeOverwriteVariant)
131+
.at(0)?.value;
132+
133+
if (overwrittenType) {
134+
stringifiedType = overwrittenType;
135+
} else {
136+
stringifiedType = stringifyPrimitiveType({
137+
fieldType: f.type as PrimitivePrismaFieldType,
138+
options: generateTypeboxOptions({
139+
exludeAdditionalProperties: true,
140+
input: annotations,
141+
}),
142+
});
143+
}
125144
} else if (processedEnums.find((e) => e.name === f.type)) {
126145
// biome-ignore lint/style/noNonNullAssertion: we checked this manually
127146
stringifiedType = processedEnums.find(
@@ -151,13 +170,21 @@ export function stringifyWhereUnique(data: DMMF.Model) {
151170
let stringifiedType = "";
152171

153172
if (isPrimitivePrismaFieldType(field.type)) {
154-
stringifiedType = stringifyPrimitiveType({
155-
fieldType: field.type as PrimitivePrismaFieldType,
156-
options: generateTypeboxOptions({
157-
exludeAdditionalProperties: true,
158-
input: annotations,
159-
}),
160-
});
173+
const overwrittenType = annotations.annotations
174+
.filter(isTypeOverwriteVariant)
175+
.at(0)?.value;
176+
177+
if (overwrittenType) {
178+
stringifiedType = overwrittenType;
179+
} else {
180+
stringifiedType = stringifyPrimitiveType({
181+
fieldType: field.type as PrimitivePrismaFieldType,
182+
options: generateTypeboxOptions({
183+
exludeAdditionalProperties: true,
184+
input: annotations,
185+
}),
186+
});
187+
}
161188
} else if (processedEnums.find((e) => e.name === field.type)) {
162189
// biome-ignore lint/style/noNonNullAssertion: we checked this manually
163190
stringifiedType = processedEnums.find(
@@ -184,13 +211,21 @@ export function stringifyWhereUnique(data: DMMF.Model) {
184211
let stringifiedType = "";
185212

186213
if (isPrimitivePrismaFieldType(field.type)) {
187-
stringifiedType = stringifyPrimitiveType({
188-
fieldType: field.type as PrimitivePrismaFieldType,
189-
options: generateTypeboxOptions({
190-
exludeAdditionalProperties: true,
191-
input: annotations,
192-
}),
193-
});
214+
const overwrittenType = annotations.annotations
215+
.filter(isTypeOverwriteVariant)
216+
.at(0)?.value;
217+
218+
if (overwrittenType) {
219+
stringifiedType = overwrittenType;
220+
} else {
221+
stringifiedType = stringifyPrimitiveType({
222+
fieldType: field.type as PrimitivePrismaFieldType,
223+
options: generateTypeboxOptions({
224+
exludeAdditionalProperties: true,
225+
input: annotations,
226+
}),
227+
});
228+
}
194229
} else if (processedEnums.find((e) => e.name === field.type)) {
195230
// biome-ignore lint/style/noNonNullAssertion: we checked this manually
196231
stringifiedType = processedEnums.find(

0 commit comments

Comments
 (0)