All Projects → piglovesyou → Graphql Let

piglovesyou / Graphql Let

A layer to start/scale the use of GraphQL code generator.

Programming Languages

typescript
32286 projects

Projects that are alternatives of or similar to Graphql Let

Magiql
🌐 💫 Simple and powerful GraphQL Client, love child of react-query ❤️ relay
Stars: ✭ 45 (-84.04%)
Mutual labels:  graphql, babel-plugin
Babel Plugin Import Graphql
Enables import syntax for .graphql and .gql files
Stars: ✭ 284 (+0.71%)
Mutual labels:  graphql, babel-plugin
React Svg Loader
A loader for webpack, rollup, babel that loads svg as a React Component
Stars: ✭ 570 (+102.13%)
Mutual labels:  webpack-loader, babel-plugin
Graphql Persisted Document Loader
Webpack loader that adds a documentId to a compiled graphql document, which can be used when persisting/retrieving documents
Stars: ✭ 74 (-73.76%)
Mutual labels:  graphql, webpack-loader
Graphql Import Loader
Webpack loader for `graphql-import`
Stars: ✭ 84 (-70.21%)
Mutual labels:  graphql, webpack-loader
Grafoo
A GraphQL Client and Toolkit
Stars: ✭ 264 (-6.38%)
Mutual labels:  graphql, babel-plugin
Babel Plugin Graphql Tag
Compiles GraphQL tagged template strings using graphql-tag.
Stars: ✭ 156 (-44.68%)
Mutual labels:  graphql, babel-plugin
Babel Blade
(under new management!) ⛸️Solve the Double Declaration problem with inline GraphQL. Babel plugin/macro that works with any GraphQL client!
Stars: ✭ 266 (-5.67%)
Mutual labels:  graphql, babel-plugin
Apollo Ios
📱  A strongly-typed, caching GraphQL client for iOS, written in Swift.
Stars: ✭ 3,192 (+1031.91%)
Mutual labels:  graphql
Morpheus Graphql
Haskell GraphQL Api, Client and Tools
Stars: ✭ 285 (+1.06%)
Mutual labels:  graphql
Ts Loader
TypeScript loader for webpack
Stars: ✭ 3,112 (+1003.55%)
Mutual labels:  webpack-loader
Saleor Dashboard
A GraphQL-powered, single-page dashboard application for Saleor.
Stars: ✭ 278 (-1.42%)
Mutual labels:  graphql
Ng Notadd
In-middle background front-end solution based on angular material 基于Angular Material的中后台前端解决方案
Stars: ✭ 287 (+1.77%)
Mutual labels:  graphql
Gqless
a GraphQL client without queries
Stars: ✭ 3,569 (+1165.6%)
Mutual labels:  graphql
Dgraph
Native GraphQL Database with graph backend
Stars: ✭ 17,127 (+5973.4%)
Mutual labels:  graphql
Boilerplay
Using the latest technology in the Scala ecosystem, Boilerplay is a reactive web application built on Play Framework, ScalaJS, Silhouette, Sangria/GraphQL, and PostgreSQL. It provides a good starting point for whatever you want to build.
Stars: ✭ 279 (-1.06%)
Mutual labels:  graphql
Wp Graphiql
GraphiQL IDE, fine tuned for use with WPGraphQL
Stars: ✭ 284 (+0.71%)
Mutual labels:  graphql
Chat App Flutter
It's a fully functioning chat app built using flutter. With both one on one chats and group chats
Stars: ✭ 277 (-1.77%)
Mutual labels:  graphql
Graphql Erlang
GraphQL implementation in Erlang.
Stars: ✭ 284 (+0.71%)
Mutual labels:  graphql
Babel Plugin Module Resolver
Custom module resolver plugin for Babel
Stars: ✭ 3,134 (+1011.35%)
Mutual labels:  babel-plugin

graphql-let Node CI npm version downloads Babel Macro

A layer to start/scale the use of GraphQL code generator.

Try a Create React App example and a Next.js example that integrate graphql-let.

Table of Contents

Why this exists

One of the strengths of GraphQL is enforcing data types on runtime. Further, TypeScript and GraphQL code generator helps it even safer to type your codebase statically. Both makes a truly type-protected development environment with rich IDE assists.

graphql-let enhances that development pattern by minimizing configuration setup, introducing intuitive syntax and confortable development experience through HMR (hot module replacement).

