All Projects → rubengrill → apollo-typed-documents

rubengrill / apollo-typed-documents

Licence: MIT license
Get type safety for your apollo documents.

Programming Languages

typescript
32286 projects
javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to apollo-typed-documents

startle
Startle C Library
Stars: ✭ 15 (-28.57%)
Mutual labels:  codegen
domainrobot-api
Swagger documentation for different APIs powered by InterNetX GmbH.
Stars: ✭ 14 (-33.33%)
Mutual labels:  codegen
codegen
Generator for dart_native bindings. Codegen can transform native SDK to Flutter plugin.
Stars: ✭ 75 (+257.14%)
Mutual labels:  codegen
graphql-cli-codegen
apollo-codegen plugin for graphql-cli
Stars: ✭ 22 (+4.76%)
Mutual labels:  codegen
rosetta
Easy to use Rust i18n library based on code generation
Stars: ✭ 37 (+76.19%)
Mutual labels:  codegen
gqty
a GraphQL client built for rapid iteration
Stars: ✭ 420 (+1900%)
Mutual labels:  codegen
d2a
A translator Django into SQLAlchemy.
Stars: ✭ 23 (+9.52%)
Mutual labels:  codegen
react-native-xaml
A React Native Windows library to use XAML / WinUI controls
Stars: ✭ 55 (+161.9%)
Mutual labels:  codegen
graphql-codegen-apollo-next-ssr
Autogenerate apollo code for nextjs ssr
Stars: ✭ 176 (+738.1%)
Mutual labels:  codegen
aws-mobile-appsync-sdk-android
Android SDK for AWS AppSync.
Stars: ✭ 101 (+380.95%)
Mutual labels:  codegen
graphql-ts-client
Typescript DSL for GraphQL.
Stars: ✭ 124 (+490.48%)
Mutual labels:  codegen
graphql-java-codegen-gradle-plugin
Gradle plugin for graphql-java-codegen
Stars: ✭ 19 (-9.52%)
Mutual labels:  codegen
sbt-guardrail
Principled code generation from OpenAPI specifications
Stars: ✭ 24 (+14.29%)
Mutual labels:  codegen
butte
No description or website provided.
Stars: ✭ 69 (+228.57%)
Mutual labels:  codegen
TypedocConverter
This is a typedoc json to C# type bindings converter. Can be used as a TypeScript to C# bindings converter.
Stars: ✭ 89 (+323.81%)
Mutual labels:  codegen
cmake-reflection-template
A template for simple C++ reflection done with CMake and Python (no other external tools)
Stars: ✭ 37 (+76.19%)
Mutual labels:  codegen
EasyEE-Auto
EasyEE 自动化代码生成器。EasyEE Automated code generator.
Stars: ✭ 39 (+85.71%)
Mutual labels:  codegen
graphql-modules-app
TypeScripted Apollo GraphQL Server using modules and a NextJS frontend utilising React modules with Apollo hooks. All bundled with a lot of dev friendly tools in a lerna setup..
Stars: ✭ 39 (+85.71%)
Mutual labels:  apollo-hooks
graphql-java-codegen
Make your GraphQL Java application schema-driven.
Stars: ✭ 167 (+695.24%)
Mutual labels:  codegen
qpmodel
A Relational Optimizer and Executor
Stars: ✭ 54 (+157.14%)
Mutual labels:  codegen

apollo-typed-documents

