ts-restのclientでNext.jsのrevalidateプロパティを渡すサンプルコード

2023/08/25に公開

追記: 2024/9
おそらくts-restがデフォルトでnextオプションに対応したっぽい?のでこの対応は不要だと思います。


備忘録として。RequestInitはNext.jsがglobal.d.tsに定義してあるので、これを利用。

node_modules/next/types/global.d.ts
//...省略

interface RequestInit {
  next?: NextFetchRequestConfig | undefined
}
import { initQueryClient } from '@ts-rest/react-query';
import { ApiFetcherArgs } from '@ts-rest/core';
import { contract } from 'your-contract-path';

if (typeof process.env.NEXT_PUBLIC_API_BASE_URL === 'undefined') {
  throw new Error(
    `env NEXT_PUBLIC_API_BASE_URL is undefined: ${process.env.NEXT_PUBLIC_API_BASE_URL}!`
  );
}

export const client = initQueryClient(contract, {
  baseUrl: process.env.NEXT_PUBLIC_API_BASE_URL,
  baseHeaders: {
    'Content-Type': 'application/json',
  },
  api: async ({
    path,
    method,
    headers,
    body,
    credentials,
    signal,
    cache,
    next,
  }: ApiFetcherArgs & RequestInit) => {
    const result = await fetch(path, {
      method,
      headers,
      body,
      credentials,
      signal,
      cache,
      next,
    });
    const contentType = result.headers.get('content-type');

    if (contentType?.includes('application/json')) {
      return {
        status: result.status,
        body: await result.json(),
        headers: result.headers,
      };
    }

    if (contentType?.includes('text/plain')) {
      return {
        status: result.status,
        body: await result.text(),
        headers: result.headers,
      };
    }

    return {
      status: result.status,
      body: await result.blob(),
      headers: result.headers,
    };
  },
});

Discussion