import { useNewsQuery } from './news.graphql'

const News: React.FC = () => {
    // Typed already️⚡️
    const { data: { news } } = useNewsQuery()
    if (news) return <div>{news.map(...)}</div>
}

Entrypoints and features

There are four entry points to start graphql-let:

  • CLI, assumed to run before type checking
  • webpack loader
  • babel-plugin-macros
  • Babel plugin

Mostly, all of them do the same as below.

  1. It loads configurations from .graphql-let.yml
  2. It finds GraphQL documents (queries, mutations, subscriptions) from config.documents including *.graphql and *.ts(x).
  3. It passes the arguments to GraphQL code generator to generate .ts(x). This is used for runtime.
  4. It also generates the corresponding .d.ts for the codegen results. This is used for static typing.

But there are a few differences between the entrypoints.

Entry pointsYou need .graphql-let.yml and: Getting codegen result from Use values of codegen result Use types of codegen result Pros/Cons
webpack loader

Configure "graphql-let/loader"
to files "/.*\.(tsx?|graphql)$/" in webpack.config.(js|ts)
File ✅ Import both value and types from a GraphQL document as a module.
import { useQuery, Query } from "./a.graphql"
HMR works as expected.
Webpack config is required even though your project only uses Babel
String literal ✅ by
import { gql } from "graphql-let" 

const { useQuery } = gql("query A { braa }")
⚠️ You can, but you have to find the internal d.ts.
import { gql } from "graphql-let"
import {Query} from 'graphql-let/__generated__/index-A'

const { useQuery } = gql("query { braa }")
babel-plugin-macros

If you've already setupbabel-plugin-macros,no config needed any more
File ✅ by
import { load } from "graphql-let/macro"

const { useQuery } = load("./a.graphql")
⚠️ You can, but you have to find the internally generated d.ts.
import { load } from "graphql-let/macro"
import {Query} from 'graphql-let/__generated__/index-A'

const { useQuery } = load("./a.graphql")
Easiest to integrate if your project already has babel-plugin-macros. create-react-app is the great fit.Cannot load types from function call.

Modifying *.graphql doesn't emit HMR.
String literal ✅ by
import { gql } from "graphql-let/macro"

const { useQuery } = gql("query A { braa }")
⚠️ You can, but you have to find the internally generated d.ts.
import { gql } from "graphql-let/macro"
import {Query} from 'graphql-let/__generated__/index-A'

const { useQuery } = gql("query { braa }")
babel-plugin

Put "graphql-let/babel"to you .babelrc as a plugin
File ✅ by
import { load } from "graphql-let"

const { useQuery } = load("./a.graphql")
⚠️ You can, but you have to find the internally generated d.ts.
import { load } from "graphql-let"
import {Query} from 'graphql-let/__generated__/index-A'

const { useQuery } = load("./a.graphql")
Mostly equivalent to babel-plugin-macros, but you always need your .babelrc configuration. Possibly, "import "./a.graphql"" could be implemented, but not supported yet.Cannot load types from function call.

Modifying *.graphql doesn't emit HMR.Possibly I can make "--watch" option butlots to do for dependency management to detect file change.
String literal ✅ by
import { gql } from "graphql-let"

const { useQuery } = gql("query A { braa }")
⚠️ You can, but you have to find the internally generated d.ts.
import { gql } from "graphql-let"
import {Query} from 'graphql-let/__generated__/index-A'

const { useQuery } = gql("query { braa }")
Efficient?

There are things to make graphql-let light and stable.

  • Sharing the processes. Generating files is expensive, so it runs less time to run GraphQL code generator and TypeScript API.
  • Caching. By embedding hashes as your source states, it reduces the number of unnecessary processing.
  • Sharing the promises. The webpack compilation in typical SSR applications as Next.js runs targets of "node" and "web" simultaneously. If sources are the same, the compilation should be once.

Get started with webpack loader

This is an example of TypeScript + React + Apollo Client on webpack. Please replace the corresponding lines depending on your needs.

1. Install dependencies

Note graphql-let is devDependencies.

yarn add -D graphql-let @graphql-codegen/cli @graphql-codegen/plugin-helpers @graphql-codegen/typescript @graphql-codegen/typescript-operations @graphql-codegen/typescript-react-apollo
yarn add @apollo/client

