ライブラリのインストール
npm i @nuxtjs/apollo graphql-tag @vue/apollo-composable
plugins の下にapolloのconfigファイルを設置
設定ファイル内で関数が必要なら別ファイルMUSTとなっていたのでいったん別ファイルで用意
import { Context } from '@nuxt/types'
export default (context:Context) => {
return {
httpEndpoint: 'GraphQLサーバのエンドポイントURL',
/*
* For permanent authentication provide `getAuth` function.
* The string returned will be used in all requests as authorization header
*/
// getAuth: () => 'Bearer my-static-token',
}
}
定義ファイル ( shims-gql.d.ts ) を設置
公式には gql.d.ts とあったのだけど、 shims-vue.d.ts と近しい設定内容にみえたのでファイル名は shims-gql.d.ts としてみた
declare module '*.gql' { import { DocumentNode } from 'graphql' const content: DocumentNode export default content } declare module '*.graphql' { import { DocumentNode } from 'graphql' const content: DocumentNode export default content }
nuxt.config.js に設定追加
modules: [
'@nuxtjs/apollo',
],
// Apollo module configuration
apollo: {
clientConfigs: {
default: '~/plugins/ApolloConfig.ts',
}
},
"files": [
"shims-gql.d.ts",
],
グローバル setup() で デフォルトのApolloクライアントインスタンスを登録
plugins/provideApolloClient.ts を設置
import { provide, onGlobalSetup } from '@nuxtjs/composition-api'
import { DefaultApolloClient } from '@vue/apollo-composable'
import { Plugin } from '@nuxt/types'
const provideApolloClient:Plugin = ({ app }) => {
onGlobalSetup(() => {
provide(DefaultApolloClient, app.apolloProvider.defaultClient)
})
}
export default provideApolloClient
nuxt.config.js に設定追加
plugins: [ '~/plugins/provideApolloClient.ts' ],
定義ファイルで app.apolloProvider に型付け
#おそらく、@nuxtjs/apollo もしくは nuxt のバージョンが高ければ(最初からあって)不要…?
import { ApolloProvider } from 'vue-apollo/types/apollo-provider'
declare module '@nuxt/types' {
interface NuxtAppOptions {
apolloProvider: ApolloProvider
}
}
HASURAでGraphQLサーバを用意
apolloのconfigファイル書き換え
headerに情報追加が必要なので default を使用しない形に書き換え
import { Context } from '@nuxt/types'
import { setContext } from 'apollo-link-context'
import { from } from 'apollo-link'
import { createHttpLink } from 'apollo-link-http'
export default (context:Context }) => {
const headersConfig = setContext(() => ({
headers: {
'content-type':'application/json',
'x-hasura-admin-secret': 'たぶんここにベタで書くべきではない気がするが…',
},
}))
const link = createHttpLink({
uri: 'GraphQLサーバのエンドポイントURL',
})
return {
link: from([
headersConfig,
link
]),
defaultHttpLink: false // これがないとエラーになる
}
}
gqlファイルを用意
HASURAのコンソール上で作成したGraphQLクエリーを貼り付け
apollo/queries/USER.gql
query USER($id: Int!) {
user_items_by_pk(id: $id) {
department
name
occupation
id
applications {
id
free_text
place
select
select_other
skills(order_by: {skill: asc}) {
skill
}
}
}
}
apollo/mutations/UPDATE_APPLICATION.gql
#HASURAはオブジェクト(&オブジェクトの配列)引数は objects で指定できた。型もHASURAコンソール上で確認できた。
mutation UPDATE_APPLICATION($id: Int!, $free_text:String!, $place:Int!, $select:Int!, $select_other:String!, $objects: [application_skills_insert_input!]! ) {
delete_application_skills(where: {application_id: {_eq: $id}}) {
affected_rows
}
insert_application_skills(objects: $objects) {
returning {
id
skill
}
}
update_application_items_by_pk(pk_columns: {id: $id}, _set: {free_text: $free_text, place: $place, select: $select, select_other: $select_other}) {
free_text
id
place
select
select_other
skills(order_by: {skill: asc}) {
skill
}
}
}
store ルートの action で nuxtServerInit をつかって取得
store/index.ts で以下の形で指定
#Context内のapp じゃなくても、this.app でもとれるっぽいな…?
export const actions = actionTree({ state }, {
async nuxtServerInit ({ commit }, {store, app}:Context) {
let res = await app.apolloProvider.defaultClient.query<TypeUser>({
query: USER,
variables: {
id: 1,
},
});
const application_id = res.data.user_items_by_pk.applications.length ? res.data.user_items_by_pk.applications[0].id : null;
const userState = {
id:res.data.user_items_by_pk.id,
name:res.data.user_items_by_pk.name,
department:res.data.user_items_by_pk.department,
occupation:res.data.user_items_by_pk.occupation,
application_id
}
const applicationValues = application_id ? res.data.user_items_by_pk.applications[0] : null;
store.dispatch('user/init',userState);
store.dispatch('application/init',{values:applicationValues});
}
})
TYPE_USER は以下のような内容で定義
(GraphQLのスキーマから生成できるやり方がありそうだけどそれはまた別途…)
type Skill = {
skill:number
}
export type Application = {
id:number
free_text:string
place:number
select:number
select_other:string
skills:Skill[]
}
export type TypeUser = {
user_items_by_pk:{
department:string
name:string
occupation:string
id:number
applications:Application[]
}
}
store module内で mutation
storeモジュール内では this.app で apolloProvider にアクセスできる
import UPDATE_APPLICATION from "@/apollo/mutations/UPDATE_APPLICATION.gql";
export const actions = actionTree({ state, getters, mutations }, {
update({state,getters,commit}){
const id = getters.getId;
const values = getters.getValues;
const apolloClient = this.app.apolloProvider.defaultClient;
const variables = {
id,
free_text: values.free_text,
place: values.place,
select: values.select,
select_other: values.select_other,
objects: values.skills? values.skills.map(skill => ({ application_id:id, skill})) : [],
}
apolloClient.mutate({
mutation:UPDATE_APPLICATION,
variables
})
}
}
コンポーネント内でuseQuery
page コンポーネントだったら fetchからとるのが適切なのかもしれない
import {defineComponent} from "@nuxtjs/composition-api";
import { GetApplication } from "@/types";
import { useQuery, useResult } from "@vue/apollo-composable";
import GET_APPLICATION from '@/apollo/queries/GET_APPLICATION.gql';
export default defineComponent({
setup(props) {
const { result } = useQuery<GetApplication>(GET_APPLICATION , {id:1});
const application = useResult(result, null, data => data.application_items_by_pk);
reutrn {}
}
}
コンポーネント内でuseMutation
取得後の処理がまだ書けてないけど…
import { defineComponent, useContext } from "@nuxtjs/composition-api";
import { useQuery, useResult, useMutation } from "@vue/apollo-composable";
import UPDATE_APPLICATION from "@/apollo/mutations/UPDATE_APPLICATION.gql";
export default defineComponent({
setup(props) {
const { $accessor } = useContext();
const onBtnClick = (): void => {
const values = $accessor.application.getValues;
uptedateApplication(
{
id: 1,
free_text: values.free_text,
place: values.place,
select: values.select,
select_other: values.select_other,
skill: 1,
}
);
};
reutrn {onBtnClick}
}
}