Skip to content
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
17 changes: 11 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,19 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
java: [ '13' ]
scala: [ '2.13.6' ]
java: [ '17' ]
scala: [ '2.13.16' ]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Set up JDK
uses: actions/setup-java@v2
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java }}
distribution: 'zulu'
distribution: temurin
java-version: ${{matrix.java}}
cache: sbt
- name: print Java version
run: java -version
- name: Setup sbt launcher
uses: sbt/setup-sbt@v1
- name: Run tests
run: sbt ++${{ matrix.scala }} clean test
10 changes: 6 additions & 4 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@

name := "apibuilder-graphql"

organization := "io.apibuilder"

ThisBuild / scalaVersion := "2.13.6"
ThisBuild / scalaVersion := "2.13.16"

lazy val allScalacOptions = Seq(
"-deprecation",
Expand All @@ -19,6 +20,7 @@ lazy val resolversSettings = Seq(
resolvers += "Typesafe repository" at "https://repo.typesafe.com/typesafe/releases/",
resolvers += "scalaz-bintray" at "https://dl.bintray.com/scalaz/releases",
resolvers += "Artifactory" at "https://flow.jfrog.io/flow/libs-release/",
resolvers += "jitpack" at "https://jitpack.io",
credentials += Credentials(
"Artifactory Realm",
"flow.jfrog.io",
Expand All @@ -32,9 +34,9 @@ lazy val root = project
.settings(resolversSettings)
.settings(
libraryDependencies ++= Seq(
"io.apibuilder" %% "apibuilder-validation" % "0.4.28",
"org.typelevel" %% "cats-core" % "2.1.1",
"org.scalatest" %% "scalatest" % "3.2.9" % Test,
"com.github.apicollective" %% "apibuilder-validation" % "0.5.8",
"org.typelevel" %% "cats-core" % "2.10.0",
"org.scalatest" %% "scalatest" % "3.2.19" % Test,
),
testOptions += Tests.Argument("-oF"),
scalacOptions ++= allScalacOptions,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ object GraphQLOperation {
}

def all(ms: MultiService, intent: GraphQLIntent): Seq[GraphQLOperation] = {
ms.services().flatMap { service =>
ms.services.flatMap { service =>
service.service.resources.flatMap { resource =>
resource.operations.flatMap { operation =>
GraphQLAttribute.fromOperation(operation).toSeq.flatMap { attribute =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ object ApiBuilderTypeMetadataGenerator {
}
}

private[this] def generate(enum: GraphQLType.Enum): String = {
private[this] def generate(`enum`: GraphQLType.Enum): String = {
Seq(
s"new EnumData(${Text.wrapInQuotes(enum.name)}, [",
s"new EnumData(${Text.wrapInQuotes(`enum`.name)}, [",
Text.indent(
enum.apiBuilderEnum.`enum`.values.map { v =>
`enum`.apiBuilderEnum.`enum`.values.map { v =>
val serverName = v.value.getOrElse(v.name)
val graphQLName = Text.allCaps(serverName)
s"new EnumValue(${Text.wrapInQuotes(graphQLName)}, ${Text.wrapInQuotes(serverName)})"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ case class GraphQLQueryMutationTypeGenerator(multiService: MultiService) extends
}
case _: ApiBuilderType.Model => unsupportedError
case _: ApiBuilderType.Union => unsupportedError
case _: ApiBuilderType.Interface => unsupportedError
case _: ApiBuilderType.Enum => Text.allCaps(d)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import io.apibuilder.validation.ApiBuilderType

case class EnumResolverGenerator() extends ResolverHelpers {

def generate(enum: ApiBuilderType.Enum): String = {
def generate(`enum`: ApiBuilderType.Enum): String = {
// TODO: Should we encapsulate formatting along with enum generator class?
generateResolver(enum)(
generateResolver(`enum`)(
enum.`enum`.values.map { v =>
val wireValue = v.value.getOrElse(v.name)
val graphQLValue = Text.allCaps(wireValue)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ case class ApiBuilderTypeToGraphQLConverter(
case v: ApiBuilderType.Union => trace("union", v.name); withNamespace(v) { converter =>
unionGenerator.generate(converter, v)
}
case v: ApiBuilderType.Interface => trace("interface", v.name); withNamespace(v) { converter =>
modelGenerator.generate(converter, v)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,36 @@ package io.apibuilder.graphql.generators.schema
import io.apibuilder.graphql.schema.{GraphQLIntent, GraphQLType, GraphQLTypeField}
import io.apibuilder.validation.{ApiBuilderField, ApiBuilderType, ScalarType}

object ModelGenerator {
case class Container(typ: String, qualified: String)

object Container {
def apply(m: ApiBuilderType.Model): Container = Container("Model", m.qualified)
def apply(i: ApiBuilderType.Interface): Container = Container("Interface", i.qualified)
}
}

case class ModelGenerator() {
import ModelGenerator.Container

def generate(converter: ApiBuilderTypeToGraphQLConverter, model: ApiBuilderType.Model): GraphQLType = {
val fields = model.fields.map { f => generateField(converter, f) }
val fields = model.fields.map { f => generateField(converter, f)(Container(model)) }
converter.intent match {
case GraphQLIntent.Query => GraphQLType.Type(model, fields)
case GraphQLIntent.Mutation => GraphQLType.Input(model, fields)
}
}

private[this] def generateField(converter: ApiBuilderTypeToGraphQLConverter, field: ApiBuilderField): GraphQLTypeField = {
// Treat same as model based on ApiBuilderType.Interface.typeDiscriminator returning TypeDiscriminator.Models
def generate(converter: ApiBuilderTypeToGraphQLConverter, interface: ApiBuilderType.Interface): GraphQLType = {
val fields = interface.fields.map { f => generateField(converter, f)(Container(interface)) }
converter.intent match {
case GraphQLIntent.Query => GraphQLType.Type(interface, fields)
case GraphQLIntent.Mutation => GraphQLType.Input(interface, fields)
}
}

private def generateField(converter: ApiBuilderTypeToGraphQLConverter, field: ApiBuilderField)(implicit container: Container): GraphQLTypeField = {
GraphQLTypeField(
originalName = field.field.name,
declaration = fieldTypeDeclaration(converter, field),
Expand All @@ -22,15 +41,15 @@ case class ModelGenerator() {
)
}

private[this] def fieldTypeDeclaration(types: ApiBuilderTypeToGraphQLConverter, field: ApiBuilderField): String = {
private def fieldTypeDeclaration(types: ApiBuilderTypeToGraphQLConverter, field: ApiBuilderField)(implicit container: Container): String = {
val f = field.field
(f.name, f.`type`, f.required) match {
case ("id", ScalarType.StringType.name, true) => "ID"
case _ => types.mustFindFieldTypeDeclaration(description(field), f.`type`)
}
}

private[this] def description(field: ApiBuilderField): String = {
s"Model '${field.model.qualified}' field '${field.field.name}'"
private def description(field: ApiBuilderField)(implicit container: Container): String = {
s"${container.typ} '${container.qualified}' field '${field.field.name}'"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ object AppendInputSuffixRewriter extends MultiServiceRewriter {
case t: ApiBuilderType.Enum => t
case t: ApiBuilderType.Model => addSuffix(t)
case t: ApiBuilderType.Union => addSuffix(t)
case t: ApiBuilderType.Interface => addSuffix(t)
}.rewrite(multiService)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package io.apibuilder.graphql.util

import apibuilder.ApiBuilderHelper
import io.apibuilder.rewriter._
import io.apibuilder.graphql.schema.GraphQLIntent
import io.apibuilder.graphql.GraphQLAttribute
import io.apibuilder.graphql.schema.GraphQLIntent
import io.apibuilder.rewriter._
import io.apibuilder.spec.v0.models.{Operation, Response}
import io.apibuilder.validation.MultiService

Expand Down Expand Up @@ -41,6 +41,7 @@ case class MultiServiceView(multiService: MultiService) {
all.headOption.toSeq
},
UnionTypesMustBeModelsRewriter,
InterfaceTypesRewriter,
RenameTypesByAttributeRewriter(intent),
ReduceTypesRewriter(intent),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ case class RenameTypesByAttributeRewriter(intent: GraphQLIntent) extends MultiSe
case e: ApiBuilderType.Enum => name(e.`enum`.attributes)
case e: ApiBuilderType.Model => name(e.model.attributes)
case e: ApiBuilderType.Union => name(e.union.attributes)
case e: ApiBuilderType.Interface => name(e.interface.attributes)
}
}

Expand Down
27 changes: 15 additions & 12 deletions src/test/resources/examples/flow/resolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ export default {
b2bInvoices: (_: any, { organization, id, key, orderNumber, limit, offset, sort }: { organization: string, id: any, key: string, orderNumber: string, limit: number, offset: number, sort: string }, { dataSources }: { dataSources: any }) =>
dataSources.api.get(`/${organization}/b2b/invoices`, { id, key, order_number: orderNumber, limit, offset, sort }),

checkout: (_: any, { id }: { id: string }, { dataSources }: { dataSources: any }) =>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests overwrite these

dataSources.api.get(`/v2/checkouts/${id}`),

consumerInvoices: (_: any, { organization, id, key, orderNumber, limit, offset, sort }: { organization: string, id: any, key: string, orderNumber: string, limit: number, offset: number, sort: string }, { dataSources }: { dataSources: any }) =>
dataSources.api.get(`/${organization}/consumer/invoices`, { id, key, order_number: orderNumber, limit, offset, sort }),

Expand All @@ -20,8 +17,8 @@ export default {
orderSummary: (_: any, { organization, number }: { organization: string, number: string }, { dataSources }: { dataSources: any }) =>
dataSources.api.get(`/${organization}/order/summaries/${number}`),

organizations: (_: any, { id, name, environment, parent, limit, offset, sort }: { id: any, name: string, environment: any, parent: string, limit: number, offset: number, sort: string }, { dataSources }: { dataSources: any }) =>
dataSources.api.get("/organizations", { id, name, environment: inputMapper("Environment", environment), parent, limit, offset, sort }),
organizations: (_: any, { id, channelId, name, environment, parent, inChannel, limit, offset, sort }: { id: any, channelId: string, name: string, environment: any, parent: string, inChannel: boolean, limit: number, offset: number, sort: string }, { dataSources }: { dataSources: any }) =>
dataSources.api.get("/organizations", { id, channel_id: channelId, name, environment: inputMapper("Environment", environment), parent, in_channel: inChannel, limit, offset, sort }),

organization: (_: any, { organizationId }: { organizationId: string }, { dataSources }: { dataSources: any }) =>
dataSources.api.get(`/organizations/${organizationId}`),
Expand All @@ -31,7 +28,6 @@ export default {
},

Mutation: {
checkout: () => ({}), // CheckoutMutations
organization: () => ({}) // OrganizationMutations
},

Expand All @@ -40,11 +36,6 @@ export default {
INVOICE: "invoice"
},

CheckoutMutations: {
createBySessionId: (_: any, { sessionId }: { sessionId: string }, { dataSources }: { dataSources: any }) =>
dataSources.api.post(`/v2/checkouts/session/${sessionId}`, {})
},

ConsumerInvoiceCustomerType: {
BUSINESS_EU_VERIFIED: "business_eu_verified",
BUSINESS_NON_VERIFIED: "business_non_verified",
Expand Down Expand Up @@ -93,6 +84,12 @@ export default {
DESTINATION: "destination"
},

EntityIdentifierType: {
IOSS: "ioss",
VOEC: "voec",
ZAZ: "zaz"
},

Environment: {
SANDBOX: "sandbox",
PRODUCTION: "production"
Expand All @@ -112,7 +109,13 @@ export default {
OrganizationStatus: {
ACTIVE: "active",
INACTIVE: "inactive",
DEACTIVATED: "deactivated"
DEACTIVATED: "deactivated",
PROVISIONED: "provisioned"
},

OrganizationType: {
STANDALONE: "standalone",
CHANNEL: "channel"
},

TaxVerificationResult: {
Expand Down
Loading