Skip to content

Commit

Permalink
Schema Gen: Add Option for Preserving Input Names (#1186)
Browse files Browse the repository at this point in the history
  • Loading branch information
LaurenceWarne authored Dec 2, 2021
1 parent c77494f commit c28285d
Show file tree
Hide file tree
Showing 11 changed files with 105 additions and 19 deletions.
4 changes: 3 additions & 1 deletion codegen-sbt/src/main/scala/caliban/codegen/CalibanCli.scala
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ object CalibanCli {

private val genSchemaHelpMsg =
s"""
|calibanGenSchema schemaPath outputPath [--scalafmtPath path] [--headers name:value,name2:value2] [--packageName name] [--effect fqdn.Effect] [--abstractEffectType true|false]
|calibanGenSchema schemaPath outputPath [--scalafmtPath path] [--headers name:value,name2:value2] [--packageName name] [--effect fqdn.Effect] [--abstractEffectType true|false] [--preserveInputNames true|false]
|
|This command will create a Scala file in `outputPath` containing all the types
|defined in the provided GraphQL schema defined at `schemaPath`. Instead of a path,
Expand All @@ -66,6 +66,8 @@ object CalibanCli {
|type is abstract, so that it will be added as a type parameter to the generated
|Query and Mutation classes (if applicable). In such cases `F` will be used by
|as the type parameter unless the `--effect` option is explicitly given.
|By default all input types will have 'Input' appended to their names in the
|derived schema. Use the --preserveInputNames flag to disable this.
|""".stripMargin

private val genClientHelpMsg =
Expand Down
14 changes: 10 additions & 4 deletions tools/src/main/scala/caliban/tools/CalibanCommonSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ final case class CalibanCommonSettings(
extensibleEnums: Option[Boolean],
genType: GenType,
effect: Option[String],
abstractEffectType: Option[Boolean]
abstractEffectType: Option[Boolean],
preserveInputNames: Option[Boolean]
) {

private[caliban] def toOptions(schemaPath: String, toPath: String): Options =
Expand All @@ -33,7 +34,8 @@ final case class CalibanCommonSettings(
abstractEffectType = abstractEffectType,
splitFiles = splitFiles,
enableFmt = enableFmt,
extensibleEnums = extensibleEnums
extensibleEnums = extensibleEnums,
preserveInputNames = preserveInputNames
)

private[caliban] def combine(r: => CalibanCommonSettings): CalibanCommonSettings =
Expand All @@ -50,7 +52,8 @@ final case class CalibanCommonSettings(
extensibleEnums = r.extensibleEnums.orElse(this.extensibleEnums),
genType = r.genType,
effect = r.effect.orElse(this.effect),
abstractEffectType = r.abstractEffectType.orElse(this.abstractEffectType)
abstractEffectType = r.abstractEffectType.orElse(this.abstractEffectType),
preserveInputNames = r.preserveInputNames.orElse(this.preserveInputNames)
)

def clientName(value: String): CalibanCommonSettings = this.copy(clientName = Some(value))
Expand All @@ -68,6 +71,8 @@ final case class CalibanCommonSettings(
def effect(effect: String): CalibanCommonSettings = this.copy(effect = Some(effect))
def abstractEffectType(abstractEffectType: Boolean): CalibanCommonSettings =
this.copy(abstractEffectType = Some(abstractEffectType))
def preserveInputNames(preserveInputNames: Boolean): CalibanCommonSettings =
this.copy(preserveInputNames = Some(preserveInputNames))
}

object CalibanCommonSettings {
Expand All @@ -85,6 +90,7 @@ object CalibanCommonSettings {
extensibleEnums = None,
genType = GenType.Client,
effect = None,
abstractEffectType = None
abstractEffectType = None,
preserveInputNames = None
)
}
4 changes: 3 additions & 1 deletion tools/src/main/scala/caliban/tools/Codegen.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ object Codegen {
effect = arguments.effect.getOrElse {
if (abstractEffectType) "F" else "zio.UIO"
}
preserveInputNames = arguments.preserveInputNames.getOrElse(false)
genView = arguments.genView.getOrElse(false)
scalarMappings = arguments.scalarMappings
splitFiles = arguments.splitFiles.getOrElse(false)
Expand All @@ -41,7 +42,8 @@ object Codegen {
effect,
arguments.imports,
scalarMappings,
abstractEffectType
abstractEffectType,
preserveInputNames
)
)
case GenType.Client =>
Expand Down
9 changes: 6 additions & 3 deletions tools/src/main/scala/caliban/tools/Options.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ final case class Options(
abstractEffectType: Option[Boolean],
splitFiles: Option[Boolean],
enableFmt: Option[Boolean],
extensibleEnums: Option[Boolean]
extensibleEnums: Option[Boolean],
preserveInputNames: Option[Boolean]
)

object Options {
Expand All @@ -34,7 +35,8 @@ object Options {
abstractEffectType: Option[Boolean],
splitFiles: Option[Boolean],
enableFmt: Option[Boolean],
extensibleEnums: Option[Boolean]
extensibleEnums: Option[Boolean],
preserveInputNames: Option[Boolean]
)

def fromArgs(args: List[String]): Option[Options] =
Expand Down Expand Up @@ -77,7 +79,8 @@ object Options {
rawOpts.abstractEffectType,
rawOpts.splitFiles,
rawOpts.enableFmt,
rawOpts.extensibleEnums
rawOpts.extensibleEnums,
rawOpts.preserveInputNames
)
}
case _ => None
Expand Down
10 changes: 7 additions & 3 deletions tools/src/main/scala/caliban/tools/SchemaWriter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ object SchemaWriter {
effect: String = "zio.UIO",
imports: Option[List[String]] = None,
scalarMappings: Option[Map[String, String]],
isEffectTypeAbstract: Boolean = false
isEffectTypeAbstract: Boolean = false,
preserveInputNames: Boolean = false
): String = {

val interfaceImplementationsMap = (for {
Expand Down Expand Up @@ -62,10 +63,13 @@ object SchemaWriter {
.map(writeField(_, typedef))
.mkString(", ")})"""

def writeInputObject(typedef: InputObjectTypeDefinition): String =
s"""${writeDescription(typedef.description)}final case class ${typedef.name}(${typedef.fields
def writeInputObject(typedef: InputObjectTypeDefinition): String = {
val name = typedef.name
val maybeAnnotation = if (preserveInputNames) s"""@GQLInputName("$name")\n""" else ""
s"""${maybeAnnotation}${writeDescription(typedef.description)}final case class $name(${typedef.fields
.map(writeInputValue)
.mkString(", ")})"""
}

def writeEnum(typedef: EnumTypeDefinition): String =
s"""${writeDescription(typedef.description)}sealed trait ${typedef.name} extends scala.Product with scala.Serializable
Expand Down
3 changes: 2 additions & 1 deletion tools/src/main/scala/caliban/tools/compiletime/Config.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ trait Config {
extensibleEnums = Some(extensibleEnums),
GenType.Client,
effect = None,
abstractEffectType = None
abstractEffectType = None,
preserveInputNames = None
)

private[caliban] def asScalaCode: String = {
Expand Down
3 changes: 2 additions & 1 deletion tools/src/test/scala/caliban/tools/CodegenSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ object CodegenSpec extends DefaultRunnableSpec {
abstractEffectType = None,
splitFiles = None,
enableFmt = None,
extensibleEnums = None
extensibleEnums = None,
preserveInputNames = None
)

getPackageAndObjectName(arguments)
Expand Down
42 changes: 40 additions & 2 deletions tools/src/test/scala/caliban/tools/OptionsSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ object OptionsSpec extends DefaultRunnableSpec {
None,
None,
None,
None,
None
)
)
Expand All @@ -54,6 +55,7 @@ object OptionsSpec extends DefaultRunnableSpec {
None,
None,
None,
None,
None
)
)
Expand All @@ -66,7 +68,7 @@ object OptionsSpec extends DefaultRunnableSpec {
assert(result)(
equalTo(
Some(
Options("schema", "output", None, None, None, None, None, None, None, None, None, None, None, None)
Options("schema", "output", None, None, None, None, None, None, None, None, None, None, None, None, None)
)
)
)
Expand Down Expand Up @@ -105,6 +107,7 @@ object OptionsSpec extends DefaultRunnableSpec {
None,
None,
None,
None,
None
)
)
Expand All @@ -131,6 +134,7 @@ object OptionsSpec extends DefaultRunnableSpec {
None,
None,
None,
None,
None
)
)
Expand All @@ -157,6 +161,7 @@ object OptionsSpec extends DefaultRunnableSpec {
None,
None,
None,
None,
None
)
)
Expand All @@ -183,6 +188,7 @@ object OptionsSpec extends DefaultRunnableSpec {
None,
None,
None,
None,
None
)
)
Expand All @@ -209,7 +215,8 @@ object OptionsSpec extends DefaultRunnableSpec {
None,
None,
None,
Some(true)
Some(true),
None
)
)
)
Expand All @@ -235,6 +242,7 @@ object OptionsSpec extends DefaultRunnableSpec {
None,
None,
None,
None,
None
)
)
Expand All @@ -261,6 +269,7 @@ object OptionsSpec extends DefaultRunnableSpec {
None,
None,
None,
None,
None
)
)
Expand All @@ -287,12 +296,40 @@ object OptionsSpec extends DefaultRunnableSpec {
Some(true),
None,
None,
None,
None
)
)
)
)
},
test("provide preserveInputNames") {
val input = List("schema", "output", "--preserveInputNames", "true")
val result = Options.fromArgs(input)
assert(result)(
equalTo(
Some(
Options(
"schema",
"output",
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
Some(true)
)
)
)
)
},
test("header with a colon in the value") {
val input = List("schema", "output", "--scalafmtPath", "fmtPath", "--headers", "aaa:bbb:ccc")
val result = Options.fromArgs(input)
Expand All @@ -313,6 +350,7 @@ object OptionsSpec extends DefaultRunnableSpec {
None,
None,
None,
None,
None
)
)
Expand Down
30 changes: 28 additions & 2 deletions tools/src/test/scala/caliban/tools/SchemaWriterSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ object SchemaWriterSpec extends DefaultRunnableSpec {
effect: String = "zio.UIO",
imports: List[String] = List.empty,
scalarMappings: Map[String, String] = Map.empty,
isEffectTypeAbstract: Boolean = false
isEffectTypeAbstract: Boolean = false,
preserveInputNames: Boolean = false
): RIO[Blocking, String] = Parser
.parseQuery(schema.stripMargin)
.flatMap(doc =>
Expand All @@ -27,7 +28,8 @@ object SchemaWriterSpec extends DefaultRunnableSpec {
effect,
Some(imports),
Some(scalarMappings),
isEffectTypeAbstract
isEffectTypeAbstract,
preserveInputNames
),
None
)
Expand Down Expand Up @@ -353,6 +355,30 @@ object SchemaWriterSpec extends DefaultRunnableSpec {
|
|}"""
),
(
"input type with preserved input",
gen(
"""
type Character {
name: String!
}
input CharacterInput {
name: String!
}
""",
preserveInputNames = true
),
"""import caliban.schema.Annotations._
|
|object Types {
|
| final case class Character(name: String)
| @GQLInputName("CharacterInput")
| final case class CharacterInput(name: String)
|
|}"""
),
(
"scala reserved word used",
gen("""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ object ConfigSpec extends DefaultRunnableSpec {
enableFmt = Some(false),
extensibleEnums = Some(true),
effect = None,
abstractEffectType = None
abstractEffectType = None,
preserveInputNames = None
)
)
)
Expand Down
2 changes: 2 additions & 0 deletions vuepress/docs/docs/schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,8 @@ By default, each Query and Mutation will be wrapped into a `zio.UIO` effect. Thi

You can also indicate that the effect type is abstract via `--abstractEffectType true`, in which case `Query` will be replaced by `Query[F[_]]` and so on (note `F` will be used unless `--effect <effect>` is explicitly given in which case `<effect>` would be used in place of `F`).

By default the suffix `Input` is appended to the type name of input types in the derived schema. Use the `--preserveInputNames` flag to disable this.

If you want to force a mapping between a GraphQL type and a Scala class (such as scalars), you can use the
`--scalarMappings` option. Also you can add additional imports by providing `--imports` option.

Expand Down

0 comments on commit c28285d

Please sign in to comment.