Skip to content

Commit

Permalink
Feat: add enum types to generated sdl.js (redwoodjs#454)
Browse files Browse the repository at this point in the history
* feat: add enum types to generated sdl.js

* chore: remove redundant comment

* fix: make lint and current tests pass
added parser to the sdl.js output

* fix: change db provider to allow enums due to dropped support

* fix: fix template to not include wild spaces

* fix: remove unnecessary spaces around enum definitions

* fix: make field const instead of let

* fix: single enum scaffolded without spaces

* fix: spacing of multiple enums generated
  • Loading branch information
Rosenberg96 authored May 1, 2020
1 parent f8a2d0b commit aa0b9ac
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
export const schema = gql`
type Shoe {
id: Int!
color: Color!
}
enum Color {
RED
GREEN
BLUE
}
type Query {
shoes: [Shoe!]!
shoe(id: Int!): Shoe!
}
input CreateShoeInput {
color: Color!
}
input UpdateShoeInput {
color: Color
}
type Mutation {
createShoe(input: CreateShoeInput!): Shoe!
updateShoe(id: Int!, input: UpdateShoeInput!): Shoe!
deleteShoe(id: Int!): Shoe!
}
`
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
datasource hammerDatasource {
provider = "sqlite"
provider = "mysql"
url = env("DB_HOST")
}

Expand Down Expand Up @@ -35,3 +35,14 @@ model UserProfile {
userId Int
user User @relation(fields: [userId], references: [id])
}

model Shoe {
id Int @id @default(autoincrement())
color Color
}

enum Color {
RED
GREEN
BLUE
}
8 changes: 8 additions & 0 deletions packages/cli/src/commands/generate/sdl/__tests__/sdl.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,11 @@ test('creates a multi word sdl file with CRUD actions', async () => {
loadGeneratorFixture('sdl', 'multiWordSdlCrud.js')
)
})

test('creates a sdl file with enum definitions', async () => {
const files = await sdl.files({ name: 'Shoe', crud: true })

expect(files['/path/to/project/api/src/graphql/shoes.sdl.js']).toEqual(
loadGeneratorFixture('sdl', 'enumGeneratedSdl.js')
)
})
23 changes: 22 additions & 1 deletion packages/cli/src/commands/generate/sdl/sdl.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ import camelcase from 'camelcase'
import pascalcase from 'pascalcase'
import pluralize from 'pluralize'

import { generateTemplate, getSchema, getPaths, writeFilesTask } from 'src/lib'
import {
generateTemplate,
getSchema,
getPaths,
writeFilesTask,
getEnum,
} from 'src/lib'
import c from 'src/lib/colors'

import { files as serviceFiles } from '../service/service'
Expand Down Expand Up @@ -72,12 +78,25 @@ const sdlFromSchemaModel = async (name) => {
)
).reduce((acc, cur) => ({ ...acc, [cur.name]: cur }), {})

// Get enum definiton and fields from user-defined types
const enums = (
await Promise.all(
model.fields
.filter((field) => field.kind === 'enum')
.map(async (field) => {
const enumDef = await getEnum(field.type)
return enumDef
})
)
).reduce((acc, curr) => acc.concat(curr), [])

return {
query: querySDL(model).join('\n '),
createInput: createInputSDL(model, types).join('\n '),
updateInput: updateInputSDL(model, types).join('\n '),
idType: idType(model),
relations: relationsForModel(model),
enums,
}
} else {
throw new Error(
Expand All @@ -93,6 +112,7 @@ export const files = async ({ name, crud }) => {
updateInput,
idType,
relations,
enums,
} = await sdlFromSchemaModel(pascalcase(pluralize.singular(name)))

const template = generateTemplate(
Expand All @@ -104,6 +124,7 @@ export const files = async ({ name, crud }) => {
createInput,
updateInput,
idType,
enums,
}
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ export const schema = gql`
type ${singularPascalName} {
${query}
}

<% if (enums.length > 0) {%>
<% enums.forEach((enumDef, idx)=> {%> enum ${enums[idx].name} {<% enums[idx].values.forEach((enumDefValue, idk)=> { %>
${enums[idx].values[idk].name}<% }) %>
}
<%}) %><% } %>
type Query {
${pluralCamelName}: [${singularPascalName}!]!<% if (crud) { %>
${singularCamelName}(id: ${idType}!): ${singularPascalName}!<% } %>
Expand Down
46 changes: 40 additions & 6 deletions packages/cli/src/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,10 @@ export const asyncForEach = async (array, callback) => {
* entire schema is returned.
*/
export const getSchema = async (name) => {
const schemaPath = path.join(getPaths().api.db, 'schema.prisma')
const metadata = await getDMMF({
datamodel: readFile(schemaPath.toString()),
})
const schema = await getSchemaDefinitions()

if (name) {
const model = metadata.datamodel.models.find((model) => {
const model = schema.datamodel.models.find((model) => {
return model.name === name
})

Expand All @@ -47,7 +44,44 @@ export const getSchema = async (name) => {
}
}

return metadata.datamodel
return schema.metadata.datamodel
}

/**
* Returns the enum defined with the given `name` parsed from
* the schema.prisma of the target applicaiton. If no `name` is given then the
* all enum definitions are returned
*/
export const getEnum = async (name) => {
const schema = await getSchemaDefinitions()

if (name) {
const model = schema.datamodel.enums.find((model) => {
return model.name === name
})

if (model) {
return model
} else {
throw new Error(
`No enum schema definition found for \`${name}\` in schema.prisma file`
)
}
}

return schema.metadata.datamodel.enums
}

/*
* Returns the DMMF defined by `prisma` resolving the relevant `shema.prisma` path.
*/
export const getSchemaDefinitions = async () => {
const schemaPath = path.join(getPaths().api.db, 'schema.prisma')
const metadata = await getDMMF({
datamodel: readFile(schemaPath.toString()),
})

return metadata
}

/**
Expand Down

0 comments on commit aa0b9ac

Please sign in to comment.