Skip to content
This repository was archived by the owner on Apr 23, 2024. It is now read-only.

Commit 3028589

Browse files
committed
✨ support scalar lists
1 parent 693b613 commit 3028589

File tree

6 files changed

+216
-39
lines changed

6 files changed

+216
-39
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ No installation! Comes preinstalled with `prisma2`! 🎉
2727
```prisma
2828
generator test-utils {
2929
provider = "prisma-test-utils"
30-
output = "node*modules/@generated/test-utils"
30+
output = "node-modules/@generated/test-utils"
3131
}
3232
```
3333

@@ -141,7 +141,7 @@ test('test with seed data', async () => {
141141
await seed({
142142
client,
143143
models: kit => ({
144-
_: {
144+
'*': {
145145
/* Default number of instances. */
146146
amount: 500,
147147
},
@@ -155,6 +155,8 @@ test('test with seed data', async () => {
155155
entry: () => {
156156
return `A generated entry from the function.`
157157
},
158+
/* Define scalar list mock functions */
159+
tags: () => kit.faker.n(kit.faker.name, 3)
158160
/* Manage relations. */
159161
posts: {
160162
max: 100,

src/__test.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,24 @@
77

88
// const seed: SeedFunction<PrismaClient, GeneratedSeedModels> = getSeed(dmmf)
99

10-
// // debugger
10+
// const dogo = await client.pet.create({
11+
// data: {
12+
// name: 'wubju',
13+
// nicknames: {
14+
// set: [
15+
// 'Arthur Parker',
16+
// 'Jack Chavez',
17+
// 'Hunter Franklin',
18+
// 'Betty Gill',
19+
// 'Louis Reeves',
20+
// ],
21+
// },
22+
// animal: 'Dog',
23+
// birthday: '2040-07-14T19:13:01.534Z',
24+
// },
25+
// })
26+
27+
// debugger
1128

1229
// // const user = await client.user.create({
1330
// // data: {
@@ -34,6 +51,12 @@
3451
// '*': {
3552
// amount: 3,
3653
// },
54+
// Pet: {
55+
// factory: {
56+
// animal: 'Dog',
57+
// nicknames: () => kit.faker.n(kit.faker.name, 5),
58+
// },
59+
// },
3760
// }),
3861
// })
3962

src/intellisense/seed.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,16 @@ export function generateGeneratedSeedModelsType(dmmf: DMMF.Document): string {
9797
}
9898
}
9999
case 'scalar': {
100+
const scalar = getTSTypeFromDMMFScalar(field.type)
101+
const supported = isSupportedScalar(field)
102+
if (field.isList) {
103+
/* prettier-ignore */
104+
return `${field.name}${q(supported)}: ${scalar}[] | (() => ${scalar}[])`
105+
}
100106
/**
101107
* The field should provide a function which results in a type
102108
* of the scalar.
103109
*/
104-
const scalar = getTSTypeFromDMMFScalar(field.type)
105-
const supported = isSupportedScalar(field)
106110
return `${field.name}${q(supported)}: ${scalar} | (() => ${scalar})`
107111
}
108112
default: {

src/static/seed.ts

Lines changed: 167 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
import { DMMF, debug } from '@prisma/client/runtime'
1+
import { DMMF } from '@prisma/client/runtime'
22
import Chance from 'chance'
3-
import _ from 'lodash'
4-
import { Dictionary } from 'lodash'
3+
import _, { Dictionary } from 'lodash'
54
import mls from 'multilines'
65

76
import { Scalar } from './scalars'
@@ -13,6 +12,7 @@ import {
1312
SeedModelFieldRelationConstraint,
1413
SeedFunction,
1514
PrismaClientType,
15+
SeedModelScalarListDefinition,
1616
} from './types'
1717
import { withDefault, not, filterKeys, mapEntries } from './utils'
1818

@@ -136,12 +136,11 @@ export function getSeed<
136136
* - { ArtistId: "uniqueid" }
137137
*/
138138
type ID = Dictionary<string | number>
139+
type Scalar = string | number | boolean | Date
139140

140141
type FixtureData = Dictionary<
141-
| string
142-
| number
143-
| boolean
144-
| Date
142+
| Scalar
143+
| { set: Scalar[] }
145144
| { connect: ID }
146145
| { connect: ID[] }
147146
| { create: FixtureData }
@@ -581,7 +580,10 @@ export function getSeed<
581580
*
582581
* -> We should create B and connect As to it.
583582
*/
584-
return { optional: false, from: relationModel }
583+
return {
584+
optional: false,
585+
from: relationModel,
586+
}
585587
} else if (field.isList && backRelationField.isRequired) {
586588
/**
587589
* model A {
@@ -593,7 +595,10 @@ export function getSeed<
593595
*
594596
* -> We should create A and connect Bs to it later.
595597
*/
596-
return { optional: false, from: fieldModel }
598+
return {
599+
optional: false,
600+
from: fieldModel,
601+
}
597602
} else if (field.isList && !backRelationField.isRequired) {
598603
/**
599604
* model A {
@@ -763,7 +768,10 @@ export function getSeed<
763768
ordinal: number,
764769
pool: Pool,
765770
order: Order,
766-
): { step: Step; pool: Pool } {
771+
): {
772+
step: Step
773+
pool: Pool
774+
} {
767775
/**
768776
* Fix optional relations' direction.
769777
*/
@@ -806,7 +814,10 @@ export function getSeed<
806814
[order.model.name]: order.model,
807815
}
808816

809-
return { step, pool: newPool }
817+
return {
818+
step,
819+
pool: newPool,
820+
}
810821
}
811822
}
812823

@@ -956,7 +967,9 @@ export function getSeed<
956967
pool: Pool
957968
tasks: Task[]
958969
data: FixtureData
959-
include: { [field: string]: true | { include: Mock['include'] } }
970+
include: {
971+
[field: string]: true | { include: Mock['include'] }
972+
}
960973
}
961974

962975
/**
@@ -998,20 +1011,52 @@ export function getSeed<
9981011
switch (typeof mock) {
9991012
case 'function': {
10001013
/* Custom function */
1001-
const value = mock.call(faker)
1002-
return {
1003-
pool,
1004-
tasks,
1005-
data: {
1006-
...data,
1007-
[field.name]: value,
1008-
},
1009-
include,
1014+
if (field.isList) {
1015+
const values = (mock as () => SeedModelFieldDefinition[]).call(
1016+
faker,
1017+
)
1018+
return {
1019+
pool,
1020+
tasks,
1021+
data: {
1022+
...data,
1023+
[field.name]: { set: values },
1024+
},
1025+
include,
1026+
}
1027+
} else {
1028+
const value = (mock as () => SeedModelFieldDefinition).call(
1029+
faker,
1030+
)
1031+
return {
1032+
pool,
1033+
tasks,
1034+
data: {
1035+
...data,
1036+
[field.name]: value,
1037+
},
1038+
include,
1039+
}
10101040
}
10111041
}
10121042
case 'object': {
1013-
/* Relation constraint */
1014-
break
1043+
/* Relation or scalar list */
1044+
if (field.isList) {
1045+
/* Scalar list */
1046+
const values = mock as SeedModelFieldDefinition[]
1047+
return {
1048+
pool,
1049+
tasks,
1050+
data: {
1051+
...data,
1052+
[field.name]: { set: values },
1053+
},
1054+
include,
1055+
}
1056+
} else {
1057+
/* Relation */
1058+
break
1059+
}
10151060
}
10161061
case 'bigint':
10171062
case 'boolean':
@@ -1078,6 +1123,104 @@ export function getSeed<
10781123

10791124
switch (field.kind) {
10801125
case 'scalar': {
1126+
/**
1127+
* List scalar mocks.
1128+
*
1129+
* We provide good default mocks for functions. Anything more complex
1130+
* or flexible can be achieved using the exposed Chance.js library.
1131+
*/
1132+
if (field.isList) {
1133+
switch (field.type) {
1134+
/**
1135+
* Scalars
1136+
*/
1137+
case Scalar.string: {
1138+
const strings = faker.n(faker.string, 3)
1139+
1140+
return {
1141+
pool,
1142+
tasks,
1143+
data: {
1144+
...data,
1145+
[field.name]: {
1146+
set: strings,
1147+
},
1148+
},
1149+
include,
1150+
}
1151+
}
1152+
case Scalar.int: {
1153+
const numbers = faker.n(faker.integer, 3, {
1154+
min: -2000,
1155+
max: 2000,
1156+
})
1157+
1158+
return {
1159+
pool,
1160+
tasks,
1161+
data: {
1162+
...data,
1163+
[field.name]: { set: numbers },
1164+
},
1165+
include,
1166+
}
1167+
}
1168+
case Scalar.float: {
1169+
const floats = faker.n(faker.floating, 3, {
1170+
min: -1000,
1171+
max: 1000,
1172+
fixed: 2,
1173+
})
1174+
1175+
return {
1176+
pool,
1177+
tasks,
1178+
data: {
1179+
...data,
1180+
[field.name]: { set: floats },
1181+
},
1182+
include,
1183+
}
1184+
}
1185+
case Scalar.date: {
1186+
const dates = faker.n(faker.date, 3)
1187+
1188+
return {
1189+
pool,
1190+
tasks,
1191+
data: {
1192+
...data,
1193+
[field.name]: { set: dates },
1194+
},
1195+
include,
1196+
}
1197+
}
1198+
case Scalar.bool: {
1199+
const booleans = faker.n(faker.bool, 3)
1200+
1201+
return {
1202+
pool,
1203+
tasks,
1204+
data: {
1205+
...data,
1206+
[field.name]: { set: booleans },
1207+
},
1208+
include,
1209+
}
1210+
}
1211+
/* Unsupported scalar */
1212+
default: {
1213+
throw new Error(
1214+
`Unsupported scalar field ${task.model.name}${field.name} of type ${field.type}`,
1215+
)
1216+
}
1217+
}
1218+
}
1219+
1220+
/**
1221+
* Scalar mocks.
1222+
*/
1223+
10811224
switch (field.type) {
10821225
/**
10831226
* Scalars
@@ -1154,7 +1297,7 @@ export function getSeed<
11541297
/* Unsupported scalar */
11551298
default: {
11561299
throw new Error(
1157-
`Unsupported scalar field of type ${field.type}`,
1300+
`Unsupported scalar field ${task.model.name}${field.name} of type ${field.type}`,
11581301
)
11591302
}
11601303
}

src/static/types.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,15 @@ export type SeedModel = {
2828
factory?: Dictionary<
2929
| SeedModelFieldDefinition
3030
| (() => SeedModelFieldDefinition)
31+
| SeedModelScalarListDefinition
3132
| SeedModelFieldRelationConstraint
3233
>
3334
}
3435

35-
export type SeedModelFieldDefinition = string | number | boolean // ID |
36-
36+
export type SeedModelFieldDefinition = string | number | boolean
37+
export type SeedModelScalarListDefinition =
38+
| SeedModelFieldDefinition[]
39+
| (() => SeedModelFieldDefinition[])
3740
export type SeedModelFieldRelationConstraint = {
3841
min?: number
3942
max?: number

0 commit comments

Comments
 (0)