2. Configure .graphql-let.yml

Run this command to generate a configuration template.

yarn graphql-let init
# This will generate .graphql-let.yml

Next, add graphql-codegen plugins in it. Please note that you have to generate a TypeScript source by the plugins.

Edit it like this:

 schema: lib/type-defs.graphqls
 documents:
   - '**/*.graphql'
   - '**/*.tsx'
 plugins:
   - typescript
+  - typescript-operations
+  - typescript-react-apollo

3. Add lines to .gitignore

graphql-let will generate .d.ts files in the same folder of .graphql. Add these lines in your .gitignore.

+*.graphql.d.ts
+*.graphqls.d.ts

4. Configure webpack.config.ts

The webpack loader also needs to be configured. Note that the content that graphql-let/loader generates is JSX-TypeScript. You have to compile it to JavaScript with an additional loader such as babel-loader.

 const config: Configuration = {
   module: {
     rules: [
+      {
+        test: /\.(tsx|graphql)$/,
+        use: [
+          { loader: 'babel-loader', options: { presets: ['@babel/preset-typescript', '@babel/preset-react'] } },
+          { loader: 'graphql-let/loader' },
+        ]
+      }
     ]
   }
 }

5. Generate type declarations

Run this to generate .d.ts.

yarn graphql-let

# This will generate files such as:
#   - src/query.graphql.d.ts
#   - src/schema.graphqls.d.ts

By --config option you can specify the custom path to the .graphql-let.yml. The directory .graphql-let.yml is located at is the basepath of the relative paths in .grpahql-let.yml. Also, the basepath should be identical to webpack's config.context so the loader can find the config file.

pwd # "/app"
yarn graphql-let --config custom/path/.graphql-let.yml

# This will point paths such as:
# /app/custom/path/src/query.graphql.d.ts
# /app/custom/path/src/schema.graphqls.d.ts

You may want to run it every time before calling tsc. Please check your package.json and modify like this.

   "scripts": {
-     "build": "tsc"
+     "build": "graphql-let && tsc"
   },

6. Code

Enjoy HMR (Hot Module Replacement) of webpack with the generated react-apollo hooks and IDE code assists.

import { gql } from 'graphql-let'
import { useNewsQuery } from './news.graphql'

const {useViewerQuery} = gql(`query Viewer { blaa }`)

const News: React.FC = () => {
    // Already typed⚡️
    const { data: { news } } = useNewsQuery()
    const { data: { viewer } } = useViewerQuery()
    return <div>{ news.map(...) }</div>
}

Getting started with babel-plugin-macros

babel-plugin-macros requires the least configuration to setup.

Please finish 1. Install dependencies and 2. Configure .graphql-let.yml as you still need .graphql-let.yml.

3. Make sure your babel-plugin-macros is ready

Put a line "plugins": ["macros"] to your .babelrc. If you use Create React App, it contains babel-plugin-macros out of the box.

If you want a custom path to .graphql-let.yml, you can use configFilePath babel option. <projectRoot>${configFilePath} should point to your .graphql-let.yml.

4. Code

Thanks to babel-plugin-macros's beautiful architecture, you're ready to use GraphQL codegen values.

import { load } from "graphql-let/macro"

// Typed⚡️
const { useQuery } = load("./viewer.graphql")

Note these functions gql() and load() can't return types. If you want them, you still can load them by finding the types generated internally.

graphql-let/__generated__/{ts relative path without extension}-{GraphQL document name} is the path.

import {Query} from 'graphql-let/__generated__/index-Viewer'

Note: The .ts(x)s are generated in node_modules/graphql-let/__generated__ by default, but you may want them to be outside of node_modules since it's often excluded to be TS compilation. Please try cacheDir: __generated__ in your .graphql-let.yml then.

Getting started with Babel Plugin

Mostly the same as babel-plugin-macros, only you can import functions from "graphql-let"".

Please finish 1. Install dependencies and 2. Configure .graphql-let.yml as you still need .graphql-let.yml.

3. Setup .babelrc

  {
+   "plugins": ["graphql-let/babel"]
  }

4. Code

import {gql, load} from "graphql-let"

const {useNewsQuery} = gql("query News { braa }")
const {useViewerQuery} = load("./viewer.graphql")

Configuration is compatible with codegen.yml, except:

