microcmsio/microcms-js-sdk

提案: `res.json` ではなく `res` を返すオプション

Opened this issue · 6 comments

現状では res.json をした結果を返しており、レスポンスヘッダーなどを利用できない。
これらを利用できるように、返却する値を変更するオプションを追加するのはどうだろうか?

dc7290 commented

関連: #51

dc7290 commented

デバッグモードという概念で実装するのが良さそう

tecsoc commented

@dc7290

export interface GetRequest {
  endpoint: string;
  contentId?: string;
  queries?: MicroCMSQueries;
  customRequestInit?: CustomRequestInit;
  response?: Response;
}

上記のように、関数の戻り値にresponse用のプロパティーを追加するのはいかがでしょうか?
responseを返却するかしないかは、retryOptionと同様にcreateClient時にオプションで切り替えられるようにする想定です。
レスポンスを取得したい場合というのは
エンドポイントごとに異なるというより、ユーズケースによると思っているので。
customRequestInitのような渡し方でも全然良いと思いますが

[提案]
Aspida の get $get のように、HTTPステータス等の付加情報と共に結果を返す関数を別で用意するのはどうでしょうか?
https://github.com/aspida/aspida/tree/main/packages/aspida-fetch#make-http-request-from-application

例:

getListDetail の結果

{
  "id": "abc",
  "publishedAt": "...",
  ...
}

$getListDetail(仮称) の結果

{
  "status": 200,
  "data": {
    "id": "abc",
    "publishedAt": "...",
    ...
  }
}

↑をそのまま採用すると Aspida の $ の有無とは返る内容が逆になってしまいますが…($ が何を意味しているのかは正直分かっていません)

私はHTTPステータスコードが欲しかったので、対応されるまでの間はfetchで取り直すことにしました。

const data = await client
  .getListDetail({ endpoint, contentId })
  .catch(async (error) => {
    // refetch with fetch API to get HTTP status code
    const { status } = await fetch(
      `https://${serviceDomain}.microcms.io/api/v1/${endpoint}/${contentId}`,
      { headers: { "X-API-KEY": apiKey } },
    );

    switch (status) {
      case 404:
        return notFound();
      default:
        throw e;
    }
  });

私もステータスコードは取得したいですねー
ダーティな実装ですが、エラーオブジェクトにステータスコードが埋め込まれていることは確認できたので、以下のようにパースして対処しています

/**
 * microCMSの例外をステータスコードに変換する関数
 *
 * microCMSのエラーオブジェクトのメッセージを解析し、ステータスコードを返却します。
 *
 * @param error
 */
function fromMicroCmsErrorToStatusCode(error: Error) {
  // 必ずmicroCMSのエラーメッセージに含まれるテキストの正規表現
  // source: https://github.com/microcmsio/microcms-js-sdk/blob/05a4efe79ce90932a6d7f33b262ff959ade88d4a/src/createClient.ts#L99
  const regex = /status: (\d{3})/;
  const statusCode = error.message.match(regex)?.at(1);
  const parsedStatusCode = parseInt(statusCode ?? "");

  // パースに失敗した場合は500
  if (Number.isNaN(parsedStatusCode)) {
    return STATUS_CODE.INTERNAL_SERVER_ERROR;
  }

  const status = pipe(
    values(STATUS_CODE),
    find((value) => value.STATUS === parsedStatusCode),
  );

  if (status) {
    return status;
  } else {
    // 想定していない例外は全て500
    return STATUS_CODE.INTERNAL_SERVER_ERROR;
  }
}