Skip to content

Commit b144c6f

Browse files
authored
feat(cli): Support generating sdls for models with only an id and relation (#11931)
1 parent a8d1c62 commit b144c6f

File tree

5 files changed

+188
-9
lines changed

5 files changed

+188
-9
lines changed

.changesets/11931.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
- feat(cli): Support generating sdls for models with only an id and relation (#11931) by @Tobbe
2+
3+
It's now possible to generate SDL files for models that look like this
4+
5+
```prisma
6+
// This would be seeded with available car brands
7+
model CarBrand {
8+
brand String @id
9+
cars Car[]
10+
}
11+
```

packages/cli/src/commands/generate/sdl/__tests__/__snapshots__/sdl.test.js.snap

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1572,6 +1572,66 @@ exports[`with graphql documentations > in typescript mode > creates a single wor
15721572
"
15731573
`;
15741574
1575+
exports[`without graphql documentations > in javascript mode > create an sdl file for model with only id and relation 1`] = `
1576+
"export const schema = gql\`
1577+
type Car {
1578+
id: Int!
1579+
brand: String!
1580+
carBrand: CarBrand!
1581+
}
1582+
1583+
type Query {
1584+
cars: [Car!]! @requireAuth
1585+
car(id: Int!): Car @requireAuth
1586+
}
1587+
1588+
input CreateCarInput {
1589+
brand: String!
1590+
}
1591+
1592+
input UpdateCarInput {
1593+
brand: String
1594+
}
1595+
1596+
type Mutation {
1597+
createCar(input: CreateCarInput!): Car! @requireAuth
1598+
updateCar(id: Int!, input: UpdateCarInput!): Car! @requireAuth
1599+
deleteCar(id: Int!): Car! @requireAuth
1600+
}
1601+
\`
1602+
"
1603+
`;
1604+
1605+
exports[`without graphql documentations > in javascript mode > create an sdl file for model with only id and relation 2`] = `
1606+
"export const schema = gql\`
1607+
type CarBrand {
1608+
brand: String!
1609+
cars: [Car]!
1610+
}
1611+
1612+
type Query {
1613+
carBrands: [CarBrand!]! @requireAuth
1614+
carBrand(brand: String!): CarBrand @requireAuth
1615+
}
1616+
1617+
input CreateCarBrandInput {
1618+
brand: String!
1619+
}
1620+
1621+
input UpdateCarBrandInput {
1622+
brand: String!
1623+
}
1624+
1625+
type Mutation {
1626+
createCarBrand(input: CreateCarBrandInput!): CarBrand! @requireAuth
1627+
updateCarBrand(brand: String!, input: UpdateCarBrandInput!): CarBrand!
1628+
@requireAuth
1629+
deleteCarBrand(brand: String!): CarBrand! @requireAuth
1630+
}
1631+
\`
1632+
"
1633+
`;
1634+
15751635
exports[`without graphql documentations > in javascript mode > creates a multi word sdl file 1`] = `
15761636
"export const schema = gql\`
15771637
type UserProfile {
@@ -1809,6 +1869,66 @@ exports[`without graphql documentations > in javascript mode > creates a single
18091869
"
18101870
`;
18111871
1872+
exports[`without graphql documentations > in typescript mode > create an sdl file for model with only id and relation 1`] = `
1873+
"export const schema = gql\`
1874+
type Car {
1875+
id: Int!
1876+
brand: String!
1877+
carBrand: CarBrand!
1878+
}
1879+
1880+
type Query {
1881+
cars: [Car!]! @requireAuth
1882+
car(id: Int!): Car @requireAuth
1883+
}
1884+
1885+
input CreateCarInput {
1886+
brand: String!
1887+
}
1888+
1889+
input UpdateCarInput {
1890+
brand: String
1891+
}
1892+
1893+
type Mutation {
1894+
createCar(input: CreateCarInput!): Car! @requireAuth
1895+
updateCar(id: Int!, input: UpdateCarInput!): Car! @requireAuth
1896+
deleteCar(id: Int!): Car! @requireAuth
1897+
}
1898+
\`
1899+
"
1900+
`;
1901+
1902+
exports[`without graphql documentations > in typescript mode > create an sdl file for model with only id and relation 2`] = `
1903+
"export const schema = gql\`
1904+
type CarBrand {
1905+
brand: String!
1906+
cars: [Car]!
1907+
}
1908+
1909+
type Query {
1910+
carBrands: [CarBrand!]! @requireAuth
1911+
carBrand(brand: String!): CarBrand @requireAuth
1912+
}
1913+
1914+
input CreateCarBrandInput {
1915+
brand: String!
1916+
}
1917+
1918+
input UpdateCarBrandInput {
1919+
brand: String!
1920+
}
1921+
1922+
type Mutation {
1923+
createCarBrand(input: CreateCarBrandInput!): CarBrand! @requireAuth
1924+
updateCarBrand(brand: String!, input: UpdateCarBrandInput!): CarBrand!
1925+
@requireAuth
1926+
deleteCarBrand(brand: String!): CarBrand! @requireAuth
1927+
}
1928+
\`
1929+
"
1930+
`;
1931+
18121932
exports[`without graphql documentations > in typescript mode > creates a multi word sdl file 1`] = `
18131933
"export const schema = gql\`
18141934
type UserProfile {

packages/cli/src/commands/generate/sdl/__tests__/fixtures/schema.prisma

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,18 @@ enum Color {
6666
}
6767

6868
model CustomData {
69-
id Int @id @default(autoincrement())
70-
data String
69+
id Int @id @default(autoincrement())
70+
data String
71+
}
72+
73+
// This would be seeded with available car brands
74+
model CarBrand {
75+
brand String @id
76+
cars Car[]
77+
}
78+
79+
model Car {
80+
id Int @id @default(autoincrement())
81+
brand String
82+
carBrand CarBrand @relation(fields: [brand], references: [brand])
7183
}

packages/cli/src/commands/generate/sdl/__tests__/sdl.test.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,37 @@ const itCreatesAnSDLFileWithByteDefinitions = (baseArgs = {}) => {
236236
})
237237
}
238238

239+
const itCreatesAnSslFileForModelWithOnlyIdAndRelation = (baseArgs = {}) => {
240+
test('create an sdl file for model with only id and relation', async () => {
241+
const files = {
242+
...(await sdl.files({
243+
...baseArgs,
244+
name: 'Car',
245+
crud: true,
246+
})),
247+
...(await sdl.files({
248+
...baseArgs,
249+
name: 'CarBrand',
250+
crud: true,
251+
})),
252+
}
253+
const extension = extensionForBaseArgs(baseArgs)
254+
255+
expect(
256+
files[
257+
path.normalize(`/path/to/project/api/src/graphql/cars.sdl.${extension}`)
258+
],
259+
).toMatchSnapshot()
260+
expect(
261+
files[
262+
path.normalize(
263+
`/path/to/project/api/src/graphql/carBrands.sdl.${extension}`,
264+
)
265+
],
266+
).toMatchSnapshot()
267+
})
268+
}
269+
239270
describe('without graphql documentations', () => {
240271
describe('in javascript mode', () => {
241272
const baseArgs = { ...getDefaultArgs(sdl.defaults), tests: true }
@@ -249,6 +280,7 @@ describe('without graphql documentations', () => {
249280
itCreatesAnSDLFileWithEnumDefinitions(baseArgs)
250281
itCreatesAnSDLFileWithJsonDefinitions(baseArgs)
251282
itCreatesAnSDLFileWithByteDefinitions(baseArgs)
283+
itCreatesAnSslFileForModelWithOnlyIdAndRelation(baseArgs)
252284
})
253285

254286
describe('in typescript mode', () => {
@@ -267,6 +299,7 @@ describe('without graphql documentations', () => {
267299
itCreatesAnSDLFileWithEnumDefinitions(baseArgs)
268300
itCreatesAnSDLFileWithJsonDefinitions(baseArgs)
269301
itCreatesAnSDLFileWithByteDefinitions(baseArgs)
302+
itCreatesAnSslFileForModelWithOnlyIdAndRelation(baseArgs)
270303
})
271304
})
272305

packages/cli/src/commands/generate/sdl/sdl.js

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,13 @@ const modelFieldToSDL = ({
7575
Bytes: 'Byte',
7676
}
7777

78-
const fieldContent = `${field.name}: ${field.isList ? '[' : ''}${
79-
prismaTypeToGraphqlType[field.type] || field.type
80-
}${field.isList ? ']' : ''}${
81-
(field.isRequired && required) | field.isList ? '!' : ''
82-
}`
78+
const gqlType = prismaTypeToGraphqlType[field.type] || field.type
79+
const type = field.isList ? `[${gqlType}]` : gqlType
80+
// lists and id fields are always required (lists can be empty, that's fine)
81+
const isRequired =
82+
(field.isRequired && required) || field.isList || field.isId
83+
const fieldContent = `${field.name}: ${type}${isRequired ? '!' : ''}`
84+
8385
if (docs) {
8486
return addFieldGraphQLComment(field, fieldContent)
8587
} else {
@@ -98,7 +100,8 @@ const inputSDL = (model, required, types = {}, docs = false) => {
98100
.filter((field) => {
99101
const idField = model.fields.find((field) => field.isId)
100102

101-
if (idField) {
103+
// Only ignore the id field if it has a default value
104+
if (idField && idField.default) {
102105
ignoredFields.push(idField.name)
103106
}
104107

@@ -162,7 +165,7 @@ const idName = (model, crud) => {
162165
const sdlFromSchemaModel = async (name, crud, docs = false) => {
163166
const model = await getSchema(name)
164167

165-
// get models for user-defined types referenced
168+
// get models for referenced user-defined types
166169
const types = (
167170
await Promise.all(
168171
model.fields

0 commit comments

Comments
 (0)