graphql-let passes most of the options to GraphQL code generator, so .graphql-let.yml is mostly compatible with codegen.yml. However, there are differences you should know. In short, the below diff is the quick migration guide.

  schema: https://api.github.com/graphql
  documents: "**/*.graphql"
- generates:
-     ./__generated__/types.ts:
-         plugins:
-             - typescript
-             - typescript-operations
+ plugins:
+     - typescript
+     - typescript-operations

No generates

codegen.yml has an option generates, but it's strictly controlled under graphql-let. Rather, think graphql-let as a tool to let you forget intermediate outputs and import/call GraphQL directly.

Therefore, we don't support output-file level configuration such as Output-file level schema, Output-file level documents and Output Level config right now. But this could be changed logically, so, please vote by issuing if you'd like.

Limitation: documents expects only string | string[]

Documen-pointer level options such as noRequire: true or Custom Document Loader are not supported.

graphql-let specific options

In addition to codegen.yml options, graphql-let accepts these.

# "plugins", required. The plugins for GraphQL documents to run GraphQL code
# generator with. Please note that you need to generate a TypeScript source here.
# See here for more information. https://graphql-code-generator.com/docs/plugins/index
# Example:
plugins:
    - typescript
    - typescript-operations
    - typescript-react-apollo
    - add: "/* eslint-disable */"

# "respectGitIgnore", optional. `true` by default.
# If true, graphql-let will ignore files in .gitignore.
# Useful to prevent parsing files in such as `node_modules`.
respectGitIgnore: true

# "cacheDir", optional. `node_modules/graphql-let/__generated__` by default.
# graphql-let takes care of intermediate `.ts(x)`s that GraphQL code generator
# generates, but we still need to write them on the disk for caching and
# TypeScript API purposes. This is the directory we store them to.
# Examples:
cacheDir: node_modules/graphql-let/__generated__
cacheDir: __generated__

# "TSConfigFile", optional. `tsconfig.json` by default.
# You can specify a custom config for generating `.d.ts`s.
# Examples:
TSConfigFile: tsconfig.json
TSConfigFile: tsconfig.compile.json

# "typeInjectEntrypoint", optional.
# `node_modules/@types/graphql-let/index.d.ts` by default. Needs to end with ".d.ts".
# Used as an entrypoint and directory of generated type declarations
# for `gql()` and `load()` calls.
typeInjectEntrypoint: node_modules/@types/graphql-let/index.d.ts

# "schemaEntrypoint", optional. You need this only if you want to use Resolver Types.
# Since you could point to multiple schemas, this path is
# used to generate `.d.ts` to generate `*.graphqls.d.ts`. If you do this,
#
#   schema: **/*.graphqls
#   schemaEntrypoint: schema.graphqls
#
# you can import the generated resolver types like below.
#
#   import { Resolvers } from '../schema.graphqls'
#
# It doesn't matter if the file of the path exists. I recommend
# you to specify a normal relative path without glob symbols (`**`) like this.
schemaEntrypoint: schema.graphqls
schemaEntrypoint: lib/schema.graphqls

Simple example:

schema: "schema/**/*.graphqls"
documents:
    - "**/*.graphql"
    - "!shouldBeIgnored1"
plugins:
    - typescript
    - typescript-operations
    - typescript-react-apollo

Example with a bit more complicated options:

schema:
    - https://api.github.com/graphql:
          headers:
              Authorization: YOUR-TOKEN-HERE
documents:
    - "**/*.graphql"
    - "!shouldBeIgnored1"
plugins:
    - typescript
    - typescript-operations
    - typescript-react-apollo
respectGitIgnore: true
config:
    reactApolloVersion: 3
    apolloReactComponentsImportFrom: "@apollo/client/react/components"
    useIndexSignature: true
cacheDir: __generated__
TSConfigFile: tsconfig.compile.json
typeInjectEntrypoint: typings/graphql-let.d.ts

Limitations of graphql-let/babel

Jest Transformer

graphql-let/jestTransformer is available. Configure your jest.config.js as:

  module.exports = {
    transform: {
+     "\\.graphql$": "graphql-let/jestTransformer",
    },
  };

Use babel-jest in Jest

babel-jest is the default subsequent transformer of graphql-let/jestTransformer. Install these:

yarn add -D graphql-let babel-jest

