├── .circleci
├── config.yml
└── install-native-deps.sh
├── .git-blame-ignore-revs
├── .github
├── FUNDING.yml
└── workflows
│ └── compatibility.yaml
├── .gitignore
├── .pre-commit-config.yaml
├── .sbtopts
├── .scalafix.conf
├── .scalafmt-for-test.conf
├── .scalafmt.conf
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── adapters
├── akka-http
│ └── src
│ │ ├── main
│ │ └── scala
│ │ │ └── caliban
│ │ │ └── AkkaHttpAdapter.scala
│ │ └── test
│ │ └── scala
│ │ └── caliban
│ │ └── AkkaHttpAdapterSpec.scala
├── http4s
│ └── src
│ │ ├── main
│ │ └── scala
│ │ │ └── caliban
│ │ │ └── Http4sAdapter.scala
│ │ └── test
│ │ └── scala
│ │ └── caliban
│ │ └── Http4sAdapterSpec.scala
├── pekko-http
│ └── src
│ │ ├── main
│ │ └── scala
│ │ │ └── caliban
│ │ │ └── PekkoHttpAdapter.scala
│ │ └── test
│ │ └── scala
│ │ └── caliban
│ │ └── PekkoHttpAdapterSpec.scala
├── play
│ └── src
│ │ ├── main
│ │ └── scala
│ │ │ └── caliban
│ │ │ └── PlayAdapter.scala
│ │ └── test
│ │ ├── resources
│ │ └── application.conf
│ │ └── scala
│ │ └── caliban
│ │ └── PlayAdapterSpec.scala
├── quick
│ └── src
│ │ ├── main
│ │ └── scala
│ │ │ └── caliban
│ │ │ ├── GraphiQLHandler.scala
│ │ │ ├── QuickAdapter.scala
│ │ │ ├── QuickHandlers.scala
│ │ │ ├── QuickRequestHandler.scala
│ │ │ └── quick
│ │ │ ├── WebSocketConfig.scala
│ │ │ └── package.scala
│ │ └── test
│ │ └── scala
│ │ └── caliban
│ │ └── QuickAdapterSpec.scala
└── zio-http
│ └── src
│ └── main
│ └── scala
│ └── caliban
│ └── ZHttpAdapter.scala
├── apollo-compatibility
├── Dockerfile
├── README.md
├── docker-compose.yaml
├── products.graphql
└── src
│ └── main
│ └── scala
│ ├── Main.scala
│ ├── ProductSchema.scala
│ ├── models
│ ├── CaseStudy.scala
│ ├── CaseStudyArgs.scala
│ ├── Custom.scala
│ ├── DeprecatedProduct.scala
│ ├── DeprecatedProductArgs.scala
│ ├── ID.scala
│ ├── Inventory.scala
│ ├── InventoryArgs.scala
│ ├── MyFederation.scala
│ ├── Product.scala
│ ├── ProductArgs.scala
│ ├── ProductDimension.scala
│ ├── ProductResearch.scala
│ ├── ProductResearchArgs.scala
│ ├── ProductVariation.scala
│ ├── QueryProductArgs.scala
│ ├── User.scala
│ ├── UserArgs.scala
│ └── package.scala
│ └── services
│ ├── InventoryService.scala
│ ├── ProductService.scala
│ └── UserService.scala
├── benchmarks
└── src
│ ├── main
│ └── scala
│ │ └── caliban
│ │ ├── ComplexQueryBenchmark.scala
│ │ ├── Data.scala
│ │ ├── FragmentsQueryBenchmark.scala
│ │ ├── ParserBenchmark.scala
│ │ ├── Schemas.scala
│ │ ├── SimpleQueryBenchmark.scala
│ │ ├── execution
│ │ ├── NestedZQueryBenchmark.scala
│ │ └── NestedZQueryBenchmarkSchema.scala
│ │ ├── json
│ │ └── JsonEncodingBenchmark.scala
│ │ └── validation
│ │ └── ValidationBenchmark.scala
│ └── test
│ └── scala
│ └── caliban
│ ├── CalibanSpec.scala
│ ├── GqlSpec.scala
│ ├── GrackleSpec.scala
│ └── SangriaSpec.scala
├── build.sbt
├── client-laminext
├── index.html
├── package.json
├── src
│ ├── main
│ │ └── scala
│ │ │ ├── caliban
│ │ │ └── client
│ │ │ │ └── laminext
│ │ │ │ ├── Subscription.scala
│ │ │ │ └── package.scala
│ │ │ └── io
│ │ │ └── laminext
│ │ │ ├── fetch
│ │ │ ├── NonOkayResponse.scala
│ │ │ └── jsoniter
│ │ │ │ ├── FetchEventStreamBuilderJsoniterOps.scala
│ │ │ │ ├── FetchJsoniterSyntax.scala
│ │ │ │ ├── JsonToRequestBody.scala
│ │ │ │ └── package.scala
│ │ │ └── websocket
│ │ │ └── jsoniter
│ │ │ ├── WebSocketReceiveBuilderJsoniterOps.scala
│ │ │ └── package.scala
│ └── test
│ │ └── scala
│ │ └── caliban
│ │ └── client
│ │ └── laminext
│ │ ├── Client.scala
│ │ ├── Main.scala
│ │ └── Page.scala
└── vite.config.js
├── client
└── src
│ ├── main
│ └── scala
│ │ └── caliban
│ │ └── client
│ │ ├── ArgEncoder.scala
│ │ ├── Argument.scala
│ │ ├── CalibanClientError.scala
│ │ ├── FieldBuilder.scala
│ │ ├── GraphQLRequest.scala
│ │ ├── GraphQLResponse.scala
│ │ ├── GraphQLResponseError.scala
│ │ ├── IntrospectionClient.scala
│ │ ├── Operations.scala
│ │ ├── ScalarDecoder.scala
│ │ ├── Selection.scala
│ │ ├── SelectionBuilder.scala
│ │ ├── Zippable.scala
│ │ ├── __Value.scala
│ │ └── ws
│ │ ├── GraphQLWSRequest.scala
│ │ └── GraphQLWSResponse.scala
│ └── test
│ └── scala
│ └── caliban
│ └── client
│ ├── ArgEncoderSpec.scala
│ ├── CalibanClientErrorSpec.scala
│ ├── GraphQLResponseSpec.scala
│ ├── SelectionBuilderSpec.scala
│ └── TestData.scala
├── codegen-sbt
└── src
│ ├── main
│ └── scala
│ │ └── caliban
│ │ └── codegen
│ │ ├── CalibanCli.scala
│ │ ├── CalibanKeys.scala
│ │ ├── CalibanPlugin.scala
│ │ ├── CalibanSettings.scala
│ │ ├── CalibanSourceGenerator.scala
│ │ ├── CompileTimeCalibanPlugin.scala
│ │ └── OptionsParser.scala
│ ├── sbt-test
│ ├── codegen
│ │ ├── gen-client-task
│ │ │ ├── .scalafmt.conf
│ │ │ ├── build.sbt
│ │ │ ├── project
│ │ │ │ ├── Version.scala
│ │ │ │ ├── gitlab-schema.graphql
│ │ │ │ ├── plugins.sbt
│ │ │ │ └── schema-to-check-name-uniqueness.graphql
│ │ │ ├── test
│ │ │ └── verify.sh
│ │ ├── test-compile-newtype
│ │ │ ├── build.sbt
│ │ │ ├── modules
│ │ │ │ └── base
│ │ │ │ │ └── src
│ │ │ │ │ └── main
│ │ │ │ │ └── scala
│ │ │ │ │ └── graphql
│ │ │ │ │ └── package.scala
│ │ │ ├── project
│ │ │ │ ├── Version.scala
│ │ │ │ └── plugins.sbt
│ │ │ ├── src
│ │ │ │ └── main
│ │ │ │ │ └── graphql
│ │ │ │ │ └── schema.graphql
│ │ │ ├── test
│ │ │ └── verify.sh
│ │ ├── test-compile
│ │ │ ├── build.sbt
│ │ │ ├── project
│ │ │ │ ├── Version.scala
│ │ │ │ └── plugins.sbt
│ │ │ ├── src
│ │ │ │ └── main
│ │ │ │ │ └── graphql
│ │ │ │ │ ├── genview
│ │ │ │ │ └── schema.graphql
│ │ │ │ │ └── schema.graphql
│ │ │ ├── test
│ │ │ └── verify.sh
│ │ └── test-split-files-compile
│ │ │ ├── build.sbt
│ │ │ ├── project
│ │ │ ├── Version.scala
│ │ │ └── plugins.sbt
│ │ │ ├── src
│ │ │ └── main
│ │ │ │ └── graphql
│ │ │ │ └── schema.graphql
│ │ │ ├── test
│ │ │ └── verify.sh
│ └── compiletime-codegen
│ │ └── test-compile
│ │ ├── README.md
│ │ ├── build.sbt
│ │ ├── modules
│ │ ├── clients
│ │ │ └── src
│ │ │ │ └── main
│ │ │ │ └── scala
│ │ │ │ └── poc
│ │ │ │ └── caliban
│ │ │ │ └── client
│ │ │ │ ├── PostClient.scala
│ │ │ │ └── PotatoesClient.scala
│ │ ├── posts-clients
│ │ │ └── .gitkeep
│ │ ├── posts
│ │ │ └── src
│ │ │ │ ├── main
│ │ │ │ └── scala
│ │ │ │ │ └── poc
│ │ │ │ │ └── caliban
│ │ │ │ │ └── posts
│ │ │ │ │ ├── GraphQLApi.scala
│ │ │ │ │ └── PostService.scala
│ │ │ │ └── test
│ │ │ │ ├── resources
│ │ │ │ └── postservice.graphql
│ │ │ │ └── scala
│ │ │ │ └── ValidateGraphQlSpec.scala
│ │ ├── potatoes-clients
│ │ │ └── .gitkeep
│ │ └── potatoes
│ │ │ └── src
│ │ │ └── main
│ │ │ └── scala
│ │ │ └── poc
│ │ │ └── caliban
│ │ │ └── potatoes
│ │ │ ├── PotatoesApi.scala
│ │ │ └── PotatoesService.scala
│ │ ├── project
│ │ ├── Version.scala
│ │ ├── build.properties
│ │ └── plugins.sbt
│ │ └── test
│ └── test
│ └── scala
│ └── caliban
│ └── codegen
│ └── OptionsParserSpec.scala
├── core
└── src
│ ├── main
│ ├── scala-2
│ │ └── caliban
│ │ │ ├── Macros.scala
│ │ │ ├── Scala3Annotations.scala
│ │ │ ├── introspection
│ │ │ └── IntrospectionDerivation.scala
│ │ │ ├── schema
│ │ │ ├── AnnotationsVersionSpecific.scala
│ │ │ ├── ArgBuilderDerivation.scala
│ │ │ ├── DerivationUtils.scala
│ │ │ ├── SchemaDerivation.scala
│ │ │ ├── SchemaVersionSpecific.scala
│ │ │ └── SubscriptionSchemaDerivation.scala
│ │ │ └── syntax.scala
│ ├── scala-3
│ │ └── caliban
│ │ │ ├── Macros.scala
│ │ │ ├── Scala3Annotations.scala
│ │ │ ├── introspection
│ │ │ └── IntrospectionDerivation.scala
│ │ │ ├── schema
│ │ │ ├── AnnotationsVersionSpecific.scala
│ │ │ ├── ArgBuilderDerivation.scala
│ │ │ ├── DerivationUtils.scala
│ │ │ ├── EnumValueSchema.scala
│ │ │ ├── ObjectSchema.scala
│ │ │ ├── ProductFieldInfo.scala
│ │ │ ├── SchemaDerivation.scala
│ │ │ ├── SchemaVersionSpecific.scala
│ │ │ ├── SubscriptionSchemaDerivation.scala
│ │ │ ├── SumSchema.scala
│ │ │ ├── TypeUnionDerivation.scala
│ │ │ ├── ValueTypeSchema.scala
│ │ │ └── macros
│ │ │ │ └── Macros.scala
│ │ │ └── syntax.scala
│ └── scala
│ │ └── caliban
│ │ ├── CalibanError.scala
│ │ ├── Configurator.scala
│ │ ├── GraphQL.scala
│ │ ├── GraphQLAspect.scala
│ │ ├── GraphQLInterpreter.scala
│ │ ├── GraphQLRequest.scala
│ │ ├── GraphQLResponse.scala
│ │ ├── GraphQLWSClose.scala
│ │ ├── GraphQLWSInput.scala
│ │ ├── GraphQLWSOutput.scala
│ │ ├── HttpUtils.scala
│ │ ├── Incremental.scala
│ │ ├── RootResolver.scala
│ │ ├── Value.scala
│ │ ├── execution
│ │ ├── Deferred.scala
│ │ ├── ExecutionRequest.scala
│ │ ├── Executor.scala
│ │ ├── Feature.scala
│ │ ├── Field.scala
│ │ ├── FieldInfo.scala
│ │ ├── Fragment.scala
│ │ └── QueryExecution.scala
│ │ ├── implicits.scala
│ │ ├── interop
│ │ ├── circe
│ │ │ └── circe.scala
│ │ ├── jsoniter
│ │ │ └── jsoniter.scala
│ │ ├── play
│ │ │ └── play.scala
│ │ ├── tapir
│ │ │ └── tapir.scala
│ │ └── zio
│ │ │ └── zio.scala
│ │ ├── introspection
│ │ ├── Introspector.scala
│ │ └── adt
│ │ │ ├── __DeprecatedArgs.scala
│ │ │ ├── __Directive.scala
│ │ │ ├── __DirectiveLocation.scala
│ │ │ ├── __EnumValue.scala
│ │ │ ├── __Field.scala
│ │ │ ├── __InputValue.scala
│ │ │ ├── __Introspection.scala
│ │ │ ├── __Schema.scala
│ │ │ ├── __Type.scala
│ │ │ ├── __TypeArgs.scala
│ │ │ └── __TypeKind.scala
│ │ ├── package.scala
│ │ ├── parsing
│ │ ├── Parser.scala
│ │ ├── SourceMapper.scala
│ │ ├── VariablesCoercer.scala
│ │ ├── adt
│ │ │ ├── Definition.scala
│ │ │ ├── Directive.scala
│ │ │ ├── Document.scala
│ │ │ ├── LocationInfo.scala
│ │ │ ├── OperationType.scala
│ │ │ ├── Selection.scala
│ │ │ ├── Type.scala
│ │ │ └── VariableDefinition.scala
│ │ └── parsers
│ │ │ ├── NumberParsers.scala
│ │ │ ├── Parsers.scala
│ │ │ ├── SelectionParsers.scala
│ │ │ ├── StringParsers.scala
│ │ │ └── ValueParsers.scala
│ │ ├── relay
│ │ ├── Base64Cursor.scala
│ │ ├── Connection.scala
│ │ ├── Cursor.scala
│ │ └── PaginationArgs.scala
│ │ ├── rendering
│ │ ├── DocumentRenderer.scala
│ │ ├── Renderer.scala
│ │ └── ValueRenderer.scala
│ │ ├── schema
│ │ ├── Annotations.scala
│ │ ├── ArgBuilder.scala
│ │ ├── ObjectFieldResolver.scala
│ │ ├── Operation.scala
│ │ ├── RootSchema.scala
│ │ ├── RootSchemaBuilder.scala
│ │ ├── RootType.scala
│ │ ├── Schema.scala
│ │ ├── SchemaUtils.scala
│ │ ├── Step.scala
│ │ ├── SubscriptionSchema.scala
│ │ └── Types.scala
│ │ ├── transformers
│ │ └── Transformer.scala
│ │ ├── uploads
│ │ ├── Upload.scala
│ │ └── Uploads.scala
│ │ ├── validation
│ │ ├── FieldMap.scala
│ │ ├── FragmentValidator.scala
│ │ ├── SchemaValidator.scala
│ │ ├── Utils.scala
│ │ ├── ValidationOps.scala
│ │ ├── Validator.scala
│ │ ├── ValueValidator.scala
│ │ └── package.scala
│ │ ├── wrappers
│ │ ├── ApolloCaching.scala
│ │ ├── ApolloPersistedQueries.scala
│ │ ├── ApolloTracing.scala
│ │ ├── Caching.scala
│ │ ├── CostEstimation.scala
│ │ ├── DeferSupport.scala
│ │ ├── FieldMetrics.scala
│ │ ├── IncrementalDelivery.scala
│ │ ├── Wrapper.scala
│ │ └── Wrappers.scala
│ │ └── ws
│ │ ├── Protocol.scala
│ │ ├── WebSocketHooks.scala
│ │ └── package.scala
│ └── test
│ ├── resources
│ └── document-tests
│ │ ├── kitchen-sink-compact.graphql
│ │ ├── kitchen-sink-query.graphql
│ │ ├── kitchen-sink.graphql
│ │ └── query-compact.graphql
│ ├── scala-2
│ └── caliban
│ │ ├── Scala2SpecificSpec.scala
│ │ ├── schema
│ │ └── ArgBuilderScala2Spec.scala
│ │ └── validation
│ │ └── InputArgumentSpecInterop.scala
│ ├── scala-3
│ └── caliban
│ │ ├── Scala3SpecificSpec.scala
│ │ ├── schema
│ │ ├── ArgBuilderDerivesAutoSpec.scala
│ │ ├── EnumFieldAutoDerivation.scala
│ │ ├── ExcludedFieldSpec.scala
│ │ ├── Scala3DerivesSpec.scala
│ │ └── SchemaDerivesAutoSpec.scala
│ │ └── validation
│ │ └── InputArgumentSpecInterop.scala
│ └── scala
│ └── caliban
│ ├── FragmentSchema.scala
│ ├── RenderingSpec.scala
│ ├── RenderingSpecSchema.scala
│ ├── RenderingSpecSchemaDescriptions.scala
│ ├── TestUtils.scala
│ ├── TriState.scala
│ ├── execution
│ ├── DefaultValueSpec.scala
│ ├── ExecutionSpec.scala
│ ├── FieldArgsSpec.scala
│ ├── FieldSpec.scala
│ ├── FragmentSpec.scala
│ ├── IncrementalDeliverySpec.scala
│ └── TestDeferredSchema.scala
│ ├── interop
│ ├── json
│ │ └── JsonAdtSpec.scala
│ └── jsoniter
│ │ ├── GraphQLRequestJsoniterSpec.scala
│ │ ├── GraphQLResponseJsoniterSpec.scala
│ │ ├── GraphQLWSInputJsoniterSpec.scala
│ │ └── GraphQLWSOutputJsoniterSpec.scala
│ ├── introspection
│ └── IntrospectionSpec.scala
│ ├── parsing
│ ├── DocumentSpec.scala
│ ├── ParserSpec.scala
│ └── SourceMapperSpec.scala
│ ├── relay
│ └── ConnectionSpec.scala
│ ├── schema
│ ├── ArgBuilderSpec.scala
│ ├── OptionalSpec.scala
│ ├── RootTypeSpec.scala
│ ├── SchemaDerivationIssuesSpec.scala
│ ├── SchemaSpec.scala
│ └── SemanticNonNullSchemaSpec.scala
│ ├── transformers
│ └── TransformerSpec.scala
│ ├── validation
│ ├── InputArgumentSpec.scala
│ ├── InputObjectSpec.scala
│ ├── ValidationSchemaSpec.scala
│ └── ValidationSpec.scala
│ └── wrappers
│ ├── CachingSpec.scala
│ ├── CostEstimationSpec.scala
│ ├── FieldMetricsSpec.scala
│ └── WrappersSpec.scala
├── docs
├── .nojekyll
├── 404.html
├── about
│ └── index.html
├── assets
│ ├── css
│ │ └── 0.styles.b5ed6211.css
│ ├── img
│ │ └── search.83621669.svg
│ └── js
│ │ ├── 1.1cbc5082.js
│ │ ├── 10.3529bcb2.js
│ │ ├── 11.d1727d19.js
│ │ ├── 12.eaba6033.js
│ │ ├── 13.03a72e64.js
│ │ ├── 14.a69b86ef.js
│ │ ├── 15.1477083d.js
│ │ ├── 16.9dd77b55.js
│ │ ├── 17.dc3323dd.js
│ │ ├── 18.648b10c4.js
│ │ ├── 19.2a696a53.js
│ │ ├── 2.10987e1d.js
│ │ ├── 20.89f58454.js
│ │ ├── 21.31e32fb9.js
│ │ ├── 22.723716f0.js
│ │ ├── 23.59b56e10.js
│ │ ├── 24.48e23614.js
│ │ ├── 25.c981091f.js
│ │ ├── 26.b3b7c765.js
│ │ ├── 27.d46b76c4.js
│ │ ├── 28.6ac4692a.js
│ │ ├── 29.4914bea3.js
│ │ ├── 3.f74b7660.js
│ │ ├── 30.14aff9e5.js
│ │ ├── 31.346dc7bb.js
│ │ ├── 32.993f3750.js
│ │ ├── 33.3da117f6.js
│ │ ├── 34.4cc63b90.js
│ │ ├── 35.bb97df3f.js
│ │ ├── 36.73fad601.js
│ │ ├── 37.eb195eb7.js
│ │ ├── 38.5498db05.js
│ │ ├── 39.baab6426.js
│ │ ├── 4.119e5097.js
│ │ ├── 40.2b6878ca.js
│ │ ├── 41.cbdf6ad3.js
│ │ ├── 42.1d861277.js
│ │ ├── 5.635a7794.js
│ │ ├── 6.301ea018.js
│ │ ├── 7.442dabf9.js
│ │ ├── app.7185a066.js
│ │ └── vendors~docsearch.d856fa52.js
├── caliban.png
├── caliban.svg
├── docs
│ ├── adapters.html
│ ├── client-codegen.html
│ ├── client.html
│ ├── examples.html
│ ├── federation.html
│ ├── index.html
│ ├── interop.html
│ ├── laminext.html
│ ├── middleware.html
│ ├── optimization.html
│ ├── relay-connections.html
│ ├── schema-comparison.html
│ ├── schema-reporting.html
│ ├── schema.html
│ ├── server-codegen.html
│ ├── stitching.html
│ └── tools.html
├── faq
│ └── index.html
├── index.html
└── resources
│ └── index.html
├── examples
├── README.md
└── src
│ └── main
│ ├── resources
│ ├── application.conf
│ ├── gateway
│ │ ├── gateway.js
│ │ └── package.json
│ └── gateway_v2
│ │ ├── gateway.js
│ │ └── package.json
│ └── scala
│ └── example
│ ├── ExampleApi.scala
│ ├── ExampleData.scala
│ ├── ExampleService.scala
│ ├── akkahttp
│ ├── AuthExampleApp.scala
│ └── ExampleApp.scala
│ ├── calibantotapir
│ ├── MainApp.scala
│ ├── README.md
│ ├── graphql
│ │ └── Book.scala
│ └── tapir
│ │ └── SampleRestEndpoint.scala
│ ├── client
│ ├── Client.scala
│ └── ExampleApp.scala
│ ├── federation
│ ├── CharacterService.scala
│ ├── EpisodeService.scala
│ ├── FederatedApi.scala
│ ├── FederatedApp.scala
│ ├── FederationData.scala
│ └── v2
│ │ ├── CharacterService.scala
│ │ ├── EpisodeService.scala
│ │ ├── FederatedApi.scala
│ │ ├── FederatedApp.scala
│ │ └── FederationData.scala
│ ├── http4s
│ ├── AuthExampleApp.scala
│ ├── AuthExampleAppF.scala
│ ├── ExampleApp.scala
│ └── ExampleAppF.scala
│ ├── interop
│ ├── cats
│ │ ├── ContextualCatsInterop.scala
│ │ ├── ContextualCatsInteropIO.scala
│ │ └── ExampleCatsInterop.scala
│ └── monix
│ │ └── ExampleMonixInterop.scala
│ ├── optimizations
│ ├── CommonData.scala
│ ├── NaiveTest.scala
│ └── OptimizedTest.scala
│ ├── pekkohttp
│ ├── AuthExampleApp.scala
│ └── ExampleApp.scala
│ ├── play
│ ├── AuthExampleApp.scala
│ └── ExampleApp.scala
│ ├── quick
│ ├── AuthExampleApp.scala
│ └── ExampleApp.scala
│ ├── stitching
│ └── ExampleApp.scala
│ └── tapirtocaliban
│ ├── Endpoints.scala
│ ├── ExampleApp.scala
│ └── README.md
├── federation
└── src
│ ├── main
│ ├── protobuf
│ │ └── reports.proto
│ └── scala
│ │ └── caliban
│ │ └── federation
│ │ ├── EntityResolver.scala
│ │ ├── FederationDirectives.scala
│ │ ├── FederationHelpers.scala
│ │ ├── FederationSupport.scala
│ │ ├── FederationV1.scala
│ │ ├── package.scala
│ │ ├── tracing
│ │ └── ApolloFederatedTracing.scala
│ │ └── v2x
│ │ ├── FederationDirectivesV2.scala
│ │ ├── FederationDirectivesV2_10.scala
│ │ ├── FederationDirectivesV2_3.scala
│ │ ├── FederationDirectivesV2_5.scala
│ │ ├── FederationDirectivesV2_6.scala
│ │ ├── FederationDirectivesV2_8.scala
│ │ ├── FederationDirectivesV2_9.scala
│ │ ├── FederationV2.scala
│ │ ├── Link.scala
│ │ └── Versions.scala
│ └── test
│ └── scala
│ └── caliban
│ └── federation
│ ├── FederationV1Spec.scala
│ ├── tracing
│ └── FederationTracingSpec.scala
│ └── v2x
│ └── FederationV2Spec.scala
├── interop
├── cats
│ └── src
│ │ ├── main
│ │ └── scala
│ │ │ └── caliban
│ │ │ └── interop
│ │ │ ├── cats
│ │ │ ├── CatsInterop.scala
│ │ │ ├── FromEffect.scala
│ │ │ ├── InjectEnv.scala
│ │ │ ├── ToEffect.scala
│ │ │ └── implicits
│ │ │ │ └── package.scala
│ │ │ └── fs2
│ │ │ ├── Fs2Interop.scala
│ │ │ └── implicits
│ │ │ └── package.scala
│ │ └── test
│ │ └── scala
│ │ └── caliban
│ │ └── interop
│ │ ├── cats
│ │ └── CatsInteropSpec.scala
│ │ └── fs2
│ │ └── Fs2InteropSchemaSpec.scala
├── monix
│ └── src
│ │ └── main
│ │ └── scala
│ │ └── caliban
│ │ └── interop
│ │ └── monix
│ │ ├── MonixInterop.scala
│ │ └── implicits
│ │ └── package.scala
└── tapir
│ └── src
│ ├── main
│ └── scala
│ │ └── caliban
│ │ └── interop
│ │ └── tapir
│ │ ├── HttpInterpreter.scala
│ │ ├── HttpUploadInterpreter.scala
│ │ ├── JsonCodecs.scala
│ │ ├── MaxCharBufSizeJsonJsoniter.scala
│ │ ├── StreamConstructor.scala
│ │ ├── TapirAdapter.scala
│ │ ├── WebSocketHooks.scala
│ │ ├── WebSocketInterpreter.scala
│ │ └── package.scala
│ └── test
│ └── scala
│ └── caliban
│ └── interop
│ └── tapir
│ ├── FakeAuthorizationInterceptor.scala
│ ├── TapirAdapterSpec.scala
│ ├── TapirSpec.scala
│ ├── TestApi.scala
│ ├── TestData.scala
│ └── TestService.scala
├── macros
└── src
│ └── main
│ └── scala-2
│ └── caliban
│ └── schema
│ ├── Derived.scala
│ └── DerivedMagnolia.scala
├── project
├── ConsoleHelper.scala
├── Scala3TestHelper.scala
├── ScriptedDependency.scala
├── build.properties
└── plugins.sbt
├── reporting
└── src
│ ├── main
│ └── scala
│ │ └── caliban
│ │ └── reporting
│ │ ├── ReportingDaemon.scala
│ │ ├── SchemaReporter.scala
│ │ ├── SchemaReportingRef.scala
│ │ ├── Util.scala
│ │ ├── client
│ │ ├── Mutation.scala
│ │ ├── ReportSchemaError.scala
│ │ ├── ReportSchemaErrorCode.scala
│ │ ├── ReportSchemaResponse.scala
│ │ ├── ReportSchemaResult.scala
│ │ ├── SchemaReport.scala
│ │ └── package.scala
│ │ └── package.scala
│ └── test
│ └── scala
│ └── caliban
│ └── reporting
│ └── ReportingDaemonSpec.scala
├── tools
└── src
│ ├── main
│ ├── resources
│ │ └── default.scalafmt.conf
│ └── scala
│ │ └── caliban
│ │ └── tools
│ │ ├── CalibanCommonSettings.scala
│ │ ├── ClientWriter.scala
│ │ ├── Codegen.scala
│ │ ├── Formatter.scala
│ │ ├── IntrospectionClient.scala
│ │ ├── Options.scala
│ │ ├── RemoteSchema.scala
│ │ ├── SchemaComparison.scala
│ │ ├── SchemaComparisonChange.scala
│ │ ├── SchemaLoader.scala
│ │ ├── SchemaWriter.scala
│ │ ├── compiletime
│ │ ├── CompileTime.scala
│ │ ├── Config.scala
│ │ └── Utils.scala
│ │ ├── package.scala
│ │ └── stitching
│ │ ├── PartialRemoteSchema.scala
│ │ ├── RemoteQuery.scala
│ │ ├── RemoteResolver.scala
│ │ ├── RemoteSchemaResolver.scala
│ │ ├── ResolveRequest.scala
│ │ └── package.scala
│ └── test
│ ├── resources
│ └── snapshots
│ │ ├── ClientWriterSpec
│ │ ├── Option types dont conflict with scala.Option.scala
│ │ ├── add scalar mappings and additional imports.scala
│ │ ├── case-insensitive name uniqueness in 2 basic objects.scala
│ │ ├── case-sensitive name uniqueness in enums values.scala
│ │ ├── default arguments for optional and list arguments.scala
│ │ ├── deprecated field + comment newline.scala
│ │ ├── deprecated field + comment.scala
│ │ ├── deprecated field argument + comment newline.scala
│ │ ├── deprecated field argument + comment.scala
│ │ ├── enum with exclude deprecated, only deprecated values.scala
│ │ ├── enum with exclude deprecated.scala
│ │ ├── enum.scala
│ │ ├── extensible enum.scala
│ │ ├── input object oneOf.scala
│ │ ├── input object with deprecated fields.scala
│ │ ├── input object with reserved name.scala
│ │ ├── input object.scala
│ │ ├── interface with implements.scala
│ │ ├── interface with list.scala
│ │ ├── interface without implements.scala
│ │ ├── interface.scala
│ │ ├── nested object type.scala
│ │ ├── object type with arguments.scala
│ │ ├── object type with reserved name.scala
│ │ ├── safe names with underscores.scala
│ │ ├── scalar mapped enum.scala
│ │ ├── schema with splitFiles.scala
│ │ ├── schema.scala
│ │ ├── simple object type with exclude deprecated and genView, only deprecated fields.scala
│ │ ├── simple object type with exclude deprecated and genView.scala
│ │ ├── simple object type.scala
│ │ ├── support for Json scalar.scala
│ │ └── union.scala
│ │ ├── ClientWriterViewSpec
│ │ ├── generic view for capital fields.scala
│ │ ├── generic view for scala keywords.scala
│ │ ├── generic view for scala.Option[List[scala.Option[A]] types.scala
│ │ ├── nested object type.scala
│ │ ├── recursive object type.scala
│ │ ├── root schema optional interface.scala
│ │ ├── simple object type.scala
│ │ ├── type with more than 22 fields _ function args _ selection args.scala
│ │ └── union case.scala
│ │ └── SchemaWriterSpec
│ │ ├── (empty schema test).scala
│ │ ├── GQLDeprecated with multiline reason and escaped quotes.scala
│ │ ├── GQLDeprecated with reason.scala
│ │ ├── GQLDescription with escaped quotes.scala
│ │ ├── add derives also to traits for @oneOf input types.scala
│ │ ├── add derives.scala
│ │ ├── add scalar mappings and additional imports.scala
│ │ ├── args names root level.scala
│ │ ├── args unique class names.scala
│ │ ├── enum type.scala
│ │ ├── final case class reserved field name used.scala
│ │ ├── generate nested @lazy fields with abstracted effect type.scala
│ │ ├── generate typesafe ids with @newtype directive, for fields on types, input types and arguments.scala
│ │ ├── inherits field with args.scala
│ │ ├── input type oneOf.scala
│ │ ├── input type with preserved input.scala
│ │ ├── input type.scala
│ │ ├── interface type.scala
│ │ ├── interface, abstracted effect and lazy combination.scala
│ │ ├── recognize @lazy intention and generate side-effecting field with abstracted effect type.scala
│ │ ├── recognize @lazy intention and generate side-effecting field.scala
│ │ ├── scala reserved word used.scala
│ │ ├── schema test.scala
│ │ ├── schema.scala
│ │ ├── simple mutation with abstracted effect type.scala
│ │ ├── simple mutation.scala
│ │ ├── simple queries with abstracted effect type.scala
│ │ ├── simple queries.scala
│ │ ├── simple subscription.scala
│ │ ├── type appears in type union and implements interface.scala
│ │ ├── type with field parameter.scala
│ │ ├── union type.scala
│ │ └── union, abstracted effect type and lazy combination.scala
│ └── scala
│ └── caliban
│ └── tools
│ ├── ClientWriterSpec.scala
│ ├── ClientWriterViewSpec.scala
│ ├── CodegenSpec.scala
│ ├── IntrospectionClientSpec.scala
│ ├── RemoteSchemaSpec.scala
│ ├── SchemaComparisonSpec.scala
│ ├── SchemaWriterSpec.scala
│ ├── SnapshotTest.scala
│ ├── compiletime
│ ├── ConfigSpec.scala
│ └── UtilsSpec.scala
│ └── stitching
│ └── RemoteQuerySpec.scala
├── tracing
└── src
│ ├── main
│ └── scala
│ │ └── caliban
│ │ └── tracing
│ │ ├── FieldTracer.scala
│ │ ├── SchemaTracer.scala
│ │ └── TracingWrapper.scala
│ └── test
│ └── scala
│ └── caliban
│ └── tracing
│ ├── MockTracer.scala
│ └── TracingWrapperSpec.scala
└── vuepress
├── docs
├── .vuepress
│ ├── config.js
│ ├── public
│ │ ├── .nojekyll
│ │ ├── caliban.png
│ │ └── caliban.svg
│ └── styles
│ │ └── index.styl
├── README.md
├── about
│ └── README.md
├── docs
│ ├── README.md
│ ├── adapters.md
│ ├── client-codegen.md
│ ├── client.md
│ ├── examples.md
│ ├── federation.md
│ ├── interop.md
│ ├── laminext.md
│ ├── middleware.md
│ ├── optimization.md
│ ├── relay-connections.md
│ ├── schema-comparison.md
│ ├── schema-reporting.md
│ ├── schema.md
│ ├── server-codegen.md
│ ├── stitching.md
│ └── tools.md
├── faq
│ └── README.md
└── resources
│ └── README.md
└── package.json
/.circleci/install-native-deps.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | sudo apt-get update
4 |
5 | sudo apt-get install -y \
6 | clang \
7 | libstdc++-12-dev \
8 | libgc-dev \
9 | libuv1-dev \
10 | openssl
11 |
--------------------------------------------------------------------------------
/.git-blame-ignore-revs:
--------------------------------------------------------------------------------
1 | # Scala Steward: Reformat with scalafmt 3.8.2
2 | 31f697d44316b1023952d5ab817d770d05f2fa76
3 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: [ghostdogpr, kyri-petrou, paulpdaniels]
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | .idea/
3 | .bsp/
4 | # vim
5 | *.sw?
6 |
7 | # Ignore [ce]tags files
8 | tags
9 |
10 | .bloop
11 | .metals
12 | .vscode
13 | project/metals.sbt
14 | *.class
15 | *.log
16 |
17 | vuepress/node_modules/*
18 | *.lock
19 | vuepress/package-lock.json
20 |
21 | package-lock.json
22 | node_modules/
23 | .DS_Store
24 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | repos:
2 | - repo: local
3 | hooks:
4 | - id: scalafmt
5 | name: scalafmt fix formatting
6 | entry: scalafmt
7 | args: [ --exclude=target, --mode=changed, --reportError ]
8 | language: system
9 | stages: [ commit, push ]
10 | always_run: true
11 | pass_filenames: false
12 | minimum_pre_commit_version: '2.8.0'
13 |
--------------------------------------------------------------------------------
/.sbtopts:
--------------------------------------------------------------------------------
1 | -J-XX:MaxMetaspaceSize=3G
2 | -J-Xmx3G
3 | -J-XX:+UseG1GC
4 |
--------------------------------------------------------------------------------
/.scalafix.conf:
--------------------------------------------------------------------------------
1 | OrganizeImports.preset = INTELLIJ_2020_3
2 |
--------------------------------------------------------------------------------
/.scalafmt-for-test.conf:
--------------------------------------------------------------------------------
1 | version = "3.1.2"
2 |
3 | runner.dialect = scala3
4 | maxColumn = 120
5 | align.preset = most
6 | continuationIndent.defnSite = 2
7 | assumeStandardLibraryStripMargin = true
8 | docstrings.style = Asterisk
9 | docstrings.wrap = no
10 | lineEndings = preserve
11 | includeCurlyBraceInSelectChains = false
12 | danglingParentheses.preset = true
13 | spaces {
14 | inImportCurlyBraces = true
15 | }
16 | optIn.annotationNewlines = true
17 |
18 | rewrite.rules = [SortImports, RedundantBraces]
19 |
20 | fileOverride {
21 | "glob:**/scala-3/**" {
22 | runner.dialect = scala3
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/.scalafmt.conf:
--------------------------------------------------------------------------------
1 | version = "3.8.2"
2 | runner.dialect = scala213
3 | maxColumn = 120
4 | align.preset = most
5 | continuationIndent.defnSite = 2
6 | assumeStandardLibraryStripMargin = true
7 | docstrings.style = Asterisk
8 | docstrings.wrap = no
9 | lineEndings = preserve
10 | includeCurlyBraceInSelectChains = false
11 | danglingParentheses.preset = true
12 | spaces {
13 | inImportCurlyBraces = true
14 | }
15 | optIn.annotationNewlines = true
16 |
17 | rewrite.rules = [SortImports, RedundantBraces]
18 |
19 | fileOverride {
20 | "glob:**/scala-3/**" {
21 | runner.dialect = scala3
22 | }
23 | }
24 |
25 | project.excludePaths = [
26 | "glob:**/target/**"
27 | "glob:**/resources/**"
28 | ]
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Code of Conduct
2 |
3 | We are committed to providing a friendly, safe and welcoming
4 | environment for all, regardless of level of experience, gender, gender
5 | identity and expression, sexual orientation, disability, personal
6 | appearance, body size, race, ethnicity, age, religion, nationality, or
7 | other such characteristics.
8 |
9 | Everyone is expected to follow the [Scala Code of Conduct] when
10 | discussing the project on the available communication channels. If you
11 | are being harassed, please contact us immediately so that we can
12 | support you.
13 |
14 | ## Moderation
15 |
16 | For any questions, concerns, or moderation requests please contact a
17 | member of the project.
18 |
19 | - [Pierre Ricadat](mailto:ghostdogpr@gmail.com)
20 |
21 | [Scala Code of Conduct]: https://www.scala-lang.org/conduct/
22 |
--------------------------------------------------------------------------------
/adapters/play/src/test/resources/application.conf:
--------------------------------------------------------------------------------
1 | http.server.max-content-length = infinite
2 | play.http.parser.maxMemoryBuffer = 100M
3 |
--------------------------------------------------------------------------------
/adapters/quick/src/main/scala/caliban/QuickHandlers.scala:
--------------------------------------------------------------------------------
1 | package caliban
2 |
3 | import zio.Trace
4 | import zio.http.{ HandlerAspect, RequestHandler }
5 | import zio.stacktracer.TracingImplicits.disableAutoTrace
6 |
7 | final case class QuickHandlers[-R](
8 | api: RequestHandler[R, Nothing],
9 | upload: RequestHandler[R, Nothing],
10 | webSocket: RequestHandler[R, Nothing]
11 | ) {
12 |
13 | /**
14 | * Applies a ZIO HTTP `HandlerAspect` to both the api and upload handlers
15 | */
16 | def @@[R1 <: R](aspect: HandlerAspect[R1, Unit]): QuickHandlers[R1] = {
17 | implicit val trace: Trace = Trace.empty
18 | QuickHandlers(
19 | api = (api @@ aspect).merge,
20 | upload = (upload @@ aspect).merge,
21 | webSocket = (webSocket @@ aspect).merge
22 | )
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/adapters/quick/src/main/scala/caliban/quick/WebSocketConfig.scala:
--------------------------------------------------------------------------------
1 | package caliban.quick
2 |
3 | import caliban.ws.WebSocketHooks
4 | import zio._
5 | import zio.http.{ WebSocketConfig => ZWebSocketConfig }
6 | import zio.stacktracer.TracingImplicits.disableAutoTrace
7 |
8 | case class WebSocketConfig[-R](
9 | keepAliveTime: Option[Duration],
10 | hooks: WebSocketHooks[R, Any],
11 | zHttpConfig: ZWebSocketConfig
12 | ) {
13 | def withHooks[R1](newHooks: WebSocketHooks[R1, Any]): WebSocketConfig[R & R1] =
14 | copy(hooks = hooks ++ newHooks)
15 |
16 | def withKeepAliveTime(time: Duration): WebSocketConfig[R] =
17 | copy(keepAliveTime = Some(time))
18 |
19 | def withZHttpConfig(newConfig: ZWebSocketConfig): WebSocketConfig[R] =
20 | copy(zHttpConfig = newConfig)
21 | }
22 |
23 | object WebSocketConfig {
24 | def default: WebSocketConfig[Any] = WebSocketConfig(None, WebSocketHooks.empty, ZWebSocketConfig.default)
25 | }
26 |
--------------------------------------------------------------------------------
/adapters/zio-http/src/main/scala/caliban/ZHttpAdapter.scala:
--------------------------------------------------------------------------------
1 | package caliban
2 |
3 | import caliban.Configurator.ExecutionConfiguration
4 | import caliban.ws.WebSocketHooks
5 | import zio.Duration
6 | import zio.http.{ WebSocketConfig => ZWebSocketConfig, _ }
7 |
8 | @deprecated(
9 | "The `caliban-zio-http` package is deprecated and scheduled to be removed in a future release. To use Caliban with zio-http, use the `caliban-quick` module instead",
10 | "2.6.0"
11 | )
12 | object ZHttpAdapter {
13 |
14 | def makeHttpService[R, E](
15 | interpreter: GraphQLInterpreter[R, E],
16 | config: ExecutionConfiguration = ExecutionConfiguration()
17 | ): RequestHandler[R, Nothing] =
18 | QuickAdapter(interpreter).configure(config).handlers.api
19 |
20 | def makeWebSocketService[R, E](
21 | interpreter: GraphQLInterpreter[R, E],
22 | keepAliveTime: Option[Duration] = None,
23 | webSocketHooks: WebSocketHooks[R, E] = WebSocketHooks.empty,
24 | zHttpConfig: ZWebSocketConfig = ZWebSocketConfig.default
25 | ): RequestHandler[R, Nothing] = {
26 | val config = quick.WebSocketConfig(keepAliveTime, webSocketHooks, zHttpConfig)
27 | QuickAdapter(interpreter).configureWebSocket(config).handlers.webSocket
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/apollo-compatibility/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM sbtscala/scala-sbt:graalvm-ce-22.3.3-b1-java17_1.9.8_2.13.12 AS build
2 |
3 | WORKDIR /app
4 | COPY build.sbt .
5 | COPY apollo-compatibility/target/apollo-subgraph-compatibility.jar /app/artifact.jar
6 | EXPOSE 4001
7 | CMD java $* -jar artifact.jar
--------------------------------------------------------------------------------
/apollo-compatibility/README.md:
--------------------------------------------------------------------------------
1 | # Federated subgraph to test apollo federation spec compatibility
2 |
3 | Implementation of a federated subgraph aligned to the requirements outlined in [apollo-federation-subgraph-compatibility](https://github.com/apollographql/apollo-federation-subgraph-compatibility).
4 |
5 | The subgraph can be used to verify compatibility against [Apollo Federation Subgraph Specification](https://www.apollographql.com/docs/federation/subgraph-spec).
6 |
7 | ### Run compatibility tests
8 | Execute the following command from the root of the repo
9 |
10 | ```
11 | npx @apollo/federation-subgraph-compatibility docker --compose apollo-compatibility/docker-compose.yml --schema apollo-compatibility/schema.graphql
12 | ```
13 |
14 | ### Printing the GraphQL Schema (SDL)
15 |
16 | ```
17 | sbt "apollo-compatibility/run printSchema"
18 | ```
--------------------------------------------------------------------------------
/apollo-compatibility/docker-compose.yaml:
--------------------------------------------------------------------------------
1 | services:
2 | products:
3 | build:
4 | context: .
5 | dockerfile: ./apollo-compatibility/Dockerfile
6 | ports:
7 | - 4001:4001
--------------------------------------------------------------------------------
/apollo-compatibility/src/main/scala/Main.scala:
--------------------------------------------------------------------------------
1 | import caliban.CalibanError
2 | import zio._
3 | import caliban.quick._
4 | import services.{ InventoryService, ProductService, UserService }
5 | import zio.http.{ Response, Routes, Server }
6 |
7 | object Main extends ZIOAppDefault {
8 |
9 | def run = for {
10 | args <- ZIOAppArgs.getArgs
11 | _ <- (args match {
12 | case Chunk("printSchema") => printSchema
13 | case _ => runServer
14 | })
15 | } yield ()
16 |
17 | private val printSchema = Console.printLine(ProductSchema.print)
18 |
19 | private val runServer = {
20 | val routes: Task[Routes[ProductService with UserService with InventoryService, Response]] =
21 | ProductSchema.api.routes("/graphql")
22 |
23 | val server: ZIO[ProductService with UserService with InventoryService with Server, Throwable, Response] =
24 | routes.flatMap(Server.serve(_))
25 |
26 | server.orDie
27 | .provide(
28 | Server.defaultWithPort(4001),
29 | ProductService.inMemory,
30 | UserService.inMemory,
31 | InventoryService.inMemory
32 | )
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/apollo-compatibility/src/main/scala/models/CaseStudy.scala:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import caliban.schema.Schema
4 |
5 | case class CaseStudy(
6 | caseNumber: ID,
7 | description: Option[String]
8 | )
9 |
10 | object CaseStudy {
11 | implicit val schema: Schema[Any, CaseStudy] = Schema.gen
12 | }
13 |
--------------------------------------------------------------------------------
/apollo-compatibility/src/main/scala/models/CaseStudyArgs.scala:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import caliban.schema.{ ArgBuilder, Schema }
4 |
5 | case class CaseStudyArgs(caseNumber: ID)
6 |
7 | object CaseStudyArgs {
8 | implicit val schema: Schema[Any, CaseStudyArgs] = Schema.gen
9 | implicit val argBuilder: ArgBuilder[CaseStudyArgs] = ArgBuilder.gen
10 | }
11 |
--------------------------------------------------------------------------------
/apollo-compatibility/src/main/scala/models/Custom.scala:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import caliban.parsing.adt.Directive
4 | import caliban.schema.Annotations.GQLDirective
5 |
6 | case class Custom() extends GQLDirective(Directive("custom"))
7 |
--------------------------------------------------------------------------------
/apollo-compatibility/src/main/scala/models/DeprecatedProduct.scala:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import caliban.schema.{ GenericSchema, Schema }
4 | import services.UserService
5 | import zio.URIO
6 |
7 | @GQLKey("sku package")
8 | case class DeprecatedProduct(
9 | sku: String,
10 | `package`: String,
11 | reason: Option[String],
12 | createdBy: URIO[UserService, Option[User]]
13 | )
14 |
15 | object DeprecatedProduct {
16 | object apiSchema extends GenericSchema[UserService]
17 |
18 | implicit val schema: Schema[UserService, DeprecatedProduct] = apiSchema.gen[UserService, DeprecatedProduct]
19 | }
20 |
--------------------------------------------------------------------------------
/apollo-compatibility/src/main/scala/models/DeprecatedProductArgs.scala:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import caliban.schema.{ ArgBuilder, Schema }
4 |
5 | case class DeprecatedProductArgs(
6 | sku: String,
7 | `package`: String
8 | )
9 |
10 | object DeprecatedProductArgs {
11 | implicit val schema: Schema[Any, DeprecatedProductArgs] = Schema.gen
12 | implicit val argBuilder: ArgBuilder[DeprecatedProductArgs] = ArgBuilder.gen[DeprecatedProductArgs]
13 | }
14 |
--------------------------------------------------------------------------------
/apollo-compatibility/src/main/scala/models/ID.scala:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import caliban.schema.{ ArgBuilder, Schema }
4 | import caliban.Value.StringValue
5 |
6 | case class ID(id: String) extends AnyVal
7 |
8 | object ID {
9 | implicit val schema: Schema[Any, ID] = Schema.scalarSchema[ID]("ID", None, None, None, id => StringValue(id.id))
10 | implicit val argBuilder: ArgBuilder[ID] = ArgBuilder.string.map(ID(_))
11 | }
12 |
--------------------------------------------------------------------------------
/apollo-compatibility/src/main/scala/models/Inventory.scala:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import caliban.schema.{ GenericSchema, Schema }
4 | import services.{ InventoryService, UserService }
5 |
6 | @GQLInterfaceObject
7 | @GQLKey("email")
8 | case class Inventory(
9 | id: ID,
10 | deprecatedProducts: List[DeprecatedProduct]
11 | )
12 |
13 | object Inventory {
14 | object genSchema extends GenericSchema[InventoryService with UserService]
15 | implicit val schema: Schema[InventoryService with UserService, Inventory] = genSchema.gen
16 | }
17 |
--------------------------------------------------------------------------------
/apollo-compatibility/src/main/scala/models/InventoryArgs.scala:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import caliban.schema.{ ArgBuilder, Schema }
4 |
5 | case class InventoryArgs(id: ID)
6 |
7 | object InventoryArgs {
8 | implicit val schema: Schema[Any, InventoryArgs] = Schema.gen
9 | implicit val argBuilder: ArgBuilder[InventoryArgs] = ArgBuilder.gen
10 | }
11 |
--------------------------------------------------------------------------------
/apollo-compatibility/src/main/scala/models/MyFederation.scala:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import caliban.federation.v2x._
4 |
5 | abstract class MyFederation
6 | extends caliban.federation.v2x.FederationV2(
7 | Versions.v2_3 :: Link(
8 | "https://myspecs.dev/myCustomDirective/v1.0",
9 | List(
10 | Import("@custom")
11 | )
12 | ) :: ComposeDirective("@custom") :: Nil
13 | )
14 | with FederationDirectivesV2_3
15 |
--------------------------------------------------------------------------------
/apollo-compatibility/src/main/scala/models/Product.scala:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import caliban.schema.Schema
4 | import zio.UIO
5 |
6 | @GQLKey("id")
7 | @GQLKey("sku package")
8 | @GQLKey("sku variation { id }")
9 | @Custom
10 | case class Product(
11 | id: ID,
12 | sku: Option[String],
13 | `package`: Option[String],
14 | variation: Option[ProductVariation],
15 | dimensions: Option[ProductDimension],
16 | @GQLProvides("totalProductsCreated") createdBy: UIO[Option[User]],
17 | @GQLTag("internal") notes: Option[String],
18 | research: List[ProductResearch]
19 | )
20 |
21 | object Product {
22 |
23 | implicit val schema: Schema[Any, Product] = Schema.gen
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/apollo-compatibility/src/main/scala/models/ProductArgs.scala:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import caliban.InputValue
4 | import caliban.schema.{ ArgBuilder, Schema }
5 |
6 | sealed trait ProductArgs
7 |
8 | object ProductArgs {
9 | case class IdOnly(id: ID) extends ProductArgs
10 | case class SkuAndPackage(sku: String, `package`: String) extends ProductArgs
11 | case class SkuAndVariationId(sku: String, variation: ProductVariation) extends ProductArgs
12 |
13 | private implicit val variationArgs: ArgBuilder[ProductVariation] = ArgBuilder.gen[ProductVariation]
14 | val idOnlyArgBuilder: ArgBuilder[IdOnly] = ArgBuilder.gen[IdOnly]
15 | val skuAndPackageArgBuilder: ArgBuilder[SkuAndPackage] = ArgBuilder.gen[SkuAndPackage]
16 | val skuAndVariationIdArgBuilder: ArgBuilder[SkuAndVariationId] = ArgBuilder.gen[SkuAndVariationId]
17 |
18 | implicit val argBuilder: ArgBuilder[ProductArgs] = (input: InputValue) =>
19 | (for {
20 | error <- skuAndVariationIdArgBuilder.build(input).swap
21 | _ <- skuAndPackageArgBuilder.build(input).swap
22 | _ <- idOnlyArgBuilder.build(input).swap
23 | } yield error).swap
24 |
25 | implicit val idOnlySchema: Schema[Any, ProductArgs.IdOnly] = Schema.gen
26 | implicit val skuAndPackageSchema: Schema[Any, ProductArgs.SkuAndPackage] = Schema.gen
27 | implicit val skuAndVariationIdSchema: Schema[Any, ProductArgs.SkuAndVariationId] = Schema.gen
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/apollo-compatibility/src/main/scala/models/ProductDimension.scala:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import caliban.schema.Schema
4 |
5 | @GQLShareable
6 | case class ProductDimension(
7 | size: Option[String],
8 | weight: Option[Float],
9 | @GQLInaccessible unit: Option[String]
10 | )
11 |
12 | object ProductDimension {
13 | implicit val schema: Schema[Any, ProductDimension] = Schema.gen
14 | }
15 |
--------------------------------------------------------------------------------
/apollo-compatibility/src/main/scala/models/ProductResearch.scala:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import caliban.schema.Schema
4 |
5 | @GQLKey("study { caseNumber }")
6 | case class ProductResearch(
7 | study: CaseStudy,
8 | outcome: Option[String]
9 | )
10 |
11 | object ProductResearch {
12 | implicit val schema: Schema[Any, ProductResearch] = Schema.gen
13 | }
14 |
--------------------------------------------------------------------------------
/apollo-compatibility/src/main/scala/models/ProductResearchArgs.scala:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import caliban.schema.{ ArgBuilder, Schema }
4 |
5 | case class ProductResearchArgs(study: CaseStudyArgs)
6 |
7 | object ProductResearchArgs {
8 | implicit val schema: Schema[Any, ProductResearchArgs] = Schema.gen
9 | implicit val argBuilder: ArgBuilder[ProductResearchArgs] = ArgBuilder.gen
10 | }
11 |
--------------------------------------------------------------------------------
/apollo-compatibility/src/main/scala/models/ProductVariation.scala:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import caliban.schema.Schema
4 |
5 | case class ProductVariation(
6 | id: ID
7 | )
8 |
9 | object ProductVariation {
10 | implicit val schema: Schema[Any, ProductVariation] = Schema.gen
11 | }
12 |
--------------------------------------------------------------------------------
/apollo-compatibility/src/main/scala/models/QueryProductArgs.scala:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import caliban.schema.{ ArgBuilder, Schema }
4 |
5 | case class QueryProductArgs(id: ID)
6 |
7 | object QueryProductArgs {
8 | implicit val argBuilder: ArgBuilder[QueryProductArgs] = ArgBuilder.gen
9 | implicit val schema: Schema[Any, QueryProductArgs] = Schema.gen
10 | }
11 |
--------------------------------------------------------------------------------
/apollo-compatibility/src/main/scala/models/User.scala:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import caliban.schema.Schema
4 |
5 | @GQLKey("email")
6 | @GQLExtend
7 | case class User(
8 | @GQLExternal email: ID,
9 | @GQLExternal totalProductsCreated: Option[Int],
10 | @GQLOverride("users") name: Option[String],
11 | @GQLRequires("totalProductsCreated yearsOfEmployment") averageProductsCreatedPerYear: Option[Int],
12 | @GQLExternal yearsOfEmployment: Int
13 | )
14 |
15 | object User {
16 | implicit val schema: Schema[Any, User] = Schema.gen
17 | }
18 |
--------------------------------------------------------------------------------
/apollo-compatibility/src/main/scala/models/UserArgs.scala:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import caliban.schema.{ ArgBuilder, Schema }
4 |
5 | case class UserArgs(email: ID)
6 |
7 | object UserArgs {
8 | implicit val schema: Schema[Any, UserArgs] = Schema.gen
9 | implicit val argBuilder: ArgBuilder[UserArgs] = ArgBuilder.gen
10 | }
11 |
--------------------------------------------------------------------------------
/apollo-compatibility/src/main/scala/models/package.scala:
--------------------------------------------------------------------------------
1 | package object models extends MyFederation
2 |
--------------------------------------------------------------------------------
/apollo-compatibility/src/main/scala/services/InventoryService.scala:
--------------------------------------------------------------------------------
1 | package services
2 |
3 | import models.{ DeprecatedProduct, ID, Inventory }
4 | import zio.{ ULayer, ZIO, ZLayer }
5 |
6 | trait InventoryService {
7 |
8 | def getById(id: String): Option[Inventory]
9 |
10 | }
11 |
12 | object InventoryService {
13 | val inventory = List(
14 | Inventory(
15 | id = ID("apollo-oss"),
16 | deprecatedProducts = List(
17 | DeprecatedProduct(
18 | sku = "apollo-federation-v1",
19 | `package` = "@apollo/federation-v1",
20 | reason = Some("Migrate to Federation V2"),
21 | createdBy = ZIO.serviceWithZIO[UserService](_.getUser)
22 | )
23 | )
24 | )
25 | )
26 |
27 | val inMemory: ULayer[InventoryService] = ZLayer.succeed(new InventoryService {
28 | def getById(id: String): Option[Inventory] = inventory.find(_.id.id == id)
29 | })
30 | }
31 |
--------------------------------------------------------------------------------
/apollo-compatibility/src/main/scala/services/UserService.scala:
--------------------------------------------------------------------------------
1 | package services
2 |
3 | import models.{ ID, User }
4 | import zio.{ UIO, ULayer, ZIO, ZLayer }
5 |
6 | trait UserService {
7 |
8 | def getUser: UIO[Option[User]]
9 | }
10 |
11 | object UserService {
12 | private val theUser = User(
13 | averageProductsCreatedPerYear = Some(1337 / 10),
14 | email = ID("support@apollographql.com"),
15 | name = Some("Jane Smith"),
16 | totalProductsCreated = Some(1337),
17 | yearsOfEmployment = 10
18 | )
19 |
20 | val inMemory: ULayer[UserService] = ZLayer.succeed(new UserService {
21 | def getUser: zio.UIO[Option[User]] = ZIO.some(theUser)
22 | })
23 | }
24 |
--------------------------------------------------------------------------------
/benchmarks/src/main/scala/caliban/Data.scala:
--------------------------------------------------------------------------------
1 | package caliban
2 |
3 | object Data {
4 | sealed trait Origin
5 |
6 | object Origin {
7 | case object EARTH extends Origin
8 | case object MARS extends Origin
9 | case object BELT extends Origin
10 | }
11 |
12 | sealed trait Role
13 |
14 | object Role {
15 | case class Captain(shipName: String) extends Role
16 | case class Pilot(shipName: String) extends Role
17 | case class Engineer(shipName: String) extends Role
18 | case class Mechanic(shipName: String) extends Role
19 | }
20 |
21 | case class Character(name: String, nicknames: List[String], origin: Origin, role: Option[Role])
22 |
23 | val characters = List(
24 | Character("James Holden", List("Jim", "Hoss"), Origin.EARTH, Some(Role.Captain("Rocinante"))),
25 | Character("Naomi Nagata", Nil, Origin.BELT, Some(Role.Engineer("Rocinante"))),
26 | Character("Amos Burton", Nil, Origin.EARTH, Some(Role.Mechanic("Rocinante"))),
27 | Character("Alex Kamal", Nil, Origin.MARS, Some(Role.Pilot("Rocinante"))),
28 | Character("Chrisjen Avasarala", Nil, Origin.EARTH, None),
29 | Character("Josephus Miller", List("Joe"), Origin.BELT, None),
30 | Character("Roberta Draper", List("Bobbie", "Gunny"), Origin.MARS, None)
31 | )
32 | }
33 |
--------------------------------------------------------------------------------
/benchmarks/src/main/scala/caliban/ParserBenchmark.scala:
--------------------------------------------------------------------------------
1 | package caliban
2 |
3 | import caliban.parsing.Parser
4 | import caliban.parsing.adt.Document
5 | import cats.data.NonEmptyList
6 | import cats.parse.Caret
7 | import gql.parser.QueryAst
8 | import grackle.Operation
9 | import org.openjdk.jmh.annotations._
10 | import sangria.parser.QueryParser
11 |
12 | import java.util.concurrent.TimeUnit
13 | import scala.concurrent.ExecutionContextExecutor
14 |
15 | @State(Scope.Thread)
16 | @BenchmarkMode(Array(Mode.Throughput))
17 | @OutputTimeUnit(TimeUnit.SECONDS)
18 | @Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
19 | @Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
20 | @Fork(1)
21 | class ParserBenchmark {
22 | import ComplexQueryBenchmark._
23 |
24 | implicit val executionContext: ExecutionContextExecutor = scala.concurrent.ExecutionContext.global
25 |
26 | @Benchmark
27 | def runCaliban(): Document =
28 | Parser.parseQuery(fullIntrospectionQuery).fold(throw _, identity)
29 |
30 | @Benchmark
31 | def runSangria(): sangria.ast.Document =
32 | QueryParser.parse(fullIntrospectionQuery).fold(throw _, identity)
33 |
34 | @Benchmark
35 | def runGrackle(): Operation =
36 | Grackle.compiler.compile(fullIntrospectionQuery).getOrElse(throw new Throwable("Grackle failed to parse query"))
37 |
38 | @Benchmark
39 | def runGql(): NonEmptyList[QueryAst.ExecutableDefinition[Caret]] =
40 | gql.parser.parseQuery(fullIntrospectionQuery).fold(e => throw new Throwable(e.prettyError.value), identity)
41 | }
42 |
--------------------------------------------------------------------------------
/benchmarks/src/test/scala/caliban/CalibanSpec.scala:
--------------------------------------------------------------------------------
1 | package caliban
2 |
3 | import caliban.SimpleQueryBenchmark.simpleQuery
4 | import caliban.ComplexQueryBenchmark.fullIntrospectionQuery
5 | import caliban.FragmentsQueryBenchmark.fragmentsQuery
6 | import caliban.parsing.Parser
7 | import zio.test._
8 |
9 | object CalibanSpec extends ZIOSpecDefault {
10 | override def spec =
11 | suite("Caliban")(
12 | test("Simple") {
13 | val io = Caliban.interpreter.execute(simpleQuery)
14 | assertTrue(Caliban.run(io).errors.isEmpty)
15 | },
16 | test("Complex") {
17 | val io = Caliban.interpreter.execute(fullIntrospectionQuery)
18 | assertTrue(Caliban.run(io).errors.isEmpty)
19 | },
20 | test("Fragments") {
21 | val io = Caliban.interpreter.execute(fragmentsQuery)
22 | assertTrue(Caliban.run(io).errors.isEmpty)
23 | },
24 | test("Parser") {
25 | Parser.parseQuery(fullIntrospectionQuery).map { doc =>
26 | assertTrue(doc.definitions.nonEmpty)
27 | }
28 | }
29 | )
30 | }
31 |
--------------------------------------------------------------------------------
/benchmarks/src/test/scala/caliban/GrackleSpec.scala:
--------------------------------------------------------------------------------
1 | package caliban
2 |
3 | import caliban.ComplexQueryBenchmark.fullIntrospectionQuery
4 | import caliban.FragmentsQueryBenchmark.fragmentsQuery
5 | import caliban.SimpleQueryBenchmark.simpleQuery
6 | import zio.test._
7 |
8 | object GrackleSpec extends ZIOSpecDefault {
9 | override def spec =
10 | suite("Grackle")(
11 | test("Simple") {
12 | val io = Grackle.compileAndRun(simpleQuery)
13 | assertTrue(!Grackle.run(io).toString.contains("errors"))
14 | },
15 | test("Complex") {
16 | val io = Grackle.compileAndRun(fullIntrospectionQuery)
17 | assertTrue(!Grackle.run(io).toString.contains("errors"))
18 | },
19 | test("Fragments") {
20 | val io = Grackle.compileAndRun(fragmentsQuery)
21 | assertTrue(!Grackle.run(io).toString.contains("errors"))
22 | },
23 | test("Parser") {
24 | val result = Grackle.compiler.compile(fullIntrospectionQuery)
25 | assertTrue(result.toEither.isRight)
26 | }
27 | )
28 | }
29 |
--------------------------------------------------------------------------------
/client-laminext/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Caliban Client
5 |
6 |
7 |
8 |
9 | <%- injectScript %>
10 |
--------------------------------------------------------------------------------
/client-laminext/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "caliban-client-demo",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "license": "MIT",
6 | "devDependencies": {
7 | "vite": "^2.1.5",
8 | "vite-plugin-html": "^2.0.6"
9 | }
10 | }
--------------------------------------------------------------------------------
/client-laminext/src/main/scala/caliban/client/laminext/Subscription.scala:
--------------------------------------------------------------------------------
1 | package caliban.client.laminext
2 |
3 | import caliban.client.CalibanClientError
4 | import com.raquo.airstream.core.EventStream
5 |
6 | trait Subscription[A] {
7 | def received: EventStream[Either[CalibanClientError, A]]
8 | def unsubscribe(): Unit
9 | }
10 |
--------------------------------------------------------------------------------
/client-laminext/src/main/scala/io/laminext/fetch/NonOkayResponse.scala:
--------------------------------------------------------------------------------
1 | package io.laminext.fetch
2 |
3 | import org.scalajs.dom.Response
4 |
5 | class NonOkayResponse(val response: Response) extends Throwable
6 |
--------------------------------------------------------------------------------
/client-laminext/src/main/scala/io/laminext/fetch/jsoniter/FetchJsoniterSyntax.scala:
--------------------------------------------------------------------------------
1 | package io.laminext.fetch.jsoniter
2 |
3 | import com.github.plokhotnyuk.jsoniter_scala.core.{ writeToString, JsonValueCodec }
4 |
5 | import scala.language.implicitConversions
6 |
7 | trait FetchJsoniterSyntax {
8 |
9 | implicit def jsonRequestBody[A](value: A)(implicit encoder: JsonValueCodec[A]): ToRequestBody =
10 | new JsonToRequestBody(writeToString(value))
11 |
12 | implicit def fetchEventStreamBuilderSyntaxJsoniter(b: FetchEventStreamBuilder): FetchEventStreamBuilderJsoniterOps =
13 | new FetchEventStreamBuilderJsoniterOps(b)
14 | }
15 |
--------------------------------------------------------------------------------
/client-laminext/src/main/scala/io/laminext/fetch/jsoniter/JsonToRequestBody.scala:
--------------------------------------------------------------------------------
1 | package io.laminext.fetch.jsoniter
2 |
3 | import org.scalajs.dom.BodyInit
4 |
5 | import scala.scalajs.js
6 | import scala.scalajs.js.UndefOr
7 |
8 | class JsonToRequestBody(jsonStr: String) extends ToRequestBody {
9 |
10 | override def apply(): UndefOr[BodyInit] = jsonStr
11 |
12 | override def updateHeaders(headers: js.UndefOr[Map[String, String]]): js.UndefOr[Map[String, String]] =
13 | headers.getOrElse(Map.empty).updated("content-type", "application/json; charset=utf-8")
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/client-laminext/src/main/scala/io/laminext/fetch/jsoniter/package.scala:
--------------------------------------------------------------------------------
1 | package io.laminext.fetch
2 |
3 | package object jsoniter extends ReExports with FetchSyntax with FetchJsoniterSyntax
4 |
--------------------------------------------------------------------------------
/client-laminext/src/main/scala/io/laminext/websocket/jsoniter/WebSocketReceiveBuilderJsoniterOps.scala:
--------------------------------------------------------------------------------
1 | package io.laminext.websocket.jsoniter
2 |
3 | import com.github.plokhotnyuk.jsoniter_scala.core.{ readFromString, writeToString, JsonValueCodec }
4 | import io.laminext.websocket.{ initialize, receive, send, WebSocketBuilder, WebSocketReceiveBuilder }
5 |
6 | import scala.util.control.NonFatal
7 |
8 | class WebSocketReceiveBuilderJsoniterOps(b: WebSocketReceiveBuilder) {
9 |
10 | @inline def json[Receive, Send](implicit
11 | receiveCodec: JsonValueCodec[Receive],
12 | sendCodec: JsonValueCodec[Send]
13 | ): WebSocketBuilder[Receive, Send] =
14 | new WebSocketBuilder[Receive, Send](
15 | url = b.url,
16 | protocol = b.protocol,
17 | initializer = initialize.text,
18 | sender = send.text[Send](writeToString(_)),
19 | receiver = receive.text[Receive] { text =>
20 | try Right(readFromString[Receive](text))
21 | catch {
22 | case NonFatal(e) => Left(e)
23 | }
24 | }
25 | )
26 | }
27 |
--------------------------------------------------------------------------------
/client-laminext/src/main/scala/io/laminext/websocket/jsoniter/package.scala:
--------------------------------------------------------------------------------
1 | package io.laminext.websocket
2 |
3 | import scala.language.implicitConversions
4 |
5 | package object jsoniter extends ReExports {
6 |
7 | implicit def webSocketReceiveBuilderSyntax(b: WebSocketReceiveBuilder): WebSocketReceiveBuilderJsoniterOps =
8 | new WebSocketReceiveBuilderJsoniterOps(b)
9 | }
10 |
--------------------------------------------------------------------------------
/client-laminext/src/test/scala/caliban/client/laminext/Main.scala:
--------------------------------------------------------------------------------
1 | package caliban.client.laminext
2 |
3 | import com.raquo.laminar.api.L._
4 | import org.scalajs.dom
5 |
6 | object Main {
7 | def main(args: Array[String]): Unit = {
8 | val _ = documentEvents(_.onDomContentLoaded).foreach { _ =>
9 | val appContainer = dom.document.querySelector("#app")
10 | appContainer.innerHTML = ""
11 | val _ = render(appContainer, Page.view)
12 | }(unsafeWindowOwner)
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/client-laminext/vite.config.js:
--------------------------------------------------------------------------------
1 | import { resolve } from 'path'
2 | import { injectHtml } from 'vite-plugin-html'
3 |
4 | const scalaVersion = '2.13'
5 |
6 | export default ({ mode }) => {
7 | const mainJS = `/target/scala-${scalaVersion}/caliban-client-laminext-test-${mode === 'production' ? 'opt' : 'fastopt'}/main.js`
8 | return {
9 | publicDir: './static/public',
10 | plugins: [
11 | injectHtml({
12 | injectData: {
13 | injectScript: ``
14 | }
15 | })
16 | ]
17 | }
18 | }
--------------------------------------------------------------------------------
/client/src/main/scala/caliban/client/GraphQLRequest.scala:
--------------------------------------------------------------------------------
1 | package caliban.client
2 |
3 | import com.github.plokhotnyuk.jsoniter_scala.core.JsonValueCodec
4 | import com.github.plokhotnyuk.jsoniter_scala.macros.JsonCodecMaker
5 |
6 | /**
7 | * Represents a GraphQL request, containing a query and a map of variables.
8 | */
9 | case class GraphQLRequest(query: String, variables: Map[String, __Value])
10 |
11 | object GraphQLRequest {
12 |
13 | implicit val jsonEncoder: JsonValueCodec[GraphQLRequest] = JsonCodecMaker.makeCirceLike[GraphQLRequest]
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/client/src/main/scala/caliban/client/GraphQLResponse.scala:
--------------------------------------------------------------------------------
1 | package caliban.client
2 |
3 | import caliban.client.__Value.__ObjectValue
4 | import com.github.plokhotnyuk.jsoniter_scala.core.JsonValueCodec
5 | import com.github.plokhotnyuk.jsoniter_scala.macros.JsonCodecMaker
6 |
7 | /**
8 | * Represents the result of a GraphQL query, containing a data object and a list of errors.
9 | */
10 | case class GraphQLResponse(
11 | data: Option[__Value],
12 | errors: List[GraphQLResponseError] = Nil,
13 | extensions: Option[__ObjectValue] = None
14 | )
15 |
16 | object GraphQLResponse {
17 |
18 | implicit val jsonCodec: JsonValueCodec[GraphQLResponse] = JsonCodecMaker.makeCirceLike[GraphQLResponse]
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/client/src/main/scala/caliban/client/Operations.scala:
--------------------------------------------------------------------------------
1 | package caliban.client
2 |
3 | import scala.annotation.implicitNotFound
4 |
5 | object Operations {
6 | type RootQuery
7 | type RootMutation
8 | type RootSubscription
9 |
10 | /**
11 | * Typeclass used to enforce that we can only create a request for one of the root fields.
12 | */
13 | @implicitNotFound(
14 | """Your selection is not a root type.
15 |
16 | You can only transform a SelectionBuilder into a GraphQL request if it's a root query, mutation or subscription.
17 | """
18 | )
19 | trait IsOperation[A] {
20 | def operationName: String
21 | }
22 |
23 | object IsOperation {
24 | implicit val query: IsOperation[RootQuery] = new IsOperation[RootQuery] {
25 | override def operationName: String = "query"
26 | }
27 | implicit val mutation: IsOperation[RootMutation] = new IsOperation[RootMutation] {
28 | override def operationName: String = "mutation"
29 | }
30 | implicit val subscription: IsOperation[RootSubscription] = new IsOperation[RootSubscription] {
31 | override def operationName: String = "subscription"
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/client/src/main/scala/caliban/client/Selection.scala:
--------------------------------------------------------------------------------
1 | package caliban.client
2 |
3 | sealed trait Selection
4 |
5 | object Selection {
6 | case class InlineFragment(onType: String, selectionSet: List[Selection]) extends Selection
7 |
8 | case class Field(
9 | alias: Option[String],
10 | name: String,
11 | arguments: List[Argument[_]],
12 | directives: List[Directive],
13 | selectionSet: List[Selection],
14 | code: Int
15 | ) extends Selection
16 |
17 | case class Directive(name: String, arguments: List[Argument[_]] = Nil) {
18 | def toGraphQL(
19 | useVariables: Boolean,
20 | dropNullInputValues: Boolean,
21 | variables: Map[String, (__Value, String)]
22 | ): (String, Map[String, (__Value, String)]) = {
23 | val (newArgs, newVariables) = arguments.foldLeft((List.empty[String], variables)) {
24 | case ((args, variables), arg) =>
25 | val (arg2, variables2) = arg.toGraphQL(useVariables, dropNullInputValues, variables)
26 | (arg2 :: args, variables2)
27 | }
28 | (s"@$name(${newArgs.reverse.mkString(",")})", newVariables)
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/client/src/main/scala/caliban/client/ws/GraphQLWSRequest.scala:
--------------------------------------------------------------------------------
1 | package caliban.client.ws
2 |
3 | import caliban.client.GraphQLRequest
4 | import com.github.plokhotnyuk.jsoniter_scala.core.JsonValueCodec
5 | import com.github.plokhotnyuk.jsoniter_scala.macros.JsonCodecMaker
6 |
7 | case class GraphQLWSRequest(`type`: String, id: Option[String], payload: Option[GraphQLRequest])
8 |
9 | object GraphQLWSRequest {
10 | implicit val graphQLWSRequestEncoder: JsonValueCodec[GraphQLWSRequest] =
11 | JsonCodecMaker.makeCirceLike[GraphQLWSRequest]
12 | }
13 |
--------------------------------------------------------------------------------
/client/src/main/scala/caliban/client/ws/GraphQLWSResponse.scala:
--------------------------------------------------------------------------------
1 | package caliban.client.ws
2 |
3 | import caliban.client.__Value.__ObjectValue
4 | import com.github.plokhotnyuk.jsoniter_scala.core.JsonValueCodec
5 | import com.github.plokhotnyuk.jsoniter_scala.macros.JsonCodecMaker
6 |
7 | case class GraphQLWSResponse(`type`: String, id: Option[String], payload: Option[__ObjectValue])
8 |
9 | object GraphQLWSResponse {
10 | private[caliban] implicit val graphQLWSResponseEncoder: JsonValueCodec[GraphQLWSResponse] =
11 | JsonCodecMaker.makeCirceLike[GraphQLWSResponse]
12 | }
13 |
--------------------------------------------------------------------------------
/client/src/test/scala/caliban/client/ArgEncoderSpec.scala:
--------------------------------------------------------------------------------
1 | package caliban.client
2 |
3 | import zio.test._
4 | import java.util.UUID
5 |
6 | object ArgEncoderSpec extends ZIOSpecDefault {
7 | override def spec =
8 | suite("ArgEncoderSpec")(
9 | suite("__StringValue")(
10 | test("regular string") {
11 | assertTrue(ArgEncoder.string.encode("abcde who am i?").toString == """"abcde who am i?"""")
12 | },
13 | test("string with quotes") {
14 | assertTrue(ArgEncoder.string.encode("abcde \"who am i?\"").toString == """"abcde \"who am i?\""""")
15 | },
16 | test("string with new line") {
17 | assertTrue(ArgEncoder.string.encode("abcde\n who\n am\n i\n").toString == """"abcde\n who\n am\n i\n"""")
18 | },
19 | test("string with null characters") {
20 | assertTrue(ArgEncoder.string.encode("abcde who am i\u0000").toString == "\"abcde who am i\\u0000\"")
21 | }
22 | ),
23 | suite("__UUIDValue")(
24 | test("regular uuid") {
25 | assertTrue(
26 | ArgEncoder.uuid
27 | .encode(UUID.fromString("20a69d87-6d68-4779-a4da-601f4c04ebf3"))
28 | .toString == """"20a69d87-6d68-4779-a4da-601f4c04ebf3""""
29 | )
30 | }
31 | )
32 | )
33 | }
34 |
--------------------------------------------------------------------------------
/codegen-sbt/src/main/scala/caliban/codegen/CalibanKeys.scala:
--------------------------------------------------------------------------------
1 | package caliban.codegen
2 |
3 | import caliban.tools.CalibanCommonSettings
4 | import sbt._
5 |
6 | import java.net.URL
7 |
8 | trait CalibanKeys {
9 | lazy val caliban = taskKey[Seq[File]]("Generate GraphQL sources using caliban-codegen-sbt")
10 | lazy val calibanGenerator = taskKey[Seq[File]]("Generate GraphQL sources using caliban-codegen-sbt")
11 |
12 | lazy val calibanSources = settingKey[File]("Where to find .graphql schemas")
13 | lazy val calibanSettings = settingKey[Seq[CalibanSettings]]("Settings that apply to individual GraphQL files")
14 |
15 | def calibanSetting(file: File)(setting: CalibanFileSettings => CalibanFileSettings): CalibanSettings =
16 | setting.apply(CalibanFileSettings(file = file, settings = CalibanCommonSettings.empty))
17 | def calibanSetting(url: URL)(setting: CalibanUrlSettings => CalibanUrlSettings): CalibanSettings =
18 | setting.apply(CalibanUrlSettings(url = url, settings = CalibanCommonSettings.empty))
19 |
20 | val calibanVersion = settingKey[String]("Version of the Caliban sbt plugin")
21 | }
22 |
23 | object CalibanKeys extends CalibanKeys
24 |
--------------------------------------------------------------------------------
/codegen-sbt/src/sbt-test/codegen/gen-client-task/.scalafmt.conf:
--------------------------------------------------------------------------------
1 | version = "3.1.2"
2 |
3 | runner.dialect = scala213
4 | preset = default
5 |
--------------------------------------------------------------------------------
/codegen-sbt/src/sbt-test/codegen/gen-client-task/build.sbt:
--------------------------------------------------------------------------------
1 | lazy val root = project
2 | .in(file("."))
3 | .enablePlugins(CalibanPlugin)
4 | .settings(
5 | libraryDependencies ++= Seq(
6 | "com.github.ghostdogpr" %% "caliban-client" % Version.pluginVersion
7 | )
8 | )
9 |
--------------------------------------------------------------------------------
/codegen-sbt/src/sbt-test/codegen/gen-client-task/project/Version.scala:
--------------------------------------------------------------------------------
1 | object Version {
2 | def pluginVersion: String =
3 | sys.props.get("plugin.version") match {
4 | case Some(x) => x
5 | case _ => sys.error("""|The system property 'plugin.version' is not defined.
6 | |Specify this property using the scriptedLaunchOpts -D.""".stripMargin)
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/codegen-sbt/src/sbt-test/codegen/gen-client-task/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | sys.props.get("plugin.version") match {
2 | case Some(x) => addSbtPlugin("com.github.ghostdogpr" % "caliban-codegen-sbt" % x)
3 | case _ => sys.error("""|The system property 'plugin.version' is not defined.
4 | |Specify this property using the scriptedLaunchOpts -D.""".stripMargin)
5 | }
6 | addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.4")
7 |
--------------------------------------------------------------------------------
/codegen-sbt/src/sbt-test/codegen/gen-client-task/verify.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | if grep -q "$1" "$2"; then
4 | echo "$1 exists in $2"
5 | exit 0
6 | else
7 | echo "$1 is missing in $2"
8 | exit 1
9 | fi
--------------------------------------------------------------------------------
/codegen-sbt/src/sbt-test/codegen/test-compile-newtype/modules/base/src/main/scala/graphql/package.scala:
--------------------------------------------------------------------------------
1 | import zio.query.ZQuery
2 | import javax.sql.DataSource
3 |
4 | package object graphql {
5 | type Env = DataSource
6 | type FID = Int
7 | type MyZQuery[A] = ZQuery[Env, Throwable, A]
8 | }
9 |
--------------------------------------------------------------------------------
/codegen-sbt/src/sbt-test/codegen/test-compile-newtype/project/Version.scala:
--------------------------------------------------------------------------------
1 | object Version {
2 | def pluginVersion: String =
3 | sys.props.get("plugin.version") match {
4 | case Some(x) => x
5 | case _ => sys.error("""|The system property 'plugin.version' is not defined.
6 | |Specify this property using the scriptedLaunchOpts -D.""".stripMargin)
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/codegen-sbt/src/sbt-test/codegen/test-compile-newtype/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | sys.props.get("plugin.version") match {
2 | case Some(x) => addSbtPlugin("com.github.ghostdogpr" % "caliban-codegen-sbt" % x)
3 | case _ => sys.error("""|The system property 'plugin.version' is not defined.
4 | |Specify this property using the scriptedLaunchOpts -D.""".stripMargin)
5 | }
6 |
--------------------------------------------------------------------------------
/codegen-sbt/src/sbt-test/codegen/test-compile-newtype/src/main/graphql/schema.graphql:
--------------------------------------------------------------------------------
1 | directive @lazy on FIELD_DEFINITION
2 | directive @newtype(name : String) on FIELD_DEFINITION | ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION
3 |
4 | scalar FID
5 |
6 | type Query {
7 | getFoo(
8 | id: ID! @newtype(name: "CustomId"),
9 | maybeId : ID @newtype(name: "ACustomIdOpt")
10 | maybeAllIDsOpt: [ID] @newtype(name: "AMaybeInnerIdOpt")
11 | ): Foo
12 | }
13 |
14 | type Mutation {
15 | updateFoo(foo: FooInput!): Foo
16 | }
17 |
18 | type Foo {
19 | id : ID! @newtype(name: "CustomId")
20 | strId : String! @newtype(name: "CustomStrId")
21 | intId : Int! @newtype(name: "CustomIntId")
22 | fid : FID! @newtype(name: "CustomFId")
23 | maybeId : ID @newtype(name: "CustomIdOpt")
24 | IDs : [ID!]!
25 | allIDs : [ID!]! @newtype(name: "InnerId")
26 | allIDsOpt: [ID]! @newtype(name: "InnerOptId")
27 | maybeAllIDs: [ID!] @newtype(name: "MaybeInnerId")
28 | maybeAllIDsOpt: [ID] @newtype(name: "MaybeInnerIdOpt")
29 | getLazyFoo : FooLazy @lazy
30 | }
31 |
32 | type FooLazy {
33 | id : ID!
34 | }
35 |
36 |
37 | input FooInput {
38 | id : ID! @newtype(name: "CustomId")
39 | allIDs : [ID!]! @newtype(name: "IInnerId")
40 | maybeAllIDsOpt: [ID] @newtype(name: "IMaybeInnerIdOpt")
41 | }
--------------------------------------------------------------------------------
/codegen-sbt/src/sbt-test/codegen/test-compile-newtype/test:
--------------------------------------------------------------------------------
1 | > compile
2 |
3 | $ exists target/scala-2.12/src_managed/main/caliban-codegen-sbt/graphql/GeneratedAPI.scala
4 | $ exec sh verify.sh Foo target/scala-2.12/src_managed/main/caliban-codegen-sbt/graphql/GeneratedAPI.scala
5 | $ exec sh verify.sh FooInput target/scala-2.12/src_managed/main/caliban-codegen-sbt/graphql/GeneratedAPI.scala
6 | $ exec sh verify.sh CustomId target/scala-2.12/src_managed/main/caliban-codegen-sbt/graphql/GeneratedAPI.scala
7 | $ exec sh verify.sh FooLazy target/scala-2.12/src_managed/main/caliban-codegen-sbt/graphql/GeneratedAPI.scala
8 |
--------------------------------------------------------------------------------
/codegen-sbt/src/sbt-test/codegen/test-compile-newtype/verify.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | if grep -q "$1" "$2"; then
4 | echo "$1 exists in $2"
5 | exit 0
6 | else
7 | echo "$1 is missing in $2"
8 | exit 1
9 | fi
--------------------------------------------------------------------------------
/codegen-sbt/src/sbt-test/codegen/test-compile/build.sbt:
--------------------------------------------------------------------------------
1 | import _root_.caliban.tools.Codegen
2 |
3 | lazy val root = project
4 | .in(file("."))
5 | .enablePlugins(CalibanPlugin)
6 | .settings(
7 | libraryDependencies ++= Seq(
8 | "com.github.ghostdogpr" %% "caliban" % Version.pluginVersion,
9 | "com.github.ghostdogpr" %% "caliban-client" % Version.pluginVersion
10 | ),
11 | Compile / caliban / calibanSettings ++= Seq(
12 | calibanSetting(file("src/main/graphql/schema.graphql"))( // Explicitly constrain to disambiguate
13 | _.clientName("Client")
14 | ),
15 | // Another entry for the same file, which will cause another generator to run
16 | calibanSetting(file("src/main/graphql/schema.graphql"))(
17 | _.genType(Codegen.GenType.Schema)
18 | .scalarMapping("Json" -> "String")
19 | .effect("scala.util.Try")
20 | .addDerives(false)
21 | ),
22 | calibanSetting(file("src/main/graphql/schema.graphql"))(
23 | _.genType(Codegen.GenType.Schema)
24 | .scalarMapping("Json" -> "String")
25 | .effect("F")
26 | .abstractEffectType(true)
27 | ),
28 | calibanSetting(file("src/main/graphql/genview/schema.graphql"))(
29 | _.clientName("Client").packageName("genview").genView(true)
30 | )
31 | )
32 | )
33 |
--------------------------------------------------------------------------------
/codegen-sbt/src/sbt-test/codegen/test-compile/project/Version.scala:
--------------------------------------------------------------------------------
1 | object Version {
2 | def pluginVersion: String =
3 | sys.props.get("plugin.version") match {
4 | case Some(x) => x
5 | case _ => sys.error("""|The system property 'plugin.version' is not defined.
6 | |Specify this property using the scriptedLaunchOpts -D.""".stripMargin)
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/codegen-sbt/src/sbt-test/codegen/test-compile/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | sys.props.get("plugin.version") match {
2 | case Some(x) => addSbtPlugin("com.github.ghostdogpr" % "caliban-codegen-sbt" % x)
3 | case _ => sys.error("""|The system property 'plugin.version' is not defined.
4 | |Specify this property using the scriptedLaunchOpts -D.""".stripMargin)
5 | }
6 |
--------------------------------------------------------------------------------
/codegen-sbt/src/sbt-test/codegen/test-compile/test:
--------------------------------------------------------------------------------
1 | > compile
2 |
3 | $ exists target/scala-2.12/src_managed/main/caliban-codegen-sbt/caliban/Client.scala
4 | $ exists target/scala-2.12/src_managed/main/caliban-codegen-sbt/genview/Client.scala
5 | $ exists target/scala-2.12/src_managed/main/caliban-codegen-sbt/caliban/schema.scala
6 | $ exec sh verify.sh CharacterView target/scala-2.12/src_managed/main/caliban-codegen-sbt/genview/Client.scala
7 | $ exec sh verify.sh OptionView target/scala-2.12/src_managed/main/caliban-codegen-sbt/genview/Client.scala
8 | $ exec sh verify.sh CharacterOneOfInput target/scala-2.12/src_managed/main/caliban-codegen-sbt/genview/Client.scala
9 |
--------------------------------------------------------------------------------
/codegen-sbt/src/sbt-test/codegen/test-compile/verify.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | if grep -q "$1" "$2"; then
4 | echo "$1 exists in $2"
5 | exit 0
6 | else
7 | echo "$1 is missing in $2"
8 | exit 1
9 | fi
--------------------------------------------------------------------------------
/codegen-sbt/src/sbt-test/codegen/test-split-files-compile/build.sbt:
--------------------------------------------------------------------------------
1 | import _root_.caliban.tools.Codegen
2 |
3 | lazy val root = project
4 | .in(file("."))
5 | .enablePlugins(CalibanPlugin)
6 | .settings(
7 | libraryDependencies ++= Seq(
8 | "com.github.ghostdogpr" %% "caliban" % Version.pluginVersion,
9 | "com.github.ghostdogpr" %% "caliban-client" % Version.pluginVersion
10 | ),
11 | Compile / caliban / calibanSettings ++= Seq(
12 | calibanSetting(file("src/main/graphql/schema.graphql"))( // Explicitly constrain to disambiguate
13 | _.clientName("Client")
14 | .splitFiles(true)
15 | )
16 | )
17 | )
18 |
--------------------------------------------------------------------------------
/codegen-sbt/src/sbt-test/codegen/test-split-files-compile/project/Version.scala:
--------------------------------------------------------------------------------
1 | object Version {
2 | def pluginVersion: String =
3 | sys.props.get("plugin.version") match {
4 | case Some(x) => x
5 | case _ => sys.error("""|The system property 'plugin.version' is not defined.
6 | |Specify this property using the scriptedLaunchOpts -D.""".stripMargin)
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/codegen-sbt/src/sbt-test/codegen/test-split-files-compile/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | sys.props.get("plugin.version") match {
2 | case Some(x) => addSbtPlugin("com.github.ghostdogpr" % "caliban-codegen-sbt" % x)
3 | case _ => sys.error("""|The system property 'plugin.version' is not defined.
4 | |Specify this property using the scriptedLaunchOpts -D.""".stripMargin)
5 | }
6 |
--------------------------------------------------------------------------------
/codegen-sbt/src/sbt-test/codegen/test-split-files-compile/test:
--------------------------------------------------------------------------------
1 | $ exec echo compiling for the first time
2 | > compile
3 |
4 | $ exists target/scala-2.12/src_managed/main/caliban-codegen-sbt/caliban/Client/package.scala
5 | $ exists target/scala-2.12/src_managed/main/caliban-codegen-sbt/caliban/Client/Character.scala
6 | $ exists target/scala-2.12/src_managed/main/caliban-codegen-sbt/caliban/Client/Canterbury.scala
7 |
8 | $ exec echo compiling second time
9 | > compile
10 |
11 | $ exists target/scala-2.12/src_managed/main/caliban-codegen-sbt/caliban/Client/package.scala
12 | $ exists target/scala-2.12/src_managed/main/caliban-codegen-sbt/caliban/Client/Character.scala
13 | $ exists target/scala-2.12/src_managed/main/caliban-codegen-sbt/caliban/Client/Canterbury.scala
14 |
--------------------------------------------------------------------------------
/codegen-sbt/src/sbt-test/codegen/test-split-files-compile/verify.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | if grep -q "$1" "$2"; then
4 | echo "$1 exists in $2"
5 | exit 0
6 | else
7 | echo "$1 is missing in $2"
8 | exit 1
9 | fi
--------------------------------------------------------------------------------
/codegen-sbt/src/sbt-test/compiletime-codegen/test-compile/README.md:
--------------------------------------------------------------------------------
1 | # Test doc
2 |
3 | This test project has been copied from:
4 | https://github.com/guizmaii/poc_compile_time_caliban_client_generation
5 |
6 | ### Running locally
7 | You can run these tests using following sbt commandos:
8 |
9 | ```sbt
10 | project codegenSbt
11 | ++2.12
12 | update
13 | scripted compiletime-codegen/test-compile
14 | ```
15 |
--------------------------------------------------------------------------------
/codegen-sbt/src/sbt-test/compiletime-codegen/test-compile/modules/clients/src/main/scala/poc/caliban/client/PostClient.scala:
--------------------------------------------------------------------------------
1 | package poc.caliban.client
2 |
3 | import poc.caliban.client.generated.posts.CalibanClient
4 | import poc.caliban.client.generated.posts.CalibanClient._
5 | import sttp.capabilities.WebSockets
6 | import sttp.capabilities.zio.ZioStreams
7 | import sttp.client3.SttpBackend
8 | import zio.Task
9 |
10 | trait PostClient {
11 | def postById(id: String): Task[Option[(String, String)]]
12 | }
13 |
14 | final class PostClientLive(backend: SttpBackend[Task, ZioStreams with WebSockets]) extends PostClient {
15 | import sttp.client3._
16 |
17 | private val serverUrl = uri"http://localhost:8088/api/graphql"
18 |
19 | /**
20 | * Jules' comment:
21 | *
22 | * In real-world code, I'd never accept to get a String and return 2 String. I'd use proper types but it's not important in this POC.
23 | */
24 | override def postById(id: String): Task[Option[(String, String)]] =
25 | CalibanClient.Query
26 | .postById(id)(Post.id(PostId.id) ~ Post.author(AuthorName.name))
27 | .toRequest(serverUrl)
28 | .send(backend)
29 | .map(_.body)
30 | .absolve
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/codegen-sbt/src/sbt-test/compiletime-codegen/test-compile/modules/clients/src/main/scala/poc/caliban/client/PotatoesClient.scala:
--------------------------------------------------------------------------------
1 | package poc.caliban.client
2 |
3 | import poc.caliban.client.generated.potatoes._
4 | import sttp.capabilities.WebSockets
5 | import sttp.capabilities.zio.ZioStreams
6 | import sttp.client3.SttpBackend
7 | import zio.{ Task, ZIO }
8 |
9 | trait PotatoesClient {
10 | def eradicate(name: String): Task[Unit]
11 | }
12 |
13 | final class PotatoesClientLive(backend: SttpBackend[Task, ZioStreams with WebSockets]) extends PotatoesClient {
14 | import sttp.client3._
15 |
16 | private val serverUrl = uri"http://localhost:8088/api/graphql"
17 |
18 | override def eradicate(name: String): Task[Unit] =
19 | Mutation
20 | .eradicate(name)
21 | .toRequest(serverUrl)
22 | .send(backend)
23 | .foldZIO(ZIO.fail(_), r => ZIO.fromEither(r.body).unit)
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/codegen-sbt/src/sbt-test/compiletime-codegen/test-compile/modules/posts-clients/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ghostdogpr/caliban/24a568744f6708a4f400d7f8f5f158b002f29806/codegen-sbt/src/sbt-test/compiletime-codegen/test-compile/modules/posts-clients/.gitkeep
--------------------------------------------------------------------------------
/codegen-sbt/src/sbt-test/compiletime-codegen/test-compile/modules/posts/src/test/resources/postservice.graphql:
--------------------------------------------------------------------------------
1 | schema {
2 | query: Query
3 | mutation: Mutation
4 | subscription: Subscription
5 | }
6 | scalar Unit
7 |
8 | input AuthorNameInput {
9 | name: String!
10 | }
11 |
12 | input PostContentInput {
13 | content: String!
14 | }
15 |
16 | input PostTitleInput {
17 | title: String!
18 | }
19 |
20 | type AuthorName {
21 | name: String!
22 | }
23 |
24 | type Mutation {
25 | createPost(authorName: AuthorNameInput!, title: PostTitleInput!, content: PostContentInput!): Post
26 | deletePost(id: ID!): Unit
27 | }
28 |
29 | type Post {
30 | id: PostId!
31 | author: AuthorName!
32 | title: PostTitle!
33 | content: PostContent!
34 | }
35 |
36 | type PostContent {
37 | content: String!
38 | }
39 |
40 | type PostId {
41 | id: ID!
42 | }
43 |
44 | type PostTitle {
45 | title: String!
46 | }
47 |
48 | type Query {
49 | postById(id: ID!): Post
50 | }
51 |
52 | type Subscription {
53 | allPostsByAuthor(name: String!): Post
54 | }
--------------------------------------------------------------------------------
/codegen-sbt/src/sbt-test/compiletime-codegen/test-compile/modules/posts/src/test/scala/ValidateGraphQlSpec.scala:
--------------------------------------------------------------------------------
1 | import poc.caliban.posts.GraphQLApi
2 |
3 | import scala.io.Source
4 | import zio.test.Assertion._
5 | import zio.test._
6 | import caliban.tools._
7 | import java.nio.file.Path
8 |
9 | object ValidateGraphQlSpec extends SnapshotTest {
10 | override val testName: String = "ValidateGraphQlSpec"
11 |
12 | val graphqlFile= "src/sbt-test/compiletime-codegen/test-compile/modules/posts/src/test/resources/postservice.graphql"
13 | val projectDir = sys.props.get("project.dir").getOrElse("")
14 |
15 | override def spec =
16 | suite("Validate Postservice")(
17 | test("Render postservice as earlier") {
18 | val gqlApi = GraphQLApi.api
19 | val renderContent: String = s"${gqlApi.render}"
20 |
21 | writeAndCompare(Path.of(projectDir).resolve(graphqlFile), renderContent, "Render postservice")
22 | }
23 | )
24 | }
--------------------------------------------------------------------------------
/codegen-sbt/src/sbt-test/compiletime-codegen/test-compile/modules/potatoes-clients/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ghostdogpr/caliban/24a568744f6708a4f400d7f8f5f158b002f29806/codegen-sbt/src/sbt-test/compiletime-codegen/test-compile/modules/potatoes-clients/.gitkeep
--------------------------------------------------------------------------------
/codegen-sbt/src/sbt-test/compiletime-codegen/test-compile/project/Version.scala:
--------------------------------------------------------------------------------
1 | object Version {
2 | def pluginVersion: String =
3 | sys.props.get("plugin.version") match {
4 | case Some(x) => x
5 | case _ => sys.error("""|The system property 'plugin.version' is not defined.
6 | |Specify this property using the scriptedLaunchOpts -D.""".stripMargin)
7 | }
8 | def zioTestVersion: String =
9 | sys.props.get("zio.test.version") match {
10 | case Some(x) => x
11 | case _ => sys.error("""|The system property 'zio.test.version' is not defined.
12 | |Specify this property using the scriptedLaunchOpts -D.""".stripMargin)
13 | }
14 | def sttpVersion: String =
15 | sys.props.get("sttp.version") match {
16 | case Some(x) => x
17 | case _ => sys.error("""|The system property 'sttp.version' is not defined.
18 | |Specify this property using the scriptedLaunchOpts -D.""".stripMargin)
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/codegen-sbt/src/sbt-test/compiletime-codegen/test-compile/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version = 1.11.1
2 |
--------------------------------------------------------------------------------
/codegen-sbt/src/sbt-test/compiletime-codegen/test-compile/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | import sbt.librarymanagement.Resolver
2 |
3 | resolvers += Resolver.mavenLocal
4 | resolvers += Resolver.sonatypeRepo("snapshots")
5 |
6 | sys.props.get("plugin.version") match {
7 | case Some(x) => addSbtPlugin("com.github.ghostdogpr" % "caliban-codegen-sbt" % x)
8 | case _ => sys.error("""|The system property 'plugin.version' is not defined.
9 | |Specify this property using the scriptedLaunchOpts -D.""".stripMargin)
10 | }
11 |
--------------------------------------------------------------------------------
/core/src/main/scala-2/caliban/Macros.scala:
--------------------------------------------------------------------------------
1 | package caliban
2 |
3 | import scala.language.experimental.macros
4 | import scala.reflect.macros.blackbox
5 |
6 | import caliban.parsing.Parser
7 |
8 | object Macros {
9 |
10 | /**
11 | * Verifies at compile-time that the given string is a valid GraphQL document.
12 | * @param document a string representing a GraphQL document.
13 | */
14 | def gqldoc(document: String): String = macro MacrosInternal.queryLiteral
15 |
16 | private class MacrosInternal(val c: blackbox.Context) {
17 | import c.universe._
18 | def queryLiteral(document: c.Expr[String]): c.Expr[String] =
19 | document.tree match {
20 | case Literal(Constant(s: String)) =>
21 | Parser.check(s).fold(document)(e => c.abort(c.enclosingPosition, s"GraphQL document is invalid: $e"))
22 | case _ =>
23 | c.abort(c.enclosingPosition, s"This macro can only be used with string literals.")
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/core/src/main/scala-2/caliban/Scala3Annotations.scala:
--------------------------------------------------------------------------------
1 | package caliban
2 |
3 | import scala.annotation.StaticAnnotation
4 |
5 | /**
6 | * Stubs for annotations that exist in Scala 3 but not in Scala 2
7 | */
8 | private[caliban] object Scala3Annotations {
9 | final class static extends StaticAnnotation
10 | }
11 |
--------------------------------------------------------------------------------
/core/src/main/scala-2/caliban/introspection/IntrospectionDerivation.scala:
--------------------------------------------------------------------------------
1 | package caliban.introspection
2 |
3 | import caliban.introspection.adt.{ __Introspection, __Type }
4 | import caliban.schema.ArgBuilder.auto._
5 | import caliban.schema.Schema
6 | import caliban.schema.Schema.auto._
7 |
8 | trait IntrospectionDerivation {
9 | private implicit lazy val typeSchema: Schema[Any, __Type] = genAll
10 |
11 | val introspectionSchema: Schema[Any, __Introspection] = genAll
12 | }
13 |
--------------------------------------------------------------------------------
/core/src/main/scala-2/caliban/schema/AnnotationsVersionSpecific.scala:
--------------------------------------------------------------------------------
1 | package caliban.schema
2 |
3 | import caliban.parsing.adt.Directive
4 |
5 | import scala.annotation.StaticAnnotation
6 |
7 | trait AnnotationsVersionSpecific {
8 |
9 | /**
10 | * Annotation used to provide directives to a schema type
11 | */
12 | class GQLDirective(val directive: Directive) extends StaticAnnotation
13 |
14 | object GQLDirective {
15 | def unapply(annotation: GQLDirective): Option[Directive] =
16 | Some(annotation.directive)
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/core/src/main/scala-2/caliban/schema/DerivationUtils.scala:
--------------------------------------------------------------------------------
1 | package caliban.schema
2 |
3 | import caliban.schema.Annotations.GQLValueType
4 | import magnolia1.ReadOnlyCaseClass
5 |
6 | private object DerivationUtils {
7 |
8 | def isValueType[F[_]](ctx: ReadOnlyCaseClass[F, ?]): Boolean =
9 | (ctx.isValueClass || ctx.annotations.exists(_.isInstanceOf[GQLValueType])) && ctx.parameters.nonEmpty
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/core/src/main/scala-2/caliban/schema/SchemaVersionSpecific.scala:
--------------------------------------------------------------------------------
1 | package caliban.schema
2 |
3 | trait SchemaVersionSpecific
4 |
--------------------------------------------------------------------------------
/core/src/main/scala-2/caliban/schema/SubscriptionSchemaDerivation.scala:
--------------------------------------------------------------------------------
1 | package caliban.schema
2 |
3 | import magnolia1._
4 |
5 | import scala.language.experimental.macros
6 |
7 | trait SubscriptionSchemaDerivation {
8 | type Typeclass[T] = SubscriptionSchema[T]
9 |
10 | def join[T](ctx: CaseClass[SubscriptionSchema, T]): Typeclass[T] = new Typeclass[T] {}
11 |
12 | implicit def gen[T]: Typeclass[T] = macro Magnolia.gen[T]
13 | }
14 |
--------------------------------------------------------------------------------
/core/src/main/scala-2/caliban/syntax.scala:
--------------------------------------------------------------------------------
1 | package caliban
2 |
3 | import scala.collection.mutable
4 |
5 | private[caliban] object syntax {
6 | val NullFn: () => AnyRef = () => null
7 |
8 | implicit class EnrichedImmutableMapOps[K, V <: AnyRef](private val self: Map[K, V]) extends AnyVal {
9 | def getOrElseNull(key: K): V = self.getOrElse(key, NullFn()).asInstanceOf[V]
10 | }
11 |
12 | implicit class EnrichedHashMapOps[K, V <: AnyRef](private val self: mutable.HashMap[K, V]) extends AnyVal {
13 | def getOrElseNull(key: K): V = self.getOrElse(key, NullFn()).asInstanceOf[V]
14 | }
15 |
16 | implicit class EnrichedListOps[A](private val self: List[A]) extends AnyVal {
17 |
18 | /**
19 | * In Scala 3, foreach is not inlined which can lead to performance issues when used in hot paths.
20 | * In Scala 2 this method simply points to foreach, but in Scala 3 it is inlined to a while loop.
21 | */
22 | @inline def foreachOne(f: A => Unit): Unit = self.foreach(f)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/core/src/main/scala-3/caliban/Macros.scala:
--------------------------------------------------------------------------------
1 | package caliban
2 |
3 | import scala.quoted._
4 |
5 | import caliban.parsing.Parser
6 |
7 | object Macros {
8 |
9 | /**
10 | * Verifies at compile-time that the given string is a valid GraphQL document.
11 | * @param document a string representing a GraphQL document.
12 | */
13 | inline def gqldoc(inline document: String): String = ${ gqldocImpl('document) }
14 |
15 | private def gqldocImpl(document: Expr[String])(using Quotes): Expr[String] = {
16 | import quotes.reflect.report
17 | document.value.fold(report.errorAndAbort("This macro can only be used with string literals."))(
18 | Parser.check(_).fold(document)(e => report.errorAndAbort(s"GraphQL document is invalid: $e"))
19 | )
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/core/src/main/scala-3/caliban/Scala3Annotations.scala:
--------------------------------------------------------------------------------
1 | package caliban
2 |
3 | import scala.annotation
4 |
5 | /**
6 | * Proxies for annotations that exist in Scala 3 but not in Scala 2
7 | */
8 | private[caliban] object Scala3Annotations {
9 | type static = annotation.static
10 | }
11 |
--------------------------------------------------------------------------------
/core/src/main/scala-3/caliban/introspection/IntrospectionDerivation.scala:
--------------------------------------------------------------------------------
1 | package caliban.introspection
2 |
3 | import caliban.InputValue
4 | import caliban.Value.StringValue
5 | import caliban.introspection.adt._
6 | import caliban.parsing.adt.Directive
7 | import caliban.schema.Schema
8 | import caliban.schema.ArgBuilder
9 |
10 | trait IntrospectionDerivation {
11 | private given Schema[Any, __InputValue] = Schema.derived
12 | private given Schema[Any, __EnumValue] = Schema.derived
13 | private given Schema[Any, __Field] = Schema.derived
14 | private given Schema[Any, __Type] = Schema.derived
15 | private given Schema[Any, __TypeArgs] = Schema.derived
16 | private given Schema[Any, __Schema] = Schema.derived
17 | private given Schema[Any, __Directive] = Schema.derived
18 | private given Schema[Any, __DeprecatedArgs] = Schema.derived
19 |
20 | // Unions, so we can auto-derive them cheaply
21 | private given Schema[Any, __TypeKind] = Schema.Auto.derived
22 | private given Schema[Any, __DirectiveLocation] = Schema.Auto.derived
23 |
24 | private given ArgBuilder[__TypeArgs] = ArgBuilder.derived
25 | private given ArgBuilder[__DeprecatedArgs] = ArgBuilder.derived
26 |
27 | val introspectionSchema: Schema[Any, __Introspection] = Schema.derived
28 | }
29 |
--------------------------------------------------------------------------------
/core/src/main/scala-3/caliban/schema/AnnotationsVersionSpecific.scala:
--------------------------------------------------------------------------------
1 | package caliban.schema
2 |
3 | import caliban.parsing.adt.Directive
4 |
5 | import scala.annotation.StaticAnnotation
6 |
7 | trait AnnotationsVersionSpecific {
8 |
9 | /**
10 | * Annotation that can be used on a case class method to mark it as a GraphQL field.
11 | * The method must be public, a `def` (does not work on `val`s / `lazy val`s) and must not take any arguments.
12 | *
13 | * '''NOTE''' This annotation is not safe for use with ahead-of-time compilation (e.g., generating a GraalVM native-image executable)
14 | */
15 | case class GQLField() extends StaticAnnotation
16 |
17 | /**
18 | * Annotation that can be used on a case class / case object to have all the public methods on it derived as fields.
19 | *
20 | * If you wish to exclude a public method from being derived as a field, you can annotate it with [[GQLExclude]].
21 | *
22 | * @see [[GQLField]] for a more fine-grained control over which methods are derived as fields
23 | */
24 | case class GQLFieldsFromMethods() extends StaticAnnotation
25 |
26 | /**
27 | * Annotation used to provide directives to a schema type
28 | */
29 | open class GQLDirective(val directive: Directive) extends StaticAnnotation
30 |
31 | object GQLDirective {
32 | def unapply(annotation: GQLDirective): Option[Directive] =
33 | Some(annotation.directive)
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/core/src/main/scala-3/caliban/schema/EnumValueSchema.scala:
--------------------------------------------------------------------------------
1 | package caliban.schema
2 |
3 | import caliban.Value.EnumValue
4 | import caliban.introspection.adt.__Type
5 | import caliban.schema.DerivationUtils.*
6 | import magnolia1.TypeInfo
7 |
8 | final private class EnumValueSchema[R, A](
9 | info: TypeInfo,
10 | anns: List[Any],
11 | enableSemanticNonNull: Boolean
12 | ) extends Schema[R, A] {
13 |
14 | def toType(isInput: Boolean, isSubscription: Boolean): __Type =
15 | if (isInput) mkInputObject[R](anns, Nil, info)(isInput, isSubscription)
16 | else mkObject[R](anns, Nil, info, enableSemanticNonNull)(isInput, isSubscription)
17 |
18 | private val step = PureStep(EnumValue(getName(anns, info)))
19 | def resolve(value: A): Step[R] = step
20 | }
21 |
--------------------------------------------------------------------------------
/core/src/main/scala-3/caliban/schema/ProductFieldInfo.scala:
--------------------------------------------------------------------------------
1 | package caliban.schema
2 |
3 | private final case class ProductFieldInfo[R](
4 | name: String,
5 | schema: Schema[R, Any],
6 | index: Int
7 | )
8 |
--------------------------------------------------------------------------------
/core/src/main/scala-3/caliban/schema/SchemaVersionSpecific.scala:
--------------------------------------------------------------------------------
1 | package caliban.schema
2 |
3 | import caliban.introspection.adt.__Field
4 | import caliban.parsing.adt.Directive
5 |
6 | transparent trait SchemaVersionSpecific extends GenericSchema[Any] {
7 |
8 | /**
9 | * Scala 3 variant of the `obj` method which improves UX for creating custom object schemas.
10 | *
11 | * {{{
12 | * case class Author(id: String, firstName: String, lastName: String)
13 | *
14 | * given Schema[Any, Author] = Schema.customObj("Author")(
15 | * field("id")(_.id),
16 | * field("fullName")(author => s"${author.firstName} ${author.lastName}"),
17 | * )
18 | * }}}
19 | *
20 | * @see [[caliban.schema.GenericSchema.obj]]
21 | */
22 | def customObj[R1, V](
23 | name: String,
24 | description: Option[String] = None,
25 | directives: List[Directive] = Nil
26 | )(
27 | fields: FieldAttributes ?=> (__Field, V => Step[R1])*
28 | ): Schema[R1, V] =
29 | obj(name, description, directives) { case given FieldAttributes =>
30 | fields.toList.map(identity)
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/core/src/main/scala-3/caliban/schema/SubscriptionSchemaDerivation.scala:
--------------------------------------------------------------------------------
1 | package caliban.schema
2 |
3 | import scala.deriving.Mirror
4 | import scala.compiletime._
5 |
6 | trait SubscriptionSchemaDerivation {
7 | inline def checkParams[T <: Tuple]: Unit =
8 | inline erasedValue[T] match {
9 | case _: EmptyTuple => ()
10 | case _: (t *: ts) =>
11 | summonInline[SubscriptionSchema[t]]
12 | checkParams[ts]
13 | }
14 |
15 | inline def derived[A]: SubscriptionSchema[A] =
16 | inline summonInline[Mirror.ProductOf[A]] match {
17 | case m: Mirror.ProductOf[A] =>
18 | checkParams[m.MirroredElemTypes]
19 | new ProductSubscriptionSchema[A]
20 | }
21 |
22 | inline given gen[A]: SubscriptionSchema[A] = derived
23 | }
24 |
25 | private final class ProductSubscriptionSchema[A] extends SubscriptionSchema[A]
26 |
--------------------------------------------------------------------------------
/core/src/main/scala-3/caliban/schema/ValueTypeSchema.scala:
--------------------------------------------------------------------------------
1 | package caliban.schema
2 |
3 | import caliban.introspection.adt.__Type
4 | import caliban.schema.Annotations.GQLValueType
5 | import caliban.schema.DerivationUtils.*
6 | import caliban.schema.Types.makeScalar
7 | import magnolia1.TypeInfo
8 |
9 | import scala.annotation.threadUnsafe
10 |
11 | final private class ValueTypeSchema[R, A](
12 | _schema: => Schema[R, Any],
13 | info: TypeInfo,
14 | anns: List[Any]
15 | ) extends Schema[R, A] {
16 | private val name = getName(anns, info)
17 |
18 | @threadUnsafe
19 | private lazy val schema = _schema
20 |
21 | def toType(isInput: Boolean, isSubscription: Boolean): __Type = {
22 | val _ = schema
23 | if (anns.contains(GQLValueType(true))) makeScalar(name, getDescription(anns))
24 | else schema.toType_(isInput, isSubscription)
25 | }
26 |
27 | def resolve(value: A): Step[R] = schema.resolve(value.asInstanceOf[Product].productElement(0))
28 | }
29 |
--------------------------------------------------------------------------------
/core/src/main/scala-3/caliban/syntax.scala:
--------------------------------------------------------------------------------
1 | package caliban
2 |
3 | import scala.annotation.static
4 |
5 | import scala.collection.mutable
6 |
7 | private[caliban] object syntax {
8 | @static val NullFn: () => AnyRef = () => null
9 |
10 | extension [K, V <: AnyRef](inline map: Map[K, V]) {
11 | transparent inline def getOrElseNull(key: K): V = map.getOrElse(key, NullFn()).asInstanceOf[V]
12 | }
13 |
14 | extension [K, V <: AnyRef](inline map: mutable.HashMap[K, V]) {
15 | transparent inline def getOrElseNull(key: K): V = map.getOrElse(key, NullFn()).asInstanceOf[V]
16 | }
17 |
18 | extension [A](inline list: List[A]) {
19 |
20 | /**
21 | * In Scala 3, foreach is not inlined which can lead to performance issues when used in hot paths.
22 | * In Scala 2 this method simply points to foreach, but in Scala 3 it is inlined to a while loop.
23 | */
24 | inline def foreachOne(inline f: A => Any): Unit = {
25 | var rem = list
26 | while (rem ne Nil) {
27 | f(rem.head)
28 | rem = rem.tail
29 | }
30 | }
31 | }
32 | }
33 |
34 | // Required for @static fields
35 | private final class syntax private
36 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/GraphQLWSClose.scala:
--------------------------------------------------------------------------------
1 | package caliban
2 |
3 | case class GraphQLWSClose(code: Int, reason: String)
4 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/GraphQLWSInput.scala:
--------------------------------------------------------------------------------
1 | package caliban
2 |
3 | import caliban.interop.tapir.IsTapirSchema
4 | import com.github.plokhotnyuk.jsoniter_scala.core._
5 | import com.github.plokhotnyuk.jsoniter_scala.macros._
6 |
7 | case class GraphQLWSInput(`type`: String, id: Option[String], payload: Option[InputValue])
8 |
9 | object GraphQLWSInput {
10 | implicit val jsoniterCodec: JsonValueCodec[GraphQLWSInput] = JsonCodecMaker.make
11 |
12 | implicit def tapirSchema[F[_]: IsTapirSchema]: F[GraphQLWSInput] =
13 | caliban.interop.tapir.schema.wsInputSchema.asInstanceOf[F[GraphQLWSInput]]
14 | }
15 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/GraphQLWSOutput.scala:
--------------------------------------------------------------------------------
1 | package caliban
2 |
3 | import caliban.interop.tapir.IsTapirSchema
4 | import com.github.plokhotnyuk.jsoniter_scala.core._
5 | import com.github.plokhotnyuk.jsoniter_scala.macros._
6 |
7 | case class GraphQLWSOutput(`type`: String, id: Option[String], payload: Option[ResponseValue])
8 |
9 | object GraphQLWSOutput {
10 | implicit val jsoniterCodec: JsonValueCodec[GraphQLWSOutput] = JsonCodecMaker.make
11 |
12 | implicit def tapirSchema[F[_]: IsTapirSchema]: F[GraphQLWSOutput] =
13 | caliban.interop.tapir.schema.wsOutputSchema.asInstanceOf[F[GraphQLWSOutput]]
14 | }
15 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/RootResolver.scala:
--------------------------------------------------------------------------------
1 | package caliban
2 |
3 | /**
4 | * A `root resolver` contains resolvers for the 3 types of operations allowed in GraphQL: queries, mutations and subscriptions.
5 | *
6 | * A `resolver` is a simple value of the case class describing the API.
7 | */
8 | case class RootResolver[+Query, +Mutation, +Subscription](
9 | queryResolver: Option[Query],
10 | mutationResolver: Option[Mutation],
11 | subscriptionResolver: Option[Subscription]
12 | )
13 |
14 | object RootResolver {
15 |
16 | /**
17 | * Constructs a [[RootResolver]] with only a query resolver.
18 | */
19 | def apply[Query](queryResolver: Query): RootResolver[Query, Unit, Unit] =
20 | RootResolver(Some(queryResolver), Option.empty[Unit], Option.empty[Unit])
21 |
22 | /**
23 | * Constructs a [[RootResolver]] with a query resolver and a mutation resolver.
24 | */
25 | def apply[Query, Mutation](queryResolver: Query, mutationResolver: Mutation): RootResolver[Query, Mutation, Unit] =
26 | RootResolver(Some(queryResolver), Some(mutationResolver), Option.empty[Unit])
27 |
28 | /**
29 | * Constructs a [[RootResolver]] with a query resolver, a mutation resolver and a subscription resolver.
30 | */
31 | def apply[Query, Mutation, Subscription](
32 | queryResolver: Query,
33 | mutationResolver: Mutation,
34 | subscriptionResolver: Subscription
35 | ): RootResolver[Query, Mutation, Subscription] =
36 | RootResolver(Some(queryResolver), Some(mutationResolver), Some(subscriptionResolver))
37 | }
38 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/execution/Deferred.scala:
--------------------------------------------------------------------------------
1 | package caliban.execution
2 |
3 | import caliban.PathValue
4 | import caliban.schema.ReducedStep
5 |
6 | sealed trait Deferred[-R] {
7 | def path: List[PathValue]
8 | def label: Option[String]
9 | }
10 |
11 | case class DeferredFragment[-R](
12 | path: List[PathValue],
13 | step: ReducedStep[R],
14 | label: Option[String]
15 | ) extends Deferred[R]
16 |
17 | case class DeferredStream[-R](
18 | path: List[PathValue],
19 | step: ReducedStep.StreamStep[R],
20 | label: Option[String],
21 | startFrom: Int
22 | ) extends Deferred[R]
23 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/execution/ExecutionRequest.scala:
--------------------------------------------------------------------------------
1 | package caliban.execution
2 |
3 | import caliban.parsing.adt.OperationType
4 |
5 | case class ExecutionRequest(
6 | field: Field,
7 | operationType: OperationType,
8 | operationName: Option[String]
9 | )
10 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/execution/FieldInfo.scala:
--------------------------------------------------------------------------------
1 | package caliban.execution
2 |
3 | import caliban.PathValue
4 | import caliban.introspection.adt.__Type
5 | import caliban.parsing.adt.Directive
6 |
7 | case class FieldInfo(
8 | name: String,
9 | details: Field,
10 | path: List[PathValue],
11 | directives: List[Directive] = Nil,
12 | parent: Option[__Type]
13 | )
14 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/execution/Fragment.scala:
--------------------------------------------------------------------------------
1 | package caliban.execution
2 |
3 | import caliban.Value.{ BooleanValue, IntValue, StringValue }
4 | import caliban.parsing.adt.{ Directive, Directives }
5 |
6 | case class Fragment(name: Option[String], directives: List[Directive]) {}
7 |
8 | object Fragment {
9 | object IsDeferred {
10 | def unapply(fragment: Fragment): Option[Option[String]] =
11 | fragment.directives.collectFirst {
12 | case Directive(Directives.Defer, args, _, _) if args.get("if").forall {
13 | case BooleanValue(v) => v
14 | case _ => true
15 | } =>
16 | args.get("label").collect { case StringValue(v) => v }
17 | }
18 | }
19 | }
20 |
21 | object IsStream {
22 | def unapply(field: Field): Option[(Option[String], Option[Int])] =
23 | field.directives.collectFirst {
24 | case Directive(Directives.Stream, args, _, _) if args.get("if").forall {
25 | case BooleanValue(v) => v
26 | case _ => true
27 | } =>
28 | (
29 | args.get("label").collect { case StringValue(v) => v },
30 | args.get("initialCount").collect { case v: IntValue => v.toInt }
31 | )
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/execution/QueryExecution.scala:
--------------------------------------------------------------------------------
1 | package caliban.execution
2 |
3 | /**
4 | * Defines which type of parallelism to use when executing queries
5 | */
6 | sealed trait QueryExecution {
7 | def tag: Int
8 | }
9 |
10 | object QueryExecution {
11 |
12 | /**
13 | * Run effectful fields sequentially.
14 | */
15 | case object Sequential extends QueryExecution {
16 | final val tag = 0
17 | }
18 |
19 | /**
20 | * Run effectful fields in parallel (default).
21 | */
22 | case object Parallel extends QueryExecution {
23 | final val tag = 1
24 | }
25 |
26 | /**
27 | * Run effectful fields sequentially but batch effects wrapped with `ZQuery.fromRequest`.
28 | * This mode is recommended when most of your effects are backed by ZQuery DataSources as it avoids forking unnecessary fibers.
29 | */
30 | case object Batched extends QueryExecution {
31 | final val tag = 2
32 | }
33 |
34 | /**
35 | * Run effectful top-level fields in [[Parallel]] mode and nested fields in [[Batched]] mode.
36 | * This mode is recommended when most of your effects are backed by ZQuery DataSources but want to guarantee that top-level fields are always executed in parallel.
37 | */
38 | case object Mixed extends QueryExecution {
39 | final val tag = 3
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/implicits.scala:
--------------------------------------------------------------------------------
1 | package caliban
2 |
3 | import zio.Unsafe
4 |
5 | private object implicits {
6 | implicit val unsafe: Unsafe = Unsafe.unsafe(identity)
7 | }
8 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/interop/tapir/tapir.scala:
--------------------------------------------------------------------------------
1 | package caliban.interop.tapir
2 |
3 | import caliban._
4 | import sttp.tapir.{ Schema, SchemaType }
5 |
6 | /**
7 | * This class is an implementation of the pattern described in https://blog.7mind.io/no-more-orphans.html
8 | * It makes it possible to mark circe dependency as optional and keep Encoders defined in the companion object.
9 | */
10 | private[caliban] trait IsTapirSchema[F[_]]
11 | private[caliban] object IsTapirSchema {
12 | implicit val isTapirSchema: IsTapirSchema[Schema] = null
13 | }
14 |
15 | object schema {
16 | implicit lazy val requestSchema: Schema[GraphQLRequest] =
17 | sttp.tapir.Schema[GraphQLRequest](SchemaType.SString[GraphQLRequest]())
18 | implicit def responseSchema[E]: Schema[GraphQLResponse[E]] =
19 | sttp.tapir.Schema[GraphQLResponse[E]](SchemaType.SString[GraphQLResponse[E]]())
20 | implicit lazy val wsInputSchema: Schema[GraphQLWSInput] =
21 | sttp.tapir.Schema[GraphQLWSInput](SchemaType.SString[GraphQLWSInput]())
22 | implicit lazy val wsOutputSchema: Schema[GraphQLWSOutput] =
23 | sttp.tapir.Schema[GraphQLWSOutput](SchemaType.SString[GraphQLWSOutput]())
24 | implicit lazy val responseValueSchema: Schema[ResponseValue] =
25 | sttp.tapir.Schema[ResponseValue](SchemaType.SString[ResponseValue]())
26 | }
27 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/introspection/adt/__DeprecatedArgs.scala:
--------------------------------------------------------------------------------
1 | package caliban.introspection.adt
2 |
3 | case class __DeprecatedArgs(includeDeprecated: Option[Boolean] = None)
4 |
5 | object __DeprecatedArgs {
6 | val include: __DeprecatedArgs = __DeprecatedArgs(Some(true))
7 | }
8 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/introspection/adt/__Directive.scala:
--------------------------------------------------------------------------------
1 | package caliban.introspection.adt
2 |
3 | import caliban.parsing.adt.Definition.TypeSystemDefinition.DirectiveDefinition
4 |
5 | case class __Directive(
6 | name: String,
7 | description: Option[String],
8 | locations: Set[__DirectiveLocation],
9 | args: __DeprecatedArgs => List[__InputValue],
10 | isRepeatable: Boolean
11 | ) {
12 | def toDirectiveDefinition: DirectiveDefinition =
13 | DirectiveDefinition(
14 | description,
15 | name,
16 | allArgs.map(_.toInputValueDefinition),
17 | isRepeatable,
18 | locations.map(_.toDirectiveLocation)
19 | )
20 |
21 | lazy val allArgs: List[__InputValue] =
22 | args(__DeprecatedArgs.include)
23 | }
24 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/introspection/adt/__EnumValue.scala:
--------------------------------------------------------------------------------
1 | package caliban.introspection.adt
2 |
3 | import caliban.Value.StringValue
4 | import caliban.parsing.adt.Definition.TypeSystemDefinition.TypeDefinition.EnumValueDefinition
5 | import caliban.parsing.adt.Directive
6 | import caliban.schema.Annotations.GQLExcluded
7 |
8 | case class __EnumValue(
9 | name: String,
10 | description: Option[String],
11 | isDeprecated: Boolean,
12 | deprecationReason: Option[String],
13 | @GQLExcluded directives: Option[List[Directive]]
14 | ) {
15 | def toEnumValueDefinition: EnumValueDefinition =
16 | EnumValueDefinition(
17 | description,
18 | name,
19 | (if (isDeprecated)
20 | List(
21 | Directive(
22 | "deprecated",
23 | List(deprecationReason.map(reason => "reason" -> StringValue(reason))).flatten.toMap
24 | )
25 | )
26 | else Nil) ++ directives.getOrElse(Nil)
27 | )
28 | }
29 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/introspection/adt/__Introspection.scala:
--------------------------------------------------------------------------------
1 | package caliban.introspection.adt
2 |
3 | case class __Introspection(
4 | __schema: __Schema,
5 | __type: __TypeArgs => Option[__Type]
6 | )
7 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/introspection/adt/__Schema.scala:
--------------------------------------------------------------------------------
1 | package caliban.introspection.adt
2 |
3 | case class __Schema(
4 | description: Option[String],
5 | queryType: __Type,
6 | mutationType: Option[__Type],
7 | subscriptionType: Option[__Type],
8 | types: List[__Type],
9 | directives: List[__Directive]
10 | )
11 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/introspection/adt/__TypeArgs.scala:
--------------------------------------------------------------------------------
1 | package caliban.introspection.adt
2 |
3 | case class __TypeArgs(name: String)
4 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/introspection/adt/__TypeKind.scala:
--------------------------------------------------------------------------------
1 | package caliban.introspection.adt
2 |
3 | sealed trait __TypeKind
4 |
5 | object __TypeKind {
6 | case object SCALAR extends __TypeKind
7 | case object OBJECT extends __TypeKind
8 | case object INTERFACE extends __TypeKind
9 | case object UNION extends __TypeKind
10 | case object ENUM extends __TypeKind
11 | case object INPUT_OBJECT extends __TypeKind
12 | case object LIST extends __TypeKind
13 | case object NON_NULL extends __TypeKind
14 |
15 | implicit val kindOrdering: Ordering[__TypeKind] = Ordering
16 | .by[__TypeKind, Int] {
17 | case __TypeKind.SCALAR => 1
18 | case __TypeKind.NON_NULL => 2
19 | case __TypeKind.LIST => 3
20 | case __TypeKind.UNION => 4
21 | case __TypeKind.ENUM => 5
22 | case __TypeKind.INPUT_OBJECT => 6
23 | case __TypeKind.INTERFACE => 7
24 | case __TypeKind.OBJECT => 8
25 | }
26 |
27 | implicit val typeOrdering: Ordering[__Type] =
28 | Ordering.by(o => (o.kind, o.name.getOrElse("")))
29 | }
30 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/parsing/adt/LocationInfo.scala:
--------------------------------------------------------------------------------
1 | package caliban.parsing.adt
2 |
3 | import caliban.ResponseValue
4 | import caliban.ResponseValue.ObjectValue
5 | import caliban.Value.IntValue
6 |
7 | case class LocationInfo(column: Int, line: Int) {
8 | def toResponseValue: ResponseValue =
9 | ObjectValue(List("line" -> IntValue(line), "column" -> IntValue(column)))
10 | }
11 |
12 | object LocationInfo {
13 | val origin: LocationInfo = LocationInfo(0, 0)
14 | }
15 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/parsing/adt/OperationType.scala:
--------------------------------------------------------------------------------
1 | package caliban.parsing.adt
2 |
3 | sealed trait OperationType extends Serializable
4 |
5 | object OperationType {
6 | case object Query extends OperationType
7 | case object Mutation extends OperationType
8 | case object Subscription extends OperationType
9 | }
10 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/parsing/adt/Selection.scala:
--------------------------------------------------------------------------------
1 | package caliban.parsing.adt
2 |
3 | import caliban.InputValue
4 | import caliban.parsing.adt.Type.NamedType
5 |
6 | sealed trait Selection extends Serializable {
7 | @transient final override lazy val hashCode: Int = super.hashCode()
8 | }
9 |
10 | object Selection {
11 |
12 | case class Field(
13 | alias: Option[String],
14 | name: String,
15 | arguments: Map[String, InputValue],
16 | directives: List[Directive],
17 | selectionSet: List[Selection],
18 | index: Int
19 | ) extends Selection
20 |
21 | case class FragmentSpread(name: String, directives: List[Directive]) extends Selection
22 |
23 | case class InlineFragment(
24 | typeCondition: Option[NamedType],
25 | dirs: List[Directive],
26 | selectionSet: List[Selection]
27 | ) extends Selection
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/parsing/adt/Type.scala:
--------------------------------------------------------------------------------
1 | package caliban.parsing.adt
2 |
3 | import scala.annotation.tailrec
4 |
5 | sealed trait Type extends Serializable { self =>
6 | val nonNull: Boolean
7 |
8 | final def nullable: Boolean = !nonNull
9 |
10 | override def toString: String = self match {
11 | case Type.NamedType(name, nonNull) => if (nonNull) s"$name!" else name
12 | case Type.ListType(ofType, nonNull) => if (nonNull) s"[$ofType]!" else s"[$ofType]"
13 | }
14 |
15 | final def toNullable: Type =
16 | self match {
17 | case Type.NamedType(name, _) => Type.NamedType(name, nonNull = false)
18 | case Type.ListType(ofType, _) => Type.ListType(ofType, nonNull = false)
19 | }
20 |
21 | final def toNonNullable: Type =
22 | self match {
23 | case Type.NamedType(name, _) => Type.NamedType(name, nonNull = true)
24 | case Type.ListType(ofType, _) => Type.ListType(ofType, nonNull = true)
25 | }
26 | }
27 |
28 | object Type {
29 |
30 | case class NamedType(name: String, nonNull: Boolean) extends Type
31 | case class ListType(ofType: Type, nonNull: Boolean) extends Type
32 |
33 | @tailrec
34 | def innerType(t: Type): String = t match {
35 | case NamedType(name, _) => name
36 | case ListType(ofType, _) => innerType(ofType)
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/parsing/adt/VariableDefinition.scala:
--------------------------------------------------------------------------------
1 | package caliban.parsing.adt
2 |
3 | import caliban.InputValue
4 |
5 | case class VariableDefinition(
6 | name: String,
7 | variableType: Type,
8 | defaultValue: Option[InputValue],
9 | directives: List[Directive]
10 | )
11 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/parsing/parsers/NumberParsers.scala:
--------------------------------------------------------------------------------
1 | package caliban.parsing.parsers
2 |
3 | import caliban.Value._
4 | import fastparse._
5 |
6 | private[caliban] trait NumberParsers extends StringParsers {
7 | def negativeSign(implicit ev: P[Any]): P[Unit] = StringIn("-")
8 | def nonZeroDigit(implicit ev: P[Any]): P[Unit] = CharIn("1-9")
9 | def digit(implicit ev: P[Any]): P[Unit] = CharIn("0-9")
10 | def integerPart(implicit ev: P[Any]): P[Unit] =
11 | negativeSign.? ~~ ("0" | (nonZeroDigit ~~ digit.repX))
12 |
13 | def intValue(implicit ev: P[Any]): P[IntValue] = integerPart.!.map(IntValue.fromStringUnsafe)
14 |
15 | def sign(implicit ev: P[Any]): P[Unit] = StringIn("-", "+")
16 | def exponentIndicator(implicit ev: P[Any]): P[Unit] = CharIn("eE")
17 | def exponentPart(implicit ev: P[Any]): P[Unit] = exponentIndicator ~~ sign.? ~~ digit.repX(1)
18 | def fractionalPart(implicit ev: P[Any]): P[Unit] = "." ~~ digit.repX(1)
19 | def floatValue(implicit ev: P[Any]): P[FloatValue] =
20 | (
21 | integerPart ~~ (fractionalPart | exponentPart | (fractionalPart ~~ exponentPart))
22 | ).!.map(FloatValue.fromStringUnsafe)
23 | }
24 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/parsing/parsers/ValueParsers.scala:
--------------------------------------------------------------------------------
1 | package caliban.parsing.parsers
2 |
3 | import caliban.InputValue
4 | import caliban.InputValue._
5 | import caliban.Value._
6 | import fastparse._
7 |
8 | import scala.annotation.nowarn
9 |
10 | @nowarn("msg=NoWhitespace") // False positive warning in Scala 2.12.x
11 | private[caliban] trait ValueParsers extends NumberParsers {
12 | def booleanValue(implicit ev: P[Any]): P[BooleanValue] =
13 | StringIn("true", "false").!.map(v => BooleanValue(v.toBoolean))
14 |
15 | def nullValue(implicit ev: P[Any]): P[InputValue] = LiteralStr("null").map(_ => NullValue)
16 | def enumValue(implicit ev: P[Any]): P[InputValue] = name.map(EnumValue.apply)
17 | def listValue(implicit ev: P[Any]): P[ListValue] = ("[" ~/ value.rep ~ "]").map(values => ListValue(values.toList))
18 |
19 | def objectField(implicit ev: P[Any]): P[(String, InputValue)] = name ~ ":" ~/ value
20 | def objectValue(implicit ev: P[Any]): P[ObjectValue] =
21 | ("{" ~/ objectField.rep ~ "}").map(values => ObjectValue(values.toMap))
22 |
23 | def variableValue(implicit ev: P[Any]): P[VariableValue] = ("$" ~/ name).map(VariableValue.apply)
24 |
25 | def value(implicit ev: P[Any]): P[InputValue] =
26 | floatValue | intValue | booleanValue | stringValue | nullValue | enumValue | listValue | objectValue | variableValue
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/relay/Base64Cursor.scala:
--------------------------------------------------------------------------------
1 | package caliban.relay
2 |
3 | import scala.util.Try
4 |
5 | /**
6 | * A cursor implementation that models an index/offset as an
7 | * opaque base64 cursor.
8 | */
9 | case class Base64Cursor(value: Int)
10 |
11 | object Base64Cursor {
12 | import java.util.Base64
13 | lazy val encoder = Base64.getEncoder()
14 | lazy val decoder = Base64.getDecoder()
15 |
16 | private val prefix = "cursor:"
17 |
18 | implicit val cursor: Cursor[Base64Cursor] = new Cursor[Base64Cursor] {
19 | type T = Int
20 | def encode(a: Base64Cursor): String =
21 | encoder.encodeToString(s"$prefix${a.value}".getBytes("UTF-8"))
22 |
23 | def decode(raw: String): Either[String, Base64Cursor] =
24 | Try({
25 | val bytes = decoder.decode(raw)
26 | val s = new String(bytes, "UTF-8")
27 | if (s.startsWith(prefix)) {
28 | Base64Cursor(s.replaceFirst(prefix, "").toInt)
29 | } else {
30 | throw new Throwable("invalid cursor")
31 | }
32 | }).toEither.left.map(_.getMessage())
33 |
34 | def value(cursor: Base64Cursor): Int = cursor.value
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/relay/Cursor.scala:
--------------------------------------------------------------------------------
1 | package caliban.relay
2 |
3 | /**
4 | * A trait representing an abstract Relay Connection cursor.
5 | */
6 | trait Cursor[A] {
7 | type T
8 | def encode(a: A): String
9 | def decode(s: String): Either[String, A]
10 | def value(cursor: A): T
11 | }
12 |
13 | object Cursor {
14 | def apply[A](implicit c: Cursor[A]): Cursor[A] = c
15 | }
16 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/schema/ObjectFieldResolver.scala:
--------------------------------------------------------------------------------
1 | package caliban.schema
2 |
3 | import caliban.Scala3Annotations.static
4 | import caliban.schema.Step.{ NullStep, ObjectStep }
5 |
6 | import scala.collection.compat._
7 | import scala.collection.mutable
8 |
9 | final private class ObjectFieldResolver[R, A] private (
10 | name: String,
11 | fields: mutable.HashMap[String, A => Step[R]]
12 | ) {
13 | import ObjectFieldResolver._
14 |
15 | private def getFieldStep(value: A): String => Step[R] =
16 | fields.getOrElse(_, NullStepFn0())(value)
17 |
18 | def resolve(value: A): Step[R] = ObjectStep(name, getFieldStep(value))
19 | }
20 |
21 | private object ObjectFieldResolver {
22 | @static private val NullStepFn: Any => Step[Any] = _ => NullStep
23 | @static private val NullStepFn0: () => Any => Step[Any] = () => NullStepFn
24 |
25 | def apply[R, A](objectName: String, fields: Iterable[(String, A => Step[R])]): ObjectFieldResolver[R, A] =
26 | // NOTE: mutable.HashMap is about twice as fast than immutable.HashMap for .get
27 | new ObjectFieldResolver(objectName, mutable.HashMap.from(fields))
28 | }
29 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/schema/Operation.scala:
--------------------------------------------------------------------------------
1 | package caliban.schema
2 |
3 | import caliban.introspection.adt.__Type
4 |
5 | case class Operation[-R](opType: __Type, plan: Step[R]) {
6 | def |+|[R1 <: R](that: Operation[R1]): Operation[R1] =
7 | Operation(opType |+| that.opType, Step.mergeRootSteps(plan, that.plan))
8 | }
9 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/schema/RootSchema.scala:
--------------------------------------------------------------------------------
1 | package caliban.schema
2 |
3 | case class RootSchema[-R](query: Operation[R], mutation: Option[Operation[R]], subscription: Option[Operation[R]])
4 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/schema/RootType.scala:
--------------------------------------------------------------------------------
1 | package caliban.schema
2 |
3 | import caliban.introspection.adt.{ __Directive, __Type }
4 | import caliban.schema.Types.collectTypes
5 |
6 | case class RootType(
7 | queryType: __Type,
8 | mutationType: Option[__Type],
9 | subscriptionType: Option[__Type],
10 | additionalTypes: List[__Type] = List.empty,
11 | additionalDirectives: List[__Directive] = List.empty,
12 | description: Option[String] = None
13 | ) {
14 | private val primitiveTypes: List[__Type] = List(Types.boolean, Types.int, Types.float, Types.string)
15 |
16 | val types: Map[String, __Type] = {
17 | val init = additionalTypes.foldLeft(List.empty[__Type]) { case (acc, t) => collectTypes(t, acc) }
18 | (init ++
19 | primitiveTypes ++
20 | collectTypes(queryType, init) ++
21 | mutationType.fold(List.empty[__Type])(collectTypes(_, init)) ++
22 | subscriptionType.fold(List.empty[__Type])(collectTypes(_, init)))
23 | .groupBy(t => (t.name, t.kind, t.origin))
24 | .flatMap(_._2.headOption)
25 | .map(t => t.name.getOrElse("") -> t)
26 | .toMap
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/schema/SubscriptionSchema.scala:
--------------------------------------------------------------------------------
1 | package caliban.schema
2 |
3 | import zio.stream.ZStream
4 |
5 | /**
6 | * Typeclass used to guarantee that the Subscriptions type is either `Unit` or a case class with `zio.stream.ZStream` for fields.
7 | */
8 | trait SubscriptionSchema[T]
9 |
10 | object SubscriptionSchema extends SubscriptionSchemaDerivation {
11 |
12 | implicit val unitSubscriptionSchema: SubscriptionSchema[Unit] = new SubscriptionSchema[Unit] {}
13 | implicit def streamSubscriptionSchema[R, E, A]: SubscriptionSchema[ZStream[R, E, A]] =
14 | new SubscriptionSchema[ZStream[R, E, A]] {}
15 | implicit def functionSubscriptionSchema[R, E, A, ARG]: SubscriptionSchema[ARG => ZStream[R, E, A]] =
16 | new SubscriptionSchema[ARG => ZStream[R, E, A]] {}
17 | }
18 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/uploads/Uploads.scala:
--------------------------------------------------------------------------------
1 | package caliban.uploads
2 |
3 | import zio.stream.ZStream
4 | import zio.{ Chunk, UIO, ULayer, URIO, ZIO, ZLayer }
5 |
6 | trait Uploads {
7 | def stream(name: String): ZStream[Any, Throwable, Byte]
8 | def file(name: String): ZIO[Any, Nothing, Option[FileMeta]]
9 | }
10 |
11 | object Uploads {
12 | val empty: ULayer[Uploads] =
13 | ZLayer.succeed(new Uploads {
14 | def stream(name: String): ZStream[Any, Throwable, Byte] = ZStream.empty
15 | def file(name: String): UIO[Option[FileMeta]] = ZIO.none
16 | })
17 |
18 | def stream(name: String): ZStream[Uploads, Throwable, Byte] =
19 | ZStream.serviceWithStream(_.stream(name))
20 |
21 | def fileMeta(name: String): URIO[Uploads, Option[FileMeta]] =
22 | ZIO.serviceWithZIO(_.file(name))
23 |
24 | def handler(fileHandle: String => UIO[Option[FileMeta]]): UIO[Uploads] =
25 | ZIO
26 | .succeed(new Uploads {
27 | def stream(name: String): ZStream[Any, Throwable, Byte] =
28 | for {
29 | ref <- ZStream.fromZIOOption(fileHandle(name).some)
30 | bytes <- ZStream.fromChunk(Chunk.fromArray(ref.bytes))
31 | } yield bytes
32 |
33 | def file(name: String): UIO[Option[FileMeta]] =
34 | fileHandle(name)
35 | })
36 | }
37 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/validation/package.scala:
--------------------------------------------------------------------------------
1 | package caliban
2 |
3 | import caliban.parsing.adt.Definition.ExecutableDefinition.{ FragmentDefinition, OperationDefinition }
4 | import caliban.introspection.adt.{ __Field, __Type }
5 | import caliban.parsing.SourceMapper
6 | import caliban.parsing.adt.{ Document, Selection, VariableDefinition }
7 | import caliban.parsing.adt.Selection.Field
8 | import caliban.schema.{ RootType, Types }
9 |
10 | package object validation {
11 | case class SelectedField(
12 | parentType: __Type,
13 | selection: Field,
14 | fieldDef: __Field
15 | ) {
16 | final override lazy val hashCode: Int = super.hashCode()
17 | }
18 |
19 | type FieldMap = Map[String, Set[SelectedField]]
20 |
21 | case class Context(
22 | document: Document,
23 | rootType: RootType,
24 | operations: List[OperationDefinition],
25 | fragments: Map[String, FragmentDefinition],
26 | selectionSets: List[Selection],
27 | variables: Map[String, InputValue]
28 | ) {
29 | lazy val variableDefinitions: Map[String, VariableDefinition] =
30 | operations.flatMap(_.variableDefinitions.map(d => d.name -> d)).toMap
31 | }
32 |
33 | object Context {
34 | val empty: Context =
35 | Context(Document(Nil, SourceMapper.empty), RootType(Types.boolean, None, None), Nil, Map.empty, Nil, Map.empty)
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/wrappers/DeferSupport.scala:
--------------------------------------------------------------------------------
1 | package caliban.wrappers
2 |
3 | import caliban.GraphQLAspect
4 | import caliban.execution.Feature
5 | import caliban.introspection.adt.__Directive
6 |
7 | object DeferSupport {
8 | @deprecated("Use Feature.Defer.directives instead", "2.9.0")
9 | private[caliban] val deferDirective: __Directive = Feature.Defer.directives.head
10 |
11 | @deprecated("Use IncrementalDelivery.defer instead", "2.9.0")
12 | val defer: GraphQLAspect[Nothing, Any] = IncrementalDelivery.defer
13 | }
14 |
--------------------------------------------------------------------------------
/core/src/main/scala/caliban/ws/package.scala:
--------------------------------------------------------------------------------
1 | package caliban
2 |
3 | import zio.stream.Stream
4 |
5 | package object ws {
6 | type Pipe[A, B] = Stream[Throwable, A] => Stream[Throwable, B]
7 | type CalibanPipe = Pipe[GraphQLWSInput, Either[GraphQLWSClose, GraphQLWSOutput]]
8 | }
9 |
--------------------------------------------------------------------------------
/core/src/test/resources/document-tests/kitchen-sink-compact.graphql:
--------------------------------------------------------------------------------
1 | directive @mydirective(input:MyDirectiveInput!) on SCHEMA directive @key(fields:String!) on OBJECT|INTERFACE directive @shareable on UNION directive @tag on OBJECT|FIELD_DEFINITION|INTERFACE|UNION|ENUM|INPUT_OBJECT schema@mydirective(input:{name:"test"}){query:Query,mutation:Mutation,subscription:Subscription} union Event@shareable=AgeChanged|NameChanged|RegistrationChanged input MyDirectiveInput{name:String!} input MyInput{name:String! age:Int=18 registered:Boolean friends:[String]!}interface Node{id:ID!@deprecated(reason:"Use `uuid` instead")}interface User@tag{name:String! age:Int! registered:Boolean! friends:[User!]! bestFriend:User friendsCount:Int!}type AgeChanged{age:Int!}type Me implements User & Node@key(fields:"id"){id:ID! name:String! age:Int! registered:Boolean! friends:[User!]! bestFriend:User friendsCount:Int!}type Mutation@tag{goodbye(input:MyInput!={name:"test"}@deprecated(reason:"Bad")):String@tag}type NameChanged{name:String!}type Query{hello(name:String!=" world",after:Int):User!}type RegistrationChanged{registered:Boolean!}type Subscription{event:Event!}
--------------------------------------------------------------------------------
/core/src/test/resources/document-tests/kitchen-sink-query.graphql:
--------------------------------------------------------------------------------
1 | query {
2 | id
3 | name
4 | }
5 |
6 | mutation {
7 | thatThing
8 | thatThingWithArgs(input: {id: 1, name: "test"}) {
9 | id
10 | name
11 | }
12 | }
13 |
14 | mutation WithArgs($args: InputType!) {
15 | thatThingWithArgs(input: $args) {
16 | id @include(if: false)
17 | name
18 | ... on SomeType @skip(if: true) {
19 | someField
20 | }
21 | ...SomeTypeFragment
22 | }
23 | }
24 |
25 | subscription {
26 | event {
27 | id
28 | name
29 | }
30 | }
31 |
32 | fragment SomeTypeFragment on SomeType {
33 | someField
34 | }
--------------------------------------------------------------------------------
/core/src/test/resources/document-tests/query-compact.graphql:
--------------------------------------------------------------------------------
1 | query Hello($name:String!){hello(name:$name,inline:{age:42})@skip(if:true){message ...on Hello{message} ...FragmentHello}} fragment FragmentHello on Hello{test}
--------------------------------------------------------------------------------
/core/src/test/scala-2/caliban/schema/ArgBuilderScala2Spec.scala:
--------------------------------------------------------------------------------
1 | package caliban.schema
2 |
3 | import caliban.Value.StringValue
4 | import caliban.schema.ArgBuilder.auto._
5 | import zio.test.Assertion._
6 | import zio.test._
7 |
8 | import java.util.UUID
9 |
10 | object ArgBuilderScala2Spec extends ZIOSpecDefault {
11 | def spec = suite("ArgBuilderScala2")(
12 | suite("AnyVal") {
13 | test("ArgBuilder that extends AnyVal") {
14 | val id = UUID.randomUUID()
15 | val value = ArgBuilder[UUIDId].build(StringValue(id.toString))
16 | assert(value)(isRight(equalTo(UUIDId(id))))
17 | }
18 | }
19 | )
20 |
21 | trait Ids[T] extends Any {
22 | self: AnyVal =>
23 | def value: T
24 | }
25 |
26 | final case class UUIDId(value: UUID) extends AnyVal with Ids[UUID]
27 | }
28 |
--------------------------------------------------------------------------------
/core/src/test/scala-2/caliban/validation/InputArgumentSpecInterop.scala:
--------------------------------------------------------------------------------
1 | package caliban.validation
2 |
3 | object InputArgumentSpecInterop {
4 | import InputArgumentSpec._
5 |
6 | case class Query(
7 | bool: BoolArg => String = _ => "result",
8 | boolNonNull: BoolArgNonNull => String = _ => "result",
9 | float: FloatArg => String = _ => "result",
10 | int: IntArg => String = _ => "result",
11 | list: ListArg => String = _ => "result",
12 | listInt: ListIntArg => Option[List[Option[Int]]] = _.input,
13 | listListInt: ListListIntArg => Option[List[Option[List[Option[Int]]]]] = _.input,
14 | string: StringArg => String = _ => "result",
15 | `enum`: EnumArg => String = _ => "result",
16 | input: InputArg => String = _ => "result",
17 | exampleObject: ExampleObjectArg => Option[ExampleObject] = _.input
18 | )
19 | }
20 |
--------------------------------------------------------------------------------
/core/src/test/scala-3/caliban/schema/ExcludedFieldSpec.scala:
--------------------------------------------------------------------------------
1 | package caliban.schema
2 |
3 | import caliban.schema.Annotations.GQLExcluded
4 |
5 | /** Compile-time "test", which ensures that we don't need to define a schema for fields annotated with @GQLExcluded */
6 | object ExcludedFieldSpec {
7 | final case class Foo(value: String)
8 | final case class Bar(value: String, @GQLExcluded foo: Foo, num: Int)
9 |
10 | given Schema[Any, Bar] = Schema.derived
11 | }
12 |
--------------------------------------------------------------------------------
/core/src/test/scala-3/caliban/validation/InputArgumentSpecInterop.scala:
--------------------------------------------------------------------------------
1 | package caliban.validation
2 |
3 | object InputArgumentSpecInterop {
4 | import InputArgumentSpec._
5 |
6 | case class Query(
7 | bool: BoolArg => String = _ => "result",
8 | boolNonNull: BoolArgNonNull => String = _ => "result",
9 | float: FloatArg => String = _ => "result",
10 | int: IntArg => String = _ => "result",
11 | list: ListArg => String = _ => "result",
12 | listInt: ListIntArg => Option[List[Option[Int]]] = _.input,
13 | // does not compile on Scala 3
14 | // listListInt: ListListIntArg => Option[List[Option[List[Option[Int]]]]] = _.input,
15 | string: StringArg => String = _ => "result",
16 | `enum`: EnumArg => String = _ => "result",
17 | input: InputArg => String = _ => "result",
18 | exampleObject: ExampleObjectArg => Option[ExampleObject] = _.input
19 | )
20 | }
21 |
--------------------------------------------------------------------------------
/core/src/test/scala/caliban/FragmentSchema.scala:
--------------------------------------------------------------------------------
1 | package caliban
2 |
3 | import caliban.schema.Annotations._
4 |
5 | object FragmentSchema {
6 |
7 | @GQLDescription("Queries")
8 | case class Query(
9 | bar: Option[Bar],
10 | foo: List[Foo]
11 | )
12 |
13 | case class Foo(
14 | id: String
15 | )
16 | case class Bar(
17 | id: String,
18 | baz: Option[Baz]
19 | )
20 |
21 | case class Baz(
22 | id: String,
23 | foo: Option[Foo]
24 | )
25 |
26 | val resolverFooBar: RootResolver[Query, Unit, Unit] = RootResolver(
27 | Query(
28 | bar = Some(Bar("1", Some(Baz("2", Some(Foo("3")))))),
29 | foo = List(Foo("1"), Foo("2"))
30 | )
31 | )
32 | }
33 |
--------------------------------------------------------------------------------
/core/src/test/scala/caliban/RenderingSpecSchema.scala:
--------------------------------------------------------------------------------
1 | package caliban
2 |
3 | import caliban.schema.Annotations.GQLDescription
4 |
5 | object RenderingSpecSchema {
6 |
7 | case class UserTest(name: String, @GQLDescription("field-description") age: Int)
8 | case class UserComplex(id: Int, user: UserTest)
9 |
10 | case class UserParams(nameLike: String, @GQLDescription("is user active currently") active: Boolean)
11 |
12 | case class QueryTest(allUsers: () => List[UserTest])
13 | case class MutationTest(
14 | id: UserComplex => Boolean,
15 | fetch: UserParams => Boolean
16 | )
17 |
18 | val resolverSchema = RootResolver(
19 | QueryTest(() => List()),
20 | MutationTest(c => true, params => true)
21 | )
22 | }
23 |
--------------------------------------------------------------------------------
/core/src/test/scala/caliban/interop/jsoniter/GraphQLWSInputJsoniterSpec.scala:
--------------------------------------------------------------------------------
1 | package caliban.interop.jsoniter
2 |
3 | import caliban.{ GraphQLWSInput, InputValue, TestUtils, Value }
4 | import com.github.plokhotnyuk.jsoniter_scala.core._
5 | import zio.test.Assertion.equalTo
6 | import zio.test.{ assert, assertTrue, ZIOSpecDefault }
7 |
8 | object GraphQLWSInputJsoniterSpec extends ZIOSpecDefault {
9 | override def spec =
10 | suite("GraphQLWSInputJsoniterSpec")(
11 | test("can be parsed from JSON by jsoniter") {
12 | val request =
13 | """{"id":"id","type":"some type","payload":{"field":"yo"}}"""
14 |
15 | val res = readFromString[GraphQLWSInput](request)
16 | assert(res)(
17 | equalTo(
18 | GraphQLWSInput(
19 | `type` = "some type",
20 | id = Some("id"),
21 | payload = Some(InputValue.ObjectValue(Map("field" -> Value.StringValue("yo"))))
22 | )
23 | )
24 | )
25 | },
26 | test("can encode to JSON by jsoniter") {
27 | val res = GraphQLWSInput(
28 | `type` = "some type",
29 | id = Some("id"),
30 | payload = Some(InputValue.ObjectValue(Map("field" -> Value.StringValue("yo"))))
31 | )
32 |
33 | assertTrue(writeToString(res) == """{"type":"some type","id":"id","payload":{"field":"yo"}}""")
34 | }
35 | )
36 | }
37 |
--------------------------------------------------------------------------------
/core/src/test/scala/caliban/interop/jsoniter/GraphQLWSOutputJsoniterSpec.scala:
--------------------------------------------------------------------------------
1 | package caliban.interop.jsoniter
2 |
3 | import caliban.{ GraphQLWSOutput, ResponseValue, TestUtils, Value }
4 | import com.github.plokhotnyuk.jsoniter_scala.core._
5 | import zio.test.Assertion.equalTo
6 | import zio.test.{ assert, assertTrue, ZIOSpecDefault }
7 |
8 | object GraphQLWSOutputJsoniterSpec extends ZIOSpecDefault {
9 | override def spec =
10 | suite("GraphQLWSOutputJsoniter")(
11 | test("can be parsed from JSON by jsoniter") {
12 | val request =
13 | """{"id":"id","type":"some type","payload":{"field":"yo"}}"""
14 |
15 | val res = readFromString[GraphQLWSOutput](request)
16 | assert(res)(
17 | equalTo(
18 | GraphQLWSOutput(
19 | `type` = "some type",
20 | id = Some("id"),
21 | payload = Some(ResponseValue.ObjectValue(List("field" -> Value.StringValue("yo"))))
22 | )
23 | )
24 | )
25 | },
26 | test("can encode to JSON by jsoniter") {
27 | val res = GraphQLWSOutput(
28 | `type` = "some type",
29 | id = Some("id"),
30 | payload = Some(ResponseValue.ObjectValue(List("field" -> Value.StringValue("yo"))))
31 | )
32 |
33 | assertTrue(writeToString(res) == """{"type":"some type","id":"id","payload":{"field":"yo"}}""")
34 | }
35 | )
36 | }
37 |
--------------------------------------------------------------------------------
/core/src/test/scala/caliban/parsing/DocumentSpec.scala:
--------------------------------------------------------------------------------
1 | package caliban.parsing
2 |
3 | import caliban.TestUtils
4 | import org.apache.commons.lang3.SerializationUtils
5 | import zio.test._
6 |
7 | object DocumentSpec extends ZIOSpecDefault {
8 | def spec = suite("DocumentSpec")(
9 | test("is serializable") {
10 | for {
11 | doc1 <- Parser.parseQuery(TestUtils.introspectionQuery)
12 | doc2 = SerializationUtils.roundtrip(doc1)
13 | } yield assertTrue(doc1 == doc2)
14 | }
15 | )
16 | }
17 |
--------------------------------------------------------------------------------
/core/src/test/scala/caliban/parsing/SourceMapperSpec.scala:
--------------------------------------------------------------------------------
1 | package caliban.parsing
2 |
3 | import caliban.parsing.adt.LocationInfo
4 | import zio.test._
5 |
6 | object SourceMapperSpec extends ZIOSpecDefault {
7 |
8 | override def spec =
9 | suite("SourceMapper")(
10 | test("should not throw IndexOutOfBounds") {
11 | assertTrue(SourceMapper("").getLocation(100) == LocationInfo(101, 1))
12 | },
13 | test("should map correctly to the source location") {
14 | val sm = SourceMapper("""
15 | |a
16 | |b
17 | |""".stripMargin)
18 | assertTrue(sm.getLocation(3) == LocationInfo(1, 3))
19 | }
20 | )
21 | }
22 |
--------------------------------------------------------------------------------
/docs/.nojekyll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ghostdogpr/caliban/24a568744f6708a4f400d7f8f5f158b002f29806/docs/.nojekyll
--------------------------------------------------------------------------------
/docs/assets/img/search.83621669.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/assets/js/19.2a696a53.js:
--------------------------------------------------------------------------------
1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[19],{271:function(t,e,n){},273:function(t,e,n){"use strict";n.r(e);var s={name:"DropdownTransition",methods:{setHeight(t){t.style.height=t.scrollHeight+"px"},unsetHeight(t){t.style.height=""}}},i=(n(274),n(25)),o=Object(i.a)(s,(function(){return(0,this._self._c)("transition",{attrs:{name:"dropdown"},on:{enter:this.setHeight,"after-enter":this.unsetHeight,"before-leave":this.setHeight}},[this._t("default")],2)}),[],!1,null,null,null);e.default=o.exports},274:function(t,e,n){"use strict";n(271)}}]);
--------------------------------------------------------------------------------
/docs/assets/js/20.89f58454.js:
--------------------------------------------------------------------------------
1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[20],{289:function(t,c,n){},301:function(t,c,n){"use strict";n(289)},314:function(t,c,n){"use strict";n.r(c);n(301);var i=n(25),s=Object(i.a)({},(function(){var t=this,c=t._self._c;return c("div",{staticClass:"sidebar-button",on:{click:function(c){return t.$emit("toggle-sidebar")}}},[c("svg",{staticClass:"icon",attrs:{xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",role:"img",viewBox:"0 0 448 512"}},[c("path",{attrs:{fill:"currentColor",d:"M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"}})])])}),[],!1,null,null,null);c.default=s.exports}}]);
--------------------------------------------------------------------------------
/docs/assets/js/22.723716f0.js:
--------------------------------------------------------------------------------
1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[22],{333:function(t,n,s){"use strict";s.r(n);var e=s(25),o=Object(e.a)({},(function(){return(0,this._self._c)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);n.default=o.exports}}]);
--------------------------------------------------------------------------------
/docs/assets/js/4.119e5097.js:
--------------------------------------------------------------------------------
1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[4],{308:function(t,e,n){},321:function(t,e,n){"use strict";n(308)},332:function(t,e,n){"use strict";n.r(e);var i={functional:!0,props:{type:{type:String,default:"tip"},text:String,vertical:{type:String,default:"top"}},render:(t,{props:e,slots:n})=>t("span",{class:["badge",e.type],style:{verticalAlign:e.vertical}},e.text||n().default)},p=(n(321),n(25)),l=Object(p.a)(i,void 0,void 0,!1,null,"15b7b770",null);e.default=l.exports}}]);
--------------------------------------------------------------------------------
/docs/assets/js/5.635a7794.js:
--------------------------------------------------------------------------------
1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[5],{309:function(t,e,a){},322:function(t,e,a){"use strict";a(309)},328:function(t,e,a){"use strict";a.r(e);var s={name:"CodeBlock",props:{title:{type:String,required:!0},active:{type:Boolean,default:!1}},mounted(){this.$parent&&this.$parent.loadTabs&&this.$parent.loadTabs()}},i=(a(322),a(25)),n=Object(i.a)(s,(function(){return(0,this._self._c)("div",{staticClass:"theme-code-block",class:{"theme-code-block__active":this.active}},[this._t("default")],2)}),[],!1,null,"759a7d02",null);e.default=n.exports}}]);
--------------------------------------------------------------------------------
/docs/assets/js/7.442dabf9.js:
--------------------------------------------------------------------------------
1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[7],{330:function(t,e,s){"use strict";s.r(e);const o=["There's nothing here.","How did we get here?","That's a Four-Oh-Four.","Looks like we've got some broken links."];var n={methods:{getMsg:()=>o[Math.floor(Math.random()*o.length)]}},h=s(25),i=Object(h.a)(n,(function(){var t=this._self._c;return t("div",{staticClass:"theme-container"},[t("div",{staticClass:"theme-default-content"},[t("h1",[this._v("404")]),this._v(" "),t("blockquote",[this._v(this._s(this.getMsg()))]),this._v(" "),t("RouterLink",{attrs:{to:"/"}},[this._v("\n Take me home.\n ")])],1)])}),[],!1,null,null,null);e.default=i.exports}}]);
--------------------------------------------------------------------------------
/docs/caliban.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ghostdogpr/caliban/24a568744f6708a4f400d7f8f5f158b002f29806/docs/caliban.png
--------------------------------------------------------------------------------
/examples/src/main/resources/application.conf:
--------------------------------------------------------------------------------
1 | # Used by the Play example
--------------------------------------------------------------------------------
/examples/src/main/resources/gateway/gateway.js:
--------------------------------------------------------------------------------
1 | const {ApolloServer} = require('apollo-server');
2 | const {ApolloGateway} = require('@apollo/gateway');
3 |
4 | const gateway = new ApolloGateway({
5 | serviceList: [
6 | { name: 'episodes', url: 'http://localhost:8088/api/graphql'},
7 | { name: 'characters', url: 'http://localhost:8089/api/graphql' }
8 | ],
9 | debug: true
10 | });
11 |
12 | (async () => {
13 | const server = new ApolloServer({
14 | gateway,
15 | subscriptions: false
16 | });
17 |
18 | server.listen().then(({url}) => {
19 | console.log(`🚀 Server ready at ${url}`)
20 | })
21 | })();
--------------------------------------------------------------------------------
/examples/src/main/resources/gateway/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "federated-gateway",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "gateway.js",
6 | "scripts": {
7 | "start": "node gateway.js"
8 | },
9 | "keywords": [],
10 | "license": "MIT",
11 | "dependencies": {
12 | "apollo-server": "3.6.7",
13 | "@apollo/gateway": "~0.50.1",
14 | "graphql": "15.8.0"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/examples/src/main/resources/gateway_v2/gateway.js:
--------------------------------------------------------------------------------
1 | import { ApolloServer } from '@apollo/server';
2 | import { ApolloServerPluginInlineTrace } from '@apollo/server/plugin/inlineTrace'
3 | import { ApolloGateway, IntrospectAndCompose } from '@apollo/gateway';
4 | import {startStandaloneServer} from "@apollo/server/standalone";
5 |
6 | const gateway = new ApolloGateway({
7 | supergraphSdl: new IntrospectAndCompose({
8 | subgraphs: [
9 | { name: 'episodes', url: 'http://localhost:8088/api/graphql'},
10 | { name: 'characters', url: 'http://localhost:8089/api/graphql' }
11 | ]
12 | }),
13 | debug: true
14 | });
15 |
16 | (async () => {
17 | const server = new ApolloServer({
18 | gateway,
19 | subscriptions: false,
20 | plugins: [
21 | ApolloServerPluginInlineTrace()
22 | ]
23 | });
24 |
25 | const { url } = await startStandaloneServer(server, {
26 | listen: { port: 4000 }
27 | })
28 |
29 | console.log(`🚀 Server ready at ${url}`)
30 | })();
--------------------------------------------------------------------------------
/examples/src/main/resources/gateway_v2/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "federated-gateway",
3 | "version": "1.0.0",
4 | "description": "",
5 | "type": "module",
6 | "main": "gateway.js",
7 | "scripts": {
8 | "start": "node gateway.js"
9 | },
10 | "keywords": [],
11 | "license": "MIT",
12 | "dependencies": {
13 | "@apollo/gateway": "2.8.0",
14 | "@apollo/server": "4.10.4",
15 | "graphql": "16.8.1"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/examples/src/main/scala/example/ExampleData.scala:
--------------------------------------------------------------------------------
1 | package example
2 |
3 | import example.ExampleData.Origin.{ BELT, EARTH, MARS }
4 | import example.ExampleData.Role.{ Captain, Engineer, Mechanic, Pilot }
5 |
6 | object ExampleData {
7 |
8 | sealed trait Origin
9 |
10 | object Origin {
11 | case object EARTH extends Origin
12 | case object MARS extends Origin
13 | case object BELT extends Origin
14 | }
15 |
16 | sealed trait Role
17 |
18 | object Role {
19 | case class Captain(shipName: String) extends Role
20 | case class Pilot(shipName: String) extends Role
21 | case class Engineer(shipName: String) extends Role
22 | case class Mechanic(shipName: String) extends Role
23 | }
24 |
25 | case class Character(name: String, nicknames: List[String], origin: Origin, role: Option[Role])
26 |
27 | case class CharactersArgs(origin: Option[Origin])
28 | case class CharacterArgs(name: String)
29 |
30 | val sampleCharacters = List(
31 | Character("James Holden", List("Jim", "Hoss"), EARTH, Some(Captain("Rocinante"))),
32 | Character("Naomi Nagata", Nil, BELT, Some(Engineer("Rocinante"))),
33 | Character("Amos Burton", Nil, EARTH, Some(Mechanic("Rocinante"))),
34 | Character("Alex Kamal", Nil, MARS, Some(Pilot("Rocinante"))),
35 | Character("Chrisjen Avasarala", Nil, EARTH, None),
36 | Character("Josephus Miller", List("Joe"), BELT, None),
37 | Character("Roberta Draper", List("Bobbie", "Gunny"), MARS, None)
38 | )
39 | }
40 |
--------------------------------------------------------------------------------
/examples/src/main/scala/example/calibantotapir/README.md:
--------------------------------------------------------------------------------
1 | # Caliban to Tapir
2 |
3 | This example shows how to convert the Caliban `GraphQL` datatype and turn them into Tapir `Endpoint`s.
4 | This is useful when you have both REST APIs and GraphQL endpoints and you want to use Tapir to expose a unified API.
5 |
6 | The example also shows how to mount the GraphQL endpoint to `POST /graphql` and `GET /graphql`, the GraphiQL UI (`GET` `/graphiql`), as well as provide `GET /example` for a sample endpoint returning JSON.
7 | All of the endpoints are documented in Swagger. Visiting `localhost:8080/` or `/docs` will show the Swagger UI.
8 |
9 | This example interprets the Tapir endpoints using ZIO HTTP.
10 |
11 | **Note:** If you are only using GraphQL endpoints, then you are much better of using the `quick` adapter instead of this. This example is provided for when you want to use both GraphQL and REST endpoints and have them managed by Tapir to gain the benefits of documentation.
--------------------------------------------------------------------------------
/examples/src/main/scala/example/calibantotapir/tapir/SampleRestEndpoint.scala:
--------------------------------------------------------------------------------
1 | package example.calibantotapir.tapir
2 |
3 | import com.github.plokhotnyuk.jsoniter_scala.core.JsonValueCodec
4 | import com.github.plokhotnyuk.jsoniter_scala.macros.JsonCodecMaker
5 | import sttp.capabilities.zio.ZioStreams
6 | import sttp.tapir.Schema
7 | import sttp.tapir.json.jsoniter._
8 | import sttp.tapir.ztapir._
9 | import zio._
10 |
11 | object SampleRestEndpoint {
12 | // NOTE: You can also add the graphiql endpoint in a similar fashion
13 | val endpoint: ZServerEndpoint[Any, ZioStreams] =
14 | infallibleEndpoint.get
15 | .in("example")
16 | .out(jsonBody[SampleResponse])
17 | .serverLogic(_ => ZIO.right(SampleResponse("Hello", 1, 2)))
18 |
19 | final case class SampleResponse(data: String, x: Int, y: Int)
20 | object SampleResponse {
21 | implicit val sampleResponseCodec: JsonValueCodec[SampleResponse] = JsonCodecMaker.make
22 | implicit val sampleResponseSchema: Schema[SampleResponse] = Schema.derived
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/examples/src/main/scala/example/federation/EpisodeService.scala:
--------------------------------------------------------------------------------
1 | package example.federation
2 |
3 | import example.federation.FederationData.episodes.Episode
4 |
5 | import zio.{ Ref, UIO, URIO, ZIO, ZLayer }
6 |
7 | trait EpisodeService {
8 | def getEpisode(season: Int, episode: Int): UIO[Option[Episode]]
9 | def getEpisodes(season: Option[Int]): UIO[List[Episode]]
10 | }
11 |
12 | object EpisodeService {
13 | def getEpisode(season: Int, episode: Int): URIO[EpisodeService, Option[Episode]] =
14 | ZIO.serviceWithZIO[EpisodeService](_.getEpisode(season, episode))
15 |
16 | def getEpisodes(season: Option[Int] = None): URIO[EpisodeService, List[Episode]] =
17 | ZIO.serviceWithZIO[EpisodeService](_.getEpisodes(season))
18 |
19 | def make(initial: List[Episode]): ZLayer[Any, Nothing, EpisodeService] = ZLayer {
20 | Ref
21 | .make(initial)
22 | .map { episodes =>
23 | new EpisodeService {
24 | def getEpisode(season: Int, episode: Int): UIO[Option[Episode]] =
25 | episodes.get.map(_.find(e => e.season == season && e.episode == episode))
26 |
27 | def getEpisodes(season: Option[Int]): UIO[List[Episode]] =
28 | episodes.get.map(_.filter(e => season.forall(_ == e.season)))
29 | }
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/examples/src/main/scala/example/federation/FederatedApp.scala:
--------------------------------------------------------------------------------
1 | package example.federation
2 |
3 | import caliban.quick._
4 | import example.federation.FederationData.characters.sampleCharacters
5 | import example.federation.FederationData.episodes.sampleEpisodes
6 | import zio._
7 |
8 | object FederatedApp extends ZIOAppDefault {
9 |
10 | val episodesApi = FederatedApi.Episodes.api.runServer(8089, "/api/graphql", Some("/graphiql"))
11 | val charactersApi = FederatedApi.Characters.api.runServer(8088, "/api/graphql", Some("/graphiql"))
12 |
13 | override def run =
14 | (episodesApi zipPar charactersApi)
15 | .provide(
16 | EpisodeService.make(sampleEpisodes),
17 | CharacterService.make(sampleCharacters)
18 | )
19 | }
20 |
--------------------------------------------------------------------------------
/examples/src/main/scala/example/federation/v2/EpisodeService.scala:
--------------------------------------------------------------------------------
1 | package example.federation.v2
2 |
3 | import example.federation.v2.FederationData.episodes.Episode
4 | import zio.{ Ref, UIO, URIO, ZIO, ZLayer }
5 |
6 | trait EpisodeService {
7 | def getEpisode(season: Int, episode: Int): UIO[Option[Episode]]
8 | def getEpisodes(season: Option[Int]): UIO[List[Episode]]
9 | }
10 |
11 | object EpisodeService {
12 |
13 | def getEpisode(season: Int, episode: Int): URIO[EpisodeService, Option[Episode]] =
14 | ZIO.serviceWithZIO[EpisodeService](_.getEpisode(season, episode))
15 |
16 | def getEpisodes(season: Option[Int] = None): URIO[EpisodeService, List[Episode]] =
17 | ZIO.serviceWithZIO[EpisodeService](_.getEpisodes(season))
18 |
19 | def make(initial: List[Episode]): ZLayer[Any, Nothing, EpisodeService] = ZLayer {
20 | Ref
21 | .make(initial)
22 | .map { episodes =>
23 | new EpisodeService {
24 | override def getEpisode(season: Int, episode: Int): UIO[Option[Episode]] =
25 | episodes.get.map(_.find(e => e.season == season && e.episode == episode))
26 |
27 | override def getEpisodes(season: Option[Int]): UIO[List[Episode]] =
28 | episodes.get.map(_.filter(e => season.forall(_ == e.season)))
29 | }
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/examples/src/main/scala/example/federation/v2/FederatedApp.scala:
--------------------------------------------------------------------------------
1 | package example.federation.v2
2 |
3 | import caliban.quick._
4 | import example.federation.v2.FederationData.characters.sampleCharacters
5 | import example.federation.v2.FederationData.episodes.sampleEpisodes
6 | import zio._
7 |
8 | object FederatedApp extends ZIOAppDefault {
9 |
10 | val characterServer =
11 | FederatedApi.Characters.api.runServer(8088, "/api/graphql")
12 |
13 | val episodeServer =
14 | FederatedApi.Episodes.api.runServer(8089, "/api/graphql")
15 |
16 | def run =
17 | (characterServer race episodeServer)
18 | .provide(EpisodeService.make(sampleEpisodes), CharacterService.make(sampleCharacters))
19 | }
20 |
--------------------------------------------------------------------------------
/examples/src/main/scala/example/optimizations/CommonData.scala:
--------------------------------------------------------------------------------
1 | package example.optimizations
2 |
3 | object CommonData {
4 | case class UserArgs(id: Int)
5 | case class FirstArgs(first: Int)
6 | case class SizeArgs(size: Int)
7 |
8 | case class ViewerMetadata(name: String)
9 | case class Tag(name: String)
10 | case class Venue(name: String)
11 |
12 | val query: String =
13 | """
14 | |query UserEventsScreen {
15 | | user(id: 1) {
16 | | fullName
17 | | username
18 | | picture(size: 50)
19 | | upcomingEvents(first: 5) {
20 | | id
21 | | name
22 | | date
23 | | startTime
24 | | endTime
25 | | viewerRsvp {
26 | | name
27 | | }
28 | | tags {
29 | | name
30 | | }
31 | | venue {
32 | | name
33 | | }
34 | | attendingFriendsOfViewer(first: 4) {
35 | | picture(size: 25)
36 | | }
37 | | }
38 | | }
39 | |}""".stripMargin
40 | }
41 |
--------------------------------------------------------------------------------
/examples/src/main/scala/example/quick/ExampleApp.scala:
--------------------------------------------------------------------------------
1 | package example.quick
2 |
3 | import caliban._
4 | import caliban.quick._
5 | import example.ExampleData._
6 | import example.{ ExampleApi, ExampleService }
7 | import zio._
8 |
9 | object ExampleApp extends ZIOAppDefault {
10 |
11 | // Only as a convenience of shutting down the server via CLI, don't add to production code!
12 | private val cliShutdownSignal =
13 | Console.printLine("Server online at http://localhost:8090/") *>
14 | Console.printLine("Press RETURN to stop...") *>
15 | Console.readLine.unit
16 |
17 | private val serve =
18 | ZIO
19 | .serviceWithZIO[GraphQL[Any]] {
20 | _.runServer(
21 | port = 8090,
22 | apiPath = "/api/graphql",
23 | graphiqlPath = Some("/graphiql"),
24 | webSocketPath = Some("/ws/graphql")
25 | )
26 | }
27 | .provide(
28 | ExampleService.make(sampleCharacters),
29 | ExampleApi.layer
30 | )
31 |
32 | override def run: ZIO[Any, Throwable, Unit] = serve race cliShutdownSignal
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/examples/src/main/scala/example/tapirtocaliban/README.md:
--------------------------------------------------------------------------------
1 | # Tapir to Caliban
2 |
3 | This example shows how you can take Tapir endpoints and turn them into Caliban GraphQL datatypes.
--------------------------------------------------------------------------------
/federation/src/main/scala/caliban/federation/FederationDirectives.scala:
--------------------------------------------------------------------------------
1 | package caliban.federation
2 |
3 | import caliban.InputValue
4 | import caliban.Value.{ BooleanValue, StringValue }
5 | import caliban.parsing.adt.Directive
6 | import caliban.schema.Annotations.GQLDirective
7 |
8 | trait FederationDirectives {
9 | case class GQLProvides(fields: String) extends GQLDirective(Provides(fields))
10 |
11 | object Provides {
12 | def apply(fields: String): Directive =
13 | Directive("provides", Map("fields" -> StringValue(fields)))
14 | }
15 |
16 | case class GQLRequires(fields: String) extends GQLDirective(Requires(fields))
17 |
18 | object Requires {
19 | def apply(fields: String): Directive =
20 | Directive("requires", Map("fields" -> StringValue(fields)))
21 | }
22 |
23 | case class GQLExtend() extends GQLDirective(Extend)
24 |
25 | val Extend = Directive("extends")
26 |
27 | case class GQLExternal() extends GQLDirective(External)
28 |
29 | val External = Directive("external")
30 |
31 | case class GQLKey(fields: String, resolvable: Boolean = true) extends GQLDirective(Key(fields, resolvable))
32 |
33 | object Key {
34 | def apply(fields: String, resolvable: Boolean = true, name: String = "key"): Directive = {
35 | val args: List[(String, InputValue)] = List(
36 | Some("fields" -> StringValue(fields)),
37 | (if (resolvable) None else Some("resolvable" -> BooleanValue(resolvable)))
38 | ).flatten
39 |
40 | Directive(name, args.toMap)
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/federation/src/main/scala/caliban/federation/package.scala:
--------------------------------------------------------------------------------
1 | package caliban
2 |
3 | import caliban.federation.v2x.{
4 | FederationDirectivesV2_10,
5 | FederationDirectivesV2_3,
6 | FederationDirectivesV2_5,
7 | FederationDirectivesV2_6,
8 | FederationDirectivesV2_8,
9 | FederationDirectivesV2_9,
10 | FederationV2,
11 | Versions
12 | }
13 |
14 | package object federation {
15 |
16 | lazy val v1 = new FederationV1 with FederationDirectives
17 | lazy val v2_0 = new FederationV2(List(Versions.v2_0))
18 | lazy val v2_1 = new FederationV2(List(Versions.v2_1))
19 | lazy val v2_3 = new FederationV2(List(Versions.v2_3)) with FederationDirectivesV2_3
20 | lazy val v2_4 = new FederationV2(List(Versions.v2_4)) with FederationDirectivesV2_3
21 | lazy val v2_5 = new FederationV2(List(Versions.v2_5)) with FederationDirectivesV2_5
22 | lazy val v2_6 = new FederationV2(List(Versions.v2_6)) with FederationDirectivesV2_6
23 | lazy val v2_7 = new FederationV2(List(Versions.v2_7)) with FederationDirectivesV2_6
24 | lazy val v2_8 = new FederationV2(List(Versions.v2_8)) with FederationDirectivesV2_8
25 | lazy val v2_9 = new FederationV2(List(Versions.v2_9)) with FederationDirectivesV2_9
26 | lazy val v2_10 = new FederationV2(List(Versions.v2_10, FederationV2.connect)) with FederationDirectivesV2_10
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/federation/src/main/scala/caliban/federation/v2x/FederationDirectivesV2.scala:
--------------------------------------------------------------------------------
1 | package caliban.federation.v2x
2 |
3 | import caliban.Value.StringValue
4 | import caliban.parsing.adt.Directive
5 | import caliban.schema.Annotations.GQLDirective
6 |
7 | trait FederationDirectivesV2 {
8 | case class GQLShareable() extends GQLDirective(Shareable)
9 |
10 | val Shareable = Directive("shareable")
11 |
12 | case class GQLInaccessible() extends GQLDirective(Inaccessible)
13 |
14 | val Inaccessible = Directive("inaccessible")
15 |
16 | case class GQLOverride(from: String) extends GQLDirective(Override(from))
17 |
18 | object Override {
19 | def apply(from: String): Directive =
20 | Directive("override", Map("from" -> StringValue(from)))
21 | }
22 |
23 | case class GQLTag(name: String) extends GQLDirective(Tag(name))
24 |
25 | object Tag {
26 | def apply(name: String): Directive =
27 | Directive("tag", Map("name" -> StringValue(name)))
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/federation/src/main/scala/caliban/federation/v2x/FederationDirectivesV2_3.scala:
--------------------------------------------------------------------------------
1 | package caliban.federation.v2x
2 |
3 | import caliban.parsing.adt.Directive
4 | import caliban.schema.Annotations.GQLDirective
5 |
6 | trait FederationDirectivesV2_3 {
7 | case class GQLInterfaceObject() extends GQLDirective(InterfaceObject)
8 |
9 | val InterfaceObject = Directive("interfaceObject")
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/federation/src/main/scala/caliban/federation/v2x/FederationDirectivesV2_5.scala:
--------------------------------------------------------------------------------
1 | package caliban.federation.v2x
2 |
3 | import caliban.InputValue.ListValue
4 | import caliban.Value.StringValue
5 | import caliban.parsing.adt.Directive
6 | import caliban.schema.Annotations.GQLDirective
7 |
8 | trait FederationDirectivesV2_5 extends FederationDirectivesV2_3 {
9 |
10 | val Authenticated = Directive("authenticated")
11 | def RequiresScopes(scopes: List[List[String]]) =
12 | Directive("requiresScopes", Map("scopes" -> ListValue(scopes.map(s => ListValue(s.map(s => StringValue(s)))))))
13 | case class GQLAuthenticated() extends GQLDirective(Authenticated)
14 |
15 | case class GQLRequiresScopes(scopes: List[List[String]]) extends GQLDirective(RequiresScopes(scopes))
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/federation/src/main/scala/caliban/federation/v2x/FederationDirectivesV2_6.scala:
--------------------------------------------------------------------------------
1 | package caliban.federation.v2x
2 |
3 | import caliban.InputValue.ListValue
4 | import caliban.Value.StringValue
5 | import caliban.parsing.adt.Directive
6 | import caliban.schema.Annotations.GQLDirective
7 |
8 | trait FederationDirectivesV2_6 extends FederationDirectivesV2_5 {
9 |
10 | def Policy(policies: List[List[String]]) =
11 | Directive("policy", Map("policies" -> ListValue(policies.map(s => ListValue(s.map(s => StringValue(s)))))))
12 |
13 | case class GQLPolicy(policies: List[List[String]]) extends GQLDirective(Policy(policies))
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/federation/src/main/scala/caliban/federation/v2x/FederationDirectivesV2_8.scala:
--------------------------------------------------------------------------------
1 | package caliban.federation.v2x
2 |
3 | import caliban.Value.StringValue
4 | import caliban.parsing.adt.Directive
5 | import caliban.schema.Annotations.GQLDirective
6 |
7 | trait FederationDirectivesV2_8 extends FederationDirectivesV2_6 {
8 |
9 | def Context(context: String) = Directive("context", Map("context" -> StringValue(context)))
10 |
11 | case class GQLContext(context: String) extends GQLDirective(Context(context))
12 |
13 | def FromContext(context: String) = Directive("fromContext", Map("context" -> StringValue(context)))
14 |
15 | case class GQLFromContext(context: String) extends GQLDirective(FromContext(context))
16 | }
17 |
--------------------------------------------------------------------------------
/federation/src/main/scala/caliban/federation/v2x/Link.scala:
--------------------------------------------------------------------------------
1 | package caliban.federation.v2x
2 |
3 | import caliban.InputValue
4 | import caliban.InputValue.ListValue
5 | import caliban.Value.StringValue
6 | import caliban.parsing.adt.Directive
7 |
8 | trait Extension {
9 | def toDirective: Directive
10 | }
11 |
12 | case class ComposeDirective(name: String) extends Extension {
13 | def toDirective: Directive = Directive("composeDirective", Map("name" -> StringValue(name)))
14 | }
15 |
16 | case class Link(url: String, `import`: List[Import]) extends Extension {
17 | def toDirective: Directive =
18 | Directive("link", Map("url" -> StringValue(url), "import" -> ListValue(`import`.map(_.toInputValue))))
19 | }
20 |
21 | case class Import(name: String, as: Option[String] = None) {
22 | def toInputValue: InputValue = as.fold[InputValue](StringValue(name))(alias =>
23 | InputValue.ObjectValue(
24 | Map("name" -> StringValue(name), "as" -> StringValue(alias))
25 | )
26 | )
27 | }
28 |
--------------------------------------------------------------------------------
/federation/src/main/scala/caliban/federation/v2x/Versions.scala:
--------------------------------------------------------------------------------
1 | package caliban.federation.v2x
2 |
3 | object Versions {
4 |
5 | val v2_0 = FederationV2.v2_0
6 | val v2_1 = FederationV2.v2_1
7 | val v2_3 = FederationV2.v2_3
8 | val v2_4 = FederationV2.v2_4
9 | val v2_5 = FederationV2.v2_5
10 | val v2_6 = FederationV2.v2_6
11 | val v2_7 = FederationV2.v2_7
12 | val v2_8 = FederationV2.v2_8
13 | val v2_9 = FederationV2.v2_9
14 | val v2_10 = FederationV2.v2_10
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/interop/cats/src/main/scala/caliban/interop/fs2/Fs2Interop.scala:
--------------------------------------------------------------------------------
1 | package caliban.interop.fs2
2 |
3 | import caliban.interop.cats.FromEffect
4 | import caliban.introspection.adt.__Type
5 | import caliban.schema.{ Schema, Step }
6 | import fs2.Stream
7 | import zio.stream.ZStream
8 | import zio.stream.interop.fs2z._
9 | import zio.{ RIO, Task }
10 |
11 | object Fs2Interop {
12 | def schemaStreamRIO[R, A](implicit ev: Schema[R, ZStream[R, Throwable, A]]): Schema[R, Stream[RIO[R, *], A]] =
13 | new Schema[R, Stream[RIO[R, *], A]] {
14 | override def toType(isInput: Boolean, isSubscription: Boolean): __Type =
15 | ev.toType_(isInput, isSubscription)
16 |
17 | override def nullable: Boolean = ev.nullable
18 | override def canFail: Boolean = ev.canFail
19 |
20 | override def resolve(value: Stream[RIO[R, *], A]): Step[R] =
21 | ev.resolve(value.toZStream())
22 | }
23 |
24 | def schemaStreamF[F[_], R, A](implicit
25 | interop: FromEffect[F, R],
26 | ev: Schema[R, Stream[RIO[R, *], A]]
27 | ): Schema[R, Stream[F, A]] =
28 | new Schema[R, Stream[F, A]] {
29 | override def toType(isInput: Boolean, isSubscription: Boolean): __Type =
30 | ev.toType_(isInput, isSubscription)
31 |
32 | override def nullable: Boolean = ev.nullable
33 | override def canFail: Boolean = ev.canFail
34 |
35 | override def resolve(value: Stream[F, A]): Step[R] =
36 | ev.resolve(value.translate(interop.fromEffectK))
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/interop/cats/src/main/scala/caliban/interop/fs2/implicits/package.scala:
--------------------------------------------------------------------------------
1 | package caliban.interop.fs2
2 |
3 | import caliban.interop.cats.FromEffect
4 | import caliban.schema.{ Schema, SubscriptionSchema }
5 | import fs2.Stream
6 | import zio.RIO
7 | import zio.stream.ZStream
8 |
9 | package object implicits {
10 |
11 | implicit def fs2SchemaStreamRIO[R, A](implicit
12 | ev: Schema[R, ZStream[R, Throwable, A]]
13 | ): Schema[R, Stream[RIO[R, *], A]] =
14 | Fs2Interop.schemaStreamRIO
15 |
16 | implicit def fs2SchemaStreamF[F[_], R, A](implicit
17 | interop: FromEffect[F, R],
18 | ev: Schema[R, Stream[RIO[R, *], A]]
19 | ): Schema[R, Stream[F, A]] =
20 | Fs2Interop.schemaStreamF
21 |
22 | implicit def fs2SubscriptionSchemaStreamF[F[_], A]: SubscriptionSchema[Stream[F, A]] =
23 | new SubscriptionSchema[Stream[F, A]] {}
24 | }
25 |
--------------------------------------------------------------------------------
/interop/tapir/src/main/scala/caliban/interop/tapir/JsonCodecs.scala:
--------------------------------------------------------------------------------
1 | package caliban.interop.tapir
2 |
3 | import caliban.{ GraphQLRequest, ResponseValue }
4 | import sttp.tapir.Codec.JsonCodec
5 | import MaxCharBufSizeJsonJsoniter._
6 |
7 | private object JsonCodecs {
8 | import caliban.interop.jsoniter.ValueJsoniter.stringListCodec
9 |
10 | val listMapCodec: JsonCodec[Map[String, List[String]]] = implicitly
11 | val requestCodec: JsonCodec[GraphQLRequest] = implicitly
12 | val responseCodec: JsonCodec[ResponseValue] = implicitly
13 | }
14 |
--------------------------------------------------------------------------------
/interop/tapir/src/main/scala/caliban/interop/tapir/MaxCharBufSizeJsonJsoniter.scala:
--------------------------------------------------------------------------------
1 | package caliban.interop.tapir
2 |
3 | import com.github.plokhotnyuk.jsoniter_scala.core.ReaderConfig
4 | import sttp.tapir.json.jsoniter.TapirJsonJsoniter
5 |
6 | object MaxCharBufSizeJsonJsoniter extends TapirJsonJsoniter {
7 | override lazy val readerConfig: ReaderConfig =
8 | ReaderConfig
9 | .withAppendHexDumpToParseException(false)
10 | .withMaxCharBufSize(Int.MaxValue - 2)
11 | .withMaxBufSize(Int.MaxValue - 2)
12 | }
13 |
--------------------------------------------------------------------------------
/interop/tapir/src/main/scala/caliban/interop/tapir/StreamConstructor.scala:
--------------------------------------------------------------------------------
1 | package caliban.interop.tapir
2 |
3 | import zio.stream.ZStream
4 |
5 | trait StreamConstructor[BS] {
6 | def apply(stream: ZStream[Any, Throwable, Byte]): BS
7 | }
8 |
9 | object StreamConstructor {
10 | implicit val zioStreams: StreamConstructor[ZStream[Any, Throwable, Byte]] =
11 | (stream: ZStream[Any, Throwable, Byte]) => stream
12 |
13 | implicit val noStreams: StreamConstructor[Nothing] =
14 | (_: ZStream[Any, Throwable, Byte]) => throw new UnsupportedOperationException("Streams are not supported")
15 | }
16 |
--------------------------------------------------------------------------------
/interop/tapir/src/test/scala/caliban/interop/tapir/FakeAuthorizationInterceptor.scala:
--------------------------------------------------------------------------------
1 | package caliban.interop.tapir
2 |
3 | import caliban.interop.tapir.TapirAdapter.TapirResponse
4 | import sttp.model.StatusCode
5 | import sttp.tapir.model.ServerRequest
6 | import zio.{ ZIO, ZLayer }
7 |
8 | object FakeAuthorizationInterceptor {
9 |
10 | def make[R](
11 | authenticate: ServerRequest => ZIO[R, (Int, String), Unit]
12 | ): ZLayer[ServerRequest with R, TapirResponse, R] =
13 | ZLayer.fromZIOEnvironment {
14 | for {
15 | request <- ZIO.service[ServerRequest]
16 | env <- ZIO.environment[R]
17 | _ <- authenticate(request).mapError { case (status, str) =>
18 | TapirResponse(StatusCode(status), body = str)
19 | }
20 | } yield env
21 | }
22 |
23 | def bearer[R]: ZLayer[ServerRequest with R, TapirResponse, R] =
24 | make[R](req => ZIO.fail((401, "You are unauthorized!")).when(req.headers("X-Invalid").nonEmpty).unit)
25 | }
26 |
--------------------------------------------------------------------------------
/macros/src/main/scala-2/caliban/schema/Derived.scala:
--------------------------------------------------------------------------------
1 | package caliban.schema
2 |
3 | import scala.annotation.implicitNotFound
4 |
5 | @implicitNotFound(
6 | """Cannot find a ${T}.
7 |
8 | Caliban derives a Schema automatically for basic Scala types, case classes and sealed traits, but
9 | you need to manually provide an implicit Schema for other types that could be nested inside your type.
10 | If you use a custom type as an argument, you also need to provide an implicit ArgBuilder for that type.
11 | See https://ghostdogpr.github.io/caliban/docs/schema.html for more information.
12 | """
13 | )
14 | case class Derived[T](schema: T) extends AnyVal
15 |
--------------------------------------------------------------------------------
/macros/src/main/scala-2/caliban/schema/DerivedMagnolia.scala:
--------------------------------------------------------------------------------
1 | package caliban.schema
2 |
3 | object DerivedMagnolia {
4 | import magnolia1.Magnolia
5 |
6 | import scala.reflect.macros.whitebox
7 |
8 | // Wrap the output of Magnolia in a Derived to force it to a lower priority.
9 | // This seems to work, despite magnolia hardcode checks for `macroApplication` symbol
10 | // and relying on getting an diverging implicit expansion error for auto-mode.
11 | // Thankfully at least it doesn't check the output type of its `macroApplication`
12 | def derivedMagnolia[TC[_], A: c.WeakTypeTag](c: whitebox.Context): c.Expr[Derived[TC[A]]] = {
13 | val magnoliaTree = c.Expr[TC[A]](Magnolia.gen[A](c))
14 | c.universe.reify(Derived(magnoliaTree.splice))
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/project/ScriptedDependency.scala:
--------------------------------------------------------------------------------
1 | import sbt.*
2 |
3 | //noinspection TypeAnnotation
4 | object ScriptedDependency {
5 | // scala steward should understand these version in context of dependencies described here
6 | object Version {
7 | val sttp = "3.10.1"
8 | val zioTest = "2.1.9"
9 | }
10 |
11 | lazy val sttp = Seq(
12 | "com.softwaremill.sttp.client3" %% "core" % Version.sttp,
13 | "com.softwaremill.sttp.client3" %% "zio" % Version.sttp
14 | )
15 |
16 | lazy val zioTest = Seq(
17 | "dev.zio" %% "zio-test" % Version.zioTest % Test,
18 | "dev.zio" %% "zio-test-sbt" % Version.zioTest % Test
19 | )
20 | }
21 |
--------------------------------------------------------------------------------
/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version = 1.11.1
2 |
--------------------------------------------------------------------------------
/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | val sbtcrossProjectVersion = "1.3.2"
2 |
3 | addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.4")
4 | addSbtPlugin("com.github.sbt" % "sbt-ci-release" % "1.11.1")
5 | addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.19.0")
6 | addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.5.7")
7 | addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % sbtcrossProjectVersion)
8 | addSbtPlugin("org.portable-scala" % "sbt-scala-native-crossproject" % sbtcrossProjectVersion)
9 | addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.7")
10 | addSbtPlugin("com.thesamet" % "sbt-protoc" % "1.0.7")
11 | addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.13.1")
12 | addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.7.1")
13 | addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "1.1.4")
14 | addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.3.1")
15 |
16 | addSbtPlugin("org.jetbrains.scala" % "sbt-ide-settings" % "1.1.2")
17 |
18 | libraryDependencies += "com.thesamet.scalapb" %% "compilerplugin" % "0.11.17"
19 | addDependencyTreePlugin
20 |
--------------------------------------------------------------------------------
/reporting/src/main/scala/caliban/reporting/Util.scala:
--------------------------------------------------------------------------------
1 | package caliban.reporting
2 |
3 | import zio.{ Task, ZIO }
4 |
5 | import java.security.MessageDigest
6 |
7 | object Util {
8 |
9 | private[caliban] def hashSchema(schema: String): Task[String] =
10 | ZIO.attempt(
11 | MessageDigest
12 | .getInstance("SHA-256")
13 | .digest(schema.getBytes("UTF-8"))
14 | .map("%02x".format(_))
15 | .mkString
16 | )
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/reporting/src/main/scala/caliban/reporting/client/ReportSchemaError.scala:
--------------------------------------------------------------------------------
1 | package caliban.reporting.client
2 |
3 | import caliban.client.FieldBuilder._
4 | import caliban.client._
5 |
6 | object ReportSchemaError {
7 | def code: SelectionBuilder[ReportSchemaError, ReportSchemaErrorCode] =
8 | _root_.caliban.client.SelectionBuilder.Field("code", Scalar())
9 | def inSeconds: SelectionBuilder[ReportSchemaError, Int] =
10 | _root_.caliban.client.SelectionBuilder.Field("inSeconds", Scalar())
11 | def message: SelectionBuilder[ReportSchemaError, String] =
12 | _root_.caliban.client.SelectionBuilder.Field("message", Scalar())
13 | def withCoreSchema: SelectionBuilder[ReportSchemaError, Boolean] =
14 | _root_.caliban.client.SelectionBuilder.Field("withCoreSchema", Scalar())
15 | }
16 |
--------------------------------------------------------------------------------
/reporting/src/main/scala/caliban/reporting/client/ReportSchemaResponse.scala:
--------------------------------------------------------------------------------
1 | package caliban.reporting.client
2 |
3 | import caliban.client.FieldBuilder._
4 | import caliban.client._
5 |
6 | object ReportSchemaResponse {
7 | def inSeconds: SelectionBuilder[ReportSchemaResponse, Int] =
8 | _root_.caliban.client.SelectionBuilder.Field("inSeconds", Scalar())
9 | def withCoreSchema: SelectionBuilder[ReportSchemaResponse, Boolean] =
10 | _root_.caliban.client.SelectionBuilder.Field("withCoreSchema", Scalar())
11 | }
12 |
--------------------------------------------------------------------------------
/reporting/src/main/scala/caliban/reporting/client/ReportSchemaResult.scala:
--------------------------------------------------------------------------------
1 | package caliban.reporting.client
2 |
3 | import caliban.client.FieldBuilder._
4 | import caliban.client._
5 |
6 | object ReportSchemaResult {
7 | def inSeconds: SelectionBuilder[ReportSchemaResult, Int] =
8 | _root_.caliban.client.SelectionBuilder.Field("inSeconds", Scalar())
9 | def withCoreSchema: SelectionBuilder[ReportSchemaResult, Boolean] =
10 | _root_.caliban.client.SelectionBuilder.Field("withCoreSchema", Scalar())
11 | }
12 |
--------------------------------------------------------------------------------
/reporting/src/main/scala/caliban/reporting/client/package.scala:
--------------------------------------------------------------------------------
1 | package caliban.reporting
2 |
3 | package object client {
4 |
5 | type ReportSchemaResult
6 | type ReportSchemaError
7 | type ReportSchemaResponse
8 | type Query = _root_.caliban.client.Operations.RootQuery
9 | type Mutation = _root_.caliban.client.Operations.RootMutation
10 | }
11 |
--------------------------------------------------------------------------------
/reporting/src/main/scala/caliban/reporting/package.scala:
--------------------------------------------------------------------------------
1 | package caliban
2 |
3 | import sttp.client3.SttpBackend
4 | import zio.Task
5 |
6 | package object reporting {
7 |
8 | type SttpClient = SttpBackend[Task, Any]
9 | }
10 |
--------------------------------------------------------------------------------
/tools/src/main/resources/default.scalafmt.conf:
--------------------------------------------------------------------------------
1 | version=3.8.2
2 | runner.dialect=scala3
--------------------------------------------------------------------------------
/tools/src/main/scala/caliban/tools/Options.scala:
--------------------------------------------------------------------------------
1 | package caliban.tools
2 |
3 | final case class Options(
4 | schemaPath: String,
5 | toPath: String,
6 | fmtPath: Option[String],
7 | headers: Option[List[Options.Header]],
8 | packageName: Option[String],
9 | clientName: Option[String],
10 | genView: Option[Boolean],
11 | effect: Option[String],
12 | scalarMappings: Option[Map[String, String]],
13 | imports: Option[List[String]],
14 | abstractEffectType: Option[Boolean],
15 | splitFiles: Option[Boolean],
16 | enableFmt: Option[Boolean],
17 | extensibleEnums: Option[Boolean],
18 | preserveInputNames: Option[Boolean],
19 | supportIsRepeatable: Option[Boolean],
20 | addDerives: Option[Boolean],
21 | envForDerives: Option[String],
22 | excludeDeprecated: Option[Boolean],
23 | supportDeprecatedArgs: Option[Boolean]
24 | )
25 |
26 | object Options {
27 | final case class Header(name: String, value: String)
28 | }
29 |
--------------------------------------------------------------------------------
/tools/src/main/scala/caliban/tools/compiletime/CompileTime.scala:
--------------------------------------------------------------------------------
1 | package caliban.tools.compiletime
2 |
3 | import caliban._
4 | import caliban.tools.Codegen.GenType
5 | import caliban.tools.compiletime.Config.ClientGenerationSettings
6 | import caliban.tools.{ Codegen, SchemaLoader }
7 | import zio.{ ExitCode, UIO, ZIO }
8 |
9 | object CompileTime {
10 |
11 | def generateClient[R](
12 | args: List[String]
13 | )(api: GraphQL[R], settings: ClientGenerationSettings): UIO[ExitCode] =
14 | args match {
15 | case baseDir :: Nil =>
16 | Codegen
17 | .generate(
18 | SchemaLoader.fromCaliban(api),
19 | settings.toCalibanCommonSettings.toOptions(
20 | schemaPath = "",
21 | toPath = {
22 | val dir = Utils.toPathDir(baseDir, settings.packageName)
23 |
24 | if (settings.splitFiles) dir else s"$dir/${settings.clientName}.scala"
25 | }
26 | ),
27 | GenType.Client
28 | )
29 | .exitCode
30 | case _ =>
31 | ZIO
32 | .fail(new RuntimeException(s"`CompileTime.generateClient` was called with invalid arguments: $args"))
33 | .exitCode
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/tools/src/main/scala/caliban/tools/compiletime/Utils.scala:
--------------------------------------------------------------------------------
1 | package caliban.tools.compiletime
2 |
3 | private[caliban] object Utils {
4 |
5 | def packagePath(packageName: String): String = packageName.split('.').mkString(java.io.File.separator)
6 | def toPathDir(baseDir: String, packageName: String): String = {
7 | val isVersioned = !baseDir.contains("src_managed")
8 | if (isVersioned) s"$baseDir/src/main/scala/${packagePath(packageName)}"
9 | else s"$baseDir/${packagePath(packageName)}"
10 | }
11 |
12 | def toScalaCode[A](l: List[A])(asScalaCode: A => String): String =
13 | if (l.isEmpty) "List.empty" else s"List(${l.map(asScalaCode).mkString(",")})"
14 |
15 | def toScalaCode(l: List[(String, String)]): String =
16 | toScalaCode[(String, String)](l) { case (a, b) => s"""("$a","$b")""" }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/tools/src/main/scala/caliban/tools/stitching/PartialRemoteSchema.scala:
--------------------------------------------------------------------------------
1 | package caliban.tools.stitching
2 |
3 | import zio._
4 | import zio.query._
5 |
6 | import caliban.{ CalibanError, ResponseValue }
7 | import caliban.schema._
8 | import caliban.introspection.adt._
9 |
10 | trait PartialRemoteSchema[R0, R, A] { self =>
11 | def toType(isInput: Boolean, isSubscription: Boolean): __Type
12 |
13 | def resolve(value: A, args: caliban.execution.Field): ZIO[R0, CalibanError, ResponseValue]
14 |
15 | def provideEnvironment[R1 <: R0](env: ZEnvironment[R1]): Schema[R, A] = new Schema[R, A] {
16 | def resolve(value: A): Step[R] =
17 | Step.MetadataFunctionStep { (args: caliban.execution.Field) =>
18 | Step.QueryStep(ZQuery.fromZIO(self.resolve(value, args).map(Step.PureStep.apply).provideEnvironment(env)))
19 | }
20 |
21 | def toType(isInput: Boolean, isSubscription: Boolean): __Type =
22 | self.toType(isInput, isSubscription)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/tools/src/main/scala/caliban/tools/stitching/ResolveRequest.scala:
--------------------------------------------------------------------------------
1 | package caliban.tools.stitching
2 |
3 | import caliban.execution.Field
4 |
5 | case class ResolveRequest[A](
6 | args: A,
7 | field: Field
8 | )
9 |
--------------------------------------------------------------------------------
/tools/src/main/scala/caliban/tools/stitching/package.scala:
--------------------------------------------------------------------------------
1 | package caliban.tools
2 |
3 | import caliban.{ CalibanError, ResponseValue }
4 |
5 | import sttp.client3._
6 |
7 | package object stitching {
8 | type HttpRequest = RequestT[Identity, Either[CalibanError.ExecutionError, ResponseValue], Any]
9 | }
10 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/ClientWriterSpec/add scalar mappings and additional imports.scala:
--------------------------------------------------------------------------------
1 | import caliban.client.FieldBuilder._
2 | import caliban.client._
3 |
4 | import java.util.UUID
5 | import a.b._
6 |
7 | object Client {
8 |
9 | type Order
10 | object Order {
11 | def date: SelectionBuilder[Order, java.time.OffsetDateTime] =
12 | _root_.caliban.client.SelectionBuilder.Field("date", Scalar())
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/ClientWriterSpec/case-insensitive name uniqueness in 2 basic objects.scala:
--------------------------------------------------------------------------------
1 | import caliban.client.FieldBuilder._
2 | import caliban.client._
3 |
4 | object Client {
5 |
6 | type Character
7 | object Character {
8 | def name: SelectionBuilder[Character, String] = _root_.caliban.client.SelectionBuilder.Field("name", Scalar())
9 | def nicknames: SelectionBuilder[Character, List[String]] =
10 | _root_.caliban.client.SelectionBuilder.Field("nicknames", ListOf(Scalar()))
11 | }
12 |
13 | type character_1
14 | object character_1 {
15 | def name: SelectionBuilder[character_1, String] = _root_.caliban.client.SelectionBuilder.Field("name", Scalar())
16 | def nicknames: SelectionBuilder[character_1, List[String]] =
17 | _root_.caliban.client.SelectionBuilder.Field("nicknames", ListOf(Scalar()))
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/ClientWriterSpec/default arguments for optional and list arguments.scala:
--------------------------------------------------------------------------------
1 | import caliban.client.FieldBuilder._
2 | import caliban.client._
3 |
4 | object Client {
5 |
6 | type Query = _root_.caliban.client.Operations.RootQuery
7 | object Query {
8 | def characters(first: Int, last: scala.Option[Int] = None, origins: List[scala.Option[String]] = Nil)(implicit
9 | encoder0: ArgEncoder[Int],
10 | encoder1: ArgEncoder[scala.Option[Int]],
11 | encoder2: ArgEncoder[List[scala.Option[String]]]
12 | ): SelectionBuilder[_root_.caliban.client.Operations.RootQuery, scala.Option[String]] =
13 | _root_.caliban.client.SelectionBuilder.Field(
14 | "characters",
15 | OptionOf(Scalar()),
16 | arguments = List(
17 | Argument("first", first, "Int!")(encoder0),
18 | Argument("last", last, "Int")(encoder1),
19 | Argument("origins", origins, "[String]!")(encoder2)
20 | )
21 | )
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/ClientWriterSpec/deprecated field + comment newline.scala:
--------------------------------------------------------------------------------
1 | import caliban.client.FieldBuilder._
2 | import caliban.client._
3 |
4 | object Client {
5 |
6 | type Character
7 | object Character {
8 |
9 | /**
10 | * name
11 | */
12 | @deprecated("""foo
13 | bar""")
14 | def name: SelectionBuilder[Character, String] = _root_.caliban.client.SelectionBuilder.Field("name", Scalar())
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/ClientWriterSpec/deprecated field + comment.scala:
--------------------------------------------------------------------------------
1 | import caliban.client.FieldBuilder._
2 | import caliban.client._
3 |
4 | object Client {
5 |
6 | type Character
7 | object Character {
8 |
9 | /**
10 | * name
11 | */
12 | @deprecated("blah")
13 | def name: SelectionBuilder[Character, String] = _root_.caliban.client.SelectionBuilder.Field("name", Scalar())
14 | @deprecated
15 | def nicknames: SelectionBuilder[Character, List[String]] =
16 | _root_.caliban.client.SelectionBuilder.Field("nicknames", ListOf(Scalar()))
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/ClientWriterSpec/deprecated field argument + comment newline.scala:
--------------------------------------------------------------------------------
1 | import caliban.client.FieldBuilder._
2 | import caliban.client._
3 |
4 | object Client {
5 |
6 | type Query = _root_.caliban.client.Operations.RootQuery
7 | object Query {
8 | def characters(
9 | first: Int,
10 | @deprecated("""foo
11 | bar""")
12 | last: scala.Option[Int] = None,
13 | @deprecated
14 | origins: scala.Option[List[scala.Option[String]]] = None
15 | )(implicit
16 | encoder0: ArgEncoder[Int],
17 | encoder1: ArgEncoder[scala.Option[Int]],
18 | encoder2: ArgEncoder[scala.Option[List[scala.Option[String]]]]
19 | ): SelectionBuilder[_root_.caliban.client.Operations.RootQuery, scala.Option[String]] =
20 | _root_.caliban.client.SelectionBuilder.Field(
21 | "characters",
22 | OptionOf(Scalar()),
23 | arguments = List(
24 | Argument("first", first, "Int!")(encoder0),
25 | Argument("last", last, "Int")(encoder1),
26 | Argument("origins", origins, "[String]")(encoder2)
27 | )
28 | )
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/ClientWriterSpec/deprecated field argument + comment.scala:
--------------------------------------------------------------------------------
1 | import caliban.client.FieldBuilder._
2 | import caliban.client._
3 |
4 | object Client {
5 |
6 | type Query = _root_.caliban.client.Operations.RootQuery
7 | object Query {
8 | def characters(
9 | first: Int,
10 | @deprecated("foo bar")
11 | last: scala.Option[Int] = None,
12 | @deprecated
13 | origins: scala.Option[List[scala.Option[String]]] = None
14 | )(implicit
15 | encoder0: ArgEncoder[Int],
16 | encoder1: ArgEncoder[scala.Option[Int]],
17 | encoder2: ArgEncoder[scala.Option[List[scala.Option[String]]]]
18 | ): SelectionBuilder[_root_.caliban.client.Operations.RootQuery, scala.Option[String]] =
19 | _root_.caliban.client.SelectionBuilder.Field(
20 | "characters",
21 | OptionOf(Scalar()),
22 | arguments = List(
23 | Argument("first", first, "Int!")(encoder0),
24 | Argument("last", last, "Int")(encoder1),
25 | Argument("origins", origins, "[String]")(encoder2)
26 | )
27 | )
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/ClientWriterSpec/enum with exclude deprecated, only deprecated values.scala:
--------------------------------------------------------------------------------
1 | import caliban.client.CalibanClientError.DecodingError
2 | import caliban.client._
3 | import caliban.client.__Value._
4 |
5 | object Client {
6 |
7 | sealed trait Origin extends scala.Product with scala.Serializable { def value: String }
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/ClientWriterSpec/enum with exclude deprecated.scala:
--------------------------------------------------------------------------------
1 | import caliban.client.CalibanClientError.DecodingError
2 | import caliban.client._
3 | import caliban.client.__Value._
4 |
5 | object Client {
6 |
7 | sealed trait Origin extends scala.Product with scala.Serializable { def value: String }
8 | object Origin {
9 | case object EARTH extends Origin { val value: String = "EARTH" }
10 | case object BELT extends Origin { val value: String = "BELT" }
11 |
12 | implicit val decoder: ScalarDecoder[Origin] = {
13 | case __StringValue("EARTH") => Right(Origin.EARTH)
14 | case __StringValue("BELT") => Right(Origin.BELT)
15 | case other => Left(DecodingError(s"Can't build Origin from input $other"))
16 | }
17 | implicit val encoder: ArgEncoder[Origin] = {
18 | case Origin.EARTH => __EnumValue("EARTH")
19 | case Origin.BELT => __EnumValue("BELT")
20 | }
21 |
22 | val values: scala.collection.immutable.Vector[Origin] = scala.collection.immutable.Vector(EARTH, BELT)
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/ClientWriterSpec/enum.scala:
--------------------------------------------------------------------------------
1 | import caliban.client.CalibanClientError.DecodingError
2 | import caliban.client._
3 | import caliban.client.__Value._
4 |
5 | object Client {
6 |
7 | sealed trait Origin extends scala.Product with scala.Serializable { def value: String }
8 | object Origin {
9 | case object EARTH extends Origin { val value: String = "EARTH" }
10 | case object MARS extends Origin { val value: String = "MARS" }
11 | case object BELT extends Origin { val value: String = "BELT" }
12 |
13 | implicit val decoder: ScalarDecoder[Origin] = {
14 | case __StringValue("EARTH") => Right(Origin.EARTH)
15 | case __StringValue("MARS") => Right(Origin.MARS)
16 | case __StringValue("BELT") => Right(Origin.BELT)
17 | case other => Left(DecodingError(s"Can't build Origin from input $other"))
18 | }
19 | implicit val encoder: ArgEncoder[Origin] = {
20 | case Origin.EARTH => __EnumValue("EARTH")
21 | case Origin.MARS => __EnumValue("MARS")
22 | case Origin.BELT => __EnumValue("BELT")
23 | }
24 |
25 | val values: scala.collection.immutable.Vector[Origin] = scala.collection.immutable.Vector(EARTH, MARS, BELT)
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/ClientWriterSpec/input object oneOf.scala:
--------------------------------------------------------------------------------
1 | import caliban.client._
2 | import caliban.client.__Value._
3 |
4 | object Client {
5 |
6 | sealed trait CharacterInput {
7 | protected def encode: __Value
8 | }
9 | object CharacterInput {
10 | final case class Name(name: String) extends CharacterInput {
11 | protected def encode: __Value = __ObjectValue(List("name" -> implicitly[ArgEncoder[String]].encode(name)))
12 | }
13 | final case class Nicknames(nicknames: List[String] = Nil) extends CharacterInput {
14 | protected def encode: __Value = __ObjectValue(
15 | List("nicknames" -> __ListValue(nicknames.map(value => implicitly[ArgEncoder[String]].encode(value))))
16 | )
17 | }
18 |
19 | implicit val encoder: ArgEncoder[CharacterInput] = new ArgEncoder[CharacterInput] {
20 | override def encode(value: CharacterInput): __Value = value.encode
21 | }
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/ClientWriterSpec/input object with deprecated fields.scala:
--------------------------------------------------------------------------------
1 | import caliban.client._
2 | import caliban.client.__Value._
3 |
4 | object Client {
5 |
6 | final case class CharacterInput(
7 | name: String,
8 | @deprecated
9 | nickname: scala.Option[String] = None,
10 | @deprecated("no longer used")
11 | address: scala.Option[String] = None
12 | )
13 | object CharacterInput {
14 | implicit val encoder: ArgEncoder[CharacterInput] = new ArgEncoder[CharacterInput] {
15 | override def encode(value: CharacterInput): __Value =
16 | __ObjectValue(
17 | List(
18 | "name" -> implicitly[ArgEncoder[String]].encode(value.name),
19 | "nickname" -> value.nickname.fold(__NullValue: __Value)(value =>
20 | implicitly[ArgEncoder[String]].encode(value)
21 | ),
22 | "address" -> value.address.fold(__NullValue: __Value)(value => implicitly[ArgEncoder[String]].encode(value))
23 | )
24 | )
25 | }
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/ClientWriterSpec/input object with reserved name.scala:
--------------------------------------------------------------------------------
1 | import caliban.client._
2 | import caliban.client.__Value._
3 |
4 | object Client {
5 |
6 | final case class CharacterInput(wait$ : String)
7 | object CharacterInput {
8 | implicit val encoder: ArgEncoder[CharacterInput] = new ArgEncoder[CharacterInput] {
9 | override def encode(value: CharacterInput): __Value =
10 | __ObjectValue(List("wait" -> implicitly[ArgEncoder[String]].encode(value.wait$)))
11 | }
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/ClientWriterSpec/input object.scala:
--------------------------------------------------------------------------------
1 | import caliban.client._
2 | import caliban.client.__Value._
3 |
4 | object Client {
5 |
6 | final case class CharacterInput(name: String, nicknames: List[String] = Nil)
7 | object CharacterInput {
8 | implicit val encoder: ArgEncoder[CharacterInput] = new ArgEncoder[CharacterInput] {
9 | override def encode(value: CharacterInput): __Value =
10 | __ObjectValue(
11 | List(
12 | "name" -> implicitly[ArgEncoder[String]].encode(value.name),
13 | "nicknames" -> __ListValue(value.nicknames.map(value => implicitly[ArgEncoder[String]].encode(value)))
14 | )
15 | )
16 | }
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/ClientWriterSpec/interface with implements.scala:
--------------------------------------------------------------------------------
1 | import caliban.client.FieldBuilder._
2 | import caliban.client._
3 |
4 | object Client {
5 |
6 | type Entity
7 | object Entity {
8 | def name: SelectionBuilder[Entity, String] = _root_.caliban.client.SelectionBuilder.Field("name", Scalar())
9 | }
10 |
11 | type Pet
12 | object Pet {
13 | def name: SelectionBuilder[Pet, String] = _root_.caliban.client.SelectionBuilder.Field("name", Scalar())
14 | }
15 |
16 | type Cat
17 | object Cat {
18 | def name: SelectionBuilder[Cat, String] = _root_.caliban.client.SelectionBuilder.Field("name", Scalar())
19 | }
20 |
21 | type Dog
22 | object Dog {
23 | def name: SelectionBuilder[Dog, String] = _root_.caliban.client.SelectionBuilder.Field("name", Scalar())
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/ClientWriterSpec/interface without implements.scala:
--------------------------------------------------------------------------------
1 | import caliban.client.CalibanClientError.DecodingError
2 | import caliban.client.FieldBuilder._
3 | import caliban.client._
4 | import caliban.client.__Value._
5 |
6 | object Client {
7 |
8 | sealed trait Status extends scala.Product with scala.Serializable { def value: String }
9 | object Status {
10 | case object Status1 extends Status { val value: String = "Status1" }
11 |
12 | implicit val decoder: ScalarDecoder[Status] = {
13 | case __StringValue("Status1") => Right(Status.Status1)
14 | case other => Left(DecodingError(s"Can't build Status from input $other"))
15 | }
16 | implicit val encoder: ArgEncoder[Status] = { case Status.Status1 =>
17 | __EnumValue("Status1")
18 | }
19 |
20 | val values: scala.collection.immutable.Vector[Status] = scala.collection.immutable.Vector(Status1)
21 | }
22 |
23 | type Entity
24 | object Entity {
25 | def statusInfo[A](innerSelection: SelectionBuilder[StatusInfo, A]): SelectionBuilder[Entity, A] =
26 | _root_.caliban.client.SelectionBuilder.Field("statusInfo", Obj(innerSelection))
27 | }
28 |
29 | type StatusInfo
30 | object StatusInfo {
31 | def status: SelectionBuilder[StatusInfo, Status] = _root_.caliban.client.SelectionBuilder.Field("status", Scalar())
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/ClientWriterSpec/interface.scala:
--------------------------------------------------------------------------------
1 | import caliban.client.FieldBuilder._
2 | import caliban.client._
3 |
4 | object Client {
5 |
6 | type Order
7 | object Order {
8 | def name: SelectionBuilder[Order, String] = _root_.caliban.client.SelectionBuilder.Field("name", Scalar())
9 | }
10 |
11 | type Ascending
12 | object Ascending {
13 | def name: SelectionBuilder[Ascending, String] = _root_.caliban.client.SelectionBuilder.Field("name", Scalar())
14 | }
15 |
16 | type Sort
17 | object Sort {
18 | def `object`[A](onAscending: SelectionBuilder[Ascending, A]): SelectionBuilder[Sort, scala.Option[A]] =
19 | _root_.caliban.client.SelectionBuilder.Field("object", OptionOf(ChoiceOf(Map("Ascending" -> Obj(onAscending)))))
20 | def objectOption[A](
21 | onAscending: scala.Option[SelectionBuilder[Ascending, A]] = None
22 | ): SelectionBuilder[Sort, scala.Option[scala.Option[A]]] = _root_.caliban.client.SelectionBuilder.Field(
23 | "object",
24 | OptionOf(
25 | ChoiceOf(Map("Ascending" -> onAscending.fold[FieldBuilder[scala.Option[A]]](NullField)(a => OptionOf(Obj(a)))))
26 | )
27 | )
28 | def objectInterface[A](`object`: SelectionBuilder[Order, A]): SelectionBuilder[Sort, scala.Option[A]] =
29 | _root_.caliban.client.SelectionBuilder.Field("object", OptionOf(Obj(`object`)))
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/ClientWriterSpec/nested object type.scala:
--------------------------------------------------------------------------------
1 | import caliban.client.FieldBuilder._
2 | import caliban.client._
3 |
4 | object Client {
5 |
6 | type Q
7 | object Q {
8 | def characters[A](innerSelection: SelectionBuilder[Character, A]): SelectionBuilder[Q, List[A]] =
9 | _root_.caliban.client.SelectionBuilder.Field("characters", ListOf(Obj(innerSelection)))
10 | }
11 |
12 | type Character
13 | object Character {
14 | def name: SelectionBuilder[Character, String] = _root_.caliban.client.SelectionBuilder.Field("name", Scalar())
15 | def nicknames: SelectionBuilder[Character, List[String]] =
16 | _root_.caliban.client.SelectionBuilder.Field("nicknames", ListOf(Scalar()))
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/ClientWriterSpec/object type with arguments.scala:
--------------------------------------------------------------------------------
1 | import caliban.client.FieldBuilder._
2 | import caliban.client._
3 |
4 | object Client {
5 |
6 | type Q
7 | object Q {
8 | def character[A](name: String)(innerSelection: SelectionBuilder[Character, A])(implicit
9 | encoder0: ArgEncoder[String]
10 | ): SelectionBuilder[Q, scala.Option[A]] = _root_.caliban.client.SelectionBuilder
11 | .Field("character", OptionOf(Obj(innerSelection)), arguments = List(Argument("name", name, "String!")(encoder0)))
12 | }
13 |
14 | type Character
15 | object Character {
16 | def name: SelectionBuilder[Character, String] = _root_.caliban.client.SelectionBuilder.Field("name", Scalar())
17 | def nicknames: SelectionBuilder[Character, List[String]] =
18 | _root_.caliban.client.SelectionBuilder.Field("nicknames", ListOf(Scalar()))
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/ClientWriterSpec/object type with reserved name.scala:
--------------------------------------------------------------------------------
1 | import caliban.client.FieldBuilder._
2 | import caliban.client._
3 |
4 | object Client {
5 |
6 | type Character
7 | object Character {
8 | def `type`: SelectionBuilder[Character, String] = _root_.caliban.client.SelectionBuilder.Field("type", Scalar())
9 | }
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/ClientWriterSpec/safe names with underscores.scala:
--------------------------------------------------------------------------------
1 | import caliban.client.FieldBuilder._
2 | import caliban.client._
3 |
4 | object Client {
5 |
6 | type Character
7 | object Character {
8 | def _$ : SelectionBuilder[Character, scala.Option[Boolean]] =
9 | _root_.caliban.client.SelectionBuilder.Field("_", OptionOf(Scalar()))
10 | def `_name_` : SelectionBuilder[Character, scala.Option[String]] =
11 | _root_.caliban.client.SelectionBuilder.Field("_name_", OptionOf(Scalar()))
12 | def _nickname: SelectionBuilder[Character, scala.Option[String]] =
13 | _root_.caliban.client.SelectionBuilder.Field("_nickname", OptionOf(Scalar()))
14 | def `age_` : SelectionBuilder[Character, scala.Option[Int]] =
15 | _root_.caliban.client.SelectionBuilder.Field("age_", OptionOf(Scalar()))
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/ClientWriterSpec/schema with splitFiles.scala:
--------------------------------------------------------------------------------
1 | --- package ---
2 | package object test {
3 | type Character
4 | type Q = _root_.caliban.client.Operations.RootQuery
5 | }
6 |
7 | --- Character ---
8 | package test
9 |
10 | import caliban.client.FieldBuilder._
11 | import caliban.client._
12 |
13 | object Character {
14 | def name: SelectionBuilder[Character, String] = _root_.caliban.client.SelectionBuilder.Field("name", Scalar())
15 | def nicknames: SelectionBuilder[Character, List[String]] =
16 | _root_.caliban.client.SelectionBuilder.Field("nicknames", ListOf(Scalar()))
17 | }
18 |
19 | --- Q ---
20 | package test
21 |
22 | import caliban.client.FieldBuilder._
23 | import caliban.client._
24 |
25 | object Q {
26 | def characters[A](
27 | innerSelection: SelectionBuilder[Character, A]
28 | ): SelectionBuilder[_root_.caliban.client.Operations.RootQuery, List[A]] =
29 | _root_.caliban.client.SelectionBuilder.Field("characters", ListOf(Obj(innerSelection)))
30 | }
31 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/ClientWriterSpec/schema.scala:
--------------------------------------------------------------------------------
1 | import caliban.client.FieldBuilder._
2 | import caliban.client._
3 |
4 | object Client {
5 |
6 | type Character
7 | object Character {
8 | def name: SelectionBuilder[Character, String] = _root_.caliban.client.SelectionBuilder.Field("name", Scalar())
9 | def nicknames: SelectionBuilder[Character, List[String]] =
10 | _root_.caliban.client.SelectionBuilder.Field("nicknames", ListOf(Scalar()))
11 | }
12 |
13 | type Q = _root_.caliban.client.Operations.RootQuery
14 | object Q {
15 | def characters[A](
16 | innerSelection: SelectionBuilder[Character, A]
17 | ): SelectionBuilder[_root_.caliban.client.Operations.RootQuery, List[A]] =
18 | _root_.caliban.client.SelectionBuilder.Field("characters", ListOf(Obj(innerSelection)))
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/ClientWriterSpec/simple object type with exclude deprecated and genView, only deprecated fields.scala:
--------------------------------------------------------------------------------
1 | import caliban.client.FieldBuilder._
2 | import caliban.client._
3 |
4 | object Client {
5 |
6 | type Character
7 | object Character {}
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/ClientWriterSpec/simple object type with exclude deprecated and genView.scala:
--------------------------------------------------------------------------------
1 | import caliban.client.FieldBuilder._
2 | import caliban.client._
3 |
4 | object Client {
5 |
6 | type Character
7 | object Character {
8 |
9 | final case class CharacterView(name: String)
10 |
11 | type ViewSelection = SelectionBuilder[Character, CharacterView]
12 |
13 | def view: ViewSelection = name.map(name => CharacterView(name))
14 |
15 | def name: SelectionBuilder[Character, String] = _root_.caliban.client.SelectionBuilder.Field("name", Scalar())
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/ClientWriterSpec/simple object type.scala:
--------------------------------------------------------------------------------
1 | import caliban.client.FieldBuilder._
2 | import caliban.client._
3 |
4 | object Client {
5 |
6 | type Character
7 | object Character {
8 | def name: SelectionBuilder[Character, String] = _root_.caliban.client.SelectionBuilder.Field("name", Scalar())
9 | def nicknames: SelectionBuilder[Character, List[String]] =
10 | _root_.caliban.client.SelectionBuilder.Field("nicknames", ListOf(Scalar()))
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/ClientWriterSpec/support for Json scalar.scala:
--------------------------------------------------------------------------------
1 | import caliban.client.FieldBuilder._
2 | import caliban.client._
3 |
4 | object Client {
5 |
6 | type Query = _root_.caliban.client.Operations.RootQuery
7 | object Query {
8 | def test: SelectionBuilder[_root_.caliban.client.Operations.RootQuery, io.circe.Json] =
9 | _root_.caliban.client.SelectionBuilder.Field("test", Scalar())
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/ClientWriterViewSpec/generic view for capital fields.scala:
--------------------------------------------------------------------------------
1 | import caliban.client.FieldBuilder._
2 | import caliban.client._
3 |
4 | object Client {
5 |
6 | type TypeWithCapitalFields
7 | object TypeWithCapitalFields {
8 |
9 | final case class TypeWithCapitalFieldsView(Name: scala.Option[String], Value: scala.Option[String])
10 |
11 | type ViewSelection = SelectionBuilder[TypeWithCapitalFields, TypeWithCapitalFieldsView]
12 |
13 | def view: ViewSelection = (Name ~ Value).map { case (name$, value$) => TypeWithCapitalFieldsView(name$, value$) }
14 |
15 | def Name: SelectionBuilder[TypeWithCapitalFields, scala.Option[String]] =
16 | _root_.caliban.client.SelectionBuilder.Field("Name", OptionOf(Scalar()))
17 | def Value: SelectionBuilder[TypeWithCapitalFields, scala.Option[String]] =
18 | _root_.caliban.client.SelectionBuilder.Field("Value", OptionOf(Scalar()))
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/ClientWriterViewSpec/recursive object type.scala:
--------------------------------------------------------------------------------
1 | import caliban.client.FieldBuilder._
2 | import caliban.client._
3 |
4 | object Client {
5 |
6 | type Character
7 | object Character {
8 |
9 | final case class CharacterView[FriendsSelection](name: String, age: Int, friends: List[FriendsSelection])
10 |
11 | type ViewSelection[FriendsSelection] = SelectionBuilder[Character, CharacterView[FriendsSelection]]
12 |
13 | def view[FriendsSelection](friendsFilter: scala.Option[String] = None)(
14 | friendsSelection: SelectionBuilder[Character, FriendsSelection]
15 | ): ViewSelection[FriendsSelection] = (name ~ age ~ friends(friendsFilter)(friendsSelection)).map {
16 | case (name, age, friends) => CharacterView(name, age, friends)
17 | }
18 |
19 | def name: SelectionBuilder[Character, String] = _root_.caliban.client.SelectionBuilder.Field("name", Scalar())
20 | def age: SelectionBuilder[Character, Int] = _root_.caliban.client.SelectionBuilder.Field("age", Scalar())
21 | def friends[A](filter: scala.Option[String] = None)(innerSelection: SelectionBuilder[Character, A])(implicit
22 | encoder0: ArgEncoder[scala.Option[String]]
23 | ): SelectionBuilder[Character, List[A]] = _root_.caliban.client.SelectionBuilder
24 | .Field("friends", ListOf(Obj(innerSelection)), arguments = List(Argument("filter", filter, "String")(encoder0)))
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/ClientWriterViewSpec/simple object type.scala:
--------------------------------------------------------------------------------
1 | import caliban.client.FieldBuilder._
2 | import caliban.client._
3 |
4 | object Client {
5 |
6 | type Character
7 | object Character {
8 |
9 | final case class CharacterView(name: String, age: Int, nicknames: List[String])
10 |
11 | type ViewSelection = SelectionBuilder[Character, CharacterView]
12 |
13 | def view: ViewSelection = (name ~ age ~ nicknames).map { case (name, age, nicknames) =>
14 | CharacterView(name, age, nicknames)
15 | }
16 |
17 | def name: SelectionBuilder[Character, String] = _root_.caliban.client.SelectionBuilder.Field("name", Scalar())
18 | def age: SelectionBuilder[Character, Int] = _root_.caliban.client.SelectionBuilder.Field("age", Scalar())
19 | def nicknames: SelectionBuilder[Character, List[String]] =
20 | _root_.caliban.client.SelectionBuilder.Field("nicknames", ListOf(Scalar()))
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/(empty schema test).scala:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/GQLDeprecated with multiline reason and escaped quotes.scala:
--------------------------------------------------------------------------------
1 | import caliban.schema.Annotations._
2 |
3 | object Types {
4 |
5 | final case class ExampleType(
6 | @GQLDeprecated("""This field is deprecated for the following reasons:
7 | 1. \"Outdated data model\": The field relies on an outdated data model.
8 | 2. \"Performance issues\": Queries using this field have performance issues.
9 | Please use `newField` instead.""")
10 | oldField: scala.Option[String],
11 | newField: scala.Option[String]
12 | )
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/GQLDeprecated with reason.scala:
--------------------------------------------------------------------------------
1 | import caliban.schema.Annotations._
2 |
3 | object Types {
4 |
5 | final case class Captain(
6 | @GQLDescription("foo")
7 | @GQLDeprecated("bar")
8 | shipName: String
9 | )
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/GQLDescription with escaped quotes.scala:
--------------------------------------------------------------------------------
1 | import caliban.schema.Annotations._
2 |
3 | object Types {
4 |
5 | final case class Captain(
6 | @GQLDescription("foo \"quotes\" bar")
7 | shipName: String
8 | )
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/add derives also to traits for @oneOf input types.scala:
--------------------------------------------------------------------------------
1 | import caliban.schema.Annotations._
2 |
3 | object Types {
4 |
5 | @GQLOneOfInput
6 | sealed trait FooInput extends scala.Product with scala.Serializable
7 | derives caliban.schema.Schema.SemiAuto,
8 | caliban.schema.ArgBuilder
9 | object FooInput {
10 | final case class OptionA(optionA: String) extends FooInput
11 | derives caliban.schema.Schema.SemiAuto,
12 | caliban.schema.ArgBuilder
13 | final case class OptionB(optionB: Int) extends FooInput
14 | derives caliban.schema.Schema.SemiAuto,
15 | caliban.schema.ArgBuilder
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/add derives.scala:
--------------------------------------------------------------------------------
1 | import Types._
2 |
3 | object Types {
4 | final case class HeroNameArgs(pad: Int) derives caliban.schema.Schema.SemiAuto, caliban.schema.ArgBuilder
5 | final case class QueryHeroArgs(episode: scala.Option[Episode])
6 | derives caliban.schema.Schema.SemiAuto,
7 | caliban.schema.ArgBuilder
8 | final case class Hero(name: HeroNameArgs => String) derives caliban.schema.Schema.SemiAuto
9 | final case class HeroInput(name: String) derives caliban.schema.Schema.SemiAuto, caliban.schema.ArgBuilder
10 |
11 | sealed trait Episode extends scala.Product with scala.Serializable
12 | derives caliban.schema.Schema.SemiAuto,
13 | caliban.schema.ArgBuilder
14 |
15 | object Episode {
16 | case object NEWHOPE extends Episode derives caliban.schema.Schema.SemiAuto, caliban.schema.ArgBuilder
17 | case object EMPIRE extends Episode derives caliban.schema.Schema.SemiAuto, caliban.schema.ArgBuilder
18 | case object JEDI extends Episode derives caliban.schema.Schema.SemiAuto, caliban.schema.ArgBuilder
19 | }
20 |
21 | }
22 |
23 | object Operations {
24 |
25 | final case class Query(
26 | hero: QueryHeroArgs => zio.UIO[scala.Option[Hero]]
27 | ) derives caliban.schema.Schema.SemiAuto
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/add scalar mappings and additional imports.scala:
--------------------------------------------------------------------------------
1 | import Types._
2 |
3 | import zio.stream.ZStream
4 |
5 | import java.util.UUID
6 | import a.b._
7 |
8 | object Types {
9 | final case class MutationAddPostArgs(author: scala.Option[String], comment: scala.Option[String])
10 | final case class Post(date: java.time.OffsetDateTime, author: scala.Option[String], comment: scala.Option[String])
11 |
12 | }
13 |
14 | object Operations {
15 |
16 | final case class Query(
17 | posts: zio.UIO[scala.Option[List[scala.Option[Post]]]]
18 | )
19 |
20 | final case class Mutation(
21 | addPost: MutationAddPostArgs => zio.UIO[scala.Option[Post]]
22 | )
23 |
24 | final case class Subscription(
25 | postAdded: ZStream[Any, Nothing, scala.Option[Post]]
26 | )
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/args names root level.scala:
--------------------------------------------------------------------------------
1 | import Types._
2 |
3 | import zio.stream.ZStream
4 |
5 | object Types {
6 | final case class QueryCharactersArgs(p: Params)
7 | final case class SubscriptionCharactersArgs(p: Params)
8 | final case class Params(p: Int)
9 |
10 | }
11 |
12 | object Operations {
13 |
14 | final case class Query(
15 | characters: QueryCharactersArgs => zio.UIO[Int]
16 | )
17 |
18 | final case class Subscription(
19 | characters: SubscriptionCharactersArgs => ZStream[Any, Nothing, Int]
20 | )
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/args unique class names.scala:
--------------------------------------------------------------------------------
1 | object Types {
2 | final case class HeroCallAlliesArgs(number: Int)
3 | final case class VillainCallAlliesArgs(number: Int, w: String)
4 | final case class Hero(callAllies: HeroCallAlliesArgs => List[Hero])
5 | final case class Villain(callAllies: VillainCallAlliesArgs => List[Villain])
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/enum type.scala:
--------------------------------------------------------------------------------
1 | object Types {
2 |
3 | sealed trait Origin extends scala.Product with scala.Serializable
4 |
5 | object Origin {
6 | case object EARTH extends Origin
7 | case object MARS extends Origin
8 | case object BELT extends Origin
9 | }
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/final case class reserved field name used.scala:
--------------------------------------------------------------------------------
1 | object Types {
2 |
3 | final case class Character(wait$ : String)
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/generate nested @lazy fields with abstracted effect type.scala:
--------------------------------------------------------------------------------
1 | import Types._
2 |
3 | object Types {
4 |
5 | final case class Foo[F[_]](bar: Bar[F])
6 | final case class Bar[F[_]](baz: F[Baz[F]])
7 | final case class Baz[F[_]](x: String, y: F[String])
8 |
9 | }
10 |
11 | object Operations {
12 |
13 | final case class Query[F[_]](
14 | foo: F[Foo[F]]
15 | )
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/inherits field with args.scala:
--------------------------------------------------------------------------------
1 | import caliban.schema.Annotations._
2 |
3 | object Types {
4 | final case class CharacterFriendsConnectionArgs(first: scala.Option[Int], after: scala.Option[ID])
5 | derives caliban.schema.Schema.SemiAuto,
6 | caliban.schema.ArgBuilder
7 | final case class Human(friendsConnection: CharacterFriendsConnectionArgs => FriendsConnection) extends Character
8 | derives caliban.schema.Schema.SemiAuto
9 | final case class Droid(friendsConnection: CharacterFriendsConnectionArgs => FriendsConnection) extends Character
10 | derives caliban.schema.Schema.SemiAuto
11 |
12 | @GQLInterface
13 | sealed trait Character extends scala.Product with scala.Serializable derives caliban.schema.Schema.SemiAuto {
14 | def friendsConnection: CharacterFriendsConnectionArgs => FriendsConnection
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/input type oneOf.scala:
--------------------------------------------------------------------------------
1 | import caliban.schema.Annotations._
2 |
3 | object Types {
4 |
5 | final case class Character(name: String)
6 |
7 | @GQLOneOfInput
8 | sealed trait CharacterArgs extends scala.Product with scala.Serializable
9 | object CharacterArgs {
10 | final case class Foo(foo: String) extends CharacterArgs
11 | final case class Bar(bar: Int) extends CharacterArgs
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/input type with preserved input.scala:
--------------------------------------------------------------------------------
1 | import caliban.schema.Annotations._
2 |
3 | object Types {
4 |
5 | final case class Character(name: String)
6 | @GQLInputName("CharacterInput")
7 | final case class CharacterInput(name: String)
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/input type.scala:
--------------------------------------------------------------------------------
1 | object Types {
2 |
3 | final case class Character(name: String)
4 | final case class CharacterArgs(name: String)
5 |
6 | }
7 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/interface type.scala:
--------------------------------------------------------------------------------
1 | import caliban.schema.Annotations._
2 |
3 | object Types {
4 |
5 | final case class Admin(
6 | id: java.util.UUID,
7 | @GQLDescription("firstName")
8 | firstName: String,
9 | lastName: String
10 | ) extends Person
11 | final case class Customer(id: java.util.UUID, firstName: String, lastName: String, email: String) extends Person
12 |
13 | @GQLInterface
14 | @GQLDescription("""person
15 | Admin or Customer""")
16 | sealed trait Person extends scala.Product with scala.Serializable {
17 | def id: java.util.UUID
18 | def firstName: String
19 | def lastName: String
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/interface, abstracted effect and lazy combination.scala:
--------------------------------------------------------------------------------
1 | import Types._
2 |
3 | import caliban.schema.Annotations._
4 |
5 | object Types {
6 |
7 | final case class T0[F[_]](i: F[Int]) extends Direct[F]
8 | final case class T1[F[_]](i: scala.Option[T2[F]]) extends Transitive[F]
9 | final case class T2[F[_]](i: F[scala.Option[Int]])
10 |
11 | @GQLInterface
12 | sealed trait Direct[F[_]] extends scala.Product with scala.Serializable {
13 | def i: F[Int]
14 | }
15 |
16 | @GQLInterface
17 | sealed trait Transitive[F[_]] extends scala.Product with scala.Serializable {
18 | def i: scala.Option[T2[F]]
19 | }
20 |
21 | }
22 |
23 | object Operations {
24 |
25 | final case class Query[F[_]](
26 | t0: F[T0[F]],
27 | t1: F[T1[F]]
28 | )
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/recognize @lazy intention and generate side-effecting field with abstracted effect type.scala:
--------------------------------------------------------------------------------
1 | object Types {
2 |
3 | final case class Foo[F[_]](bar: String, baz: F[String])
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/recognize @lazy intention and generate side-effecting field.scala:
--------------------------------------------------------------------------------
1 | object Types {
2 |
3 | final case class Foo(bar: String, baz: zio.UIO[String])
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/scala reserved word used.scala:
--------------------------------------------------------------------------------
1 | object Types {
2 |
3 | final case class Character(`private`: String, `object`: String, `type`: String)
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/schema test.scala:
--------------------------------------------------------------------------------
1 | import Types._
2 |
3 | import zio.stream.ZStream
4 |
5 | object Types {
6 | final case class MutationAddPostArgs(author: scala.Option[String], comment: scala.Option[String])
7 | final case class Post(author: scala.Option[String], comment: scala.Option[String])
8 |
9 | }
10 |
11 | object Operations {
12 |
13 | final case class Query(
14 | posts: zio.UIO[scala.Option[List[scala.Option[Post]]]]
15 | )
16 |
17 | final case class Mutation(
18 | addPost: MutationAddPostArgs => zio.UIO[scala.Option[Post]]
19 | )
20 |
21 | final case class Subscription(
22 | postAdded: ZStream[Any, Nothing, scala.Option[Post]]
23 | )
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/schema.scala:
--------------------------------------------------------------------------------
1 | object Operations {
2 |
3 | final case class Queries(
4 | characters: zio.UIO[Int]
5 | )
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/simple mutation with abstracted effect type.scala:
--------------------------------------------------------------------------------
1 | import Types._
2 |
3 | object Types {
4 | final case class MutationSetMessageArgs(message: scala.Option[String])
5 |
6 | }
7 |
8 | object Operations {
9 |
10 | final case class Mutation[F[_]](
11 | setMessage: MutationSetMessageArgs => F[scala.Option[String]]
12 | )
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/simple mutation.scala:
--------------------------------------------------------------------------------
1 | import Types._
2 |
3 | object Types {
4 | final case class MutationSetMessageArgs(message: scala.Option[String])
5 |
6 | }
7 |
8 | object Operations {
9 |
10 | final case class Mutation(
11 | setMessage: MutationSetMessageArgs => zio.UIO[scala.Option[String]]
12 | )
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/simple queries with abstracted effect type.scala:
--------------------------------------------------------------------------------
1 | import Types._
2 |
3 | object Types {
4 | final case class QueryUserArgs(id: scala.Option[Int])
5 | final case class User(id: scala.Option[Int], name: scala.Option[String], profilePic: scala.Option[String])
6 |
7 | }
8 |
9 | object Operations {
10 |
11 | final case class Query[F[_]](
12 | user: QueryUserArgs => F[scala.Option[User]],
13 | userList: F[List[scala.Option[User]]]
14 | )
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/simple queries.scala:
--------------------------------------------------------------------------------
1 | import Types._
2 |
3 | object Types {
4 | final case class QueryUserArgs(id: scala.Option[Int])
5 | final case class User(id: scala.Option[Int], name: scala.Option[String], profilePic: scala.Option[String])
6 |
7 | }
8 |
9 | object Operations {
10 |
11 | final case class Query(
12 | user: QueryUserArgs => zio.UIO[scala.Option[User]],
13 | userList: zio.UIO[List[scala.Option[User]]]
14 | )
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/simple subscription.scala:
--------------------------------------------------------------------------------
1 | import Types._
2 |
3 | import zio.stream.ZStream
4 |
5 | object Types {
6 | final case class SubscriptionUserWatchArgs(id: Int)
7 |
8 | }
9 |
10 | object Operations {
11 |
12 | final case class Subscription(
13 | UserWatch: SubscriptionUserWatchArgs => ZStream[Any, Nothing, String]
14 | )
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/type appears in type union and implements interface.scala:
--------------------------------------------------------------------------------
1 | import Types._
2 |
3 | import caliban.schema.Annotations._
4 |
5 | object Types {
6 |
7 | final case class Bar(message: String) extends Error with AllErrors derives caliban.schema.Schema.SemiAuto
8 | final case class Foo(message: String) extends Error with AllErrors derives caliban.schema.Schema.SemiAuto
9 | final case class FooBar(message: String) extends Error with AllErrors derives caliban.schema.Schema.SemiAuto
10 |
11 | sealed trait AllErrors extends scala.Product with scala.Serializable derives caliban.schema.Schema.SemiAuto
12 | @GQLInterface
13 | sealed trait Error extends scala.Product with scala.Serializable derives caliban.schema.Schema.SemiAuto {
14 | @GQLDescription("description")
15 | def message: String
16 | }
17 |
18 | }
19 |
20 | object Operations {
21 |
22 | final case class Query(
23 | errorInterface: zio.UIO[Error],
24 | errorUnion: zio.UIO[AllErrors]
25 | ) derives caliban.schema.Schema.SemiAuto
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/type with field parameter.scala:
--------------------------------------------------------------------------------
1 | object Types {
2 | final case class HeroNameArgs(pad: Int)
3 | final case class Hero(name: HeroNameArgs => String, nick: String, bday: scala.Option[Int])
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/union type.scala:
--------------------------------------------------------------------------------
1 | import caliban.schema.Annotations._
2 |
3 | object Types {
4 |
5 | final case class Captain(
6 | @GQLDescription("ship")
7 | shipName: String
8 | ) extends Role
9 | with Role2
10 | final case class Pilot(shipName: String) extends Role with Role2
11 | final case class Stewart(shipName: String) extends Role2
12 |
13 | @GQLDescription("""role
14 | Captain or Pilot""")
15 | sealed trait Role extends scala.Product with scala.Serializable
16 | @GQLDescription("""role2
17 | Captain or Pilot or Stewart""")
18 | sealed trait Role2 extends scala.Product with scala.Serializable
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/tools/src/test/resources/snapshots/SchemaWriterSpec/union, abstracted effect type and lazy combination.scala:
--------------------------------------------------------------------------------
1 | import Types._
2 |
3 | object Types {
4 | final case class BLazyFieldWithArgsArgs(int: scala.Option[Int])
5 | final case class A[F[_]](lazyField: F[scala.Option[Int]]) extends U0[F]
6 | final case class B[F[_]](lazyFieldWithArgs: BLazyFieldWithArgsArgs => F[scala.Option[Int]]) extends U0[F]
7 | final case class C[F[_]](field: scala.Option[Int]) extends U0[F] with U1
8 | final case class D(field: scala.Option[Int]) extends U1
9 |
10 | sealed trait U0[F[_]] extends scala.Product with scala.Serializable
11 | sealed trait U1 extends scala.Product with scala.Serializable
12 |
13 | }
14 |
15 | object Operations {
16 |
17 | final case class Query[F[_]](
18 | effectful: F[U0[F]],
19 | pure: F[U1]
20 | )
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/tools/src/test/scala/caliban/tools/compiletime/UtilsSpec.scala:
--------------------------------------------------------------------------------
1 | package caliban.tools.compiletime
2 |
3 | import zio.test._
4 |
5 | object UtilsSpec extends ZIOSpecDefault {
6 |
7 | private val toPathDirSpec =
8 | suite(".toPathDir")(
9 | test("returns a different path according to the `baseDir` passed") {
10 | val result_0 = Utils.toPathDir("/user/Jules/workspace/awesome-project", "io.example.awesome.project.generated")
11 | val result_1 = Utils.toPathDir(
12 | "/user/Jules/workspace/awesome-project/target/scala-2.13/src_managed/main",
13 | "io.example.awesome.project.generated"
14 | )
15 |
16 | assertTrue(
17 | result_0 == "/user/Jules/workspace/awesome-project/src/main/scala/io/example/awesome/project/generated"
18 | ) &&
19 | assertTrue(
20 | result_1 == "/user/Jules/workspace/awesome-project/target/scala-2.13/src_managed/main/io/example/awesome/project/generated"
21 | )
22 | }
23 | )
24 |
25 | override def spec =
26 | suite("Utils spec")(
27 | toPathDirSpec
28 | )
29 | }
30 |
--------------------------------------------------------------------------------
/tracing/src/main/scala/caliban/tracing/FieldTracer.scala:
--------------------------------------------------------------------------------
1 | package caliban.tracing
2 |
3 | import caliban.{ CalibanError, ResponseValue }
4 | import caliban.execution.FieldInfo
5 | import caliban.wrappers.Wrapper.FieldWrapper
6 | import io.opentelemetry.api.trace.StatusCode
7 | import zio._
8 | import zio.query.ZQuery
9 | import zio.telemetry.opentelemetry.tracing.{ StatusMapper, Tracing }
10 |
11 | object FieldTracer {
12 | val wrapper = new FieldWrapper[Tracing] {
13 | def wrap[R <: Tracing](
14 | query: ZQuery[R, CalibanError.ExecutionError, ResponseValue],
15 | info: FieldInfo
16 | ): ZQuery[R, CalibanError.ExecutionError, ResponseValue] =
17 | ZQuery.acquireReleaseWith(
18 | ZIO.serviceWithZIO[Tracing](_.spanUnsafe(info.name))
19 | ) { case (_, end) => end } { case (span, _) =>
20 | query.foldCauseQuery(
21 | cause =>
22 | ZQuery.failCause {
23 | val status =
24 | cause.failureOption.flatMap(StatusMapper.default.failure.lift).fold(StatusCode.ERROR)(_.statusCode)
25 | span.setStatus(status, cause.prettyPrint)
26 | cause
27 | },
28 | value => ZQuery.succeed(value)
29 | )
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/tracing/src/main/scala/caliban/tracing/TracingWrapper.scala:
--------------------------------------------------------------------------------
1 | package caliban.tracing
2 |
3 | object TracingWrapper {
4 | val traced = SchemaTracer.wrapper @@ FieldTracer.wrapper
5 | }
6 |
--------------------------------------------------------------------------------
/vuepress/docs/.vuepress/public/.nojekyll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ghostdogpr/caliban/24a568744f6708a4f400d7f8f5f158b002f29806/vuepress/docs/.vuepress/public/.nojekyll
--------------------------------------------------------------------------------
/vuepress/docs/.vuepress/public/caliban.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ghostdogpr/caliban/24a568744f6708a4f400d7f8f5f158b002f29806/vuepress/docs/.vuepress/public/caliban.png
--------------------------------------------------------------------------------
/vuepress/docs/.vuepress/styles/index.styl:
--------------------------------------------------------------------------------
1 | .home .hero img {
2 | max-height: 200px !important;
3 | }
4 |
--------------------------------------------------------------------------------
/vuepress/docs/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | home: true
3 | heroImage: /caliban.svg
4 | actionText: Get Started →
5 | actionLink: /docs/
6 | features:
7 | - title: High performance
8 | details: While all public interfaces are pure and immutable, the library's internals are optimized for speed.
9 | - title: Minimal boilerplate
10 | details: No need to manually define schemas for every type in your API. Let the compiler handle the tedious work.
11 | - title: Excellent interoperability
12 | details: Out-of-the-box support for major HTTP server libraries, effect types, JSON libraries, and more.
13 | ---
--------------------------------------------------------------------------------
/vuepress/docs/about/README.md:
--------------------------------------------------------------------------------
1 | # About
2 |
3 | Caliban is a project created by Pierre Ricadat aka [@ghostdogpr](https://github.com/ghostdogpr).
4 |
5 | Current maintainers:
6 | - [@ghostdogpr](https://github.com/ghostdogpr)
7 | - [@paulpdaniels](https://github.com/paulpdaniels)
8 | - [@frekw](https://github.com/frekw)
9 | - [@kyri-petrou](https://github.com/kyri-petrou)
10 |
11 | The name is inspired by the SF novel and tv series [The Expanse](https://en.wikipedia.org/wiki/Caliban%27s_War).
12 |
13 | **Thanks**:
14 | - [@deckerst](https://github.com/deckerst) for the logo
15 | - [@yoohaemin](https://github.com/yoohaemin), [@adamgfraser](https://github.com/adamgfraser) and [@jdegoes](https://github.com/jdegoes) for the early feedback
16 | - the [Morpheus](https://morpheusgraphql.com/) library in Haskell for the inspiration leading to the GraphQL backend implementation
17 | - the [elm-graphql](https://github.com/dillonkearns/elm-graphql) library for the inspiration leading to the GraphQL client implementation
18 | - all Caliban's [contributors](https://github.com/ghostdogpr/caliban/graphs/contributors)!
--------------------------------------------------------------------------------
/vuepress/docs/docs/tools.md:
--------------------------------------------------------------------------------
1 | # Getting Started
2 |
3 | Caliban comes with a module called `caliban-tools` that exposes some useful features:
4 | - all the code generation features from `caliban-codegen-sbt`, so that you can use them without sbt: see `caliban.tools.Codegen`.
5 | - a client for GraphQL introspection: see `caliban.tools.IntrospectionClient`.
6 | - utilities for [stitching GraphQL schemas](stitching.md).
7 | - a way to [compare GraphQL schemas](schema-comparison.md), whether they come from Caliban or a remote server.
8 |
9 | ## Dependency
10 |
11 | ```scala
12 | "com.github.ghostdogpr" %% "caliban-tools" % "2.10.0"
13 | ```
14 |
--------------------------------------------------------------------------------
/vuepress/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "devDependencies": {
3 | "vuepress": "^1.9.9"
4 | },
5 | "scripts": {
6 | "docs:dev": "vuepress dev docs",
7 | "docs:build": "vuepress build docs"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------