🐡

MicroCMSのAPIをTypeScriptで型カッチリに実装する

2021/09/15に公開

MicroCMSとTypeScript

MicroCMSAPIをTypeScript上で扱う場合、設定したスキーマに沿って自分で型を書かなければなりません。
この作業はそれなりに手間がかかるので、自動化していきたいと思います。

今回使用しているソースコード

https://github.com/SoraKumo001/microcms-test

MicroCMSの設定

サービスの作成

まずはMicroCMS上でサービスを作成します。
名前は早い者勝ち方式のようなので、空いている名前を設定します。

開発確認用なのでプランは無料を選びます

APIの作成

今回はAPIを一つ作ってスキーマを設定します

作成後の画面になっていますが、以下のようにスキーマを設定します。

APIを作成したら、右上のAPI設定からAPIスキーマに移動してこの設定をエクスポートするを選び、出力されたファイルを保存します。
ファイルは以下のような内容になっています。
これを元にTypeScriptの型を生成します。

{
    "apiFields": [
        {
            "idValue": "lWs_WVisjo",
            "fieldId": "title",
            "name": "タイトル",
            "kind": "text",
            "isUnique": false
        },
        {
            "fieldId": "body",
            "name": "本文",
            "kind": "textArea"
        },
        {
            "fieldId": "visible",
            "name": "表示",
            "kind": "boolean"
        }
    ],
    "customFields": []
}

HTTPメソッドの設定で、全てを有効にします
これをやっておかないと、この後必要になるGET以外のメソッドが使用できません

TypeScriptによるAPIアクセス

ここからがプログラムの解説です。

必要なモジュールのインストール

モジュールのインストールと必要なディレクトリの作成をします

yarn add dotenv microcms-lib
yarn add -D @types/node microcms-typescript ts-node typescript
mkdir types
mkdir schema

TypeScriptの型情報を作成

フォルダが出来たらschemaにエクスポートしたファイルをコピーし、以下のコマンドを実行します
cms-types.tsというファイルに型情報が出力されます

yarn microcms-typescript schema types/cms-types.ts

ファイル名からエンドポイント名を取り出すので、スキーマのファイル名は変更しないでください
また、フォルダ上に同じエンドポイント名のファイルがある場合は、ファイル末尾の日付から最新のものが選択されます

コマンドの使い方はmicrocms-typescriptを確認してください

以下のように型情報が作成されます

type Reference<T, R> = T extends 'get' ? R : string | null;
type DateType = {
  createdAt: string;
  updatedAt: string;
  publishedAt: string;
  revisedAt: string;
};

type Structure<T, P> = T extends 'get'
  ? { id: string } & DateType & Required<P>
  : Partial<DateType> & (T extends 'patch' ? Partial<P> : P);

export type contents<T='get'> = Structure<
T,
{
  /**
   * タイトル
   */
  title?: string
  /**
   * 本文
   */
  body?: string
  /**
   * 表示
   */
  visible?: boolean
}>


export interface EndPoints {
  get: {
    contents: contents<'get'>
  }
  post: {
    contents: contents<'post'>
  }
  put: {
    contents: contents<'put'>
  }
  patch: {
    contents: contents<'patch'>
  }
}

APIKeyを環境変数として設定

APIキーはサービス設定メニューのAPI-KEYから持ってきます

.envファイルを作成し、以下のように設定します

# サービス名
SERVICE=

# 読み込み用APIキー
APIKEY=

# 書き込み用APIキー
APIKEY_WRITE=

# 下書きデータ取得用APIキー
APIKEY_GLOBAL=

テストプログラムの作成

MicroCMSクラスの使い方はmicrocms-libを確認してください

src/index.ts

import type { EndPoints } from '../types/cms-types'
import { MicroCMS } from 'microcms-lib'
import { config } from 'dotenv'

config() // .env

const cms = new MicroCMS<EndPoints>({
  service: process.env.SERVICE!,
  apiKey: process.env.APIKEY,
  apiWriteKey: process.env.APIKEY_WRITE,
  apiGlobalKey: process.env.APIKEY_GLOBAL
})

const main = async () => {
  // 10 write tests
  console.log('\n-- write --')
  for (let i = 0; i < 10; i++) {
    await cms
      .post('contents', { title: 'データ' + i, body: '本文', visible: true })
      .then((id) => console.log(`id:${id}`))
  }

  // display data
  const result = await cms.gets('contents', {
    limit: 10000,
    fields: ['id', 'title'],
    orders: 'createdAt'
  })
  if (result) {
    const { totalCount, contents } = result
    console.log(`\n-- read: ${contents.length}/${totalCount} --`)
    contents.forEach(({ id, title }) => {
      console.log(id, title)
    })
  }

  // // batch deletion
  console.log('\n-- delete --')
  if (result) {
    for (let i = 0; i < result.contents.length; i++) {
      await cms
        .del('contents', result.contents[i]['id'])
        .then((v) => (v ? console.log(`削除:${result.contents[i]['id']}`) : false))
    }
  }
}
main()

テストプログラムの実行

yarn ts-node src

実行結果

結果がnullになる場合は、APIキーやメソッドが有効になっているか確認してください

-- write --
id:t0xhfy9bx
id:ijjoyma41
id:7t7086v07l
id:we0b9me8q
id:ecdaipta97
id:jksu9r36m6o
id:z3vn5fg72
id:lhjoz8jxfm
id:urqu1qufif
id:s-9w96qe8

-- read: 10/10 --
t0xhfy9bx データ0
ijjoyma41 データ1
7t7086v07l データ2
we0b9me8q データ3
ecdaipta97 データ4
jksu9r36m6o データ5
z3vn5fg72 データ6
lhjoz8jxfm データ7
urqu1qufif データ8
s-9w96qe8 データ9

-- delete --
削除:t0xhfy9bx
削除:ijjoyma41
削除:7t7086v07l
削除:we0b9me8q
削除:ecdaipta97
削除:jksu9r36m6o
削除:z3vn5fg72
削除:lhjoz8jxfm
削除:urqu1qufif
削除:s-9w96qe8

microcms-libに関して

microcms-libのMicroCMSクラスを使うと、以下の関数が型設定付きで利用出来ます

  • 単独データの取得
    get
  • 複数データの取得
    gets
  • データの新規作成
    post
  • IDを指定した新規作成
    put
  • データの更新
    patch
  • データの削除
    del

getのオプションでfieldsを設定した場合など、戻り値の型も自動的にフィルタされるようになっています。
またpostやput等の場合スキーマの必須項目の確認を行うので、データが足りないと文法チェックの段階でエラーになります。
その他、今回扱っていないデータ型などにも一通り対応を入れてあります。

ちなみにputはRestAPI的にはデータが無ければ作成、あれば更新なのですが、MicroCMSではあるとエラーです。

まとめ

MicroCMSを使って何か作ろうと思ったら、作るためのライブラリになっていました。
今回の型の組み替えはOpenAPIの定義ファイルから型カッチリでAPIを呼び出すrequest-restapiを作ったときより遙かに楽でした。
以前作ったものは実処理の三倍、型変換部分のコードがあるという内容です。
何かやろうとすると脱線して変な副産物が生み出されていきますが、npmのダウンロード数は伸びません。
これからも誰も使わないライブラリを量産していこうと思います。

GitHubで編集を提案

Discussion