JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 37
  • Score
    100M100P100Q88916F
  • License MIT

A GraphQL code generator plug-in that automatically generates utility functions for SWR.

Package Exports

  • graphql-codegen-plugin-swr
  • graphql-codegen-plugin-swr/build/main/index.js
  • graphql-codegen-plugin-swr/build/module/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (graphql-codegen-plugin-swr) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

graphql-codegen-plugin-swr

Forked from graphql-codegen-plugin-typescript-swr

A GraphQL code generator plug-in that automatically generates utility functions for SWR.

Table of Contents

API Reference

excludeQueries

type: string | string[] default: ""

Exclude queries that are matched by micromatch (case-sensitive).

useSWRInfinite

type: string | string[] default: ""

Add useSWRInfinite() wrapper for the queries that are matched by micromatch (case-sensitive).

autogenSWRKey

type: boolean default: false

Generate key to use useSWR() automatically.
But, ​the cache may not work unless you separate the variables object into an external file and use it, or use a primitive type for the value of each field.

Config Example

generates:
  path/to/graphql.ts:
    schema: 'schemas/github.graphql'
    documents: 'src/services/github/**/*.graphql'
    plugins:
      - typescript
      - typescript-operations
      # Put `plugin-typescript-swr` below `typescript-graphql-request`
      - typescript-graphql-request
      - plugin-typescript-swr
config:
  rawRequest: false
  excludeQueries:
    - foo*
    - bar
  useSWRInfinite:
    - hoge
    - bar{1,3}
  autogenSWRKey: true

Usage Examples

For the given input:

query continents {
  continents {
    name
    countries {
      ...CountryFields
    }
  }
}

fragment CountryFields on Country {
  name
  currency
}

It generates SDK you can import and wrap your GraphQLClient instance, and get fully-typed SDK based on your operations:

import { GraphQLClient } from 'graphql-request'
import { getSdkWithHooks } from './sdk'

function Continents() {
  const client = new GraphQLClient('https://countries.trevorblades.com/')
  const sdk = getSdkWithHooks(client)

  const { data, error } = sdk.useContinents('Continents')

  if (error) return <div>failed to load</div>
  if (!data) return <div>loading...</div>

  return (
    <ul>
      {data.continents.map((continent) => (
        <li>{continent.name}</li>
      ))}
    </ul>
  )
}

Pagination

codegen.yaml

config:
  useSWRInfinite:
    - MyQuery

Functional Component

const { data, size, setSize } = sdk.useMyQueryInfinite(
  'id_for_caching',
  (pageIndex, previousPageData) => {
    if (previousPageData && !previousPageData.search.pageInfo.hasNextPage)
      return null
    return [
      'after',
      previousPageData ? previousPageData.search.pageInfo.endCursor : null,
    ]
  },
  variables, // GraphQL Query Variables
  config // Configuration of useSWRInfinite
)

Authorization

import { GraphQLClient } from 'graphql-request'
import { getSdkWithHooks } from './sdk'
import { getJwt } from './jwt'

const getAuthorizedSdk = () => {
  const headers: Record<string, string> = { 'Content-Type': 'application/json' }
  const jwt = getJwt()
  if (jwt) {
    headers.Authorization = `Bearer ${jwt}`
  }
  return getSdkWithHooks(
    new GraphQLClient(`${process.env.NEXT_PUBLIC_API_URL}`, {
      headers,
    })
  )
}

export default getAuthorizedSdk

Next.js

// pages/posts/[slug].tsx
import { GetStaticProps, NextPage } from 'next'
import ErrorPage from 'next/error'
import { useRouter } from 'next/router'
import Article from '../components/Article'
import sdk from '../sdk'
import { GetArticleQuery } from '../graphql'

type StaticParams = { slug: string }
type StaticProps = StaticParams & {
  initialData: {
    articleBySlug: NonNullable<GetArticleQuery['articleBySlug']>
  }
}
type ArticlePageProps = StaticProps & { preview?: boolean }

export const getStaticProps: GetStaticProps<StaticProps, StaticParams> = async ({
  params,
  preview = false,
  previewData
}) => {
  if (!params) {
    throw new Error('Parameter is invalid!')
  }

  const { articleBySlug: article } = await sdk().GetArticle({
    slug: params.slug,
  })

  if (!article) {
    throw new Error('Article is not found!')
  }

  const props: ArticlePageProps = {
    slug: params.slug,
    preview,
    initialData: {
      articleBySlug: article
    }
  }

  return {
    props: preview
      ? {
          ...props,
          ...previewData,
        }
      : props,
  }
})

export const ArticlePage: NextPage<ArticlePageProps> = ({ slug, initialData, preview }) => {
  const router = useRouter()
  const { data: { article }, mutate: mutateArticle } = sdk().useGetArticle(
    `GetArticle/${slug}`, { slug }, { initialData }
  )

  if (!router.isFallback && !article) {
    return <ErrorPage statusCode={404} />
  }

  // because of typescript problem
  if (!article) {
    throw new Error('Article is not found!')
  }

  return (
    <Layout preview={preview}>
      <>
        <Head>
          <title>{article.title}</title>
        </Head>
        <Article article={article} />
      </>
    </Layout>
  )
}