Skip to content

Commit c9beece

Browse files
russell-dot-jsorta
andauthored
feat(codegen): support sdl generation for model with compound id (#8556)
partial resolution of #8552 with this prisma schema: ``` model Temp { tenantId String id String @default(uuid()) name String @@id([tenantId, id]) } ``` running `yarn rw g sdl temp` now generates: ``` export const schema = gql` type Temp { tenantId: String! id: String! name: String! } type Query { temps: [Temp!]! @requireAuth temp(id: TempIdInput!): Temp @requireAuth } input CreateTempInput { tenantId: String! name: String! } input TempIdInput { tenantId: String! id: String! } input UpdateTempInput { tenantId: String name: String } type Mutation { createTemp(input: CreateTempInput!): Temp! @requireAuth updateTemp(id: TempIdInput!, input: UpdateTempInput!): Temp! @requireAuth deleteTemp(id: TempIdInput!): Temp! @requireAuth } ` ``` It's not perfect for the following reasons: 1. Generated service still expects a single { id } argument (but this may or may not be correct depending on where you get your tenantId from) 2. CreateTempInput is expecting part of the primary key in the request 3. UpdateTempInput duplicates the tenantId property from the TempIdInput #⁠2 and #⁠3 above are easily fixable. In my opinion #⁠3 above makes sense to fix, but for both #⁠1 and #⁠2, we cannot draw assumptions about what the developer intends to take as an input when using a compound primary key. Sometimes it might be part of the input, sometimes (in the case of tenantId) it might come from the authorized user and be invisible to the API consumers. The important thing is, now you can generate your SDL's and modify from there. Previously, redwood threw an error and you couldn't use codegen. This may be considered a breaking change because users who supply their own `sdl.{j,t}s.template` should now update to support `idInput`. However, since the feature didn't exist before, I personally don't consider this breaking. --------- Co-authored-by: Orta Therox <[email protected]>
1 parent 5e6c258 commit c9beece

File tree

5 files changed

+62
-0
lines changed

5 files changed

+62
-0
lines changed

.changesets/8556.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
- feat(codegen): support sdl generation for model with compound id (#8556) by @russell-dot-js
2+
3+
The SDL generator will no longer error when handling a table with a composite id, like so:
4+
5+
```prisma
6+
model Order {
7+
tenantId String
8+
id String @unique @default(uuid())
9+
@@id([tenantId, id])
10+
}
11+
```
12+
13+
It will now generate code in the SDL that handles input of both these variables:
14+
15+
```gql
16+
input TempIdInput {
17+
tenantId: String!
18+
id: String!
19+
}
20+
```
21+
22+
If you are using a custom `sdl.{j,t}s.template` then you may have to update it to support the new `idInput`.

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ export const files = async ({ name, typescript, ...options }) => {
4242

4343
// needed for the singular cell GQL query find by id case
4444
try {
45+
// todo should pull from graphql schema rather than prisma!
4546
model = await getSchema(pascalcase(singularize(cellName)))
4647
idName = getIdName(model)
4748
idType = getIdType(model)

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,15 @@ const inputSDL = (model, required, types = {}, docs = false) => {
107107
.map((field) => modelFieldToSDL({ field, required, types, docs }))
108108
}
109109

110+
const idInputSDL = (idType, docs) => {
111+
if (!Array.isArray(idType)) {
112+
return []
113+
}
114+
return idType.map((field) =>
115+
modelFieldToSDL({ field, required: true, types: {}, docs }),
116+
)
117+
}
118+
110119
// creates the CreateInput type (all fields are required)
111120
const createInputSDL = (model, types = {}, docs = false) => {
112121
return inputSDL(model, true, types, docs)
@@ -122,7 +131,14 @@ const idType = (model, crud) => {
122131
return undefined
123132
}
124133

134+
// When using a composite primary key, we need to return an array of fields
135+
if (model.primaryKey?.fields.length) {
136+
const { fields: fieldNames } = model.primaryKey
137+
return fieldNames.map((name) => model.fields.find((f) => f.name === name))
138+
}
139+
125140
const idField = model.fields.find((field) => field.isId)
141+
126142
if (!idField) {
127143
missingIdConsoleMessage()
128144
throw new Error('Failed: Could not generate SDL')
@@ -174,12 +190,15 @@ const sdlFromSchemaModel = async (name, crud, docs = false) => {
174190
const modelDescription =
175191
model.documentation || `Representation of ${modelName}.`
176192

193+
const idTypeRes = idType(model, crud)
194+
177195
return {
178196
modelName,
179197
modelDescription,
180198
query: querySDL(model, docs).join('\n '),
181199
createInput: createInputSDL(model, types, docs).join('\n '),
182200
updateInput: updateInputSDL(model, types, docs).join('\n '),
201+
idInput: idInputSDL(idTypeRes, docs).join('\n '),
183202
idType: idType(model, crud),
184203
idName: idName(model, crud),
185204
relations: relationsForModel(model),
@@ -200,6 +219,7 @@ export const files = async ({
200219
query,
201220
createInput,
202221
updateInput,
222+
idInput,
203223
idType,
204224
idName,
205225
relations,
@@ -221,6 +241,7 @@ export const files = async ({
221241
query,
222242
createInput,
223243
updateInput,
244+
idInput,
224245
idType,
225246
idName,
226247
enums,

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,15 @@ export const schema = gql`
3737
${createInput}
3838
}
3939

40+
<% if (idInput) { %>
41+
<% if (docs) { %>
42+
"""Autogenerated ID input type of ${singularPascalName}Id."""
43+
<% } %>
44+
input ${singularPascalName}IdInput {
45+
${idInput}
46+
}
47+
<% } %>
48+
4049
<% if (docs) { %>
4150
"""Autogenerated input type of Update${singularPascalName}."""
4251
<% } %>

packages/cli/src/commands/generate/sdl/templates/sdl.ts.template

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,15 @@ export const schema = gql`
3737
${createInput}
3838
}
3939

40+
<% if (idInput) { %>
41+
<% if (docs) { %>
42+
"""Autogenerated ID input type of ${singularPascalName}Id."""
43+
<% } %>
44+
input ${singularPascalName}IdInput {
45+
${idInput}
46+
}
47+
<% } %>
48+
4049
<% if (docs) { %>
4150
"""Autogenerated input type of Update${singularPascalName}."""
4251
<% } %>

0 commit comments

Comments
 (0)