Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/croutonn/graphql-codegen-plugin-typescript-swr

A GraphQL code generator plug-in that automatically generates utility functions for SWR.
https://github.com/croutonn/graphql-codegen-plugin-typescript-swr

graphql graphql-code-generator nextjs react stale-while-revalidate swr

Last synced: about 2 months ago
JSON representation

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

Awesome Lists containing this project

README

        

# graphql-codegen-plugin-typescript-swr

A [GraphQL code generator](https://graphql-code-generator.com/) plug-in that automatically generates utility functions for [SWR](https://swr.vercel.app/).

## Table of Contents

- [API Reference](#api-reference)
- [`excludeQueries`](#excludequeries)
- [`useSWRInfinite`](#useswrinfinite)
- [`autogenSWRKey`](#autogenswrkey)
- [Config Example](#config-example)
- [Usage Examples](#usage-examples)
- [Pagination](#pagination)
- [Authorization](#authorization)
- [Next.js](#nextjs)

## 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

```yaml
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:

```graphql
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:

```tsx
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

failed to load

if (!data) return
loading...

return (


    {data.continents.map((continent) => (
  • {continent.name}

  • ))}

)
}
```

### Pagination

#### codegen.yaml

```yaml
config:
useSWRInfinite:
- MyQuery
```

#### Functional Component

```tsx
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

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

const getAuthorizedSdk = () => {
const headers: Record = { '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

```tsx
// 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
}
}
type ArticlePageProps = StaticProps & { preview?: boolean }

export const getStaticProps: GetStaticProps = 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 = ({ slug, initialData, preview }) => {
const router = useRouter()
const { data: { article }, mutate: mutateArticle } = sdk().useGetArticle(
`GetArticle/${slug}`, { slug }, { initialData }
)

if (!router.isFallback && !article) {
return
}

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

return (

<>

{article.title}


>

)
}
```