SwiftGraphQLClient is a SwiftPM GraphQL toolkit built as Kindred's typed GraphQL runtime and codegen stack.
Current status: the Kindred replacement surface and the Apollo iOS parity layers are in place and tested. The implemented surface covers the core HTTP client, GraphQL input/runtime types, auth headers, GraphQL error parsing, refresh retry coordination, normalized cache integration, local cache mutations, multipart upload requests, subscription transports, HTTP multipart incremental delivery with typed patch merging, APQ/persisted query requests, introspection SDL export, operation manifests, and native Swift operation generation.
The codegen CLI can read the current YAML config or a legacy JSON config, parse schema scalars/enums/input objects/object/interface/union fields plus operation and fragment selections, and emit operation structs, input objects, fragments, scalar aliases, abstract-type projections, local cache mutation helpers, and nested Codable response Data models under the configured namespace.
- You want a Swift-native GraphQL client that keeps operation definitions, generated types, runtime execution, and cache integration in one SwiftPM package.
- You need typed queries, mutations, subscriptions, fragments, input objects,
custom scalar mappings, and generated
Codableresponse models without maintaining a separate JavaScript codegen toolchain. - You want modular adoption: use only the HTTP runtime, then add normalized caching, SQLite persistence, uploads, WebSocket subscriptions, AppSync realtime transport, or the SwiftPM codegen plugin as your app needs them.
- You need production-oriented runtime behavior such as auth headers, coordinated refresh-on-401 retry, multipart uploads, GraphQL error parsing, cache policies, optimistic cache layers, and reconnecting subscriptions.
- You prefer Swift concurrency APIs and package-local generated sources that fit iOS and macOS builds without extra application-level scaffolding.
SwiftGraphQLClient: typed operation protocols, HTTP runtime, auth providers, errors, scalars.SwiftGraphQLCache: in-memory normalized record store with watchers, partial-read detection, optimistic layers, and cursor-list reference helpers.SwiftGraphQLSQLiteStore: SQLite normalized record persistence.SwiftGraphQLUpload:GraphQLUpload, multipart request body builder, and upload-aware request encoder.SwiftGraphQLWebSocket: single-operation and multiplexedgraphql-transport-wssubscription transports.SwiftGraphQLAppSync: single-operation and multiplexed AppSync realtime transports.SwiftGraphQLPagination: cursor, offset, directional, and query pager helpers.SwiftGraphQLTestSupport: mock client and typed test data builder helpers.swift-graphql: CLI for introspection SDL export and Swift generation.swift-graphql-codegen: compatibility CLI alias for existing generation scripts.SwiftGraphQLCodegenPlugin: SwiftPM build tool plugin that runs generation fromswift-graphql-codegen.yml.
let client = GraphQLClient(configuration: .init(
endpointURL: URL(string: "https://example.com/graphql")!,
authProvider: BearerTokenAuthProvider(token: "token")
))
let data = try await client.fetch(KindredAPI.HomeQuery(...))
let result = try await client.perform(KindredAPI.SendMessageMutation(...))
let stream = client.subscribe(KindredAPI.MessageCreatedSubscription(...))- GraphQL-over-HTTP
POST. Accept: application/graphql-response+json, application/json;q=0.9.GraphQLOperation,GraphQLQuery,GraphQLMutation,GraphQLSubscription.GraphQLNullable.none/null/some.GraphQLEnum.GraphQLID.GraphQLJSON.GraphQLResult,GraphQLError,GraphQLClientError.GraphQLSubscriptionTransportplusGraphQLClient.subscribe.GraphQLOperationCacheplusGraphQLClient.fetch(..., cachePolicy:)support fornetworkOnly,cacheFirst,cacheOnly,cacheAndNetwork, andnoCache.- Bearer token, API key, and custom header auth providers.
- Device fingerprint and custom headers.
- Single coordinated refresh-on-401 retry.
- GraphQL variable builder with omitted-vs-null support.
- Multipart upload body builder plus
GraphQLUploadRequestEncoderfor auto-switching configured clients to multipart when upload variables are present. - Automatic persisted query and safelisted persisted query request modes, including operation SHA-256 identifiers and APQ fallback retry.
- Request and response interceptor hooks for custom networking pipelines.
- HTTP multipart response parsing for incremental
@defer-style responses throughGraphQLClient.fetchIncremental. - Incremental patch merging for
@defer/@streamresponses throughGraphQLClient.fetchIncrementalMerged. - HTTP multipart subscription transport through
GraphQLHTTPSubscriptionTransport. - Fragment projection helper for generated
.fragments.fooaccessors. - Standard
graphql-transport-wstransports for connection init, subscribe, ping/pong, next/error/complete message decoding, reconnect, keepalive timeout, fresh auth headers per reconnect, generated subscription streams, and optional single-socket multiplexing viaGraphQLMultiplexedWebSocketClient. - AppSync realtime transports for
graphql-wsconnection init, start, stop, ack/keepalive/data/error/complete message decoding, reconnect, keepalive timeout, fresh auth headers per reconnect, generated subscription streams, and optional single-socket multiplexing viaAppSyncMultiplexedRealtimeClient. - Introspection JSON to SDL conversion plus
swift-graphql-codegen introspect --endpoint ... --output .... - Codegen emits
Upload = GraphQLUploadand importsSwiftGraphQLUploadwhen the schema declaresscalar Upload. - Codegen supports scalar mappings via
scalars,scalarMappings, orcustomScalarsinswift-graphql-codegen.yml. - Codegen emits stable
operationIdentifiervalues and can generate or publish Apollo persisted-query-compatible operation manifests. - Codegen models
interfaceandunionselections with optionalasTypeprojections for inline fragments and concrete fragment spreads. - Codegen emits per-operation
localCacheMutation(data:)helpers for typed cache writes. - Codegen emits fragment selection metadata for cache partial-read detection through fragment spreads.
- SwiftPM build tool plugin discovers
swift-graphql-codegen.yml/.yamlin the target or package root and emits generated sources into the plugin work directory.
- Normalized records keyed by
GraphQLRecordID. - Merge writes and field-level partial read detection.
- Record watchers via
AsyncStream. - Eviction and clear.
- Prefix removal, oldest-record trimming, and record ID listing.
- Optimistic layer write, eviction, rollback, and commit.
- Programmatic cache key resolvers that take precedence over declarative/custom key fields.
- ApolloStore-style
GraphQLOperationCacheStore.withinReadWriteTransactionfor typed read/write/update cache transactions. - Generated local cache mutations can be written through
GraphQLReadWriteTransaction.write(_:). - Cursor/list reference append with deduplication.
- SQLite-backed record persistence with merge writes, partial-read detection, eviction, clear, batch transactions, and WAL mode.
GraphQLNormalizedCachebridges normalized records intoGraphQLClientcache policies, stores entities by__typename:idby default, supports custom key fields, and falls back to stable response paths for unkeyed objects.SQLiteNormalizedCacheprovides the sameGraphQLOperationCachebridge on top of SQLite persistence.
See KindredGraphQLMigrationInventory.md for the Kindred GraphQL migration inventory.
See ApolloMigrationGuide.md for common Apollo iOS API replacements.
See SwiftGraphQLClient-0.6.0-Plan.md for the next production-hardening plan.
Kindred smoke-test command used during development:
swift run swift-graphql generate \
--config /path/to/kindred_mobile/swift-graphql-codegen.yml \
--output /private/tmp/kindred-swift-graphql-generated-typedIntrospection command:
swift run swift-graphql introspect \
--endpoint https://example.com/graphql \
--header "Authorization: Bearer TOKEN" \
--output schema.graphqlsOperation manifest command:
swift run swift-graphql generate-operation-manifest \
--config swift-graphql-codegen.yml \
--output operation-manifest.jsonOperation manifest publish command:
swift run swift-graphql publish-operation-manifest \
--manifest operation-manifest.json \
--endpoint https://example.com/persisted-query-manifest \
--header "Authorization: Bearer TOKEN"