diff --git a/packages/docs/src/.vuepress/config.js b/packages/docs/src/.vuepress/config.js index ee435059..5a53a4fc 100644 --- a/packages/docs/src/.vuepress/config.js +++ b/packages/docs/src/.vuepress/config.js @@ -14,6 +14,11 @@ module.exports = { lang: 'zh-CN', title: 'Vue Apollo', description: '🚀 ćœšäœ çš„ Vue.js ćș”甚䞭集成 GraphQL', + }, + '/fr/': { + lang: 'fr-FR', + title: 'Vue Apollo', + description: '🚀 IntĂ©grez GraphQL dans vos apps Vue.js !', } }, plugins: { @@ -24,6 +29,10 @@ module.exports = { message: "New content is available.", buttonText: "Refresh" }, + '/fr/': { + message: "Du nouveau contenu est disponible.", + buttonText: "RafraĂźchir" + }, }, }, }, @@ -223,6 +232,101 @@ module.exports = { '/zh-cn/migration/': [''], }, }, + '/fr/': { + selectText: 'Langages', + label: 'Français', + lastUpdated: 'DerniĂšre mise Ă  jour', + nav: [ + { + text: 'Guide', + link: '/fr/guide/', + }, + { + text: 'API', + link: '/fr/api/', + }, + { + text: 'Migration', + link: '/fr/migration/', + }, + { + text: 'Plugin CLI', + link: 'https://github.com/Akryum/vue-cli-plugin-apollo', + }, + { + text: 'Sponsor', + link: 'https://github.com/sponsors/Akryum', + }, + ], + sidebarDepth: 2, + sidebar: { + '/fr/guide/': [ + '', + 'installation', + { + title: 'Premiers pas', + collapsable: false, + children: [ + 'apollo/', + 'apollo/queries', + 'apollo/mutations', + 'apollo/subscriptions', + 'apollo/pagination', + 'apollo/special-options', + ], + }, + { + title: 'Composants', + collapsable: false, + children: [ + 'components/', + 'components/query', + 'components/mutation', + 'components/subscribe-to-more', + ], + }, + { + title: 'Utilisation avancĂ©e', + collapsable: false, + children: [ + 'multiple-clients', + 'ssr', + 'local-state', + 'testing', + ], + }, + ], + '/fr/api/': [ + { + title: 'Vue Apollo', + collapsable: false, + children: [ + 'apollo-provider', + 'dollar-apollo', + 'ssr', + ], + }, + { + title: 'Smart Apollo', + collapsable: false, + children: [ + 'smart-query', + 'smart-subscription', + ], + }, + { + title: 'Apollo Components', + collapsable: false, + children: [ + 'apollo-query', + 'apollo-mutation', + 'apollo-subscribe-to-more', + ], + }, + ], + '/fr/migration/': [''], + }, + }, }, }, } diff --git a/packages/docs/src/fr/README.md b/packages/docs/src/fr/README.md new file mode 100644 index 00000000..5dc7169a --- /dev/null +++ b/packages/docs/src/fr/README.md @@ -0,0 +1,50 @@ +--- +home: true +heroImage: /logo.png +actionText: Commencer → +actionLink: /fr/guide/ +features: +- title: RafraĂźchissements automatiques + details: Ne vous prĂ©occupez pas de refraĂźchir l'interface utilisteur ou de refaire les requĂȘtes ! +- title: Composants dans les templates + details: Utilisez Apollo de façon vraiment dĂ©clarative grĂące aux composants Apollo. +- title: Compatible avec le rendu cĂŽtĂ© serveur + details: Faites vos requĂȘtes cĂŽtĂ© serveur avant de rendre le HTML. +footer: LICENCE MIT - Créé par Guillaume CHAU (@Akryum) +--- + + + +## Sponsors + +### Or + +

+ + sum.cumo logo + + + + Vue Mastery logo + +

+ +### Argent + +

+ + VueSchool logo + +

+ +### Bronze + +

+ + Vuetify logo + + + + Frontend Developer Love logo + +

