Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Schema Gen: Add Option for Preserving Input Names #1186

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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