Strapi + GraphQL API を各クライアントで利用してみた【iOSアプリ編】【未解決】

今回は前回用意した Strapi + GraphQL を利用して、iOSアプリからAPIを叩いてみます。

前回👉Strapi GraphQL導入編

できなさすぎて心折れたので今回の記事はiOSアプリからAPIを叩けていません。一部役にたつ部分もあるかもしれないので投稿させていただきました。

プロジェクトの作成

Xcode 14.2を利用してSwiftUIでプロジェクトを作成します。

iOSアプリとしましたが、SwiftUI ならマルチプラットフォームで利用できるので、今回はマルチプラットフォームでプロジェクトを作成しました。

ライブラリの選定

GraphQL クライアント側のライブラリを選定するために以下の記事を読みました。

iOS アプリから GraphQL API を利用する
「最適なiOS のGraphQLクライアントを求めて」という発表をしました

apollographql/apollo-iosSwiftGraphQLのどちらかを選べば良さそうです。

前者の「iOS アプリから GraphQL API を利用する」の記事のSwiftGraphQL を採用しなかった理由として以下のように挙げられていました。

Swift でクエリを定義できるのは面白いと思いましたが、クエリを Swift で書く方法を覚える必要があり、Android 側とクエリを共有したかったので今回は採用しませんでした。

今回は私も Android 側とクエリを共有したいと思うので、apollographql/apollo-iosを選択しようと思います。

apollo-ios の導入

Apolloのドキュメントを参考に導入します。

STEP.1
Swift Package Manager で導入

apollographql/apollo-iosをSwift Package Manager を利用して導入します。

PROJECT > Package Dependencies より Package の追加を行います。

https://github.com/apollographql/apollo-iosで検索して 今回は mainブランチを指定して導入しました。

一番上のApolloのみを選択して Add Packageをします。

STEP.2
schema.json を用意する

schema.jsonという、型定義がまとめられた json ファイルを用意します。

Strapi を開発環境で起動します。

# 作業ディレクトリに移動する
$ cd ~/StrapiProjects/vps-docker-strapi

$ docker compose -f docker-compose.dev.yml --env-file .env.development up

http://localhost:1337/graphql にアクセスし、SCHEMAを開きDOWNLOADします。

ダウンロードされたファイルを schema.jsonという名前に変更して、プロジェクトに追加します。

STEP.3
.graphql ファイルを作成して操作を定義する
次に 前回「Strapi GraphQL導入編」、GraphQL Playground で書いたような実際の操作の定義を書いたファイルの用意をします。

GraphQLフォルダを作り、その中にGetArticle.graphqlを作成しました。

STEP.4
Codegen CLIをインストールする
Swift Package Manager で導入した Apollo から、さらに Codegen CLI をインストールします。

プロジェクトターゲットを右クリックして、Install CLIを選択します。

一番上を選択しました。

Allow Command to Change Files を選択しました。

しばらくすると成功した通知が来ました。

これにより、プロジェクトのルートにapollo-ios-cliのショートカットが生成されました。

apollo-ios-cliのオリジナル

apollo-ios-cliのショートカットを右クリックしてオリジナルを表示をしてみました。

/Users/ユーザ名/Library/Developer/Xcode/DerivedData/StrapiArticleSample-cpdrlqdfmosvfbenzyriapaewhpd/Build/Products/Debug/apollo-ios-cliに配置されていました。

/Users/ユーザ名/Library/Developer/Xcode/DerivedData/内は Xcode に不具合が起きた時によく消すフォルダでもあるので、そういった場合は再度STEP.4の手順でインストールし直すと良さそうです。

STEP.5
apollo-codegen-config.json を生成する

STEP.4でインストールしたapollo-ios-cliをターミナルから使います。

まずは apollo-codegen-config.json を生成します。

# 作業ディレクトリに移動する
$ cd ~/XcodeProjects/StrapiArticleSample

# apollo-codegen-config.json を生成
# apollo-ios-cli init --schema-namespace ${MySchemaName} --module-type ${ModuleType}

Project configurationを参考に${MySchemaName}${ModuleType}を考えます。

MySchemaName はapollo.fetch(query: MySchemaName.GetArticleQuery()) {}といったようなクラス名になるようです。
今回は GraphQLSchemaという名前にしました。

ModuleType はSchema Types Moduleを読んだところ、生成されるコードをモジュールとして切り分けるか、そのままターゲットに配置するかの設定のようです。

When setting up codegen for the first time, you’ll need to specify a location path for the generated module and the moduleType. The moduleType property configures how the code generation engine links generated schema types in your project.

For most projects, we recommend creating a separate schema module. This enables you to share your generated models across modules as your project grows. For simple single-target applications, you can embed your schema types directly in your target.

多くの場合では分けるといいよということなので、swiftPackageManagerを利用してパッケージ化します。

その他のModuleType

embeddedInTarget(name:)swiftPackageManagerotherが指定できます。

詳しくは Codegen configuration の Module Type セクションに書かれています。

先ほどのコマンドを実際にうってみます。

# 作業ディレクトリに移動する
$ cd ~/XcodeProjects/StrapiArticleSample

