An opinionated Swift GraphQL Code Generator CLI tool which generate the GraphQL Query and doesn't require any dependencies (Library/Framework) in your app.
- 🏖️ Zero GraphQL Query to be written manually
- ✨ Zero library/framework dependency in the app
- 🎉 Plain Swift Types with Type Safety
- 🎊 Network Layer agnostic, use whichever networking library you prefer
- 🚀 Favor Swift coding convention whenever applicable/possible
- 🤏 Minimal code to be written to get started
Usage example without writing a single line of GraphQL query
// Auto generated Request Model
let request = VendorQueryRequest(
name: "vendor name", // Argument1 is code-generated
country: .sg, // Argument2 is code-generated
)
// Auto generated ApiClient
let vendor = apiClient.vendor(
with: request,
// Auto generated Selections class, this allows you to select
// specifically which fields to be returned for this request
selections: VendorQuerySelections(
// An array of Enum representing the fields to be returned
vendor: [.id, .name, .attributes],
// Alternatively, you can use `.allFields` explicitly to return all fields
// All selections have `.allFields` as default value, so it's optional to explicitly assign this value.
attributes: .allFields
)
)
// Additional mapping if necessary
.map { response in // Response Model are auto generated
// Assuming you have a Vendor domain model, this is how you would map it
Vendor(
// Similar to how Decodable can throw an Error, the fields in Response Model
// are throwable so the proper error context can be returned to you for
// debugging purpose, e.g.: Selection are missing for field name ***, please
// rectify it by selecting the field.
id: try response.id
name: try response.name,
attributes: try response.attributes
)
return responseModel
}
// RxSwift
.subscribe...
Further reading
- GETSTARTED.md Step by step tutorial with examples on how to setup and integrate with the code generation tool.
- TEMPLATES.md Collections of template to help you get started with the code generation tool.
- CONFIG.md Overview on how to setup the config file
- STRUCTURE.md For overview of the entire code generation implementation structure
- ADVANCED.md For detailed explanation of each sub-commands beyond
bootstrap
- ISSUES.md List of known issues
- CONTRIBUTE.md How to contribute to this repository
Code implementation is created based on swift-graphl AST
Supports GraphQL Native Feature
- Object
- InputValue
- InputObject
- Enum / Enumeration
- Interface
- Union
- Query
- Mutation
- Subscription; Codes are generated except for ApiClient because ApiClient have no implementation for WebSocket yet
- Introspection
- Root level query
- Recursive fragment resolution (Up to 5 recursion)
- Directive, no plan to support it atm.
- Aliases, no plan to support it atm.
Support Custom Requirements
- SPM package
- Brew package
- Local schema
- Remote schema, download using introspection query
- Remote schema authorization headers
- Remote schema cache
- Scalar Map extension
- Entity Name Map, override entity naming convention using config
- Custom field whitelisting
- Custom query/mutation/subscription whitelisting
- Support for custom unknown enum, this is necessary to ensure the generated code can work with future unknown enum value
- Support for optional namespace to avoid naming collision
- Default APIClient
- Provide service dependency injection for APIClient
- Subcommand to simplify code generation
- Support for Apollo Automated Persisted Queries (APM)
- Cache
TODO
- Nested field selection with arguments is not handled yet
- ApiClientPrefix needs to be removed from EntityNameMap
- Rewrite ApiClient generator to use URLSession
- Add support for async await for the generated ApiClient
- Ramp up test cases for the generated classes
- Ramp up documentation
- Setting up CI workflow to run the test for each PR
- Adding performance metric when generating GraphQL Query at runtime
Future
- Mapper class, the mapping logic will also be used to compute the selections automatically
brew tap lromyl/tap
brew install swift-graphql-codegen
# if there are conflict, use the command below instead
brew install lromyl/tap/swift-graphql-codegen
Goto GETSTARTED.md for detailed step-by-step to installing the CLI, setting up environment variables and examples on integration.
Download remote schema as introspection file
Type | Name | Optional | Description |
---|---|---|---|
argument | schema |
No | Path or URL of the GraphQL Schema |
option | --output-path |
No | The directory to generate all the files |
option | --output |
Yes | The file name, default is schema.json |
Example command
swift-graphql-codegen introspection "https://www.domain.com" --output-path "directory_name"
Generate GraphQL files
Type | Name | Optional | Description |
---|---|---|---|
argument | schema | No | Path or URL of the GraphQL Schema |
option | --output-path |
No | The directory to generate all the files |
option | --api-client-prefix |
No | The prefix to generate ApiClient related files, this will affect the folders and class name |
option | --schema-source |
Yes | Source of the schema, local and remote |
option | --config-path |
Yes | File path of the configuration |
flag | --is-throwable-getter-enabled |
Yes | Specify if the generated code could use throwable getter introduced in Swift 5.5 |
There are other optional option that can be used to manipulate the generated file names, type swift-graphql-codegen bootstrap --help
command to see the full list
Example command
swift-graphql-codegen bootstrap "schema.json" --config-path "config.json" --output-path "API" --api-client-prefix "Groceries"
apollo-ios is the most popular GraphQL codegeneration tool for Swift that comes with networking layer, web socket, caching and etc.
The a few key differences between apollo-ios and swift-graphql-codegen
- swift-graphql-codegen generated codes have no external dependencies, so you can continue to use whichever networking framework in your project without importing a new dependencies.
- swift-graphql-codegen handle on generate most of the common
GraphQL Operation
on code level so you don't have to write a single line of GraphQL syntax. - apollo-ios generate unique models for every single
GraphQL Operation
you include in the projects so there are a lot of redundant codes, it can easily have more than ten thousands lines of generated code if you have a moderate size backend with more than 10GraphQL Operation
.- Using the Apollo Fullstack Tutorial as a benchmark
- apollo-ios will generate
8000+
lines of code for15
GraphQL Operation
- swift-graphql-codegen will generate
2000+
lines of code irregardless of how manyGraphQL Operation
you will need. - For our use case, the backend are much larger than the sample project in the tutorial and have at least
50+
GraphQL Operation
, thus using apollo-ios is not feasible at all.
swift-graphql-codegen is designed with swift-grapqhl as a reference so there are a lot of similarities in how it works
The key differences are
- swift-grapqhl-codegen generated code doesn't have dependencies on any networking layer
- swift-graphql-codegen request and selection is done on request model, so it's decoupled from the mapping logic while swift-grapqhl derived the selections directly from the mapping logic.
swift-graphql
mapping and selection logic is tightly coupled so you will need to define how the mapping is done before a request can be executed.- This approach provide build-time safety at the expense of more boilerplate up-front and possibly a violation of single responsibility.
swift-graphql-codegen
decoupled both selection and mapping logic so it's possible to execute the query without defining the mapping logic.- The mapping-selection logic can be included in the next phase as an optional module which provides build-time safety.
swift-graphql-codegen
defined selections and arguments on request parameter whileswift-graphql
defined it through mapping logic. Both implementations are entirely different so please read the code example for more insight.