Provides graphql-codegen plugins (https://graphql-code-generator.com/) for type safe GraphQL documents (DocumentNode).

It allows functions to accept a generic TypedDocumentNode<TVariables, TData> so that types of other arguments or the return type can be inferred.

It is helpful for TypeScript projects but also if used only within an IDE, e.g. it works extremely well with VSCode (uses TypeScript behind the scenes).

$ yarn add apollo-typed-documents

codegenTypedDocuments

Generates TypeScript typings for .graphql files.

Similar to @graphql-codegen/typescript-graphql-files-modules (https://graphql-code-generator.com/docs/plugins/typescript-graphql-files-modules).

The difference is that is uses generic types, so that you have type safety with Apollo (e.g. useQuery / useMutation).

The apollo-typed-documents plugin also accepts the same modulePathPrefix, relativeToCwd and prefix config settings as typescript-graphql-files-modules.

Install

$ yarn add @graphql-codegen/add @graphql-codegen/typescript @graphql-codegen/typescript-operations
$ yarn add apollo-typed-documents

codegen.yml:

schema: schema.graphql
documents: src/**/*.graphql
config:
  scalars:
    Date: string
generates:
  ./src/codegenTypedDocuments.d.ts:
    plugins:
      - apollo-typed-documents/lib/codegenTypedDocuments
    config:
      typesModule: "@codegen-types"
  ./src/codegenTypes.d.ts:
    plugins:
      - add:
          placement: prepend
          content: 'declare module "@codegen-types" {'
      - add:
          placement: append
          content: "}"
      - typescript
      - typescript-operations

tsconfig.json:

Add node_modules/apollo-typed-documents/lib/reactHooks.d.ts in include to override the typings for hooks of @apollo/client, so that types can be inferred from typed documents.

{
  "compilerOptions": {
    "noEmit": true,
    "allowJs": true,
    "checkJs": true,
    "strict": true,
    "jsx": "react",
    "esModuleInterop": true
  },
  "include": ["src", "node_modules/apollo-typed-documents/lib/reactHooks.d.ts"]
}

Example

src/authors.graphql:

query authors {
  authors {
    id
    createdAt
    name
    description
    books {
      id
      title
    }
  }
}

src/createAuthor.graphql:

mutation createAuthor($input: AuthorInput!) {
  createAuthor(input: $input) {
    id
    createdAt
    name
    description
    books {
      id
      title
    }
  }
}

src/codegenTypedDocuments.d.ts (generated):

declare module "*/authors.graphql" {
  import { TypedDocumentNode } from "apollo-typed-documents";
  import { AuthorsQuery, AuthorsQueryVariables } from "@codegen-types";
  export const authors: TypedDocumentNode<AuthorsQueryVariables, AuthorsQuery>;
  export default authors;
}

declare module "*/createAuthor.graphql" {
  import { TypedDocumentNode } from "apollo-typed-documents";
  import { CreateAuthorMutation, CreateAuthorMutationVariables } from "@codegen-types";
  export const createAuthor: TypedDocumentNode<CreateAuthorMutationVariables, CreateAuthorMutation>;
  export default createAuthor;
}

src/AuthorList.js:

import { useMutation, useQuery } from "@apollo/client";
import React from "react";

import authorsQuery from "./authors.graphql";
import createAuthorMutation from "./createAuthor.graphql";

const AuthorList = () => {
  // Type of `data` is inferred (AuthorsQuery)
  const { data } = useQuery(authorsQuery);
  const [createAuthor] = useMutation(createAuthorMutation);

  return (
    <>
      <ul>
        {data?.authors.map((author) => (
          <li key={author.id}>{author.name}</li>
        ))}
      </ul>
      <button
        onClick={() => {
          createAuthor({
            // Type of variables is inferred (CreateAuthorMutationVariables)
            variables: { input: { name: "Foo", books: [{ title: "Bar" }] } },
          });
        }}
      >
        Add
      </button>
    </>
  );
};

export default AuthorList;

Notes for create-react-app users

create-react-app supports graphql.macro for loading .graphql files (https://create-react-app.dev/docs/loading-graphql-files/).

The codegenTypedDocuments plugin generates ambient module declarations for .graphql files, which means that .graphql files must be imported as regular modules (import syntax) so that TypeScript knows about the types.

You can use the babel plugin babel-plugin-import-graphql (https://github.com/detrohutt/babel-plugin-import-graphql), but then you need to use react-app-rewired (https://github.com/timarney/react-app-rewired/) and customize-cra (https://github.com/arackaf/customize-cra) so that you can define custom babel plugins.

$ yarn add react-app-rewired customize-cra
$ yarn add babel-plugin-import-graphql

config-overrides.js

const { override, useBabelRc } = require("customize-cra");

module.exports = override(useBabelRc());

.babelrc

{
  "presets": ["react-app"],
  "plugins": ["babel-plugin-import-graphql"]
}

package.json

"scripts": {
  "start": "react-app-rewired start",
  "build": "react-app-rewired build",
  "test": "react-app-rewired test",
  ...
}

If you have a TypeScript app, you need to override the @apollo/client types for hooks in tsconfig.json:

tsconfig.json

{
  "compilerOptions": {
    ...
  },
  "include": ["src", "node_modules/apollo-typed-documents/lib/reactHooks.d.ts"]
}

If you don't have a TypeScript app (you just want TypeScript support within your IDE) you can't create a tsconfig.json in your app folder, because create-react-app uses that file to detect if this is a TypeScript project.

Instead, you have to create the tsconfig.json in your src folder:

src/tsconfig.json

{
  "compilerOptions": {
    "noEmit": true,
    "allowJs": true,
    "checkJs": true,
    "strict": true,
    "jsx": "react",
    "esModuleInterop": true
  },
  "include": [".", "../node_modules/apollo-typed-documents/lib/reactHooks.d.ts"]
}

Please see the following example projects for more details:

codegenApolloMock

Creates a helper method to easily create mocks for Apollo MockedProvider (https://www.apollographql.com/docs/react/api/react-testing/#mockedprovider).

The returned object is guaranteed to conform to the GraphQL Schema of the query / mutation: reference.

For required (non-null) fields which are not provided (in data / variables), it will use a default value (e.g. "Author-id").

For optional fields which are not provided (in data / variables), it will use undefined for variables and null for data.

Works for any nested selections (data) and any nested inputs (variables).

It will include __typename in data by default. This can be deactivated as an option:

apolloMock(documentNode, variables, result, { addTypename: false });

When used together with codegenTypedDocuments the data and variables are type checked (type inference).

To mock errors, you can provide errors in result (GraphQLError) or pass an Error instead of result:

apolloMock(documentNode, variables, { errors: [new GraphQLError("Already exists")] });
apolloMock(documentNode, variables, new Error("Network error"));

Install

$ yarn add apollo-typed-documents

codegen.yml

schema: schema.graphql
documents: src/**/*.graphql
config:
  scalars:
    Date: string
generates:
  ./src/apolloMock.js:
    plugins:
      - apollo-typed-documents/lib/codegenApolloMock

Example

schema.graphql:

scalar Date

type Author {
  id: ID!
  createdAt: Date!
  name: String!
  description: String
  books: [Book!]!
}

type Book {
  id: ID!
  title: String!
}

input AuthorInput {
  name: String!
  description: String
  books: [BookInput!]!
}

input BookInput {
  title: String!
}

type Query {
  authors: [Author!]!
}

type Mutation {
  createAuthor(input: AuthorInput!): Author!
}

schema {
  query: Query
  mutation: Mutation
}

src/authors.graphql:

query authors {
  authors {
    id
    createdAt
    name
    description
    books {
      id
      title
    }
  }
}

src/createAuthor.graphql:

mutation createAuthor($input: AuthorInput!) {
  createAuthor(input: $input) {
    id
    createdAt
    name
    description
    books {
      id
      title
    }
  }
}

src/apolloMock.js (generated):

See: reference

src/apolloMock.test.js:

import { GraphQLError } from "graphql";

import apolloMock from "./apolloMock";
import authors from "./authors.graphql";
import createAuthor from "./createAuthor.graphql";

describe("apolloMock", () => {
  it("produces the minimal output that is valid according to graphql schema", () => {
    expect(apolloMock(authors, {}, {})).toEqual({
      request: {
        query: authors,
        variables: {},
      },
      result: {
        data: {
          authors: [],
        },
      },
    });

    expect(apolloMock(authors, {}, { data: { authors: [{}] } })).toEqual({
      request: {
        query: authors,
        variables: {},
      },
      result: {
        data: {
          authors: [
            {
              __typename: "Author",
              id: "Author-id",
              createdAt: "Author-createdAt",
              name: "Author-name",
              description: null,
              books: [],
            },
          ],
        },
      },
    });

    expect(
      apolloMock(
        createAuthor,
        { input: { name: "Foo", books: [{ title: "Bar" }] } },
        { data: { createAuthor: { name: "Foo", books: [{ title: "Bar" }] } } }
      )
    ).toEqual({
      request: {
        query: createAuthor,
        variables: {
          input: {
            name: "Foo",
            description: undefined,
            books: [{ title: "Bar" }],
          },
        },
      },
      result: {
        data: {
          createAuthor: {
            __typename: "Author",
            id: "Author-id",
            createdAt: "Author-createdAt",
            name: "Foo",
            description: null,
            books: [
              {
                __typename: "Book",
                id: "Book-id",
                title: "Bar",
              },
            ],
          },
        },
      },
    });
  });

  it("allows overriding default values for scalar types", () => {
    const scalarValues = { Date: "2020-01-01" };

    expect(
      apolloMock(authors, {}, { data: { authors: [{}] } }, { scalarValues })
    ).toEqual({
      request: {
        query: authors,
        variables: {},
      },
      result: {
        data: {
          authors: [
            {
              __typename: "Author",
              id: "Author-id",
              createdAt: "2020-01-01",
              name: "Author-name",
              description: null,
              books: [],
            },
          ],
        },
      },
    });
  });

  it("supports errors", () => {
    expect(
      apolloMock(authors, {}, { errors: [new GraphQLError("Already exists")] })
    ).toEqual({
      request: {
        query: authors,
        variables: {},
      },
      result: {
        errors: [new GraphQLError("Already exists")],
      },
    });

    expect(apolloMock(authors, {}, new Error("Network error"))).toEqual({
      request: {
        query: authors,
        variables: {},
      },
      error: new Error("Network error"),
    });
  });
});
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].