# apollo-codegen-config.json を生成
$ ./apollo-ios-cli init --schema-name GrqphQLSchema --module-type swiftPackageManager

New configuration output to ./apollo-codegen-config.json.

これで apollo-codegen-config.jsonが生成されました。

STEP.6
Swift のコードを生成する
先ほど生成した config ファイルを元に実際に query 等を Swift で利用できるように、コードの生成を行います。

# 作業ディレクトリに移動する
$ cd ~/XcodeProjects/StrapiArticleSample

# Swift のコードを生成
$ ./apollo-ios-cli generate
schema.json の場所

上記を実行すると
Error: A GraphQL schema could not be found. Please verify the schema search paths.というエラーが発生しました。

これは STEP.2 で追加した schema.jsonがどこにあるかわからないよーとエラーです。

apollo-codegen-config.jsonを開き指定してあげます。

schema.jsonGraphQLディレクトリに配置しなおしました。

apollo-codegen-config.json
  "input" : {
    "operationSearchPaths" : [
      "**/GraphQL/*.graphql"
    ],
    "schemaSearchPaths" : [
      "**/GraphQL/*.json"
    ]
  },

エラーの解消

http://locahost:1337/graphql からダウンロードした schema.json が不完全であるというエラーが出ました。

Error: Error: Invalid or incomplete introspection result. Ensure that you are passing "data" property of introspection response and no "errors" was returned alongside: 

以下はうまくいきませんでした。

json だとうまくいかなかったので、再度 http://localhost:1337/graphql にアクセスして SCHEMA > DOWNLOAD > CDLをダウンロードしました。

schema.graphqlを GrqphQL ディレクトリに配置しました。

apollo-codegen-config.jsonを開きschemaSearchPaths.grqphqlに変更します。

schema.jsonGraphQLディレクトリに配置しなおしました。

apollo-codegen-config.json
  "input" : {
    "operationSearchPaths" : [
      "**/GraphQL/*.graphql"
    ],
    "schemaSearchPaths" : [
      "**/GraphQL/*.grqphql"
    ]
  },

エラーの解消2

Apollo does not support anonymous operations because operation names are used during code generation. Please give this operation a name.

続いて GetArticle.graphqlを修正します。queryという操作ワードが抜けていたので追加しました。

GetArticle.graphql
query getArticle {
  article(id: 1) {
    data {
      attributes {
        title
        content
      }
    }
  }
}

上記メモのエラーを解消して、再度実行します。

# 作業ディレクトリに移動する
$ cd ~/XcodeProjects/StrapiArticleSample

# Swift のコードを生成
$ ./apollo-ios-cli generate

できません😢

STEP.2 に立ち返って 以下のように schema.json or schema.graphql の生成を試してみましたが、ダメでした。

ためしたこと1

apollo ではなく Rover CLIを利用します。(後述するメモ内のエラーによりschemaファイルが取得できなかったため)

# Rover をインストールする
$ npm install -g @apollo/rover

roverが使えない場合はターミナルを再起動すると使えるようになりました。

ローカル環境を起動している状態で以下を実行します

$ rover graph introspect http://localhost:1337/graphql > schema.graphql    

生成された schema.graphqlはSTEP.6で利用します。(現在このschema.graphql でもSTEP.6で失敗している状況を打破できないでいます。😭)

ためしたこと2

iOS | Apollo を使って GraphQL を使えるようにするを参考にしました。

ターミナルを開き

# apollo と grqphql をインストールする
$ npm install -g apollo
$ npm install -g graphql

# schema を取得する
$ npx apollo schema:download --endpoint=https://本番環境のドメイン/graphql schema.json --header="Authorization: Bearer APIトークン"

header に追加する Authorization: Bearer のAPIトークンの取得はStrapi管理画面から行います。
Strapi を開発環境と本番環境のDockerで動かしたい【その7】- APIとして公開するのSTEP.5を参考にしてください。

上記を実行するとエラーが出てダウンロードできません。

  ✖ Saving schema to schema.json
    → ServerError: Response not successful: Received status code 400
    Error: ServerError: Response not successful: Received status code 400

SwiftUIでGraphQLを使う準備 – Zennを参考にNodeのバージョンを変更したところ、実行できました。

$ node -v
v16.16.0

$ nodenv versions 
  system
  14.16.0
* 16.16.0

$ nodenv local 14.16.0

$ node -v
v14.16.0

変更後に再度 apollo と grqphql のダウンロードをしないとError: Cannot find module 'graphql/validation/rules/KnownArgumentNamesRule'というエラーで実行できませんでした。

# apollo と grqphql をインストールする
$ npm install -g apollo
$ npm install -g graphql

# schema を取得する
$ npx apollo schema:download --endpoint=https://本番環境のドメイン/graphql schema.json --header="Authorization: Bearer APIトークン"

未解決でごめんなさい😢

https://github.com/apollographql/apollo-tooling/issues/344
この問題で The schema definition is not executable.がでて一向に./apollo-ios-cli generateができません。

取得してきたschema.jsonが悪いのかなと色々な方法で取得してみたんですがダメでした。

お蔵入りするにはもったいないのでぐちゃぐちゃですがこのまま投稿させていただきます。