{"id":13621218,"url":"https://github.com/bufbuild/knit","last_synced_at":"2025-08-28T12:41:03.371Z","repository":{"id":161861931,"uuid":"632011522","full_name":"bufbuild/knit","owner":"bufbuild","description":"GraphQL-like capabilities to services using Protocol Buffers, gRPC, and Connect","archived":false,"fork":false,"pushed_at":"2025-08-28T02:07:52.000Z","size":313,"stargazers_count":159,"open_issues_count":2,"forks_count":4,"subscribers_count":12,"default_branch":"main","last_synced_at":"2025-08-28T05:56:15.940Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://github.com/bufbuild/knit","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bufbuild.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}},"created_at":"2023-04-24T14:23:24.000Z","updated_at":"2025-08-27T21:43:04.000Z","dependencies_parsed_at":"2024-04-19T15:34:29.374Z","dependency_job_id":"dd5e4d9a-373c-4aee-9c6a-4825ad23b90f","html_url":"https://github.com/bufbuild/knit","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/bufbuild/knit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bufbuild%2Fknit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bufbuild%2Fknit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bufbuild%2Fknit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bufbuild%2Fknit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bufbuild","download_url":"https://codeload.github.com/bufbuild/knit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bufbuild%2Fknit/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272492651,"owners_count":24943816,"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-08-28T02:00:10.768Z","response_time":74,"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":"2024-08-01T21:01:03.709Z","updated_at":"2025-08-28T12:41:03.320Z","avatar_url":"https://github.com/bufbuild.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"# 🧶 Knit\n[![License](https://img.shields.io/github/license/bufbuild/knit?color=blue)][badges_license]\n[![Slack](https://img.shields.io/badge/slack-buf-%23e01563)][badges_slack]\n\n**Knit brings GraphQL-like capabilities to RPCs. Knit has type-safe and\ndeclarative queries that shape the response, batching support to eliminate\nthe N+1 problem, and first-class support for error handling with partial\nresponses. It is built on top of Protobuf and Connect.**\n\n**Deploy the Knit gateway to call all of your Connect/gRPC services from\nthe web with the Knit client over HTTP/1.1 or HTTP/2. No changes to your\nservices are needed to use type-safe declarative queries, response masking, or the\nerror handling. Use more advanced feature like relations and partial responses\nas the need arises.**\n\n**Knit is currently in alpha (α), and looking for feedback. Learn how to use it with the [Tutorial].**\n\n---\nMap of Knit repositories:\n- **[github.com/bufbuild/knit]**: You are here 🚀\n- **[github.com/bufbuild/knit-ts]**: Knit client and embeddable gateway in TypeScript\n- **[github.com/bufbuild/knit-go]**: Knit standalone gateway and embeddable gateway in Go\n- **[github.com/bufbuild/knit-proto]**: Protobuf custom options and gateway protocol definition\n- **[github.com/bufbuild/knit-demo]**: Source for the demo app at https://knit-demo.connect.build/\n\n## Overview\n```mermaid\n%%{ init: { 'flowchart': { 'curve': 'basis' } } }%%\nflowchart LR\n\nsubgraph b [Browser]\n  C[Knit Client]\nend\n\nsubgraph i [Cloud]\n  G[Knit Gateway]\n  X[Service X]\n  Y[Service Y]\n  Z[Service Z]\nend\n\nC -- http --\u003e G\nG -- gRPC --\u003e X\nG -- gRPC-web --\u003e Y\nG -- connect --\u003e Z\n```\n## Client queries\nKnit clients specify declarative queries that pull data from multiple backend APIs\nin a single call via the Knit gateway. Knit queries can shape the data into a\nhierarchy that matches the needs of the caller, and can filter the response to get\nonly the fields the caller actually uses.\n\nThe example query below is from the Knit [Tutorial] which uses a Star Wars API as\na running example. Note that queries are actual TypeScript, not just strings:\n\n```TypeScript\nimport type { FilmService } from \"./gen/buf/starwars/film/v1/film_knit\";\nimport type { StarshipService } from \"./gen/buf/starwars/starship/v1/starship_knit\";\nimport type { } from './gen/buf/starwars/relation/v1/relation_knit';\nimport { createClient } from \"@bufbuild/knit\";\n\n// Include the services to use in the schema\ntype Schema = FilmService \u0026 StarshipService;\n\n// Create a client to the Knit gateway\nconst client = createClient\u003cSchema\u003e({\n  baseUrl: \"https://knit-demo.connect.build/\",\n});\n\n// Do the query, getting only what is needed\nconst filmsResult = await client.do({\n  \"buf.starwars.film.v1.FilmService\": {\n    getFilms: {\n      // Use $ to provide the request.\n      $: { ids: [\"1\"] },\n      // Start selecting the fields that you want\n      // in the response. They can be nested as\n      // deep as needed.\n      films: {\n        id: {},\n        title: {},\n        director: {},\n        releaseDate: {},\n        starships: {\n          // This is a relation field, it looks like a\n          // normal field but it is actually coming\n          // from a different rpc.\n          //\n          // It can also be nested as deep as needed\n          // and accept parameters.\n          $: { limit: 10 },\n          id: {},\n          name: {},\n        },\n      },\n    },\n  },\n});\n```\n\n## Client methods\nKnit clients issue requests via three different methods:\n\n`fetch()` for [SAFE][safe] endpoints (GET support coming soon for better browser and CDN caching)\n\n`do()` for mutating endpoints like create/update/delete, and always uses http POST\n\n`listen()` for streaming endpoints, where the backend can continuously stream results to the client\n\n## Reusing queries and co-location\nKnit queries in TypeScript are TS literals, co-location and the ability to use all the constructs of\nTS, like the spread `...` operator, are possible:\n\n```TypeScript\nconst filmQuery = {\n  id: {},\n  title: {},\n} satisfies Query\u003cFilm\u003e; // Use satisfies to ensure the query is valid\n\nconst filmReleaseDates = await client.fetch({\n  \"buf.starwars.film.v1.FilmService\": {\n    getFilms: {\n      $: { ids: [\"1\"] },\n      films: {\n        ...filmQuery,\n        releaseDate: {},\n      },\n    },\n  },\n});\n```\n\n## Multiple queries\nKnit clients can issue multiple queries in a single request. The Knit\ngateway will call these in parallel, gather the results, and respond\nback to the client with a single response.\n\n```TypeScript\nconst filmsAndPeople = await client.fetch({\n  \"buf.starwars.film.v1.FilmService\": {\n    getFilms: {\n      $: { ids: [\"1\"] },\n      films: {\n        title,\n        releaseDate: {},\n      },\n    },\n  },\n  \"buf.starwars.person.v1.PersonService\": {\n    getPeople: {\n      $: { ids: [\"1\"] },\n      people: {\n        name,\n      },\n    },\n  },\n});\n```\n\n## Schema first\nBecause Knit builds on top of Protocol Buffers, it is schema first. This makes\nthe Knit clients strongly typed, improving the developer experience, and gives\naccess to all the tooling that proto schemas have for linting, formatting,\nbreaking change detection, and multi-language code generation. See the [buf CLI]\nfor example.\n\nThis also means that Knit client queries are actual TypeScript object literals,\nand code generation is required only once, not per query.\n\n## Relations between services\nRelations extend the available fields in a type without needing to modify\nthe original proto definition of that type. Relations between entities in\nindependent APIs are created by defining an RPC, and adding the\n`buf.knit.relation` option to the RPC definition.\n\nUsing the `Film` and `Starship` types from the [Tutorial] as an example, a\nrelationship can be made by defining a Knit RPC that extends `Film` with a\n`starships` field usable by the Knit client. One side of the relationship\nis defined in the request message of the RPC defining the relation, the\nother side is defined in the response message:\n\n```protobuf\n// Defined in file film.proto\nmessage Film {\n    string film_id = 1;\n    string title = 2;\n    repeated string starship_ids = 3;\n}\n```\n\n```protobuf\n// Defined in file starship.proto\nmessage Starship {\n    string starship_id = 1;\n    string name = 2;\n    uint64 model = 3;\n}\n```\n\n```protobuf\n// Defined in file relation.proto\nservice RelationService {\n    rpc GetStarshipsForFilm(StarshipsForFilmRequest) returns (StarshipsForFilmResponse) {\n        option (buf.knit.relation).name = \"starships\";\n    }\n}\n\n// Relation requests always need to accept a batch of inputs\nmessage StarshipsForFilmRequest {\n    repeated Film bases = 1;\n}\n\n// Relation responses always return a corresponding batch of outputs\nmessage StarshipsForFilmResponse {\n    repeated Result values = 1;\n    message Result {\n        repeated Starship starships = 1;\n    }\n}\n```\n\nThe difference between just adding a new field to the base type and using a\nKnit relation, is that with a relation, these new fields can be added\nafter-the-fact and without updating the base types.\n\nThe RPCs that define relationships do not need to be put into their own service,\nhowever in the [Tutorial] they have been put into their own `RelationService` so that\nit is clear this is possible.\n\nOnce a relation RPC is defined a Knit client can call the RPCs of the base service,\nin the [Tutorial] that would be the `FilmService` or the `StarshipService`, and use\nthe new field defined in the relation as if it was defined in the base type itself:\n\n```TypeScript\nconst resp = await client.do({\n  \"buf.starwars.film.v1.FilmService\": {\n    getFilms: {\n      $: { filmIds: [\"1\",\"2\"] },\n      films: {\n        title: {},\n        // The \"starships\" field does not exist\n        // on Film, but because of the relation\n        // RPC it is available to use by Knit\n        // clients as if it was defined on Film.\n        starships: {\n          $: {},\n          model: {},\n        },\n      },\n    },\n  },\n});\n```\n\n## Components\nSystems using Knit will have three types of components:\n\n1. Knit clients\n2. gRPC, gRPC-web, or Connect services\n3. Knit gateways (embedded or using the standalone gateway)\n\n### Clients\nKnit clients issue Knit queries to Knit gateways using the Connect\nprotocol over https (or http), making Knit usable in the browser. 🧑‍💻 🌐\n\nThe client is currently only available for TypeScript. Read the [Tutorial]\nto learn how to use the client, or see  [github.com/bufbuild/knit-ts] for\ndetailed specifics.\n\n### Services\nServices are normal gRPC, gRPC-web or Connect protocol services,\nand require no special Knit tooling. That means all existing such\nservices work with Knit out of the box.\n\nServices are defined in any languge that has support for gRPC, gRPC-web or\nthe Connect protocol. The [Tutorial] uses [connect-es] and [connect-go] in\nits examples.\n\n### Gateways\nThe Knit gateway knows how to execute Knit queries from Knit clients, which\nmay require calling the RPCs of other services, and the Knit gateway\nknows how to issue them in the correct order, and flow required data from\nresponses into subsequent requests until a query is fully executed.\n\nThe Knit gateway is available as a standalone binary, or it can be embedded\nin a TypeScript service or Go service. The [Tutorial] shows how to use both\nthe standalone gateway and the embeddable gateways.\n\n## Deployment\nKnit can be used with all gRPC, gRPC-web and Connect protocol services\nwithout any modifications. The Knit gateway  can be configured to point\nto any number of services, allowing Knit clients to call all of them out\nof the box.\n\nAs the need arises more advanced usage of Knit can be employed, such as using\nrelations, or splitting the system into finer grain RPCs (independent of the\nservices they are defined in).\n\nBelow are several examples using the Star Wars API from the Knit [Tutorial]\nto show how parts of the system could be organized:\n\n#### Everything independent\n```mermaid\n%%{ init: { 'flowchart': { 'curve': 'basis' } } }%%\nflowchart LR\nA[Knit Client] --\u003e B[Knit Gateway]\nsubgraph r [Relation Service]\n    R{{Relation RPCs}}\nend\nsubgraph f [Film Service]\n    F{{Film RPCs}}\nend\nsubgraph s [Starship Service]\n    S{{Starship RPCs}}\nend\nB --\u003e R\nB --\u003e F\nB --\u003e S\n```\n\n#### Relations embedded in an existing service\n```mermaid\n%%{ init: { 'flowchart': { 'curve': 'basis' } } }%%\nflowchart LR\nA[Knit Client] --\u003e B[Knit Gateway]\nsubgraph f [Film Service]\n    R{{Relation RPCs}}\n    F{{Film RPCs}}\nend\n\nsubgraph s [Starship Service]\n    S{{Starship RPCs}}\nend\nB --\u003e R\nB --\u003e F\nB --\u003e S\n```\n\n#### Relations embedded across existing services\n```mermaid\n%%{ init: { 'flowchart': { 'curve': 'basis' } } }%%\nflowchart LR\nA[Knit Client] --\u003e B[Knit Gateway]\nsubgraph f [Film Service]\n    R1{{Relation RPCs}}\n    F{{Film RPCs}}\nend\n\nsubgraph s [Starship Service]\n    R2{{Relation RPCs}}\n    S{{Starship RPCs}}\nend\nB --\u003e R1\nB --\u003e R2\nB --\u003e F\nB --\u003e S\n```\n\n#### One backend monolith when using the embeddable gateway in TypeScript or Go\n```mermaid\n%%{ init: { 'flowchart': { 'curve': 'basis' } } }%%\nflowchart LR\nsubgraph f [Monolithic Service]\n    G{{Knit Gateway}}\n    R{{Relation RPCs}}\n    F{{Film RPCs}}\n    S{{Starship RPCs}}\nend\nA[Knit Client] --\u003e G\nG --\u003e R\nG --\u003e F\nG --\u003e S\n```\n\n## Learning to use Knit\nKnit has an end-to-end [Tutorial] that use the Star Wars API as a running example, and\nfully working code with longer explanations:\n\n* [Star Wars Knit client app in TypeScript](/tutorial/starwars-knit-client-app-ts) 🧑‍💻 🌐\n* [Star Wars Knit gateway](/tutorial/starwars-knit-gateway-standalone) or [(embeddable gateway in Go)](/tutorial/starwars-knit-gateway-go)\n* [Star Wars Knit relation service in TypeScript](/tutorial/starwars-knit-relation-service-ts) or [Go](/tutorial/starwars-knit-relation-service-go)\n* [Star Wars film service in TypeScript](/tutorial/starwars-film-service-ts) or [Go](/tutorial/starwars-film-service-go)\n* [Star Wars starship service in TypeScript](/tutorial/starwars-starship-service-ts) or [Go](/tutorial/starwars-starship-service-go)\n\n[badges_license]: https://github.com/bufbuild/knit/blob/main/LICENSE\n[badges_slack]: https://buf.build/links/slack\n[Tutorial]: /tutorial\n[github.com/bufbuild/knit]: https://github.com/bufbuild/knit\n[github.com/bufbuild/knit-ts]: https://github.com/bufbuild/knit-ts\n[github.com/bufbuild/knit-go]: https://github.com/bufbuild/knit-go\n[github.com/bufbuild/knit-demo]: https://github.com/bufbuild/knit-demo\n[github.com/bufbuild/knit-proto]: https://github.com/bufbuild/knit-proto\n[github.com/bufbuild/connect-es]: https://github.com/bufbuild/connect-es\n[github.com/bufbuild/connect-go]: https://github.com/bufbuild/connect-go\n[connect-es]: https://github.com/bufbuild/connect-es\n[connect-go]: https://github.com/bufbuild/connect-go\n[knit-ts]: https://github.com/bufbuild/knit-ts\n[knit-go]: https://github.com/bufbuild/knit-go\n[buf CLI]: https://github.com/bufbuild/buf\n[safe]: https://developer.mozilla.org/en-US/docs/Glossary/Safe/HTTP\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbufbuild%2Fknit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbufbuild%2Fknit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbufbuild%2Fknit/lists"}