{"id":13877552,"url":"https://github.com/strise/gintonic","last_synced_at":"2026-01-25T19:03:31.096Z","repository":{"id":57127771,"uuid":"158833852","full_name":"strise/gintonic","owner":"strise","description":"A declarative transformation language for GraphQL 🍸","archived":false,"fork":false,"pushed_at":"2019-07-12T09:42:11.000Z","size":1163,"stargazers_count":28,"open_issues_count":8,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-05-02T01:02:40.465Z","etag":null,"topics":["bucklescript","code","graphql","library","transformation"],"latest_commit_sha":null,"homepage":"","language":"OCaml","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/strise.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}},"created_at":"2018-11-23T13:05:05.000Z","updated_at":"2024-10-09T11:50:43.000Z","dependencies_parsed_at":"2022-08-31T16:11:22.189Z","dependency_job_id":null,"html_url":"https://github.com/strise/gintonic","commit_stats":null,"previous_names":["mitoai/graphql-transformer","mitoai/gintonic"],"tags_count":36,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/strise%2Fgintonic","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/strise%2Fgintonic/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/strise%2Fgintonic/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/strise%2Fgintonic/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/strise","download_url":"https://codeload.github.com/strise/gintonic/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253837405,"owners_count":21971983,"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","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":["bucklescript","code","graphql","library","transformation"],"created_at":"2024-08-06T08:01:07.825Z","updated_at":"2026-01-25T19:03:31.027Z","avatar_url":"https://github.com/strise.png","language":"OCaml","funding_links":[],"categories":["OCaml"],"sub_categories":[],"readme":"# Gintonic\n\n![](./resources/streamer.svg)\n\n\u003cdiv align=\"center\"\u003e\n    \u003cbr /\u003e\n    \u003cbr /\u003e\n    \u003cb\u003eA declarative transformation language for GraphQL\u003c/b\u003e\n    \u003cbr /\u003e\n    \u003cbr /\u003e\n\u003c/div\u003e\n\nThis project contains our efforts to build a scalable and maintainable GraphQL transformation tool. This is done by\ndefining a new DSL, which is described and implemented at the\n[gintonic](https://github.com/mitoai/graphql-transformer/tree/master/packages/gintonic) sub-project.\n\n[View demo here](https://mito.ai/gintonic/demo)\n\nGiven a transformation, this implementation allows you to do two things:\n\n1. Apply the transformation to a source schema thus generating a new target schema.\n2. Apply the transformation to a query on the target schema thus generating a new query against the source schema.\n\n**Example:** Given the schema\n\n```graphql\ntype Query {\n    field: String\n    secretField: String\n}\n```\n\nwe may apply the transformation\n\n```graphql\ntransform type Query {\n  # Filter fields and alias 'field' to 'f'\n  f: field\n}\n\n```\n\nthis transformation filters all fields on type `Query` that are not `field`, and aliases that field to `f`.\nThis will generate the target schema\n\n```graphql\ntype Query {\n    f: String\n}\n\n```\n\nNow given a query on the target schema:\n\n```graphql\nquery {\n    f\n}\n```\n\nthis can be transformed into a valid query on the source schema:\n\n```graphql\nquery  {\n    f: field\n}\n```\nNotice that the result of the generated query is valid output for the previous query.\n\n## Transformations\n\nThe language currently supports five transformation features, which can be applied to the different types and schema when\nappropriate:\n\n1. **Field and type aliasing**: Rename a field or a type\n2. **Field filtering**: Filter fields from objects or interfaces\n3. **Input locking**: Supply values to input, thus removing them from the target API\n4. **Documenting**: Supply or overwrite documentation on fields, arguments, etc.\n5. **Schema operation filtering**: Filter root-operations.\n\nFor each GraphQL type definition (object, union, interface, enum, and input object) and schema definition, there\nexists a corresponding transformation:\n\n### Schema transformation\n\nThe schema transformation supports schema operation filtering. This effectively allows you to exclude root operations\n(query, mutation, or subscription) from your target API.\n\n```graphql\n# Source schema\nschema {\n    query: Query\n    mutation: Mutation\n    subscription: Subscription\n}\n\n# Transformation\ntransform schema {\n    # Exclude any non-query operations\n    query\n}\n\n# Target schema\nschema {\n    query: Query\n}\n```\n\nThis is a crude but effective way to disallow users from making any mutation calls on your API.\n\n### Object type transformation\n\nObject type transformations support field-filtering, field-aliasing, documenting, and input locking on arguments.\n\n```graphql\n# Source type\ntype Type {\n    stringField: String\n    fieldWithArguments(arg1: String arg2: String): String\n    superSecretField: String\n}\n\n# Transformation\n\n\"New docs\"                                              # Update type docs\ntransform type T: Type {                                # Type aliasing Type -\u003e T\n    stringField                                         # Include string-field\n    field: stringField                                  # Field aliasing\n    \"New docs\"                                          # Update field docs\n    fieldWithArgument: fieldWithArguments(\n        \"New docs\"\n        arg1                                            # Update argument docs\n        arg2: \"Locked value\"                            # Input locking\n    )     \n    # superSecretField is not specified, so it's filtered.    \n}\n\n# Target type\n\n\"New docs\"\ntype T {\n    stringField: String\n    field: String\n    \"New docs\"\n    fieldWithArgument(\n        \"New docs\"\n        arg1: String\n    ): String\n}\n```\n\nnotice that a field can be transformed an arbitrary number of times. The only limitation is that the target schema\nmust be valid.\n\n\n### Interface type transformation\n\nThe interface type transformation supports the same features as the object type transformation.\n\n\n```graphql\n# Source type\ninterface Type {\n    stringField: String\n    fieldWithArguments(arg1: String arg2: String): String\n    superSecretField: String\n}\n\n# Transformation\n\n\"New docs\"                                              # Update type docs\ntransform interface T: Type {                           # Type aliasing Type -\u003e T\n    stringField                                         # Include string-field\n    field: stringField                                  # Field aliasing\n    \"New docs\"                                          # Update field docs\n    fieldWithArgument: fieldWithArguments(\n        \"New docs\"\n        arg1                                            # Update argument docs\n        arg2: \"Locked value\"                            # Input locking\n    )     \n    # superSecretField is not specified, so it's filtered.    \n}\n\n# Target type\n\n\"New docs\"\ninterface T {\n    stringField: String\n    field: String\n    \"New docs\"\n    fieldWithArgument(\n        \"New docs\"\n        arg1: String\n    ): String\n}\n```\n\nNotice that the validity of a transformation heavily relies upon the validity of the target schema.\nIt is up to the implementer to ensure that all transformations are generating a valid target schema and that\nall implementing types have the appropriate fields.\n\n### Scalar and Union transformations\n\nThe scalar and union transformations all support documenting and type-aliasing.\n\n```graphql\n# Source schema\nunion Union = T1 | T2 | T3\n\nscalar Scalar\n\n# Transformation\n\"New docs\"                      # Type documentation\ntransform unon U: Union         # Type aliasing\n\n\"New docs\"                      # Type documentation\ntransform scalar S: Scalar      # Type alias\n\n# Target schema\n\n\"New docs\"\nunion U = T1 | T2 | T3\n\n\"New docs\"\nscalar S\n```\n\n### Enum transformation\n\nSimilarly to scalar and union transformations, the enum transformation supports documenting and type-aliasing. It\ndoes however also support enum value documentation.\n\n\n```graphql\n# Source schema\nenum Enum {\n    V1\n    V2\n}\n\n# Transformation\n\"New docs\"                  # Type docuemntation\ntransform enum E: Enum {    # Type alias\n    \"New docs\"              # Value documentation\n    V1\n}\n\n# Target schema\n\"New docs\"\nenum E {\n    \"New docs\"\n    V1\n    V2\n}\n\n```\n\n### Input object transformation\n\nThe input object transformation supports type-aliasing, documenting, and input locking:\n\n```graphql\n# Source schema\n\ninput Input {\n    f1: String\n    f2: String\n}\n\n# Transformation\n\n\"new docs\"\ntransform input I: Input {\n    \"new docs\"\n    f1\n    f2 = \"Lock value\"\n}\n\n# Target schema\n\n\"new docs\"\ninput I {\n    \"new docs\"\n    f1: String\n}\n\n```\n\nWhile we could consider doing field aliasing, notice that the input object is fundamentally different from objects.\nFurthermore, remember that the target schema should always be valid. Therefore locking all fields will yield\nan input object with no fields in the target schema. This is not valid.\n\n## Query transformation\n\nThe schema transformations would mean little without the ability to link actually retrieve data from the target API.\nTherefor graphql-transformer allows you to transform a query against the target API to a query against the source API,\nwhere the result can be returned directly to the original caller.\n\nE.g. with the following schemas and transformation:\n\n```graphql\n# Source schema\ntype Query {\n    field(arg: String): String\n}\n\n# Transformation\ntransform type Query {\n    f: field(arg = \"locked\")        # Field aliasing and argument locking\n}\n\n# Target schema\ntype Query {\n    f: String\n}\n\n```\n\nan incoming query to the target schema would be transformed into\n```graphql\n# Query against the target schema\nquery {\n    f\n}\n\n# Transformed query\n\nquery {\n    f: field(arg: \"locked\")\n}\n\n```\n\npreserving the output structure, thus making field resolution trivial.\n\nNotice that the target schema should always be served from a GraphQL API resolving meta-fields and validating\nincoming queries against the target schema.\n\n## Koa middleware\n\nYou may easily integrate using the provided koa middleware available as a submodule. Read more at\n[gintonic-koa](https://github.com/mitoai/graphql-transformer/tree/master/packages/gintonic-koa).\n\n## Serverless\n\nGintonic can be deployed on serverless infrastructure using the Koa middleware.\nAn example can be found at [examples/serverless](./examples/serverless).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstrise%2Fgintonic","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstrise%2Fgintonic","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstrise%2Fgintonic/lists"}