TypeScriptを用いてContentfulへ新規投稿する

他のサイトで書いた記事を取得し、contetfulへ保存する処理についてまとめています。
contentfulの基礎的な概念や扱いを把握していることを前提としてい記事を書いております。
間違いなどあれば、指摘していただけると幸いです。

利用するサードパーティーのインストール([https://www.npmjs.com/package/contentful-management](https://www.npmjs.com/package/contentful-management))

```bash
yarn add contentful-management
```

記事を取得するだけならば、[こちら(contentful)](https://github.com/contentful/contentful.js) のサードパーティーだけで事足りますが、記事の保存などを行う場合は上の　contentful-management を利用することをお勧めします。

### まずapi key や spaceの情報を用いてclientを作成する

APIKEY, SPACEID はそれぞれのアカウントのものに読み替えてください。

spaceのenvironmentはデフォルトの `master`を利用しています

```tsx

import * as contentful from "contentful-management";
import { Environment } from "contentful-management/dist/typings/entities/environment";

export const connect = async (): Promise<Environment> => {
  const client = contentful.createClient({
    accessToken: APIKEY,
  });
  const mySpace = await client.getSpace(SPACEID);

  return await mySpace.getEnvironment("master");
};
```

上の connect メソッドによって返されるspace の Environment オブジェクトがspace のエントリーやメディアを操作するためのapiを提供してくれています。

## 新規記事の追加方法

まず、インターネット上にある画像のURLをもとにmediaの画像を作成 => それを利用して、新規の投稿を作ります。

### Mediaへ新規画像の登録

createAssetWithIdメソッドは第一引数にidとなるstring, 第二引数にmedia objectを渡します。

```tsx
const myEnvironment = await connect();

const assetRes = await myEnvironment
    .createAssetWithId("id-absdef", {
      fields: {
        title: {
          "en-US": "タイトル",
        },
        file: {
          "en-US": {
            contentType: "image/webp",
            fileName: "filename.webp",
            upload: "https://-------",
          },
        },
      },
    })
    .then((asset) => asset.processForAllLocales());

  await assetRes.publish();

// asset mediaのidさえあれば紐づけられる！
  const assetObj = {
    sys: {
      id: assetRes.sys.id,
      type: assetRes.sys.type,
      linkType: "Asset",
    },
  };
```

assetObj は次の新規投稿に用いるオブジェクトです。mediaのidさえあれば、contentful内で自動で既存メディアと紐づけてくれるようです。

`await assetRes.publish()`を忘れると投稿がdraft状態のままとなるので注意してください

### 新規記事の登録

contetTypeは利用するcontent typeに読み替えてください

createEntryWithIdメソッドは第一引数にcontent type, 第二引数にid, 第三引数に登録するobjectを渡します。

```tsx
const res = await myEnvironment.createEntryWithId(
    "contentType",
    "id-ghijk",
    {
      fields: {
        title: { "en-US": "title" },
        slug: { "en-US": "slug" },
				// assetObjはmediaを新規登録した際に作成したオブジェクト
        image: { "en-US": assetObj },
        contents: { "en-US": "test test test test test test" },
        time: { "en-US": new Date() },
        tags: { "en-US": ["aaa", "bbb", "ccc"] },
      },
    }
  );
  await res.publish();
```

## 既存の投稿を更新する場合

```tsx
let item = await myEnvironment.getEntry("id-gihjk");

item.fields.title["en-US"] = "new title";
item.fields.image["en-US"] = assetObj;
item.fields.contents["en-US"] = "new test test test test";
item.fields.tags["en-US"] = ["aaa", "bbb", "ccc", "zzz", "xxx"];
// 変更の適用
await item.update();
// 変更の更新
item = await myEnvironment.getEntry("id-gihjk");
await item.publish();
```

updateメソッドを呼ぶだけでは状態がchangeになるだけで、変更が公開されないので、publishメソッドまで呼ぶことを忘れずに、、

### 参考

- [https://www.npmjs.com/package/contentful-management](https://www.npmjs.com/package/contentful-management)
- [https://contentful.github.io/contentful-management.js/contentful-management/3.10.0/ContentfulSpaceAPI.html](https://contentful.github.io/contentful-management.js/contentful-management/3.10.0/ContentfulSpaceAPI.html)
- [https://www.contentful.com/developers/docs/references/content-management-api/](https://www.contentful.com/developers/docs/references/content-management-api/)
- [https://www.youtube.com/watch?v=v98waYVjQtk&list=LL&index=1](https://www.youtube.com/watch?v=v98waYVjQtk&list=LL&index=1)