PTRESTfulAPIClientの使用方法

JavaScriptからPowerCMS XのAPIを容易に利用できる「PTRESTfulAPIClient」が配布されています。私が開発したもので、ブラウザ環境とNode.js環境どちらでも利用できます。本稿ではNext.jsでの利用を解説します。Next.jsの公式ドキュメント「Basic Features: Data Fetching | Next.js」が参考になりました。PTRESTfulAPIClientが提供する各メソッドの引数の詳細はREADMEをご確認ください。

準備

libs/pt-restful-api-client.jsにPTRESTfulAPIClientのファイルを配置した後、libs/client.jsでPTRESTfulAPIClientのインスタンスを作成しておきます。(※2021年11月8日追記:npmコマンドでもインスール可能になりました。)

import PTRESTfulAPIClient from './pt-restful-api-client';
export const client = new PTRESTfulAPIClient('https://jamstack.anothersky.pw/powercmsx/api', 1);

一覧ページ

オブジェクトの一覧ページ(例えばentry一覧)ではlistObjectsでオブジェクト一覧を取得します。PTRESTfulAPIClientがURLの組み立てやFetch APIの呼び出しを行うので、モデルとワークスペースを引数で指定するだけで済みます。記事数や並び順などのパラメーターも指定できます。

import Link from 'next/link';
import { client } from '../libs/client';

export default function Home({ entries }) {
  return (
    <ul>
      {entries.map(entry => (
        <li key={entry.id}>
          <Link href={`/information/${entry.basename}`}>
            <a>{entry.title}</a>
          </Link>
        </li>
      ))}
    </ul>
  )
}

export const getStaticProps = async () => {
  const params = {
    sort_by: 'published_on',
    sort_order: 'desc',
    limit: 6,
  };
  const response = await client.listObjects('entry', 1, params);
  const data = await response.json();
  return {
    props: {
      entries: data.items,
    },
  };
};

個別ページ

オブジェクトの個別ページ(例えばentryの個別ページ)ではgetObjectでオブジェクトのデータを取得します。サンプルコードではオブジェクトのIDではなく、ベースネームでオブジェクトを特定しています。カラムを指定しない時は全カラムのデータがレスポンスに含まれるので、モデル設計とページの出力状態によっては無駄が生じる可能性があります。パラメーターで必要なカラムを指定するのがよいでしょう。

import { client } from '../../libs/client';

export default function BlogDetail({ entry }) {
  return (
    <>
      <h1>{entry.title}</h1>
      <div>
        <time dateTime={entry.published_on.replace(/(\d{4}-\d{2}-\d{2}).*/, '$1')}>{entry.published_on.replace(/(\d{4})-(\d{2})-(\d{2}).*/, '$1年$2月$3日')}</time>
      </div>
      <div
       dangerouslySetInnerHTML={{
          __html: entry.text,
        }}
      />
    </>
  );
}

export const getStaticPaths = async () => {
  const response = await client.listObjects('entry', 1);
  const entries = await response.json();
  const paths = entries.items.map(entry => ({
    params: { basename: entry.basename },
  }));
  return { paths, fallback: false };
};

export const getStaticProps = async (context) => {
  const options = {
    cols: 'title,text,published_on',
    basename: context.params.basename,
  };
  const response = await client.getObject('entry', null, 1, options);
  const entry = await response.json();
  return {
    props: {
        entry,
    }
  }
};

認証が必要な時

下書きのオブジェクトを取得する時など、認証が必要な場合は以下のコードで認証を行いアクセストークンを取得します。取得したアクセストークンはgetObjectメソッドなどの引数として渡します。認証に必要なユーザー名やパスワードは.envに記述しておきます。

const name = process.env.CMS_USERNAME;
const password = process.env.CMS_PASSWORD;
const authResponse = await client.authentication(name, password);
if (!authResponse.ok) {
  return res.status(401).json({ message: 'Authentication faild.' });
}
const authData = await authResponse.json();
const token = authData.access_token;