diff --git a/packages/docs/src/fr/api/README.md b/packages/docs/src/fr/api/README.md new file mode 100644 index 00000000..e0ece1f5 --- /dev/null +++ b/packages/docs/src/fr/api/README.md @@ -0,0 +1,7 @@ +# RĂ©fĂ©rence API + +Bienvenue dans la rĂ©fĂ©rence API ! + +::: warning Work-in-Progress +Si quelque chose manque, merci d'ouvrir une pull request ! +::: diff --git a/packages/docs/src/fr/api/apollo-mutation.md b/packages/docs/src/fr/api/apollo-mutation.md new file mode 100644 index 00000000..a531ff29 --- /dev/null +++ b/packages/docs/src/fr/api/apollo-mutation.md @@ -0,0 +1,49 @@ +# Composant ApolloMutation + +Exemple : + +```vue + + + +``` + +## Props + +- `mutation`: une requĂȘte GraphQL (transformĂ©e par `graphql-tag`) ou bien une fonction qui reçoit le gabarit `gql` comme argument et doit retourner la requĂȘte transformĂ©e +- `variables`: objet de variables GraphQL +- `optimisticResponse`: Consultez le guide sur [les interfaces optimistes](https://www.apollographql.com/docs/react/performance/optimistic-ui/) +- `update`: Consultez le guide sur [comment mettre Ă  jour le cache aprĂšs une mutation](https://www.apollographql.com/docs/react/data/mutations/#options) +- `refetchQueries`: Consultez le guide sur [comment re-requĂȘter aprĂšs une mutation](https://www.apollographql.com/docs/react/data/mutations/#options) +- `clientId`: l'identifiant du client Apollo utilisĂ© par la requĂȘte (dĂ©fini dans l'option `clients` d'ApolloProvider) +- `tag`: le nom de la balise HTML (par dĂ©faut: `div`); si `undefined`, le composant n'a pas de rendu (le contenu ne sera pas englobĂ© dans une balise) +- `context`: Consultez [l'option `context` d'Apollo](https://www.apollographql.com/docs/react/data/mutations/#options) + +## Les props de slots avec portĂ©e + +- `mutate(options = undefined)`: une fonction pour appeler une mutation. Vous pouvez Ă©craser les options de mutation (par exemple : `mutate({ variables: { foo: 'bar } })`) +- `loading`: un boolĂ©en qui indique que la requĂȘte est en cours +- `error`: une erreur Ă©ventuelle lors de la derniĂšre mutation +- `gqlError`: la premiĂšre erreur GraphQL Ă©ventuelle + +## ÉvĂ©nements + +- `done(resultObject)` +- `error(errorObject)` +- `loading(boolean)` diff --git a/packages/docs/src/fr/api/apollo-provider.md b/packages/docs/src/fr/api/apollo-provider.md new file mode 100644 index 00000000..cfbc7658 --- /dev/null +++ b/packages/docs/src/fr/api/apollo-provider.md @@ -0,0 +1,49 @@ +# ApolloProvider + +## Constructeur + +```js +const apolloProvider = new VueApollo({ + // Support de plusieurs clients + // Utilise l'option 'client' dans les requĂȘtes + // ou bien '$client' sur la dĂ©finition Apollo + clients: { + a: apolloClientA, + b: apolloClientB, + }, + // Client par dĂ©faut + defaultClient: apolloClient, + // DĂ©fition 'apollo' par dĂ©faut + defaultOptions: { + // Consultez la dĂ©finition 'apollo' + // Par exemple : les options de requĂȘte par dĂ©faut + $query: { + loadingKey: 'loading', + fetchPolicy: 'cache-and-network', + }, + }, + // Observation de l'Ă©tat de chargement pour toutes les requĂȘtes + // Consultez 'RequĂȘtes intelligentes > options > watchLoading' pour plus de dĂ©tails + watchLoading (isLoading, countModifier) { + loading += countModifier + console.log('Global loading', loading, countModifier) + }, + // Gestion globale des erreurs pour toutes les requĂȘtes intelligentes et les souscriptions + errorHandler (error) { + console.log('Gestion globale des erreurs') + console.error(error) + }, + // DĂ©sactivation globale de la prĂ©-requĂȘte lors du rendu cĂŽtĂ© serveur (SSR) + prefetch: Boolean, +}) +``` + +Vous pouvez utiliser le provider Apollo dans votre application Vue : + +```js +new Vue({ + el: '#app', + apolloProvider, + render: h => h(App), +}) +``` diff --git a/packages/docs/src/fr/api/apollo-query.md b/packages/docs/src/fr/api/apollo-query.md new file mode 100644 index 00000000..2808bd05 --- /dev/null +++ b/packages/docs/src/fr/api/apollo-query.md @@ -0,0 +1,69 @@ +# Composant ApolloQuery + +Exemple : + +```vue + + + +``` + +::: warning +Pour activer le support du gabarit Ă©tiquetĂ© `gql` dans les templates Vue, consultez l'Ă©tape nĂ©cessaire dans [le guide](../guide/components/query.md#tag-setup). +::: + +## Props + +- `query`: une requĂȘte GraphQL (transformĂ©e par `graphql-tag`) ou bien une fonction qui reçoit le gabarit `gql` comme argument et doit retourner la requĂȘte transformĂ©e +- `variables`: objet de variables GraphQL +- `fetchPolicy`: consultez [l'option `fetchPolicy` d'Apollo](https://www.apollographql.com/docs/react/data/queries/#options) +- `pollInterval`: consultez [l'option `pollInterval` d'Apollo](https://www.apollographql.com/docs/react/data/queries/#options) +- `notifyOnNetworkStatusChange`: consultez [l'option `notifyOnNetworkStatusChange` d'Apollo](https://www.apollographql.com/docs/react/data/queries/#options) +- `context`: consultez [l'option `context` d'Apollo](https://www.apollographql.com/docs/react/data/queries/#options) +- `update`: une fonction qui transforme le rĂ©sultat `data`, pratique pour rĂ©cupĂ©rer des parties spĂ©cifiques de la rĂ©ponse. Exemple : `:update="data => data.user.messages"` +- `skip`: un boolĂ©en qui dĂ©sative le requĂȘtage +- `clientId`: l'identifiant du client Apollo utilisĂ© par la requĂȘte (dĂ©fini dans l'option `clients` d'ApolloProvider) +- `deep`: boolĂ©en pour permettre l'utilisation d'observateurs Vue imbriquĂ©s +- `tag`: le nom de la balise HTML (par dĂ©faut: `div`); si Ă©value Ă  `false` (par exemple `null` ou `undefined`), le composant n'a pas de rendu (le contenu ne sera pas englobĂ© dans une balise), et dans ce cas, uniquement le premier enfant sera rendu +- `debounce`: nombre de millisecondes pour stabiliser les nouvelles requĂȘtes (par exemple quand les variables changent) +- `throttle`: nombre de millisecondes pour rĂ©guler les nouvelles requĂȘtes (par exemple quand les variables changent) +- `prefetch`: si `false`, pas de prĂ©-requĂȘte lors du rendu cĂŽtĂ© serveur (SSR) +- `options`: autres options Apollo Watch Query + +## Slots avec portĂ©e + +- `result`: rĂ©sulta Apollo Query + - `result.data`: donnĂ©e retournĂ©e par la requĂȘte (peut ĂȘtre transformĂ©e dans la prop `update`) + - `result.fullData`: donnĂ©e brute retournĂ©e par la requĂȘte (non transformĂ©e dans la prop `update`) + - `result.loading`: un boolĂ©en qui indique si requĂȘte est en cours (il est possible que vous deviez assigner la prop `notifyOnNetworkStatusChange` pour qu'il se mette Ă  jour) + - `result.error`: erreur Ă©vntuelle pour le rĂ©sultat en cours + - `result.networkStatus`: consultez [l'option `networkStatus` d'Apollo](https://www.apollographql.com/docs/react/data/queries/#result) +- `query`: requĂȘte intelligente associĂ©e au composant. C'est pratique pour exĂ©cuter certaines opĂ©rations comme `query.refetch` ou bien `query.fetchMore`. +- `isLoading`: Ă©tat de chargement de la requĂȘte intelligente +- `gqlError`: la premiĂšre erreur GraphQL Ă©vntuelle +- `times`: combien de fois le rĂ©sultat a Ă©tĂ© mis Ă  jour + +## ÉvĂ©nements + +- `result(resultObject)` +- `error(errorObject)` +- `loading(boolean)` diff --git a/packages/docs/src/fr/api/apollo-subscribe-to-more.md b/packages/docs/src/fr/api/apollo-subscribe-to-more.md new file mode 100644 index 00000000..c71142a0 --- /dev/null +++ b/packages/docs/src/fr/api/apollo-subscribe-to-more.md @@ -0,0 +1,55 @@ +# Composant ApolloSubscribeToMore + +Exemple : + +```vue + + + +``` + +## Props + +- `document`: un document GraphQL qui contient la souscription ou une fonction qui reçoit le gabarit `gql` en argument et doit retourner le document transformĂ©. +- `variables`: un objet qui met automatiquement Ă  jour les variables de souscription. +- `updateQuery`: une fonction qui met Ă  jour le rĂ©sultat de requĂȘte si nĂ©cessaire. diff --git a/packages/docs/src/fr/api/dollar-apollo.md b/packages/docs/src/fr/api/dollar-apollo.md new file mode 100644 index 00000000..9c4a765d --- /dev/null +++ b/packages/docs/src/fr/api/dollar-apollo.md @@ -0,0 +1,23 @@ +# Dollar Apollo + +Il s'agit du gestionnaire Apollo ajoutĂ© Ă  chaque composant qui utilise Apollo. Il est possible d'y accĂ©der Ă  l'intĂ©rieur d'un composant via `this.$apollo`. + +## PropriĂ©tĂ©s + +- `vm`: composant associĂ©. +- `queries`: tableau des requĂȘtes intelligentes du composant. +- `subscriptions`: tableau des souscriptions intelligentes du composant. +- `provider`: [Apollo Provider](./apollo-provider.md) injectĂ©. +- `loading`: si au moins une requĂȘte est en cours. +- `skipAllQueries`: (mutateur) boolĂ©en pour mettre en pause ou redĂ©marrer toutes les requĂȘtes intelligentes. +- `skipAllSubscriptions`: (mutateur) boolĂ©en pour mettre en pause ou redĂ©marrer toutes les souscriptions intelligentes. +- `skipAll`: (mutateur) boolĂ©en pour mettre en pause ou redĂ©marrer toutes les requĂȘtes et souscriptions intelligentes. + +## MĂ©thodes + +- `query`: exĂ©cute une requĂȘte (consultez [RequĂȘtes](../guide/apollo/queries.md)). +- `mutate`: exĂ©cute une mutation (consultez [Mutations](../guide/apollo/mutations.md)). +- `subscribe`: mĂ©thode de souscription standard Apollo (consultez [Souscriptions](../guide/apollo/subscriptions.md)). +- `addSmartQuery`: ajouter une requĂȘte intelligente manuellement (non recommandĂ©). +- `addSmartSubscription`: ajouter une souscription intelligente manuellement (consultez [Souscriptions](../guide/apollo/subscriptions.md)). +- `getClient`: retourne le client Apollo utilisĂ©. diff --git a/packages/docs/src/fr/api/smart-query.md b/packages/docs/src/fr/api/smart-query.md new file mode 100644 index 00000000..bf4b8f1b --- /dev/null +++ b/packages/docs/src/fr/api/smart-query.md @@ -0,0 +1,254 @@ +# RequĂȘte intelligente + +Chaque requĂȘte dĂ©clarĂ©e dans la dĂ©finition `apollo` (c'est-Ă -dire, qui ne commence pas avec un signe `$`) d'un composant donne lieu Ă  la crĂ©ation d'une requĂȘte intelligente. + +## Options + +- `query`: document GraphQL (un fichier ou une chaĂźne `gql`). +- `variables`: un objet ou une fonction rĂ©active qui retourne un objet. Chaque clĂ© est mappĂ©e avec un `'$'` dans le document GraphQL, par exemple `foo` devient `$foo`. +- `throttle`: rĂ©gule les mises Ă  jour des variables (en millisecondes). +- `debounce`: stabilise les mises Ă  jour des variables (en millisecondes). +- `pollInterval`: mise Ă  jour automatique en utilisant le *polling* (en requĂȘtant toutes les `x` millisecondes). Par dĂ©faut : `undefined`, `0` - arrĂȘt du polling. +- `update(data) {return ...}` pour personnaliser la valeur qui est assignĂ©e dans la propriĂ©tĂ© Vue, par exemple si les noms de champs ne correspondent pas. +- `result(ApolloQueryResult, key)` est un hook appelĂ© lorsqu'un rĂ©sultat est reçu (consultez la documentation de [ApolloQueryResult](https://github.com/apollographql/apollo-client/blob/master/src/core/types.ts)). `key` est la clĂ© de requĂȘte dans l'option `apollo`. +- `error(error, vm, key, type, options)` est un hook appelĂ© lorsqu'une erreur survient. `error` est une erreur Apollo avec soit une propriĂ©tĂ© `graphQLErrors` ou bien une propriĂ©tĂ© `networkError`. `vm` est l'instance du composant correspondant. `key` est la clĂ© de la requĂȘte intelligente. `type` est soit `'query'` ou `'subscription'`. `options` est l'objet d'options `watchQuery` final. +- `loadingKey` met Ă  jour la propriĂ©tĂ© de donnĂ©e du composant passĂ©e en valeur. Vous devez initialiser cette propriĂ©tĂ© Ă  `0` dans le hook `data` du composant. Quand la requĂȘte charge, cette propriĂ©tĂ© est incrĂ©mentĂ©e de 1. Quand elle termine de charger, elle est dĂ©crĂ©mentĂ©e de 1. De cette façon, cette propriĂ©tĂ© peut servir de compteur des requĂȘtes en cours. +- `watchLoading(isLoading, countModifier)` est un hook appelĂ© lorsque l'Ă©tat de chargement d'une requĂȘte change. Le paramĂštre `countModifier` est Ă©gal Ă  `1` quand la requĂȘte charge, ou `-1` quand elle a terminĂ©. +- `manual` est un boolĂ©en qui permet de dĂ©sactiver les mises Ă  jour automatiques des propriĂ©tĂ©s. Si vous l'utilisez, vous devez spĂ©cifier une fonction de retour `result` (voir l'exemple ci-dessous). +- `deep` est un boolĂ©en qui permet d'utiliser `deep: true` sur les observateurs Vue. +- `skip` est un boolĂ©en ou une fonction (rĂ©active) qui retourne un boolĂ©en. La fonction reçoit le composant en cours et la clĂ© d'une requĂȘte intelligente en arguments, pour pouvoir ĂȘtre utilisĂ© dans `$query` et dans les `defaultOptions` d'`ApolloProvider`. +- `subscribeToMore`: un objet ou un tableau d'objets d'[options subscribeToMore](../guide/apollo/subscriptions.md#subscribetomore). +- `prefetch` est soit un boolĂ©en, soit une fonction qui dĂ©termine si une requĂȘte doit ĂȘtre prĂ©-requĂȘtĂ©e. Consultez [Rendu cĂŽtĂ© serveur (SSR)](../guide/ssr.md). +- Vous pouvez Ă©galement utiliser n'importe quelle autre option `watchQuery` options (consultez [la documentation d'Apollo](https://www.apollographql.com/docs/react/api/apollo-client.html#ApolloClient.watchQuery)). + +Exemple : + +```js +// Options spĂ©cifiques Ă  Apollo +apollo: { + // RequĂȘte avancĂ©e avec des paramĂštres + // La mĂ©thode 'variables' est observĂ©e par Vue + pingMessage: { + query: gql`query PingMessage($message: String!) { + ping(message: $message) + }`, + // ParamĂštres rĂ©actifs + variables () { + // Utilisez des propriĂ©tĂ©s rĂ©actives Vue + return { + message: this.pingInput, + } + }, + // Variables : observation imbriquĂ©e + deep: false, + // On utilise une fonction de retour personnalisĂ©e car + // les noms de champs ne correspondent pas + // Par dĂ©faurt, l'attribut 'pingMessage' + // serait utilisĂ© sur l'objet de rĂ©sultat 'data' + // Ici, nous savons que le rĂ©sultat est dans l'attribut 'ping' + // sachant comment le serveur Apollo fonctionn + update (data) { + console.log(data) + // La valeur retournĂ©e met Ă  jour + // la propriĂ©tĂ© Vue 'pingMessage' + return data.ping + }, + // Hook de rĂ©sultat optionnel + result ({ data, loading, networkStatus }) { + console.log('Nous avons des rĂ©sultats !') + }, + // Gestion d'erreur + error (error) { + console.error('Nous avons une erreur !', error) + }, + // État de chargement + // loadingKey est le nom de la propriĂ©tĂ© + // qui sera incrĂ©mentĂ©e quand la requĂȘte chargera + // et dĂ©crĂ©mentĂ©e lorsqu'elle sera terminĂ©e. + loadingKey: 'loadingQueriesCount', + // watchLoading est appelĂ© quand l'Ă©tat de chargement change + watchLoading (isLoading, countModifier) { + // isLoading est un boolĂ©en + // countModifier est soit 1 ou -1 + }, + }, +}, +``` + +Si vous utilisez `ES2015`, vous pouvez Ă©galement Ă©crire `update` de cette façon : + +```js +update: data => data.ping +``` + +Exemple en mode manuel : + +```js +{ + query: gql`...`, + manual: true, + result ({ data, loading }) { + if (!loading) { + this.items = data.items + } + }, +} +``` + +## PropriĂ©tĂ©s + +### Skip + +Vous pouvez mettre `skip` en pause ou pas : + +```js +this.$apollo.queries.users.skip = true +``` + +### loading + +Si la requĂȘte est en cours : + +```js +this.$apollo.queries.users.loading +``` + +## MĂ©thodes + +### refresh + +ArrĂȘte et reprend la requĂȘte : + +```js +this.$apollo.queries.users.refresh() +``` + +### start + +DĂ©marre la requĂȘte : + +```js +this.$apollo.queries.users.start() +``` + +### stop + +ArrĂȘte la requĂȘte : + +```js +this.$apollo.queries.users.stop() +``` + +### fetchMore + +Charge plus de donnĂ©es pour la pagination : + +```js +this.page++ + +this.$apollo.queries.tagsPage.fetchMore({ + // Nouvelles variables + variables: { + page: this.page, + pageSize, + }, + // Transformation du rĂ©sultat prĂ©cĂ©dent avec de nouvelles donnĂ©es + updateQuery: (previousResult, { fetchMoreResult }) => { + const newTags = fetchMoreResult.tagsPage.tags + const hasMore = fetchMoreResult.tagsPage.hasMore + + this.showMoreEnabled = hasMore + + return { + tagsPage: { + __typename: previousResult.tagsPage.__typename, + // Union des tableaux de libellĂ©s + tags: [...previousResult.tagsPage.tags, ...newTags], + hasMore, + }, + } + }, +}) +``` + +### subscribeToMore + +Souscrire Ă  plus de data en utilisant des souscription GraphQL : + +```js +// Nous devons nous dĂ©sinscrire avant de souscrire Ă  nouveau +if (this.tagsSub) { + this.tagsSub.unsubscribe() +} +// Souscription dans la requĂȘte +this.tagsSub = this.$apollo.queries.tags.subscribeToMore({ + document: TAG_ADDED, + variables: { + type, + }, + // Mutation du rĂ©sultat prĂ©cĂ©dent + updateQuery: (previousResult, { subscriptionData }) => { + // Si nous avons dĂ©jĂ  ajoutĂ© le libellĂ©, on ne fait rien + // Cela peut ĂȘtre causĂ© par `updateQuery` dans notre mutation addTag + if (previousResult.tags.find(tag => tag.id === subscriptionData.data.tagAdded.id)) { + return previousResult + } + + return { + tags: [ + ...previousResult.tags, + // Ajout du nouveau libellĂ© + subscriptionData.data.tagAdded, + ], + } + }, +}) +``` + +### refetch + +RequĂȘte Ă  nouveau, potentiellement avec de nouvelles variables : + +```js +this.$apollo.queries.users.refetch() +// Avec de nouvelles variables +this.$apollo.queries.users.refetch({ + friendsOf: 'id-user' +}) +``` + +### setVariables + +Met Ă  jour les variables de la requĂȘte et l'exĂ©cute Ă  nouveau si elle a changĂ©. Pour forcer une requĂȘte, vous pouvez utiliser `refetch`. + +```js +this.$apollo.queries.users.setVariables({ + friendsOf: 'id-uset' +}) +``` + +### setOptions + +Met Ă  jour les options Apollo [watchQuery](https://www.apollographql.com/docs/react/api/apollo-client/#ApolloClient.watchQuery) et requĂȘte Ă  nouveau : + +```js +this.$apollo.queries.users.setOptions({ + fetchPolicy: 'cache-and-network' +}) +``` + +### startPolling + +Commence une mise Ă  jour automatique en utilisant le *polling* (en requĂȘtant toutes les `x` millisecondes) : + +```js +this.$apollo.queries.users.startPolling(2000) // millisecondes +``` + +### stopPolling + +ArrĂȘt du *polling* : + +```js +this.$apollo.queries.users.stopPolling() +``` diff --git a/packages/docs/src/fr/api/smart-subscription.md b/packages/docs/src/fr/api/smart-subscription.md new file mode 100644 index 00000000..46cc2b52 --- /dev/null +++ b/packages/docs/src/fr/api/smart-subscription.md @@ -0,0 +1,49 @@ +# Souscription intelligente + +Chaque souscription dĂ©clarĂ©e dans l'option `apollo.$subscribe` dans les rĂ©sultats d'un composant gĂ©nĂšre la crĂ©ation d'iun objet de souscriptions intelligentes. + +## Options + +- `query`: document GraphQL (un fichier ou une chaĂźne `gql`). +- `variables`: un objet ou une fonction rĂ©active qui retourne un objet. Chaque clĂ© est mappĂ©e avec un `'$'` dans le document GraphQL, par exemple `foo` devient `$foo`. +- `throttle`: rĂ©gule les mises Ă  jour des variables (en millisecondes). +- `debounce`: stabilise les mises Ă  jour des variables (en millisecondes). +- `result(data, key)` est un hook appelĂ© lorsqu'un rĂ©sultat est reçu +- `error(error)` est un hook appelĂ© quand des erreurs surviennent. `error` est un objet d'erreur Apollo avec soit une propriĂ©tĂ© `graphQLErrors` ou bien une propriĂ©tĂ© `networkError`. +- `skip` est un boolĂ©en ou une fonction (rĂ©active) qui retourne un boolĂ©en. La fonction reçoit le composant en cours et la clĂ© d'une requĂȘte intelligente en arguments, pour pouvoir ĂȘtre utilisĂ© dans `$query` et dans les `defaultOptions` d'`ApolloProvider`. + +## PropriĂ©tĂ©s + +### Skip + +Vous pouvez mettre `skip` en pause ou pas : + +```js +this.$apollo.subscriptions.users.skip = true +``` + +## MĂ©thodes + +### refresh + +ArrĂȘte et reprend la requĂȘte : + +```js +this.$apollo.subscriptions.users.refresh() +``` + +### start + +DĂ©marre la requĂȘte : + +```js +this.$apollo.subscriptions.users.start() +``` + +### stop + +ArrĂȘte la requĂȘte : + +```js +this.$apollo.subscriptions.users.stop() +``` diff --git a/packages/docs/src/fr/api/ssr.md b/packages/docs/src/fr/api/ssr.md new file mode 100644 index 00000000..35b01be2 --- /dev/null +++ b/packages/docs/src/fr/api/ssr.md @@ -0,0 +1,48 @@ +# ApolloSSR + +## Utilisation + +Voir le [guide du rendu cĂŽtĂ© serveur (SSR)](../guide/ssr.md). + +## MĂ©thodes + +### getStates + +Retourne les Ă©tats des stores Apollo sous forme d'objets. + +```js +const states = ApolloSSR.getStates(apolloProvider, options) +``` + +`options` utilise par dĂ©faut : + +```js +{ + // PrĂ©fixe pour les clĂ©s de chaque Ă©tat du client Apollo + exportNamespace: '', +} +``` + +### exportStates + +Retourne les Ă©tats des stores Apollo sous forme de code JavaScript dans une `string`. Ce code peut ĂȘtre injectĂ© directement dans la page HTML dans une balise ` +``` + +## `$apollo` + +Tous les composants enfant d'un composant possĂ©dant l'option `apolloProvider` ont un utilitaire `$apollo` de disponible. C'est le lien entre le composant et Apollo, il gĂšre toute la complexitĂ© Ă  votre place (y compris les mises Ă  jours et le nettoyage). + +Vous pouvez accĂ©der aux instances [apollo-client](https://www.apollographql.com/docs/react/) avec `this.$apollo.provider.defaultClient` ou bien `this.$apollo.provider.clients.` (pour [les clients multiple](../multiple-clients.md)) dans tous vos composants Vue. + +Si vous ĂȘtes curieux, consultez [l'API d'$apollo](../../api/dollar-apollo.md). + +## RequĂȘtes + +Dans l'objet `apollo`, ajoutez un attribut pour chaque propriĂ©tĂ© Ă  laquelle vous voulez fournir le rĂ©sultat d'une requĂȘte Apollo. + +```vue + + + +``` + +Pour en savoir plus, consultez la [section RequĂȘtes](./queries.md). + +## Mutations + +Utilisez `this.$apollo.mutate` pour envoyer des mutations : + +```js +methods: { + async addTag() { + // Appel Ă  la mutation GraphQL + const result = await this.$apollo.mutate({ + // RequĂȘte + mutation: gql`mutation ($label: String!) { + addTag(label: $label) { + id + label + } + }`, + // ParamĂštres + variables: { + label: this.newTag, + }, + }) + } +} +``` + +Pour en savoir plus, consultez la [section Mutations](./mutations.md). + +## Options spĂ©ciales + +Les options spĂ©ciales commencent par un `$` dans l'objet `apollo`. + +Pour en savoir plus, consultez la [section Options spĂ©ciales](./special-options.md). diff --git a/packages/docs/src/fr/guide/apollo/mutations.md b/packages/docs/src/fr/guide/apollo/mutations.md new file mode 100644 index 00000000..217948d9 --- /dev/null +++ b/packages/docs/src/fr/guide/apollo/mutations.md @@ -0,0 +1,123 @@ +# Mutations + +Les mutations sont des requĂȘtes qui changent l'Ă©tat de vos donnĂ©es sur votre serveur Apollo. + +Pour envoyer une mutation GraphQL, il faut utiliser `this.$apollo.mutate()`. + +Il existe une [application d'exemple](https://github.com/Akryum/vue-apollo-todos) focalisĂ©e sur les mutations que vopus pouvez consulter. + +::: warning +Il n'est pas recommandĂ© d'envoyer les champs `__typename` dans les variables, il faut donc Ă©viter d'envoyer les rĂ©ponses Apollo directement. +::: + +```js +methods: { + addTag() { + // On sauvegarde l'entrĂ©e utilisateur en cas d'erreur + const newTag = this.newTag + // On la supprime tĂŽt pour donner une sensation de rĂ©activitĂ© Ă  l'interface utilisateur + this.newTag = '' + // Appel Ă  la mutation GraphQL + this.$apollo.mutate({ + // RequĂȘte + mutation: gql`mutation ($label: String!) { + addTag(label: $label) { + id + label + } + }`, + // ParamĂštres + variables: { + label: newTag, + }, + // Mise Ă  jour du cache avec le rĂ©sultat + // La requĂȘte sera mise Ă  jour avec une rĂ©ponse optimiste + // puis avec le rĂ©sultat de la mutation + update: (store, { data: { addTag } }) => { + // Lecture de la donnĂ©e depuis le cache pour cette requĂȘte + const data = store.readQuery({ query: TAGS_QUERY }) + // Ajout du libellĂ© de la mutation en fin de tableau + data.tags.push(addTag) + // Réécriture en cache + store.writeQuery({ query: TAGS_QUERY, data }) + }, + // Interface utilisateur optimiste + // UtilisĂ© comme "fausse" donnĂ©e dĂšs qu'une requĂȘte est rĂ©alisĂ©e afin que + // l'interface rĂ©agisse rapidement, pour une meilleur expĂ©rience + optimisticResponse: { + __typename: 'Mutation', + addTag: { + __typename: 'Tag', + id: -1, + label: newTag, + }, + }, + }).then((data) => { + // RĂ©sultat + console.log(data) + }).catch((error) => { + // Erreur + console.error(error) + // On restaure l'entrĂ©e utilisateur initiale + this.newTag = newTag + }) + }, +}, +``` + +## Exemple cĂŽtĂ© serveur + +```js +export const schema = ` +type Tag { + id: Int + label: String +} + +type Query { + tags: [Tag] +} + +type Mutation { + addTag(label: String!): Tag +} + +schema { + query: Query + mutation: Mutation +} +` + +// Faux gĂ©nĂ©rateur de mots +import faker from 'faker' + +// GĂ©nĂ©rons quelques libellĂ©s +var id = 0 +var tags = [] +for (let i = 0; i < 42; i++) { + addTag(faker.random.word()) +} + +function addTag (label) { + let t = { + id: id++, + label, + } + tags.push(t) + return t +} + +export const resolvers = { + Query: { + tags (root, args, context) { + return tags + }, + }, + Mutation: { + addTag (root, { label }, context) { + console.log(`adding tag '${label}'`) + return addTag(label) + }, + }, +} +``` diff --git a/packages/docs/src/fr/guide/apollo/pagination.md b/packages/docs/src/fr/guide/apollo/pagination.md new file mode 100644 index 00000000..47ccb269 --- /dev/null +++ b/packages/docs/src/fr/guide/apollo/pagination.md @@ -0,0 +1,95 @@ +# Pagination avec `fetchMore` + +*Voici un [exemple simple](https://github.com/Akryum/apollo-server-example/blob/master/schema.js#L21) cĂŽtĂ© serveur.* + +Parfois, il se peut que votre jeu de donnĂ©es soit tellement grand qu'il faille le charger petit Ă  petit. + +Vous pouvez utiliser la mĂ©thode `fetchMore` sur une requĂȘte intelligente pour charger plus de donnĂ©es. + +::: warning +N'oubliez pas d'inclure le `__typename` au nouveau rĂ©sultat. + +Ne changez pas les variables retournĂ©es initialement lorsque vous utilisez `variables`, ou bien vous pourriez perdre de la donnĂ©e dans la liste. +::: + +Exemple : + +```vue + + + +``` diff --git a/packages/docs/src/fr/guide/apollo/queries.md b/packages/docs/src/fr/guide/apollo/queries.md new file mode 100644 index 00000000..6b26caa5 --- /dev/null +++ b/packages/docs/src/fr/guide/apollo/queries.md @@ -0,0 +1,449 @@ +# RequĂȘtes + +Dans GraphQL, une requĂȘte est un appel Ă  une API pour rĂ©cupĂ©rer de la donnĂ©e. C'est reprĂ©sentĂ© par un *document GraphQL* comme ceci : + +```graphql +query myHelloQueryName { + hello +} +``` + +Dans l'objet `apollo`, ajoutez un attribut pour chaque propriĂ©tĂ© Ă  laquelle vous voulez fournir le rĂ©sultat d'une requĂȘte Apollo. Chacune deviendra une requĂȘte intelligente. + +## RequĂȘte simple + +Vous pouvez utiliser `gql` pour Ă©crire vos requĂȘtes GraphQL : + +```js +import gql from 'graphql-tag' +``` + +Ajoutez la requĂȘte [gql](https://github.com/apollographql/graphql-tag) directement en valeur : + +```js +apollo: { + // Une requĂȘte simple qui rafraĂźchit la propriĂ©tĂ© Vue 'hello' + hello: gql`{hello}`, +}, +``` + +Vous pouvez accĂ©der Ă  la requĂȘtes avec `this.$apollo.queries.`. + +Vous pouvez initialiser la propriĂ©tĂ© dans le hook `data` de votre composant Vue : + +```js +data () { + return { + // Intialiser votre donnĂ©e Apollo + hello: '', + }, +}, +``` + +CĂŽtĂ© serveur, ajoutez le schĂ©ma et le rĂ©solveur correspondants : + +```js +export const schema = ` +type Query { + hello: String +} + +schema { + query: Query +} +` + +export const resolvers = { + Query: { + hello (root, args, context) { + return 'Hello world!' + }, + }, +} +``` + +Pour plusz d'informations, consultez la [documentation d'Apollo](https://www.apollographql.com/docs/apollo-server/). + +Vous pouvez utiliser votre propriĂ©tĂ© comme d'habitude dans votre composant Vue : + +```vue + +``` + +## Correspondance de noms + +Notez qu'une erreur de dĂ©butant claqque est d'utiliser un nom de donnĂ©e diffĂ©rent du champ dans la requĂȘte, par exemple : + +```js +apollo: { + world: gql`query { + hello + }` +} +``` + +Vous remarquez que `world` est diffĂ©rent de `hello`. Vue Apollo ne peut pas deviner quelle donnĂ©e vous souhaitez utiliser dans votre composant depuis le rĂ©sultat de la requĂȘte. Par dĂ©faut, il essaiera simplemnt le nom que vous utilisez pour la donnĂ©e dans le composant (la clĂ© dans l'objet `apollo`), dans notre cas, `world`. Si les noms ne correspondent pas, vous ppuvez utiliser l'option `update` pour dire Ă  Vue Apollo quelle donnĂ©e utiliser dans le rĂ©sultat : + +```js +apollo: { + world: { + query: gql`query { + hello + }`, + update: data => data.hello + } +} +``` + +Vous pouvez Ă©galement renommer le champ directement dans le document GraphQL : + +```js +apollo: { + world: gql`query { + world: hello + }` +} +``` + +Dans cet exemple, nous renommons le champ `hello` en `world`, pour que Vue Apollo puisse automatiquement infĂ©rer ce qu'il doit rĂ©cupĂ©rer depuis le rĂ©sultat. + +## RequĂȘte avec des paramĂštres + +Vous pouvez ajouter des variables (et d'autres paramĂštres) Ă  votre requĂȘte `gql` en dĂ©clarant `query` et `variables` dans l'objet au lieu de la requĂȘte GraphQL : + +```js +// Options spĂ©cifiques Ă  Apollo +apollo: { + // RequĂȘte avec des paramĂštres + ping: { + // RequĂȘte gql + query: gql`query PingMessage($message: String!) { + ping(message: $message) + }`, + // ParamĂštres statiques + variables: { + message: 'Meow', + }, + }, +}, +``` + +Vous pouvez utiliser les options Apollo `watchQuery` dans l'objet, comme ceci : + - `fetchPolicy` + - `pollInterval` + - ... + +Consulter la [documentation d'Apollo](https://www.apollographql.com/docs/react/api/apollo-client/#ApolloClient.watchQuery) pour plus de dĂ©tails. + +Par exemple, vous pouvez ajouter l'option Apollo `fetchPolicy` comme ceci : + +```js +apollo: { + // RequĂȘte avec des paramĂštres + ping: { + query: gql`query PingMessage($message: String!) { + ping(message: $message) + }`, + variables: { + message: 'Meow' + }, + // Options supplĂ©mentaires + fetchPolicy: 'cache-and-network', + }, +}, +``` + +À nouveau, vous pouvez utiliser votre propriĂ©tĂ© dans votre composant Vue : + +```js +data () { + return { + // Initialisation de votre donnĂ©e Apollo + ping: '', + } +}, +``` + +CĂŽtĂ© serveur, ajoutez le schĂ©ma et le rĂ©solveur correspondants : + +```js +export const schema = ` +type Query { + ping(message: String!): String +} + +schema { + query: Query +} +` + +export const resolvers = { + Query: { + ping (root, { message }, context) { + return `RĂ©ponse Ă  ${message}` + }, + }, +} +``` + +Et vous pouvez l'utiliser dans votre composant Vue : + +```vue + +``` + +## État de chargement + +Vous pouvez afficher un Ă©tat de chargement grĂące Ă  la prop `$apollo.loading` : + +```vue +
Chargement...
+``` + +Ou bien cette requĂȘte spĂ©cifique `ping` : + +```vue +
Chargement...
+``` + +## Fonction d'options + +Vous pouvez utiliser une fonction qui sera appelĂ©e quand le composant est créé, et qui retourne l'objet d'options : + +```js +// Options spĂ©cifiques Ă  Apollo +apollo: { + // RequĂȘte avec des paramĂštres + ping () { + // AppelĂ© lors de la crĂ©ation du composant + // Doit retourner un objet d'options + return { + // RequĂȘte gql + query: gql`query PingMessage($message: String!) { + ping(message: $message) + }`, + // ParamĂštres statiques + variables: { + message: 'Miaou', + }, + } + }, +}, +``` + +::: tip +Cela fonctionne Ă©galement pour les [souscriptions](./subscriptions.md). +::: + +## DĂ©finition de requĂȘte rĂ©active + +Vous pouvez utiliser une fonction pour l'option `query`. Cela rafraĂźchira la dĂ©finition de requĂȘte GraphQL automatiquement : + +```js +// Le libellĂ© mis en avant peut ĂȘtre soit un libellĂ© au hasard, ou bien le dernier ajoutĂ© +featuredTag: { + query () { + // Vous pouvez accĂ©der Ă  l'instance du composant avec 'this' + if (this.showTag === 'random') { + return gql`{ + randomTag { + id + label + type + } + }` + } else if (this.showTag === 'last') { + return gql`{ + lastTag { + id + label + type + } + }` + } + }, + // Nous devons assigner la valeur de la propriĂ©tĂ© 'featuredTag' du composant + update: data => data.randomTag || data.lastTag, +}, +``` + +::: tip +Cela fonctionne Ă©galement pour les [souscriptions](./subscriptions.md). +::: + +## ParamĂštres rĂ©actifs + +Vous pouvez utiliser une fonction pour rendre les paramĂštres rĂ©actifs avec les propriĂ©tĂ©s Vue : + +```js +// Options spĂ©cifiques Ă  Apollo +apollo: { + // RequĂȘte avec des paramĂštres + ping: { + query: gql`query PingMessage($message: String!) { + ping(message: $message) + }`, + // ParamĂštres rĂ©actifs + variables () { + // Utilisez des propriĂ©tĂ©s rĂ©actives Vue + return { + message: this.pingInput, + } + }, + }, +}, +``` + +Cela requĂȘtera Ă  nouveau Ă  chaque fois qu'un paramĂštre change, par exemple : + +```vue + +``` + +## Sauter la requĂȘte + +Si la requĂȘte est sautĂ©e, elle est dĂ©sactivĂ©e et ne sera plus mise Ă  jour. Vous pouvez utiliser l'options `skip` : + +```js +// Options spĂ©cifiques Ă  Apollo +apollo: { + tags: { + // RequĂȘte GraphQL + query: gql`query tagList ($type: String!) { + tags(type: $type) { + id + label + } + }`, + // Variables rĂ©actives + variables () { + return { + type: this.type, + } + }, + // DĂ©sactivation de la requĂȘte + skip () { + return this.skipQuery + }, + }, +}, +``` + +Ici, `skip` est appelĂ© automatiquement dĂšs que la propriĂ©tĂ© `skipSubscription` du composant change. + +Vous pouvez aussi accĂ©der Ă  la souscription directemnt et assigner la propriĂ©tĂ© `skip` : + +```js +this.$apollo.queries.tags.skip = true +``` + +Si la requĂȘte `skip` devient `false`, la requĂȘte s'exĂ©cutera Ă  nouveau automatiquement. + +## Exemple de requĂȘte rĂ©axctive + +Voici un exemple de requĂȘte rĂ©active utilisant le *polling* : + +```js +// Options spĂ©cifiques Ă  Apollo +apollo: { + // PropriĂ©tĂ© `tags` sur l'instance Vue + tags: { + query: gql`query tagList { + tags { + id, + label + } + }`, + pollInterval: 300, // millisecondes + }, +}, +``` + +Voici Ă  quoi ressemble le serveur : + +```js +export const schema = ` +type Tag { + id: Int + label: String +} + +type Query { + tags: [Tag] +} + +schema { + query: Query +} +` + + +// Faux gĂ©nĂ©rateur de mots +import casual from 'casual' + +// GĂ©nĂ©rons quelques libellĂ©s +var id = 0 +var tags = [] +for (let i = 0; i < 42; i++) { + addTag(casual.word) +} + +function addTag (label) { + let t = { + id: id++, + label, + } + tags.push(t) + return t +} + +export const resolvers = { + Query: { + tags(root, args, context) { + return tags + }, + }, +} +``` + +## Éditer une requĂȘte intelligente manuellement + +Vous pouvez ajouter une requĂȘte intelligente manuellement avec la mĂ©thode `$apollo.addSmartQuery(key, options)` : + +```js +created () { + this.$apollo.addSmartQuery('comments', { + // Quelques options comme au-dessus + }) +} +``` + +::: tip +En interne, cette mĂ©thode est appelĂ©e pour chaque entrĂ©e de l'option `apollo` du composant. +::: + +## Options avancĂ©es + +Il y a encore bien d'autres options spĂ©cifiques Ă  Vue Apollo, consultez [la rĂ©fĂ©rence API](../../api/smart-query.md). diff --git a/packages/docs/src/fr/guide/apollo/special-options.md b/packages/docs/src/fr/guide/apollo/special-options.md new file mode 100644 index 00000000..48322de2 --- /dev/null +++ b/packages/docs/src/fr/guide/apollo/special-options.md @@ -0,0 +1,75 @@ + +# Options spĂ©ciales + +Les options spĂ©ciales commencent par un `$` dans l'objet `apollo`. + +- `$skip` pour dĂ©sactiver toutes les requĂȘtes et souscriptions (voir ci-dessous) +- `$skipAllQueries` pour dĂ©sactiver toutes les requĂȘtes (voir ci-dessous) +- `$skipAllSubscriptions` pour dĂ©sactiver toutes les souscriptions (voir ci-dessous) +- `$deep` pour observer les propriĂ©tĂ©s ci-dessus avec `deep: true` quand une fonction est fournie +- `$error` pour intercepter les erreurs dans un fonction de gestion par dĂ©faut (voir les options avancĂ©es d'`error` pour les requĂȘtes intelligentes) +- `$query` pour appliquer les options par dĂ©faut Ă  toutes les requĂȘtes d'un composant + +Exemple : + +```vue + +``` + +Vous pouvez dĂ©finir un ensemble d'options par dĂ©faut dans le provider Apollo afin d'appliquer les dĂ©finitions `apollo`. Par exemple : + +```js +const apolloProvider = new VueApollo({ + defaultClient: apolloClient, + defaultOptions: { + // Les options Apollo appliquĂ©es Ă  toutes les requĂȘtes dans les composants + $query: { + loadingKey: 'loading', + fetchPolicy: 'cache-and-network', + }, + }, +}) +``` + +## Tout sauter + +Vous pouvez dĂ©sactiver toutes les requĂȘtes d'un composant avec `skipAllQueries`, toutes les souscriptions avec `skipAllSubscriptions`, et les deux `skipAll`: + +```js +this.$apollo.skipAllQueries = true +this.$apollo.skipAllSubscriptions = true +this.$apollo.skipAll = true +``` + +Vous pouvez aussi dĂ©clarer ces propriĂ©tĂ©s dans l'option `apollo` du composant. Ils peuvent prendre des boolĂ©ens : + +```js +apollo: { + $skipAll: true +} +``` + +Ou bien des fonctions rĂ©actives : + +```js +apollo: { + $skipAll () { + return this.foo === 42 + } +} +``` diff --git a/packages/docs/src/fr/guide/apollo/subscriptions.md b/packages/docs/src/fr/guide/apollo/subscriptions.md new file mode 100644 index 00000000..54eafd58 --- /dev/null +++ b/packages/docs/src/fr/guide/apollo/subscriptions.md @@ -0,0 +1,341 @@ +# Souscriptions + +## Installation + +*Pour l'implĂ©mentation serveur, vous ppuvez jeter un Ɠil Ă  [cet exemple simple](https://github.com/Akryum/apollo-server-example).* + +Pour activer la souscription par websockets, vous devez configurer un peu plus de choses : + +``` +npm install --save apollo-link-ws apollo-utilities +``` + +```js +import Vue from 'vue' +import { ApolloClient } from 'apollo-client' +import { HttpLink } from 'apollo-link-http' +import { InMemoryCache } from 'apollo-cache-inmemory' +// Nouveaux imports +import { split } from 'apollo-link' +import { WebSocketLink } from 'apollo-link-ws' +import { getMainDefinition } from 'apollo-utilities' + +import VueApollo from 'vue-apollo' + +const httpLink = new HttpLink({ + // Vous devez utiliser un URL absolu + uri: 'http://localhost:3020/graphql', +}) + +// CrĂ©ation du lien de souscription websocket +const wsLink = new WebSocketLink({ + uri: 'ws://localhost:3000/subscriptions', + options: { + reconnect: true, + }, +}) + +// GrĂące Ă  la possibilitĂ© de scinder les liens, vous pouvez envoyer de la donnĂ©e +// Ă  chaque lien, en fonction du type d'opĂ©ration Ă  envoyer +const link = split( + // Scission en fonction du type d'opĂ©ration + ({ query }) => { + const definition = getMainDefinition(query) + return definition.kind === 'OperationDefinition' && + definition.operation === 'subscription' + }, + wsLink, + httpLink +) + +// CrĂ©ation du client Apollo +const apolloClient = new ApolloClient({ + link, + cache: new InMemoryCache(), + connectToDevTools: true, +}) + +// Installation du plugin Vue comme prĂ©cĂ©demment +Vue.use(VueApollo) +``` + +## Souscriptions supplĂ©mentaires + +Si vous souhaitez mettre Ă  jour une requĂȘte intelligente depuis une souscription, la meilleure façon est d'utiliser la mĂ©thode de requĂȘte intelligente `subscribeToMore`. Cela crĂ©e des [souscriptions intelligentes](../../api/smart-subscription.md) liĂ©es Ă  votre requĂȘte intelligente. Ajoutez simplement `subscribeToMore` Ă  votre requĂȘte intelligente : + +```js +apollo: { + tags: { + query: TAGS_QUERY, + subscribeToMore: { + document: gql`subscription name($param: String!) { + itemAdded(param: $param) { + id + label + } + }`, + // Variables passĂ©es Ă  la souscription + // Comme nous utilisons une fonction, elles sont rĂ©actives + variables () { + return { + param: this.param, + } + }, + // Mutation du rĂ©sultat prĂ©cĂ©dent + updateQuery: (previousResult, { subscriptionData }) => { + // On retourne le nouveau rĂ©sultat depuis le prĂ©cĂ©dent, + // avec la nouvelle donnĂ©e + }, + } + } +} +``` + +::: tip +Notez qu'il est possible de passer un tableau de souscriptions Ă  `subscribeToMore` pour souscrire Ă  plusieurs souscriptions dans une requĂȘte. +::: + +### Utilisation alternative + +Vous pouvez accĂ©der aux requĂȘtes que vous avez dĂ©finies dans l'option `apollo` avec `this.$apollo.queries.`, ce qui ressemblerait Ă  ceci : + +```js +this.$apollo.queries.tags.subscribeToMore({ + // Document GraphQL + document: gql`subscription name($param: String!) { + itemAdded(param: $param) { + id + label + } + }`, + // Variables passĂ©es Ă  la souscription + variables: { + param: '42', + }, + // Mutation du rĂ©sultat prĂ©cĂ©dent + updateQuery: (previousResult, { subscriptionData }) => { + // On retourne le nouveau rĂ©sultat depuis le prĂ©cĂ©dent + // avec la nouvelle donnĂ©e + }, +}) +``` + +Si la requĂȘte concernĂ©e est arrĂȘtĂ©e, la souscription est automatiquement dĂ©truite. + +Voici un exemple : + +```js +// Souscription au document GraphQL +const TAG_ADDED = gql`subscription tags($type: String!) { + tagAdded(type: $type) { + id + label + type + } +}` + +// LibellĂ©s SubscribeToMore +// Nous avons plusieurs types de libellĂ©s +// avec une souscription 'channl' pour chaque +this.$watch(() => this.type, (type, oldType) => { + if (type !== oldType || !this.tagsSub) { + // Nous devons nous dĂ©sinscrire avant de souscrire Ă  nouveau + if (this.tagsSub) { + this.tagsSub.unsubscribe() + } + // Souscription dans la requĂȘte + this.tagsSub = this.$apollo.queries.tags.subscribeToMore({ + document: TAG_ADDED, + variables: { + type, + }, + // Mutation du rĂ©sultat prĂ©cĂ©dent + updateQuery: (previousResult, { subscriptionData }) => { + // Si nous avons dĂ©jĂ  ajoutĂ© le libellĂ©, on ne fait rien + // Cela peut ĂȘtre causĂ© par `updateQuery` dans notre mutation addTag + if (previousResult.tags.find(tag => tag.id === subscriptionData.data.tagAdded.id)) { + return previousResult + } + + return { + tags: [ + ...previousResult.tags, + // Ajout du nouveau libellĂ© + subscriptionData.data.tagAdded, + ], + } + }, + }) + } +}, { + immediate: true, +}) +``` + +## Abstraction simple + +::: danger +Si vous souhaitez mettre Ă  jour une requĂȘte avec le rĂ©sultat d'une souscription, utilisez `subscribeToMore`. +Les mĂ©thodes ci-dessous s'appliquent dans le cas d'une notification. +::: + +Vous pouvez dĂ©clarer des [souscriptions intelligentes](../../api/smart-subscription.md) dans l'option `apollo` avec le mot-clĂ© `$subscribe` : + +```js +apollo: { + // Souscriptions + $subscribe: { + // Lorsqu'un libellĂ© est ajoutĂ© + tagAdded: { + query: gql`subscription tags($type: String!) { + tagAdded(type: $type) { + id + label + type + } + }`, + // Variables rĂ©actives + variables () { + // Le fonctionnement est le mĂȘme que pour des requĂȘtes classiques + // et souscrit Ă  nouveau avec les bonnes variables + // chaque fois qu'un valeur change + return { + type: this.type, + } + }, + // Hook de rĂ©sultat + // N'oubliez pas de dĂ©composer `data` + result ({ data }) { + console.log(data.tagAdded) + }, + }, + }, +}, +``` + +Vous pouvez accĂ©der Ă  la souscription avec `this.$apollo.subscriptions.`. + +:::tip +Comme pour les requĂȘtes, vous pouvez dĂ©clarer la souscription [avec une fonction](./queries.md#option-function), et vous pouvez dĂ©clarer l'option `query` [avec une fonction rĂ©active](./queries.md#reactive-query-definition). +::: + +Lorsqu'un serveur supporte les requĂȘtes en temps rĂ©el et utilise les souscriptions pour les mettre Ă  jour, comme [Hasura](https://hasura.io/), vous pouvez utiliser de simples souscriptions pour les requĂȘtes rĂ©actives : + +```js +data () { + return { + tags: [], + }; +}, +apollo: { + $subscribe: { + tags: { + query: gql`subscription { + tags { + id + label + type + } + }`, + result ({ data }) { + this.tags = data.tags; + }, + }, + }, +}, +``` + +## Sauter la souscription + +Si la souscription est sautĂ©e, elle est dĂ©sactivĂ©e et ne sera plus mise Ă  jour. Vous pouvez utiliser l'options `skip` : + +```js +// Options spĂ©cifiques Ă  Apollo +apollo: { + // Souscriptions + $subscribe: { + // Lorsqu'un libellĂ© est ajoutĂ© + tags: { + query: gql`subscription tags($type: String!) { + tagAdded(type: $type) { + id + label + type + } + }`, + // Variables rĂ©actives + variables () { + return { + type: this.type, + } + }, + // Hook de rĂ©sultat + result (data) { + // Mise Ă  jour de l'Ă©tat local + this.tags.push(data.tagAdded) + }, + // On saute la souscription + // Skip the subscription + skip () { + return this.skipSubscription + } + }, + }, +}, +``` + +Ici, `skip` est appelĂ© automatiquement dĂšs que la propriĂ©tĂ© `skipSubscription` du composant change. + +Vous pouvez aussi accĂ©der Ă  la souscription directemnt et assigner la propriĂ©tĂ© `skip` : + +```js +this.$apollo.subscriptions.tags.skip = true +``` + +## Ajouter des souscription intelligentes manuellement + +Vous pouvez ajouter manellement une souscription intelligente avec la mĂ©thode `$apollo.addSmartSubscription(key, options)` : + +```js +created () { + this.$apollo.addSmartSubscription('tagAdded', { + // MĂȘmes options que pour '$subscribe' ci-dessus + }) +} +``` + +:::tip +En interne, cette mĂ©thode est appelĂ©e pour chaque entrĂ©e de l'objet `$subscribe` dans l'option `apollo` du composant. +::: + +## Souscription Apollo standard + +Utilisez la mĂ©thode `$apollo.subscribe()` pour souscrire Ă  une souscription GraphQL qui sera automatiquement dĂ©truite lors que le composant le sera Ă©galement. Cela ne crĂ©e **pas** de souscription intelligente. + +```js +mounted () { + const subQuery = gql`subscription tags($type: String!) { + tagAdded(type: $type) { + id + label + type + } + }` + + const observer = this.$apollo.subscribe({ + query: subQuery, + variables: { + type: 'City', + }, + }) + + observer.subscribe({ + next (data) { + console.log(data) + }, + error (error) { + console.error(error) + }, + }) +}, +``` diff --git a/packages/docs/src/fr/guide/components/README.md b/packages/docs/src/fr/guide/components/README.md new file mode 100644 index 00000000..3f128a6c --- /dev/null +++ b/packages/docs/src/fr/guide/components/README.md @@ -0,0 +1,29 @@ +# Qu'est-ce qu'un composant Apollo ? + +Ces composants sont comme les autres. Ils prennnt un document GraphQL en props et utilisent les [slots avec portĂ©e](https://vuejs.org/v2/guide/components-slots.html#Scoped-Slots) pour passer les rĂ©sultats. + +L'avantage est que vous pouvez utiliser ces composants directement dans le template au lieu d'utiliser l'option `apollo` de votre composant. Dans certains cas, vous n'avez mĂȘme pas besoin d'ajouter de script du tout dans votre fichier `.vue` ! C'est encore plus dĂ©claratif. + +Voici un rapide exemple d'une [ApolloQuery](./query.md) dans un template : + +```vue + + + +``` + +Consultez [ApolloQuery](./query.md) pour en savoir plus sur comment Ă©crire des requĂȘtes GraphQL dans le template. diff --git a/packages/docs/src/fr/guide/components/mutation.md b/packages/docs/src/fr/guide/components/mutation.md new file mode 100644 index 00000000..5babd8f6 --- /dev/null +++ b/packages/docs/src/fr/guide/components/mutation.md @@ -0,0 +1,210 @@ +# ApolloMutation + +Vous pouvez utiliser le composant `ApolloMutation` (ou `apollo-mutation`) pour invoquer des mutations Apollo directement dans vos templates. + +Voici un exemple : + +```vue + + + +``` + +Consultez [ApolloQuery](./query.md) pour en savoir plus sur comment Ă©crire des requĂȘtes GraphQL dans le template. + +Consultez [la rĂ©fĂ©rence API](../../api/apollo-subscribe-to-more.md) pour connaĂźtre toutes les options disponibles. + +## RafraĂźchir le cache + +Si la mutation ne met Ă  jour que des objets qui existent dĂ©jĂ  en cache (par exemple, qui change des champs existants), vous n'avez pas besoin de faire quoi que ce soit, Apollo Client rafraĂźchira le cache automatiquement. Cela fonctionnera uniquement si l'objet dans le rĂ©sultat de la mutation contient les champs `__typename` et `id` (ou les champs personnalisĂ©s que vous utilisez pour [normaliser le cache](https://www.apollographql.com/docs/react/advanced/caching#normalization)). + +Sinon, vous devez dire Ă  Apollo Client comment mettre le cache Ă  jour avec le rĂ©sultat de la mutation. Par exemple, si la mutation ajoute un nouvel Ă©lĂ©ment, vous devez mettre Ă  jour le rĂ©sultat concernĂ© pour pouvoir pousser ce nouvel Ă©lĂ©ment dans la requĂȘte. + +### Ajouter un Ă©lĂ©ment + +```vue + + + +``` + +### Retirer un Ă©lĂ©ment + +```vue + + + +``` diff --git a/packages/docs/src/fr/guide/components/query.md b/packages/docs/src/fr/guide/components/query.md new file mode 100644 index 00000000..653b5a06 --- /dev/null +++ b/packages/docs/src/fr/guide/components/query.md @@ -0,0 +1,427 @@ +# ApolloQuery + +Vous pouvez utiliser le composant `ApolloQuery` (ou `apollo-query`) pour avoir des requĂȘtes Apollo observĂ©es directement dans vos templates. +AprĂšs avoir lu cette page, consultez [la rĂ©fĂ©rence API](../../api/apollo-query.md) pour connaĂźtre toutes les options disponibles. + +## Le gabarit Ă©tiquetĂ© `gql` + +C'est la mĂ©thode recommandĂ©e pour utiliser le composant `ApolloQuery`. Il utilise la mĂȘme syntaxe avec le gabarit Ă©tiquetĂ© `gql` que dans les autres exemples : + +```vue + +``` + +Nous passons une fonction Ă  la prop `query` qui prent le gabarit `gql` en argument, afin de pouvoir le document GraphQL directement. + +L'exemple ci-dessus passe Ă©galement `variables` Ă  la requĂȘte en utilisant la prop du mĂȘme nom. + +Dans le slot par dĂ©faut d'`ApolloQuery`, vous pouvez accĂ©der Ă  de la donnĂ©e concernant la requĂȘte observĂ©e, comme par exemple l'object `result` : + +```vue + +``` + +Voici un exemple complet : + +```vue + + + +``` + +### Mise en place du gabarit Ă©tiquetĂ© + +Si vous n'utilisez pas [vue-cli-plugin-apollo](https://github.com/Akryum/vue-cli-plugin-apollo) (`v0.20.0+`), vous devez configurer [vue-loader](https://vue-loader.vuejs.org) pour transpiler le gabarit Ă©tiquetĂ©. `vue-loader` utilise [BublĂ©](https://buble.surge.sh/guide/) sous le capot pour transpiler le code dans les templates des composants. Nous devons ajouter la transformation `dangerousTaggedTemplateString` Ă  BublĂ© pour que `gql` fonctionne. Par exemple, avec Vue CLI : + +```js +// vue.config.js + +module.exports = { + chainWebpack: config => { + config.module + .rule('vue') + .use('vue-loader') + .loader('vue-loader') + .tap(options => { + options.transpileOptions = { + transforms: { + dangerousTaggedTemplateString: true, + }, + } + return options + }) + } +} +``` + +Dans une configuration Webpack de base, ça ressemblerait Ă  ça : + +```js +module.exports = { + module: { + rules: [ + { + test: /\.vue$/, + use: [ + { + loader: 'vue-loader', + options: { + transpileOptions: { + transforms: { + dangerousTaggedTemplateString: true + } + } + } + } + ] + }, + + /* D'autres rĂšgles... */ + ] + } +} +``` + +## RequĂȘter avec des fichiers `gql` + +Une façon alternative d'utiliser le composant est de crĂ©er des fichirs `.gql` sĂ©parĂ©s. Ces fichiers doivent ĂȘtre prĂ©-trasnformĂ©s avec [graphql-tag](https://github.com/apollographql/graphql-tag#webpack-preprocessing-with-graphql-tagloader). + +```vue + +``` + +## OpĂ©rations de requĂȘte + +Vous pouvez accĂ©der Ă  l'object de requĂȘte intelligent avec le prop de slot `query`. Voici un composant d'exemple qui pagine des donnĂ©es en utilisant `fetchMore` : + +```vue + + + +``` + +Consultez [la rĂ©fĂ©rence API](../../api/smart-query.md#methods) pour connaĂźtre toutes les mĂ©thodes de requĂȘte intelligentes. + +## Utiliser des fragments + +Les fragments sont intĂ©ressants pour partager des morceaux de documents GraphQL dans d'autres documents pour rĂ©cupĂ©rer la mĂȘme donnĂ©e de façon uniforme, et Ă©viter de dupliquer du code. + +Imaginons que nous avons une requĂȘte `GetMessages` avec un champ `messages` qui est un tableau d'objets `Message` : + +```graphql +query GetMessages { + messages { + id + user { + id + name + } + text + created + } +} +``` + +Nous voulons extraire tous les champs de `messages` qui ont le type `Message` dans un fragment, pour pouvoir les rĂ©utiliser ailleurs. + +D'abord, importez le gabarit `gql` dans le composant : + +```js +import gql from 'graphql-tag' +``` + +Puis, dans la dĂ©finition du composant, dĂ©clarez un nouvel objet `fragments` : + +```js +export default { + fragments: { + /** TODO */ + } +} +``` + +Voici Ă  quoi le fragment `message`, qui est appliquĂ© au type `Message`, ressemble : + +```graphql +fragment message on Message { + id + user { + id + name + } + text + created +} +``` + +Nous pouvons utiliser le gabarit `gql` comme avec les requĂȘtes : + +```js +export default { + fragments: { + message: gql` + fragment message on Message { + id + user { + id + name + } + text + created + } + ` + } +} +``` + +Dans notre composant, nous pouvons maintenant accĂ©der au fragment grĂące Ă  `this.$options.fragments.message`. Pour utiliser ce fragmnt dans notre requĂȘte `GetMessages`, nous devons utiliser la syntaxe de dĂ©composition de GraphQL (`...`), ainsi que d'ajouter le fragment avec la requĂȘte : + +```js +gql` + query GetMessages { + messages { + ...message + } + } + ${$options.fragments.message} +` +``` + +Cela produira le document GraphQL (que vous pouvez essayer dans l'environnement de test de GraphQL de votre API) : + +```graphql +query GetMessages { + messages { + ...message + } +} +fragment message on Message { + id + user { + id + name + } + text + created +} +``` + +Que se passe-t-il ici ? GraphQL trouve l'opĂ©rateur `...` oĂč l'on sĂ©lectionne des champs dans le champ `messages` Ă  l'intĂ©rieur de notre requĂȘte. L'opĂ©rateur `...` est suivi par le nom du fragment, `message`, qui est ensuite recherchĂ© dans tout le document GraphQL. Nous avons correctement dĂ©fini le fragment, que nous trouvons juste aprĂšs la requĂȘte. Enfin, GraphQL copie tout le contenu du fragment et remplace `...message` avec. + +On obtient la requĂȘte finale : + +```graphql +query GetMessages { + messages { + id + user { + id + name + } + text + created + } +} +fragment message on Message { + id + user { + id + name + } + text + created +} +``` + +Voici le composant d'exemple complet : + +```vue + + + + +``` + +### RĂ©utiliser le fragment + +Nous pouvons dĂ©sormais rĂ©cupĂ©rer le fragment `message` dans d'autres composants : + +```vue + + +``` diff --git a/packages/docs/src/fr/guide/components/subscribe-to-more.md b/packages/docs/src/fr/guide/components/subscribe-to-more.md new file mode 100644 index 00000000..465047e3 --- /dev/null +++ b/packages/docs/src/fr/guide/components/subscribe-to-more.md @@ -0,0 +1,100 @@ +# ApolloSubscribeToMore + +Vous pouvez souscrire Ă  davantage de donnĂ©e avec le composant `ApolloSubscribeToMore` (ou `apollo-subscribe-to-more`). Vous pouvez en utiliser autant que vous voulez dans un composant ``. + +::: tip +Si la mise Ă  jour est liĂ©e Ă  un objet existant (par exemple, changer la valeur d'un champ), `updateQuery` n'est pas requis, puisque le client Apollo sera capable de mettre le cache Ă  jour automatiquement. +::: + +Voici un exemple : + +```vue + + + +``` + +Consultez [ApolloQuery](./query.md) pour en savoir plus sur comment Ă©crire des requĂȘtes GraphQL dans le template. + +Consultez [la rĂ©fĂ©rence API](../../api/apollo-subscribe-to-more.md) pour connaĂźtre toutes les options disponibles. + +## Exemples avec `updateQuery` + +Ajouter un nouvel Ă©lĂ©ment en cache : + +```js +methods: { + onMessageAdded (previousResult, { subscriptionData }) { + // Le rĂ©sultat prĂ©cĂ©dent est immuable + const newResult = { + messages: [...previousResult.messages], + } + // Ajout la question dans la liste + newResult.messages.push(subscriptionData.data.messageAdded) + return newResult + } +} +``` + +Retirer un Ă©lĂ©ment du cache : + +```js +methods: { + onMessageAdded (previousResult, { subscriptionData }) { + const removedMessage = subscriptionData.data.messageRemoved + const index = previousResult.messages.findIndex( + m => m.id === removedMessage.id + ) + + if (index === -1) return previousResult + + // Le rĂ©sultat prĂ©cĂ©dent est immuable + const newResult = { + messages: [...previousResult.messages], + } + // Retire la question de la liste + newResult.messages.splice(index, 1) + return newResult + } +} +``` diff --git a/packages/docs/src/fr/guide/installation.md b/packages/docs/src/fr/guide/installation.md new file mode 100644 index 00000000..1073f972 --- /dev/null +++ b/packages/docs/src/fr/guide/installation.md @@ -0,0 +1,167 @@ +# Installation + +## Plugin Vue CLI + +J'ai créé un plugin pour [vue-cli](http://cli.vuejs.org) afin que vous puissiez ajouter Apollo (ainsi qu'un serveur GraphQL optionnel!) en deux minutes ! ✹🚀 + +Dans votre projet Vue CLI 3 : + +```bash +vue add apollo +``` + +Ensuite, vous pouvz passer Ă  la section suivante: [Premiers pas](./apollo/). + +[Plus d'informations](https://github.com/Akryum/vue-cli-plugin-apollo) + +## Manuel d'installation + +### 1. Apollo Client + +Vous pouvez utiliser soit [Apollo Boost](#apollo-boost), soit [Apollo Client directement](#apollo-client-full-configuration) (davantage de configuration). + +#### Apollo Boost + +Apollo Boost est une façon de commencer Ă  utiliser Apollo Client sans rien avoir Ă  configurer. Cela inclut des valeurs par dĂ©faut intĂ©ressantes, comme les dĂ©pendances `InMemoryCache` et `HttpLink` recommandĂ©es, prĂ©-configurĂ©es avec nos paramĂštres recommandĂ©s. C'est parfait pour commencer rapidement. + +Installez-le, ainsi que `vue-apollo` and `graphql`: + +``` +npm install --save vue-apollo graphql apollo-boost +``` + +Ou bien : + +``` +yarn add vue-apollo graphql apollo-boost +``` + +Dans votre application, crĂ©ez une instance d'`ApolloClient` : + +```js +import ApolloClient from 'apollo-boost' + +const apolloClient = new ApolloClient({ + // Vous devez utiliser un URL absolu + uri: 'https://api.graphcms.com/simple/v1/awesomeTalksClone' +}) +``` + +#### Apollo Client et configuration complĂšte + +Si vous souhaitez plus de contrĂŽle, installez ces packages Ă  la place d'Apollo Boost : + +``` +npm install --save vue-apollo graphql apollo-client apollo-link apollo-link-http apollo-cache-inmemory graphql-tag +``` + +Ou bien : + +``` +yarn add vue-apollo graphql apollo-client apollo-link apollo-link-http apollo-cache-inmemory graphql-tag +``` + +Dans votre application, crĂ©ez une instance d'`ApolloClient` : + +```js +import { ApolloClient } from 'apollo-client' +import { createHttpLink } from 'apollo-link-http' +import { InMemoryCache } from 'apollo-cache-inmemory' + +// Connection HTTP Ă  l'API +const httpLink = createHttpLink({ + // Vous devez utiliser un URL absolu + uri: 'http://localhost:3020/graphql', +}) + +// ImplĂ©mentation du cache +const cache = new InMemoryCache() + +// CrĂ©ation du client Apollo +const apolloClient = new ApolloClient({ + link: httpLink, + cache, +}) +``` + +### 2. Installation du plugin dans Vue + +```js +import Vue from 'vue' +import VueApollo from 'vue-apollo' + +Vue.use(VueApollo) +``` + +### 3. Apollo provider + +Le provider contient les instances du client Apollo qui peuvent ensuite ĂȘtre utilisĂ©s par tous les composants enfant. + +```js +const apolloProvider = new VueApollo({ + defaultClient: apolloClient, +}) +``` + +Ajoutez-le Ă  votre application avec l'option `apolloProvider`: + +```js +new Vue({ + el: '#app', + // Injectez le provider Apollo, comme avec Vue Router ou Vuex + apolloProvider, + render: h => h(App), +}) +``` + +Vous ĂȘtes maintenant prĂȘt Ă  utiliser Apollo dans vos composanst ! + +## IntĂ©gration dans l'IDE + +### Visual Studio Code + +Si vous utilisez VS Code, il est recommandĂ© d'installer l'[extension Apollo GraphQL](https://marketplace.visualstudio.com/items?itemName=apollographql.vscode-apollo). + +Ensuite, configurez-la en crĂ©ant un fichier `apollo.config.js` Ă  la racine de votre projet Vue: + +```js +// apollo.config.js +module.exports = { + client: { + service: { + name: 'my-app', + // URL de l'API GraphQL + url: 'http://localhost:3000/graphql', + }, + // Fichiers traitĂ©s par extension + includes: [ + 'src/**/*.vue', + 'src/**/*.js', + ], + }, +} +``` + +### WebStorm + +Si vous utilisez WebStorm, il est recommandĂ© d'installer l'[extension JS GraphQL](https://plugins.jetbrains.com/plugin/8097-js-graphql/). + +Ensuite, configurez-la en crĂ©ant un fichier `.graphqlconfig` Ă  la racine de votre projet Vue: + +```graphqlconfig +{ + "name": "Untitled GraphQL Schema", + "schemaPath": "./path/to/schema.graphql", + "extensions": { + "endpoints": { + "Default GraphQL Endpoint": { + "url": "http://url/to/the/graphql/api", + "headers": { + "user-agent": "JS GraphQL" + }, + "introspect": false + } + } + } +} +``` diff --git a/packages/docs/src/fr/guide/local-state.md b/packages/docs/src/fr/guide/local-state.md new file mode 100644 index 00000000..7d5b5275 --- /dev/null +++ b/packages/docs/src/fr/guide/local-state.md @@ -0,0 +1,281 @@ +# État local + +## Pourquoi utiliser Apollo comme gestionnaire d'Ă©tat local? + +Quand vous faites des requĂȘtes GraphQL abec Apollo, les rĂ©sultats sont stockĂ©s dans le **cache Apollo**. Maintenant, imaginez que vous ayez Ă©galement besoin d'un Ă©tat applicatif local et de le mettre Ă  disposition de plusieurs composants. Normalement, dans une application Vue, nous utilisons [Vuex](https://vuex.vuejs.org/) pour ça. Mais utiliser Apollo et Vuex en mĂȘme temps implique de stocker la donnĂ©e Ă  deux endroits diffĂ©rents, ce qui donne lieu Ă  _deux sources de vĂ©ritĂ©_. + +La bonne nouvelle, c'est qu'Apollo a un mĂ©canisme pour stocker l'Ă©tat applicatif local en cache. Auparavant, il utilisait la bibliothĂšque [apollo-link-state](https://github.com/apollographql/apollo-link-state) pour cela. Depuis la sortie d'Apollo 2.5, cette fonctionnalitĂ© est inclue dans Apollo. + +## CrĂ©er un schĂ©ma local + +Tout comme crĂ©er un schĂ©ma GraphQL est la premiĂšre Ă©tape pour dĂ©finir un modĂšle de donnĂ©es sur le serveur, Ă©crire un schĂ©ma local est la premiĂšre Ă©tape cĂŽtĂ© client. + +CrĂ©ons donc un schĂ©ma local pour dĂ©crire le premier Ă©lĂ©ment d'une liste de tĂąches Ă  accomplir ("todo"). Cette tĂąche comporte du texte, une propriĂ©tĂ© qui dĂ©termine si ell est dĂ©ja achevĂ©e, et un identifiant pour distinguer les tĂąches entre elles. On la reprĂ©sente donc sous la forme d'un objet avec trois propriĂ©tĂ©s : + +```js +{ + id: 'identifiantUnique', + text: 'Du texte', + done: false +} +``` + +Nous sommes maintenant prĂȘts Ă  ajouter un type `Item` Ă  notre schĂ©ma GraphQL. + +```js +// main.js + +import gql from 'graphql-tag'; + +export const typeDefs = gql` + type Item { + id: ID! + text: String! + done: Boolean! + } +`; +``` + +`qgl` est un gabarit Ă©tiquetĂ© qui analyse les requĂȘtes GraphQL. + +Nous devons maintenant ajouter `typeDefs` Ă  notre client Apollo. + +```js{4-5} +// main.js + +const apolloClient = new ApolloClient({ + typeDefs, + resolvers: {}, +}); +``` + +:::warning WARNING +Comme vous pouvez le constater, nous avons Ă©galement ajoutĂ© un objet `resolvers` vide : si nous oublions de l'ajouter dans les options du client Apollo, il ne pourra pas reconnaĂźtre les requĂȘtes vers l'Ă©tat local et tentera de les envoyer Ă  des URLs distants Ă  la place. +::: + +## Étendre un schĂ©ma GraphQL distant localement + +Vous pouvez non seulement crĂ©et un schĂ©ma local Ă  partir de zĂ©ro, mais aussi ajouter des **champs virtuels** locaux Ă  votre schĂ©ma distant. Ces champs existent uniquement cĂŽtĂ© client, et sont parfaits pour injecter de l'Ă©tat local Ă  votre donnĂ©e serveur. + +Imaginez que nous ayons un type `User` dans notre schĂ©ma distant : + +```js +type User { + name: String! + age: Int! +} +``` + +Et que nous souhaitions ajouter une propriĂ©tĂ© locale Ă  `User` : + +```js +export const schema = gql` + extend type User { + twitter: String + } +`; +``` + +Maintenant, quand vous requĂȘtez un utilisateur, il vous faudra spĂ©cifier que le champ `twitter` est local : + +```js +const userQuery = gql` + user { + name + age + twitter @client + } +`; +``` + +## Initialiser un cache Apollo + +Pour initialiser un cach Apollo dans votre application, vous devez utiliser un constructeur `InMemoryCache`. Tout d'abord, importez-le dans votre fichier principal : + +```js{4,6} +// main.js + +import ApolloClient from 'apollo-boost'; +import { InMemoryCache } from 'apollo-cache-inmemory'; + +const cache = new InMemoryCache(); +``` + +Nous pouvons maintenant l'ajouter aux options de notre client Apollo : + +```js{4} +// main.js + +const apolloClient = new ApolloClient({ + cache, + typeDefs, + resolvers: {}, +}); +``` + +Pour l'instant, le cache est vide. Pour y ajouter des donnĂ©es initiales, nous deevons utiliser la mĂ©thode `writeData` : + +```js{9-20} +// main.js + +const apolloClient = new ApolloClient({ + cache, + typeDefs, + resolvers: {}, +}); + +cache.writeData({ + data: { + todoItems: [ + { + __typename: 'Item', + id: 'dqdBHJGgjgjg', + text: 'test', + done: true, + }, + ], + }, +}); +``` + +Nous venons d'ajouter un tableau de `todoItems` Ă  notre cache et nous avons dĂ©terminĂ© que chaque Ă©lĂ©ment a un `__typename` nommĂ© `Item` (spĂ©cifiĂ© dans notre schĂ©ma local). + +## RequĂȘter de la donnĂ©e locale + +RequĂȘter le cache local est similaire Ă  [envoyer des requĂȘtes GraphQL Ă  un serveur distant](apollo/queries.md). D'abord, nous devons crĂ©er une requĂȘte : + +```js +// App.vue + +import gql from 'graphql-tag'; + +const todoItemsQuery = gql` + { + todoItems @client { + id + text + done + } + } +`; +``` + +La diffĂ©rence principale avec des requĂȘtes distantes est la directive `@client`. Elle spĂ©cifie que cette requĂȘte ne doit pas ĂȘtre exĂ©cutĂ©e vers l'API GraphQL distante. À la place, le client Apollo doit rĂ©cupĂ©rer les rĂ©sultats depuis le cache local. + +Nous pouvons maintenant utiliser cette requĂȘte dans notre composant Vue comme n'import quelle requĂȘte Apollo : + +```js +// App.vue + +apollo: { + todoItems: { + query: todoItemsQuery + } +}, +``` + +## Changer de la donnĂ©e locale avec des mutations + +Il existe deux façons diffĂ©rentes de modifier la donnĂ©e locale : + +- l'Ă©crire directement avec la mĂ©thode `writeData` comme nous l'avons fait lors de [l'initialisation du cache](#initializing-an-apollo-cache); +- invoquer une mutation GraphQL. + +Ajoutons quelques mutations Ă  notre [schĂ©ma GraphQL local](#creating-a-local-schema) : + +```js{10-14} +// main.js + +export const typeDefs = gql` + type Item { + id: ID! + text: String! + done: Boolean! + } + + type Mutation { + checkItem(id: ID!): Boolean + addItem(text: String!): Item + } +`; +``` + +La mutation `checkItem` inversera la propriĂ©tĂ© boolĂ©enne `done` d'un Ă©lĂ©ment donnĂ©. CrĂ©ons-la en utilisant `gql` : + +```js +// App.vue + +const checkItemMutation = gql` + mutation($id: ID!) { + checkItem(id: $id) @client + } +`; +``` + +Nous avons dĂ©fini une mutation _locale_ (car nous utilisons la directive `@client`) qui accepte un identifiant unique en paramĂštre. Maintenant, il nous faut un _rĂ©solveur_: une fonction qui rĂ©sout une valeur pour un type ou un champ dans un schĂ©ma. + + +Dans notre cas, le rĂ©solveur dĂ©finit les changements que nous souhaitons apporter Ă  notre cache local Apollo quand nous avons certaines mutations. Les rĂ©solveurs locaux ont la mĂȘme signature que les distants (`(parent, args, context, info) => data`). En rĂ©alitĂ©, nous aurons uniquement besoin d'`args` (les arguments passĂ©s Ă  la mutation) et de `context` (nous aurons besoin de ses propriĂ©tĂ©s de cache pour lire et Ă©crire de la donnĂ©e). + +Ajoutons donc un rĂ©solveur Ă  notre fichier principal : + +```js +// main.js + +const resolvers = { + Mutation: { + checkItem: (_, { id }, { cache }) => { + const data = cache.readQuery({ query: todoItemsQuery }); + const currentItem = data.todoItems.find(item => item.id === id); + currentItem.done = !currentItem.done; + cache.writeQuery({ query: todoItemsQuery, data }); + return currentItem.done; + }, +}; +``` + +Que se passe-t-il ici ? + +1. on lit `todoItemsQuery` depuis notre cache pour voir quelles `todoItems` nous avons; +2. on cherche un Ă©lĂ©ment qui possĂšde un certain identifiant; +3. on inverse la propriĂ©tĂ© `done` de l'Ă©lĂ©ment rĂ©cupĂ©rĂ©; +4. on Ă©crit nos `todoItems` modifiĂ©es en cache; +5. on retourne la propriĂ©tĂ© `done` comme rĂ©sultat de mutation. + +Nous devons maintenant remplacer notre objet `resolvers` vide avec nos nouveaux `resolvers` dans les options du client Apollo : + +```js{17} +// main.js + +const resolvers = { + Mutation: { + checkItem: (_, { id }, { cache }) => { + const data = cache.readQuery({ query: todoItemsQuery }); + const currentItem = data.todoItems.find(item => item.id === id); + currentItem.done = !currentItem.done; + cache.writeQuery({ query: todoItemsQuery, data }); + return currentItem.done; + }, +}; + +const apolloClient = new ApolloClient({ + cache, + typeDefs, + resolvers, +}); +``` + +AprĂšs cela, nous pouvons utiliser notre mutation dans notre composant Vue comme n'importe quelle [mutation](apollo/mutations.md): + +```js +// App.vue + +methods: { + checkItem(id) { + this.$apollo.mutate({ + mutation: checkItemMutation, + variables: { id } + }); + }, +} +``` diff --git a/packages/docs/src/fr/guide/multiple-clients.md b/packages/docs/src/fr/guide/multiple-clients.md new file mode 100644 index 00000000..e3afea4e --- /dev/null +++ b/packages/docs/src/fr/guide/multiple-clients.md @@ -0,0 +1,72 @@ +# Clients multiples + +Vous pouvez spĂ©cifier plusieurs client Apollo si votre application doit se connecter Ă  diffĂ©rents serveurs GraphQL : + +```js +const defaultOptions = { + // Vous pouvez utiliser `wss` pour sĂ©curiser la connexion (recommandĂ© en production) + // Utilisez `null` pour dĂ©sactiver les souscriptions + wsEndpoint: process.env.VUE_APP_GRAPHQL_WS || 'ws://localhost:4000/graphql', + // Jeton LocalStorage + tokenName: AUTH_TOKEN, + // Activation des requĂȘtes persistĂ©es automatiquement avec Apollo Engine + persisting: false, + // Utilisation gĂ©nĂ©rale des websockets (pas de requĂȘtes HTTP) + // Il vous faudra passer un `wsEndpoint` pour que ça fonctionne + websocketsOnly: false, + // Rendu cĂŽtĂ© serveur ? + ssr: false, +} + +const clientAOptions = { + // Utilisez `https` pour sĂ©curiser la connexion (recommandĂ© en production) + httpEndpoint: 'http://localhost:4000/graphql', +} + +const clientBOptions = { + httpEndpoint: 'http://example.org/graphql', +} + +// Invoquez cette fonction dans votre fichier d'application Vue +export function createProvider (options = {}) { + const createA= createApolloClient({ + ...defaultOptions, + ...clientAOptions, + }); + + const createB = createApolloClient({ + ...defaultOptions, + ...clientBOptions, + }); + + const a = createA.apolloClient; + const b = createB.apolloClient; + + // CrĂ©ation du provider Vue Apollo + const apolloProvider = new VueApollo({ + clients: { + a, + b + } + defaultClient: a, +}) +``` + +Dans l'option `apollo` du composant, vous pouvez dĂ©finir un client pour toutes vos requĂȘtes, souscriptions, et mutations avec `$client` (uniquement pour ce composant) : + +```js +export default { + apollo: { + $client: 'b', + }, +} +``` + +Vous pouvez Ă©galement sp"cifier le client dans chaque requĂȘte, souscription et mutation grĂące Ă  l'option `client`: + +```js +tags: { + query: gql`...`, + client: 'b', +} +``` diff --git a/packages/docs/src/fr/guide/ssr.md b/packages/docs/src/fr/guide/ssr.md new file mode 100644 index 00000000..e4bea960 --- /dev/null +++ b/packages/docs/src/fr/guide/ssr.md @@ -0,0 +1,323 @@ +# Rendu cĂŽtĂ© serveur (SSR) + +::: warning +**NĂ©cessite Vue 2.6+ avec `serverPrefetch`** +::: + +## Plugin Vue CLI + +J'ai créé un plugin pour [vue-cli](http://cli.vuejs.org) afin que vous puissiez ajouter Apollo (ainsi qu'un serveur GraphQL optionnel!) en deux minutes ! ✹🚀 + +Dans votre projet Vue CLI 3 : + + +```bash +vue add @akryum/ssr +``` + +[Plus d'informations](https://github.com/Akryum/vue-cli-plugin-ssr) + +## RĂ©cupĂ©ration de component + +::: tip +Suivez le [guide SSR officiel](https://ssr.vuejs.org) pour en savoir plus sur le rendu cĂŽtĂ© serveur avec Vue. +::: + +Par dĂ©faut, avez `vue-server-renderer`, toutes les requĂȘtes GraphQL de vos composant rendus cĂŽtĂ© serveur sont prĂ©-rĂ©cupĂ©rĂ©es automatiquement. + +::: tip +Vous avec accĂšs Ă  `this` dans les options telles que `variables`, mĂȘme cĂŽtĂ© serveur ! +::: + +Exemple : + +```js +export default { + apollo: { + allPosts: { + query: gql`query AllPosts { + allPosts { + id + imageUrl + description + } + }`, + } + } +} +``` + +Exemple 2 : + +```js +export default { + apollo: { + post: { + query: gql`query Post($id: ID!) { + post (id: $id) { + id + imageUrl + description + } + }`, + variables () { + return { + id: this.id, + } + }, + } + } +} +``` + +## Sauter la prĂ©-rĂ©cupĂ©ration de donnĂ©es + +Vous pouvez ne pas prĂ©-rĂ©cupĂ©rer de donnĂ©es cĂŽtĂ© serveur pour une requĂȘte spĂ©cifique en assignant l'option `prefetch` Ă  `false`. + +Voici un exemple qui ne prĂ©-rĂ©cupĂšre pas la requĂȘte : + +```js{12} +export default { + apollo: { + allPosts: { + query: gql`query AllPosts { + allPosts { + id + imageUrl + description + } + }`, + // Pas de prĂ©-rĂ©cupĂ©ration + prefetch: false, + } + } +} +``` + +Si vous souhaitez ne pas prĂ©-rĂ©cupĂ©rer de donnĂ©es pour toutes les requĂȘtes, vous pouvez utiliser l'option `$prefetch` option : + +```js{4} +export default { + apollo: { + // Pas de prĂ©-rĂ©cupĂ©ration + $prefetch: false, + allPosts: { + query: gql`query AllPosts { + allPosts { + id + imageUrl + description + } + }`, + } + } +} +``` + +## CrĂ©er le client Apollo + +Il est recommandĂ© de crĂ©er les clients Apollo dans une fonction prenant un argument `ssr`, assignĂ© Ă  `true` cĂŽtĂ© serveur et `false` cĂŽtĂ© client. + +Lorsque `ssr` est `false`, nous essayons de rĂ©cupĂ©rer l'Ă©tat du cache Apollo avec `cache.restore`, en rĂ©cupĂ©rant la variable `window.__APOLLO_STATE__` qui est injectĂ©e dans le fichier HTML sur le serveur lors du rendu. + +Voici un exemple : + +```js{21-30} +// apollo.js + +import Vue from 'vue' +import { ApolloClient } from 'apollo-client' +import { HttpLink } from 'apollo-link-http' +import { InMemoryCache } from 'apollo-cache-inmemory' +import VueApollo from 'vue-apollo' + +// Installation du plugin Vue +Vue.use(VueApollo) + +// CrĂ©ation du client Apollo +export function createApolloClient (ssr = false) { + const httpLink = new HttpLink({ + // Vous devez utiliser un URL absolu + uri: ENDPOINT + '/graphql', + }) + + const cache = new InMemoryCache() + + // CĂŽtĂ© client, on rĂ©cupĂšre l'Ă©tat injectĂ© + if (!ssr) { + if (typeof window !== 'undefined') { + const state = window.__APOLLO_STATE__ + if (state) { + // Si vous utilisez plusieurs clients, utilisez `state.` + cache.restore(state.defaultClient) + } + } + } + + const apolloClient = new ApolloClient({ + link: httpLink, + cache, + ...(ssr ? { + // On active cette option cĂŽtĂ© serveur pour optimiser les requĂȘtes lors du SSR + ssrMode: true, + } : { + // DĂ©sactivation temporaire de la rĂ©cupĂ©ration forcĂ©e de requĂȘtes + ssrForceFetchDelay: 100, + }), + }) + + return apolloClient +} +``` + +## CrĂ©ation de l'application + +AU lieu de crĂ©er notre instance Vue racine tout de suite, nous utilisons une fonction `createApp` qui accepte un paramĂštre `context`. + +Cette fonction est utilisĂ©e cĂŽtĂ© client et cĂŽtĂ© serveur avec une valeur `ssr` diffĂ©rente dans le `context`. Nous utilisons cette valeur dans la mĂ©thode `createApolloClient` que nous avons Ă©crite plus tĂŽt. + +Voici un exemple d'une fonction `createApp` classique : + +```js{9,37} +// app.js + +import Vue from 'vue' +import VueRouter from 'vue-router' +import Vuex from 'vuex' +import { sync } from 'vuex-router-sync' + +import VueApollo from 'vue-apollo' +import { createApolloClient } from './apollo' + +import App from './ui/App.vue' +import routes from './routes' +import storeOptions from './store' + +Vue.use(VueRouter) +Vue.use(Vuex) + +function createApp (context) { + const router = new VueRouter({ + mode: 'history', + routes, + }) + + const store = new Vuex.Store(storeOptions) + + // On synchronise le router avec le store Vuex + // Cela enregistre `store.state.route` + sync(store, router) + + // Restauration de l'Ă©tat Vuex + if (!context.ssr && window.__INITIAL_STATE__) { + // On initialise l'Ă©tat du store avec la donnĂ©e injectĂ©e depuis le serveur + store.replaceState(window.__INITIAL_STATE__) + } + + // Apollo + const apolloClient = createApolloClient(context.ssr) + const apolloProvider = new VueApollo({ + defaultClient: apolloClient, + }) + + return { + app: new Vue({ + el: '#app', + router, + store, + apolloProvider, + ...App, + }), + router, + store, + apolloProvider, + } +} + +export default createApp +``` + +## CĂŽtĂ© client + + +La partie client est simple -- on appelle `createApp` avec `ssr` passĂ© Ă  `false` : + +```js +// client-entry.js + +import createApp from './app' + +createApp({ + ssr: false, +}) +``` + +## CĂŽtĂ© serveur + +Nous n'avons besoin de rien faire de particulier, Ă  part de stocker le cache Apollo pour pouvoir l'injecter dans le HTML du client. Vous pouvez trouver plus d'informations sur [le routage cĂŽtĂ© serveur](https://ssr.vuejs.org/guide/routing.html#routing-with-vue-router) et la [prĂ©-rĂ©cupĂ©ration de donnĂ©es](https://ssr.vuejs.org/guide/data.html#data-store) dans le guide SSR officiel. + +Voici un exemple avec Vue Router et un store Vuex : + +```js{3,26} +// server-entry.js + +import ApolloSSR from 'vue-apollo/ssr' +import createApp from './app' + +export default () => new Promise((resolve, reject) => { + const { app, router, store, apolloProvider } = createApp({ + ssr: true, + }) + + // Ajout de l'emplacement du routeur + router.push(context.url) + + // On attend que le routeur ait rĂ©solu les possibles hooks asynchrones + router.onReady(() => { + // Ce hook `rendered` est appelĂ© lorsque l'application est rendue + context.rendered = () => { + // Un fois l'application rendue, notre store est maintenant + // rempli avec l'Ă©tat de nos composants. + // Lorsque nous attachons un Ă©tat au contexte et que l'option `template` + // est utilisĂ©e comme moteur de rendu, l'Ă©tat est automatiquement + // sĂ©rialisĂ© et injectĂ© dans le HTML dans `window.__INITIAL_STATE__`. + context.state = store.state + + // On injecte Ă©galement l'Ă©tat du cache Apollo + context.apolloState = ApolloSSR.getStates(apolloProvider) + } + resolve(app) + }) +}) +``` + +Vous pouvez utiliser la mĂ©thode [ApolloSSR.getStates](../api/ssr.md#getstates) pour rĂ©cupĂ©rer le code JavaScript nĂ©cessaire Ă  l'injection dans la page gĂ©nĂ©rĂ©e pour passer la donnĂ©e du cache Apollo au client. + +Dans le [template de page](https://ssr.vuejs.org/guide/#using-a-page-template), utilisez l'utilitaire `renderState` : + +```html +{{{ renderState({ contextKey: 'apolloState', windowKey: '__APOLLO_STATE__' }) }}} +``` + +Voici un exemple complet : + +```html{15} + + + + + + + + {{ title }} + {{{ renderResourceHints() }}} + {{{ renderStyles() }}} + + + + {{{ renderState() }}} + {{{ renderState({ contextKey: 'apolloState', windowKey: '__APOLLO_STATE__' }) }}} + {{{ renderScripts() }}} + + +``` diff --git a/packages/docs/src/fr/guide/testing.md b/packages/docs/src/fr/guide/testing.md new file mode 100644 index 00000000..27877afe --- /dev/null +++ b/packages/docs/src/fr/guide/testing.md @@ -0,0 +1,186 @@ +# Tests + +Pour tester unitairement vos requĂȘtes et vos mutations Vue Apollo, vous pouvez faire des tests simples, ou bien tester avec un schĂ©ma GraphQL mockĂ©. Tous les exemples documentĂ©s utilisent [Jest](https://jestjs.io/) et [vue-test-utils](https://github.com/vuejs/vue-test-utils). + +## Tests simples + +Pour tester une requĂȘte, vous pouvez simplement assigner de la donnĂ©e au composant et rgarder comment il est rendu grĂące aux snapshots Jest. Imaginons que vous ayez une requĂȘte pour rĂ©cupĂ©rer les hĂ©ros de Vue, vous pouvez ajouter une fausse liste avec un seul hĂ©ros : + +```js +test('affiche les hĂ©ros correctement avec la donnĂ©e requĂȘtĂ©e', () => { + const wrapper = shallowMount(App, { localVue }) + wrapper.setData({ + allHeroes: [ + { + id: 'un-identifiant', + name: 'Evan You', + image: 'https://pbs.twimg.com/profile_images/888432310504370176/mhoGA4uj_400x400.jpg', + twitter: 'youyuxi', + github: 'yyx990803', + }, + ], + }) + expect(wrapper.element).toMatchSnapshot() +}) +``` + +Pour un simple test de mutation, vous devez vĂ©rifier que la mĂ©thode `mutate` d'`$apollo` a Ă©tĂ© appelĂ©e dans votre composant. Dans l'exemple qui suit, la mutation a Ă©tĂ© appelĂ©e dans la mĂ©thode `addHero` : + +```js +test('appelle la mutation Apollo dans la mĂ©thode `addHero`', () => { + const mutate = jest.fn() + const wrapper = mount(App, { + localVue, + mocks: { + $apollo: { + mutate, + }, + }, + }) + wrapper.vm.addHero() + expect(mutate).toBeCalled() +}) +``` + +### Tester l'Ă©tat de chargement en mockant `$apollo` + +Si vous souhaitez tester ce que votre composant affiche lorsque les rĂ©sultats de votre requĂȘte GraphQL sont encore en train de charger, vous pouvez Ă©galement mocker un Ă©tat de chargement dans les requĂȘtes Apollo respctives : + +```js +test('s\'affiche correctement lorsque allHeroes sont en train de charger', () => { + const wrapper = mount(App, { + mocks: { + $apollo: { + queries: { + allHeroes: { + loading: true, + }, + }, + }, + }, + }) + + expect(wrapper.element).toMatchSnapshot(); +}) +``` + +## Tester avec un schĂ©ma GraphQL mockĂ© + +Vous pouvez Ă©galement faire des tests plus complexes et plus en profondeur grĂące Ă  [un schĂ©ma GraphQL mockĂ©](https://www.apollographql.com/docs/graphql-tools/mocking.html). Cette mĂ©thode n'inclut pas Apollo, mais vous laisse vĂ©rifier qu'une requĂȘte s'exĂ©cute correctement avec un schĂ©ma donnĂ©. + +Pour cela, vous avez d'abord besoin d'un schĂ©ma : + +```js +const sourceSchema = ` + type VueHero { + id: ID! + name: String! + image: String + github: String + twitter: String + } + + input HeroInput { + name: String! + image: String + github: String + twitter: String + } + + + type Query { + allHeroes: [VueHero] + } + + type Mutation { + addHero(hero: HeroInput!): VueHero! + deleteHero(name: String!): Boolean + } +` +``` + +Ensuite, il vous faut crĂ©er un schĂ©ma exĂ©cutable avec la mĂ©thode `graphql-tools` : + +```js +import { makeExecutableSchema } from 'graphql-tools' + +// ... + +const schema = makeExecutableSchema({ + typeDefs: sourceSchema, +}) +``` + +Puis vous devez ajouter les fonctions mockĂ©es au schĂ©ma : + +```js +import { addMockFunctionsToSchema } from 'graphql-tools' + +// ... + +addMockFunctionsToSchema({ + schema, +}) +``` + +SpcĂ©fiez la requĂȘte GraphQL : + +```js +const query = ` + query { + allHeroes { + id + name + twitter + github + image + } + } +` +``` + +Appelez la requĂȘte GraphQL dans le test, passez la rĂ©ponse comme donnĂ©e au composant, puis vĂ©rifiez que le rendu du composant correspond au snapshot : + +```js +graphql(schema, query).then(result => { + wrapper.setData(result.data) + expect(wrapper.element).toMatchSnapshot() +}) +``` + +Dans ce cas, tous les champs de types `string` seront Ă©gales Ă  "Hello World" et tous ceux de type `number` seront nĂ©gatifs. Si vous souhaitez une rĂ©ponse plus rĂ©aliste, vous devez spĂ©cifier les rĂ©solveurs pour chaque requĂȘte : + +```js +const resolvers = { + Query: { + allHeroes: () => [ + { + id: '-pBE1JAyz', + name: 'Evan You', + image: + 'https://pbs.twimg.com/profile_images/888432310504370176/mhoGA4uj_400x400.jpg', + twitter: 'youyuxi', + github: 'yyx990803', + }, + ], + }, +} +``` + +Ensuite, vous devez ajouter des rĂ©solveurs Ă  votre schĂ©ma exĂ©cutable et assigner la propriĂ©tĂ© `preserveResolvers` Ă  `true` lorsque vous ajoutez les fonctions mockĂ©es : + +```js +const schema = makeExecutableSchema({ + typeDefs: sourceSchema, + resolvers, +}) + +addMockFunctionsToSchema({ + schema, + preserveResolvers: true, +}) +``` + +Vous pouvez tester les mutations de la mĂȘme façon. + +--- \ No newline at end of file diff --git a/packages/docs/src/fr/migration/README.md b/packages/docs/src/fr/migration/README.md new file mode 100644 index 00000000..8ebc2bc4 --- /dev/null +++ b/packages/docs/src/fr/migration/README.md @@ -0,0 +1,196 @@ +# De vue-apollo 2 Ă  Apollo 1 + +Les principaux changements concernent la mise en place du client Apollo. Le code Ă  l'intĂ©rieur de vos composants ne devraient pas ĂȘtre affectĂ©s. Apollo utilise dĂ©sormais [apollo-link](https://github.com/apollographql/apollo-link), un systĂšme plus flexible qui permet de composer plusieurs liens et permettre plus de choses (traitement par lots, support hors-connexion, et plus encore). + +## Installation + +### Packages + +Avant : + +``` +npm install --save vue-apollo apollo-client +``` + +AprĂšs : + +``` +npm install --save vue-apollo@next graphql apollo-client apollo-link apollo-link-http apollo-cache-inmemory graphql-tag +``` + +### Imports + +Avant : + +```js +import Vue from 'vue' +import { ApolloClient, createBatchingNetworkInterface } from 'apollo-client' +import VueApollo from 'vue-apollo' +``` + +AprĂšs : + +```js +import Vue from 'vue' +import { ApolloClient } from 'apollo-client' +import { HttpLink } from 'apollo-link-http' +import { InMemoryCache } from 'apollo-cache-inmemory' +import VueApollo from 'vue-apollo' +``` + +### Apollo Setup + +Avant : + +```js +// CrĂ©ation de l'interface rĂ©seau +const networkInterface = createNetworkInterface({ + uri: 'http://localhost:3000/graphql', + transportBatching: true, +}) + +// CrĂ©ation de la souscription au client websocket +const wsClient = new SubscriptionClient('ws://localhost:3000/subscriptions', { + reconnect: true, +}) + +// Extension de l'interface rĂ©seau avec la souscription au client +const networkInterfaceWithSubscriptions = addGraphQLSubscriptions( + networkInterface, + wsClient, +) + +// CrĂ©ation du client Apollo avc la nouvell interface rĂ©seau +const apolloClient = new ApolloClient({ + networkInterface: networkInterfaceWithSubscriptions, + connectToDevTools: true, +}) +``` + +AprĂšs : + +```js +const httpLink = new HttpLink({ + // Vous devez utiliser un URL absolu + uri: 'http://localhost:3020/graphql', +}) + +// CrĂ©ation du lien websocket +const wsLink = new WebSocketLink({ + uri: 'ws://localhost:3000/subscriptions', + options: { + reconnect: true, + }, +}) + +// En utilisant la possibilitĂ© de scinder les liens, vous pouvez envoyer +// des donnĂ©es Ă  chaque lien en fonction du type d'opĂ©ration envoyĂ© +const link = split( + // Scission basĂ©e sur le type d'opĂ©ration + ({ query }) => { + const { kind, operation } = getMainDefinition(query) + return kind === 'OperationDefinition' && + operation === 'subscription' + }, + wsLink, + httpLink +) + +// CrĂ©ation du client Apollo +const apolloClient = new ApolloClient({ + link, + cache: new InMemoryCache(), + connectToDevTools: true, +}) +``` + +### Plugin Setup + +Avant : + +```js +// CrĂ©ation du client Apollo +const apolloClient = new ApolloClient({ + networkInterface: createBatchingNetworkInterface({ + uri: 'http://localhost:3020/graphql', + }), + connectToDevTools: true, +}) + +// Intallation du plugin Vue +Vue.use(VueApollo, { + apolloClient, +}) + +new Vue({ + // ... +}) +``` + +AprĂšs : + +```js +const httpLink = new HttpLink({ + // Vous devez utiliser un URL absolu + uri: 'http://localhost:3020/graphql', +}) + +// CrĂ©ation du client Apollo +const apolloClient = new ApolloClient({ + link: httpLink, + cache: new InMemoryCache(), + connectToDevTools: true, +}) + +// Intallation du plugin Vue +Vue.use(VueApollo) + +// CrĂ©ation d'un provider +const apolloProvider = new VueApollo({ + defaultClient: apolloClient, +}) + +// Utilisation du provider +new Vue({ + apolloProvider, + // ... +}) +``` + +## Mutations + +Les query reducers ont Ă©tĂ© retirĂ©s. Utilisez l'API `update` pour mettre le cache Ă  jour. + +## Souscriptions + +### Packages + +Avant : + +``` +npm install --save subscriptions-transport-ws +``` + +AprĂšs : + +``` +npm install --save apollo-link-ws apollo-utilities +``` + +### Imports + +Avant : + +```js +import { SubscriptionClient, addGraphQLSubscriptions } from 'subscriptions-transport-ws' +``` + +AprĂšs : + +```js +import { split } from 'apollo-link' +import { WebSocketLink } from 'apollo-link-ws' +import { getMainDefinition } from 'apollo-utilities' +``` + +Pour plus d'informations, visitez la [documentation Apollo officielle](https://www.apollographql.com/docs/react/v2.5/recipes/2.0-migration). \ No newline at end of file