And make sure your babel config can compile generated .ts(x)s.

Use ts-jest or other subsequent transformers in Jest

The option subsequentTransformer is available. If you use ts-jest, your jest.config.js will look like this:

  const { defaults: tsjPreset } = require("ts-jest/presets");

  module.exports = {
    preset: "ts-jest",
    transform: {
      ...tsjPreset.transform,
+     "\\.graphql$": [
+       "graphql-let/jestTransformer",
+       { subsequentTransformer: "ts-jest" },
+     ],
    },
  };

Transform .graphqls in Jest

If you use graphql-let/schema/loader, you may want a corresponding transformer, but remember graphql-let does not transform the content of GraphQL schema. Just use what you need, it's most likely to be jest-transform-graphql.

  module.exports = {
    transform: {
      "\\.graphql$": "graphql-let/jestTransformer",
+     "\\.graphqls$": "jest-transform-graphql",
    },
  };

Experimental feature: Resolver Types

If you meet the following conditions, graphql-let generates Resolver Types.

  • You have schemaEntrypoint in the config
  • You have file paths including glob patterns in schema
  • You have @graphql-codegen/typescript-resolvers installed
  • your schemaEntrypoint in .graphql-let.yml points to a single local GraphQL schema file (.graphqls)

Run:

yarn add -D @graphql-codegen/typescript-resolvers

yarn graphql-let

Then you will get ${schemaEntrypoint}.d.ts. Import the types from it.

import { Resolvers } from "../schema.graphqls";

const resolvers: Resolvers = {
  Query: {
    // All typed⚡️
    viewer(parent, args, context, info) {
      return { ... }
    },
  }
};

export default resolvers;

graphql-let/schema/loader is also available. It generates/updates ${schemaEntrypoint}.d.ts but it doesn't transpile anything; just passes the file content to the next webpack loader. Set it up as below:

 const config: Configuration = {
   module: {
     rules: [
+      {
+        test: /\.graphqls$/,
+        use: [
+          { loader: 'graphql-tag/loader' },
+          { loader: 'graphql-let/schema/loader' },
+        ]
+      }
     ]
   }
 }

FAQ

So, it's just a graphql-codegen wrapper generating d.ts...?

Yes.

Supported combination of tools? / x + y don't work!

Basically both syntax import './a.graphql' and gql(`query {}` ) are suposed to work, but currently some of combinations require more effort. Please vote by creating issues. Sponsering me is another way to get my attention🍩🍦

These are the states/tools for the syntaxes.

states/tools for syntax File import as
import './a.graphql';
Inline GraphQL as
import gql from 'graphql-tag';
gql(`query {}` );
generating .d.tss by command graphql-let
importing GraphQL content from another as
# import A from './a.graphql'
webpack loader graphql-let/loader
Babel Plugin graphql-let/babel
Jest Transformer graphql-let/jestTransfomer Vote by issuing
Experimental: Resolver Types for
GraphQL schema
✅ by
import './schema.graphqls'
Vote by issuing

Is this a tool only for React?

No. There are more plugins that also generates .ts(x)s from GraphQL documents.

Can I write GraphQL documents in my .tsx as const query = gql`query News{ ... }`;?

Please try the Babel Plugin graphql-let/babel, but you need parenthesis gql(`query {}`).

What's the extensions .graphql and .graphqls? Can I use .gql or something else?

Not exactly, but I recommend you to distinguish GraphQL documents and GraphQL schemas. I think using different extensions for them leads to a more understandable configuration for webpack loaders with fewer pitfalls. Another reason for .graphqls is that it's one of the supported extensions in the internal library.

How to integrate Apollo refetchQueries?

Query document exports DocumentNode named ${QueryName}Document that you can make use of.

How to import .graphql from another document, especially GraphQL Fragment?

Thanks to graphql-tools/import, the syntax # import X from './fragment.graphql' is supported.

Define your fragment named as partial.graphql

fragment Partial on User {
    id
    name
}

and import it.

# import Partial from './partial.graphql'

query Viewer {
    viewer {
        ...Partial
    }
}

Contribution

  • Create an issue if you have ideas, found a bug or anything.
  • Creating a PR is always welcome!
    • Running npm run prepublishOnly locally will get your local development ready.
    • Adding tests is preferable, but don't hesitate without it, maybe someone else will fill it.

License

MIT

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].