{"id":32643414,"url":"https://github.com/graphqlswift/graphqlws","last_synced_at":"2025-10-31T03:54:22.796Z","repository":{"id":44305869,"uuid":"512032251","full_name":"GraphQLSwift/GraphQLWS","owner":"GraphQLSwift","description":"Swift implementation of the graphql-ws WebSocket subprotocol.","archived":false,"fork":false,"pushed_at":"2025-09-22T22:50:42.000Z","size":84,"stargazers_count":2,"open_issues_count":1,"forks_count":3,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-09-23T00:24:36.660Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/GraphQLSwift.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-07-08T21:38:36.000Z","updated_at":"2023-04-12T17:44:40.000Z","dependencies_parsed_at":"2025-08-29T05:19:29.055Z","dependency_job_id":"7ba80dfc-7229-4e4f-81b9-3fad390b934f","html_url":"https://github.com/GraphQLSwift/GraphQLWS","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/GraphQLSwift/GraphQLWS","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GraphQLSwift%2FGraphQLWS","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GraphQLSwift%2FGraphQLWS/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GraphQLSwift%2FGraphQLWS/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GraphQLSwift%2FGraphQLWS/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GraphQLSwift","download_url":"https://codeload.github.com/GraphQLSwift/GraphQLWS/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GraphQLSwift%2FGraphQLWS/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":281925791,"owners_count":26584821,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-31T02:00:07.401Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-10-31T03:54:17.079Z","updated_at":"2025-10-31T03:54:22.788Z","avatar_url":"https://github.com/GraphQLSwift.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GraphQLWS\n\nThis implements the [graphql-ws WebSocket subprotocol](https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md).\nIt is mainly intended for server support, but there is a basic client implementation included.\n\nFeatures:\n- Server implementation that implements defined protocol conversations\n- Client and Server types that wrap messengers\n- Codable Server and Client message structures\n- Custom authentication support\n\n## Usage\n\nTo use this package, include it in your `Package.swift` dependencies:\n\n```swift\n.package(url: \"git@gitlab.com:PassiveLogic/platform/GraphQLWS.git\", from: \"\u003cversion\u003e\"),\n```\n\nThen create a class to implement the `Messenger` protocol. Here's an example using\n[`WebSocketKit`](https://github.com/vapor/websocket-kit):\n\n```swift\nimport WebSocketKit\nimport GraphQLWS\n\n/// Messenger wrapper for WebSockets\nclass WebSocketMessenger: Messenger {\n    private weak var websocket: WebSocket?\n    private var onReceive: (String) -\u003e Void = { _ in }\n\n    init(websocket: WebSocket) {\n        self.websocket = websocket\n        websocket.onText { _, message in\n            try await self.onReceive(message)\n        }\n    }\n\n    func send\u003cS\u003e(_ message: S) async throws where S: Collection, S.Element == Character async throws {\n        guard let websocket = websocket else { return }\n        try await websocket.send(message)\n    }\n\n    func onReceive(callback: @escaping (String) async throws -\u003e Void) {\n        self.onReceive = callback\n    }\n\n    func error(_ message: String, code: Int) async throws {\n        guard let websocket = websocket else { return }\n        try await websocket.send(\"\\(code): \\(message)\")\n    }\n\n    func close() async throws {\n        guard let websocket = websocket else { return }\n        try await websocket.close()\n    }\n}\n```\n\nNext create a `Server`, provide the messenger you just defined, and wrap the API `execute` and `subscribe` commands:\n\n```swift\nroutes.webSocket(\n    \"graphqlSubscribe\",\n    onUpgrade: { request, websocket in\n        let messenger = WebSocketMessenger(websocket: websocket)\n        let server = GraphQLWS.Server\u003cEmptyInitPayload?\u003e(\n            messenger: messenger,\n            onExecute: { graphQLRequest in\n                try await api.execute(\n                    request: graphQLRequest.query,\n                    context: context,\n                    on: self.eventLoop,\n                    variables: graphQLRequest.variables,\n                    operationName: graphQLRequest.operationName\n                )\n            },\n            onSubscribe: { graphQLRequest in\n                try await api.subscribe(\n                    request: graphQLRequest.query,\n                    context: context,\n                    on: self.eventLoop,\n                    variables: graphQLRequest.variables,\n                    operationName: graphQLRequest.operationName\n                )\n            }\n        )\n    }\n)\n```\n\n### Authentication\n\nThis package exposes authentication hooks on the `connection_init` message. To perform custom authentication,\nprovide a codable type to the Server init and define an `auth` callback on the server. For example:\n\n```swift\nstruct UsernameAndPasswordInitPayload: Equatable \u0026 Codable {\n    let username: String\n    let password: String\n}\n\nlet server = GraphQLWS.Server\u003cUsernameAndPasswordInitPayload\u003e(\n    messenger: messenger,\n    onExecute: { ... },\n    onSubscribe: { ... }\n)\nserver.auth { payload in\n    guard payload.username == \"admin\" else {\n        throw Abort(.unauthorized)\n    }\n}\n```\n\nThis example would require `connection_init` message from the client to look like this:\n\n```json\n{\n    \"type\": \"connection_init\",\n    \"payload\": {\n        \"username\": \"admin\",\n        \"password\": \"supersafe\"\n    }\n}\n```\n\nIf the `payload` field is not required on your server, you may make Server's generic declaration optional like `Server\u003cPayload?\u003e`\n\n## Memory Management\n\nMemory ownership among the Server, Client, and Messenger may seem a little backwards. This is because the Swift/Vapor WebSocket\nimplementation persists WebSocket objects long after their callback and they are expected to retain strong memory references to the\nobjects required for responses. In order to align cleanly and avoid memory cycles, Server and Client are injected strongly into Messenger\ncallbacks, and only hold weak references to their Messenger. This means that Messenger objects (or their enclosing WebSocket) must\nbe persisted to have the connected Server or Client objects function. That is, if a Server's Messenger falls out of scope and deinitializes,\nthe Server will no longer respond to messages.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgraphqlswift%2Fgraphqlws","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgraphqlswift%2Fgraphqlws","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgraphqlswift%2Fgraphqlws/lists"}