ApolloのTutorialをやる
2021/5/27にやった
別projectに書いてたやつを移してきたmrsekut.icon
ApolloのTutorialをやる
GraphQLよくわからんので触ってみる
server側のコードはどれぐらい書き換える必要があるのか
web/RNで共通の実装を使えるのか
clientはどういう実装になるのか
Entityとか
既存の実装からの移行はどれぐらい大変か
SpaceXの宇宙行き便へ搭乗予約をするためのアプリケーションを作る
GraphQL Serverは、
SQLiteとREST
を中継する
cloneしたやつにはstartとfinalディレクトリがある
finalは完成版。お手本
startに実装を追加していく。最終的にfinalになる
この構成良いなmrsekut.icon
server/client両方書く
実装場所は別々
Apollo Srverをセットアップする
apollo-server と graphqlをinstall
Schemaを構築する
ここにSchemaを書く
code:js
const typeDefs = gql`
# Your schema will go here
`;
なんかのVSCode拡張入れないと色が付かないmrsekut.icon
Launchは、1つのロケット発射情報的なやつ
こういうのをObject Typeというらしい
普通のtsの文脈におけるそれのことか?
code:gql
type Launch {
id: ID!
site: String
mission: Mission
rocket: Rocket
isBooked: Boolean!
}
!があるものがnon Null
null許容の方がデフォなんだ..mrsekut.icon
code:gql
type User {
id: ID!
email: String!
token: String
}
[]は配列
code:gql
type Mission {
name: String
missionPatch(size: PatchSize): String
}
enum PatchSize {
SMALL
LARGE
}
missionPathは引数を取る
SMALLかLARGE
Query type
code:gql
type Query {
launch(id: ID!): Launch
me: User
}
見た目は同じだが、Queryという名のSchemaは扱いが特殊
1つ1つのfiledが、client目線のqueryになる
この例なら、clientは例えばmeという問い合わせができる
あれ、なんか思ってたのと違うな?mrsekut.icon
server sideで用意したAPI endpointじゃないと問い合わせできないの #?? なんかclientで適当にgraph qlのコード書いたらその形式のデータが自由に取れるものだと思ってたんだが
できるmrsekut.icon
こんな感じで書く
code:query
query Query {
me {
id
email
trips {
site
mission {
missionPatch
name
}
}
}
}
Mutationtype
これも特殊
code:gql
type Mutation {
bookTrips(launchIds: ID!): TripUpdateResponse! cancelTrip(launchId: ID!): TripUpdateResponse!
login(email: String): User
}
データ変更するquery的なやつ
各fieldがendpointっぽい感じにならしい
Queryとか、Mutationって、fieldがめちゃくちゃ増えそうな気がするが、同名(QueryやMutation)で複数の型定義できるのか?
npm startでよく見る画面が出る
https://gyazo.com/3c26a0c457ae94b5b7ab126d5c154c14
データソースをGraphQL APIにつなぎこむ
DataSourceというclassを使う
RESTとDBをこれにつなげる
RESTと繋ぐ
apollo-datasource-restのRESTDataSourceclassをextendsして使う
追加の設定無しでcacheしてくれる
this.getの基盤になるやつか
baseURL=https://google.comなら、this.get('hoge')としたら、http://google.com/hogeからfetchする感じ
上で定義したQueryの各fieldに対応する実装をLaunchAPIclassのmethodとして実装していく
RESTと繋ぐってそっちか〜mrsekut.icon
そらそうか。
client→graphQL→ここ→なんかのAPI server
ここの部分を作っている
既存API Serverに対してGraphQLを接続しているので、こういう実装が必要になる
今作っているLaunchAPI内のmethodで、
RESTのresponseを、さっき定義したGraphQL Schemaに変換する実装を手動で書く
ってことは、API Serverは今後も作り続けないといけないの #?? 何も嬉しくなっていない
たぶんこれはあとから説明される「DBとの接続」で解決されるはず
運営し続けたときの修正箇所メッチャ多くないか?
こういう実装のおかげでGraphQLとAPI Serverが疎結合になる
これ普通に外部APIサービス使っているって話だったmrsekut.icon
忘れてた
https://api.spacexdata.com/v2/は外部のサービスだ
これって結局、client目線で新しいAPI必要になったらServerも修正しないといけないのか #?? 場合に依るか
DBと接続する
SQLiteとそのORMを使っている
UserAPI classはORMでSQLiteの中身をゴニョる実装を書いている
別にORMが必須というわけでもないだろうmrsekut.icon
各methodに適合するSQLをそこに書けば同じことはできるはず
2つのDataSourceとApolloServerを接続する
今まで書いていたものは読み取り専用ってことかmrsekut.icon
対象はRESTとDB
ちがう、queryを使って読み取りもできていない
わからんくなった、Data Sourceってなんだ #?? 今まで書いていたものをresolversと呼ぶと思ってたがそういうわけではないんだなmrsekut.icon
QueryのResolverを書く
これでようやくqueryで読み取りができるようになる
Resolver
GraphQL Schemaの1filedごとにfetchする関数を定義する?
だるそーmrsekut.icon
これらの関数(resolver)は、Shcmeaで定義した型のデータか、Promiseを返す
各resolverのinterfaceは決まっている
e.g. fieldName: (parent, args, context, info) => data;
引数部分の型が決まっている
object型には入れ子関係があるが、親のresolverのほうが子より先に呼ばれる
Queryのfieldと名前を合わせて定義する
code:js
Query: {
launches: (_, __, { dataSources }) =>
dataSources.launchAPI.getAllLaunches(),
launch: (_, { id }, { dataSources }) =>
dataSources.launchAPI.getLaunchById({ launchId: id }),
me: (_, __, { dataSources }) => dataSources.userAPI.findOrCreateUser()
}
これ別にQueryに限らず他のSchemaに対しても定義しないといけないらしい
でも全部やる必要はない
みづれーmrsekut.icon
あ、でもこれでresolver完成7日
ここに出てくるgetAllLaunchesとかはさっきのDataSource定義したやつ
たぶん
contextを仲介してアクセスする
resolverを薄く保つのがベスプラらしい
resolverは定義してなくてもdefaultのものがある程度がんばってくれるらしい
どういうロジックかは知らん
https://gyazo.com/640a283280955529427f956f7a6dd845
allで返すのではなくpagenationできる
LaunchConnectionを使う
cursorは現在のindex
なぜString?
mutationのResolverを書く
ApploServerのcontextに指定する
この関数はclientがserverに送信するたびに呼ばれる
認証とかに使う
読んでない
clientを見ていく
clientはtsなんだmrsekut.icon
うわ、5を読んでないと無理やんけ
動かさずに読むだけにしよう
めちゃくちゃ雑に読んでる
Componentごとかなんかでquery書いて、useQueryで呼べばデータが取れる
ノリはSWRとかに近い
data, loading, errorとかも返してくれる
clientはメッチャ楽になるなmrsekut.icon
まさにGraphQLという感じ
確かにうまくやればReduxとかは不要になりそう
もういいかな
残りは読んでない