issue152:c_c
Différences
Ci-dessous, les différences entre deux révisions de la page.
| Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente | ||
| issue152:c_c [2020/01/03 09:28] – d52fr | issue152:c_c [2020/01/04 14:13] (Version actuelle) – auntiee | ||
|---|---|---|---|
| Ligne 1: | Ligne 1: | ||
| **This month marks the final Command & Conquer article I’ll be writing. For more details on why, you may want to look at last month’s article. That being said, I wanted to do something a little different for the last article. The first part of the article will be dedicated to some articles I’m most proud of having written, and the second half will be dedicated to writing a GraphQL API to track my Go games. So if you’re interested in one but not the other, you know where to jump to.** | **This month marks the final Command & Conquer article I’ll be writing. For more details on why, you may want to look at last month’s article. That being said, I wanted to do something a little different for the last article. The first part of the article will be dedicated to some articles I’m most proud of having written, and the second half will be dedicated to writing a GraphQL API to track my Go games. So if you’re interested in one but not the other, you know where to jump to.** | ||
| - | L' | + | L' |
| **Part 1 | **Part 1 | ||
| Ligne 8: | Ligne 8: | ||
| • CLI Cookbook - FCM #76. I’m most proud of this one because we managed to get the community involved and actually created something together. I can’t guarantee that all the commands are still accurate, but I’m sure there are still a good few ideas that are valid. The actual PDF/LaTeX documents can be found here: https:// | • CLI Cookbook - FCM #76. I’m most proud of this one because we managed to get the community involved and actually created something together. I can’t guarantee that all the commands are still accurate, but I’m sure there are still a good few ideas that are valid. The actual PDF/LaTeX documents can be found here: https:// | ||
| - | 1ère partie | + | Première |
| - | J' | + | J' |
| - | ••CLI Cookbook - FCM n° 76. C'est de celui là dont je suis le plus fier parce que nous avons réussi à y associer la communauté pour vraiment créer quelque chose ensemble. Je ne peux pas assurer que toutes les commandes soient encore | + | ••CLI Cookbook - n° 76 du FCM . C'est de celui-là dont je suis le plus fier parce que nous avons réussi à y associer la communauté pour vraiment créer quelque chose ensemble. Je ne peux pas assurer que toutes les commandes soient encore |
| Ligne 17: | Ligne 17: | ||
| • Tailwind CSS - FCM #134. This article introduced my readers to a tool that completely changed my approach to designing and styling websites, and is a method I still use to this day. Definitely a worthwhile read to anyone who’s interested in web development.** | • Tailwind CSS - FCM #134. This article introduced my readers to a tool that completely changed my approach to designing and styling websites, and is a method I still use to this day. Definitely a worthwhile read to anyone who’s interested in web development.** | ||
| - | ••Flexbox Stylus - FCM n° 92. C' | + | ••Flexbox Stylus - n° 92 du FCM. C' |
| - | ••Tailwind CSS - FCM n° 134. Cet article présentait à mes lecteurs un outil qui avait complètement changé mon approche | + | ••Tailwind CSS - n° 134 du FCM. Cet article présentait à mes lecteurs un outil qui avait complètement changé mon approche |
| **• My web development articles. I won’t list all the issues I had web development focused articles in (though there will be a few at the end of this item). The reason I’m proud of these articles is quite simple - I both enjoyed the topic, and used the knowledge in my professional life (I still do!). In writing those sorts of articles, I always hoped to make the entry into new web technologies easier for beginners. Noteworthy articles: Gatsby Multi-Language (151), AMP (127), CSS Grids (125), Static Site Generation (103). | **• My web development articles. I won’t list all the issues I had web development focused articles in (though there will be a few at the end of this item). The reason I’m proud of these articles is quite simple - I both enjoyed the topic, and used the knowledge in my professional life (I still do!). In writing those sorts of articles, I always hoped to make the entry into new web technologies easier for beginners. Noteworthy articles: Gatsby Multi-Language (151), AMP (127), CSS Grids (125), Static Site Generation (103). | ||
| Ligne 24: | Ligne 24: | ||
| There are other articles on a wide range of topics - guitar, note taking, virtualization, | There are other articles on a wide range of topics - guitar, note taking, virtualization, | ||
| - | Mes articles sur le développement Web. Je ne voudrais pas lister tous les numéros dans lesquels je me suis concentré sur le développement Web (bien qu'il y en ait quelques-uns | + | •• |
| - | Il y a d' | + | Il y a d' |
| Ligne 35: | Ligne 35: | ||
| For anyone not familiar with Go, it’s an ancient chinese board game (estimated at over 2500 years old), played with black and white stones on a 19x19 grid. It’s also known as Baduk or Weiqi in Korea and China, respectively.** | For anyone not familiar with Go, it’s an ancient chinese board game (estimated at over 2500 years old), played with black and white stones on a 19x19 grid. It’s also known as Baduk or Weiqi in Korea and China, respectively.** | ||
| - | 2ème partie | + | Seconde |
| Et maintenant, passons à d' | Et maintenant, passons à d' | ||
| - | + | Pour ceux qui ne connaissent | |
| - | Pour ceux qui ne sont pas familiers avec le Go, c'est un jeu chinois ancien sur plateau (on l' | + | |
| **GraphQL is a (much) more recent invention. It’s a query language for APIs that define a schema of data, and allow flexible querying for information. Basic example - you could define a schema for a book and an author, and keep track of things like ISBN, number of pages, publishing date, author, title, etc. Anyone who has access to the API can, using the same URL, selectively query only the data they want (i.e. title, author, and cover page) instead of getting everything back every time. It’s the backend to Gatsby’s static site generation (controlled via the gatsby-node.js file), and is extremely powerful. Ever since using it for the first time, I’ve wanted to create my own GraphQL API to replace my aging Ruby on Rails application that I use for tracking movies and video games I want to see/buy. I have since converted the information I already had (stored in a sqlite database from Rails) into mongodb, and written the API to the point where it can access and create entries in the database. Now it’s time to expand the functionality - adding in my Go games. I will not be covering the frontend aspect (planned to be a Gatsby PWA that hydrates data on load), as it’s not been completed yet, and GraphQL is flexible enough that you can access it from pretty much anything.** | **GraphQL is a (much) more recent invention. It’s a query language for APIs that define a schema of data, and allow flexible querying for information. Basic example - you could define a schema for a book and an author, and keep track of things like ISBN, number of pages, publishing date, author, title, etc. Anyone who has access to the API can, using the same URL, selectively query only the data they want (i.e. title, author, and cover page) instead of getting everything back every time. It’s the backend to Gatsby’s static site generation (controlled via the gatsby-node.js file), and is extremely powerful. Ever since using it for the first time, I’ve wanted to create my own GraphQL API to replace my aging Ruby on Rails application that I use for tracking movies and video games I want to see/buy. I have since converted the information I already had (stored in a sqlite database from Rails) into mongodb, and written the API to the point where it can access and create entries in the database. Now it’s time to expand the functionality - adding in my Go games. I will not be covering the frontend aspect (planned to be a Gatsby PWA that hydrates data on load), as it’s not been completed yet, and GraphQL is flexible enough that you can access it from pretty much anything.** | ||
| - | GraphQL est une invention (beaucoup) plus récente. C'est un langage de requête pour les API qui définit un schéma de données et permet un requêtage flexible des informations. Un exemple simple | + | GraphQL est une invention (beaucoup) plus récente. C'est un langage de requête pour les API qui définit un schéma de données et permet un requêtage flexible des informations. Un exemple simple |
| **All code has been placed into a Gist here: https:// | **All code has been placed into a Gist here: https:// | ||
| Ligne 62: | Ligne 61: | ||
| Les bases | Les bases | ||
| - | J'ai paramétré mon API en utilisant Express.js, mongoose, apollo-server et apollo-server-express. La plupart des points ne changeront pas suivant l' | + | J'ai paramétré mon API en utilisant Express.js, mongoose, apollo-server et apollo-server-express. La plupart des points ne changeront pas suivant l' |
| - | Comment fonctionne l'API GraphQL ? Vous définissez quelques schémas (voyez-les comme un définition de classe) pour les requêtes, les types et les mutations. Les mutations sont le côté créer/ | + | Comment fonctionne l'API GraphQL ? Vous définissez quelques schémas (voyez-les comme une définition de classe) pour les requêtes, les types et les mutations. Les mutations sont le côté créer/ |
| **GraphQL then takes your defined schema and uses it for validation, typing, and for understanding the requests sent to it. The schemas also control which fields from your database are available in the API. | **GraphQL then takes your defined schema and uses it for validation, typing, and for understanding the requests sent to it. The schemas also control which fields from your database are available in the API. | ||
| Ligne 75: | Ligne 74: | ||
| / | / | ||
| - | GraphQL prend ensuite le schéma défini et l' | + | GraphQL prend ensuite le schéma défini et l' |
| Structure de base des dossiers : | Structure de base des dossiers : | ||
| Ligne 94: | Ligne 93: | ||
| yarn add -D nodemon @babel/core @babel/node @babel/ | yarn add -D nodemon @babel/core @babel/node @babel/ | ||
| - | Exigences | + | Requis |
| - | Asssurez-vous d' | + | Asssurez-vous d' |
| Pour installer et lancer le projet, vous pouvez faire ce qui suit (si vous préférez npm, toutes les commandes yarn ont des équivalents npm) : | Pour installer et lancer le projet, vous pouvez faire ce qui suit (si vous préférez npm, toutes les commandes yarn ont des équivalents npm) : | ||
| Ligne 136: | Ligne 135: | ||
| / | / | ||
| - | Étape 1 Schéma de Mongoose | + | Étape 1 - Schéma de Mongoose |
| Pour une implémentation de mongodb avec mongoose, vous définissez un mongoose.Schema (différent du schéma de GraphQL). Ici, vous définissez en gros la structure du document à charger/ | Pour une implémentation de mongodb avec mongoose, vous définissez un mongoose.Schema (différent du schéma de GraphQL). Ici, vous définissez en gros la structure du document à charger/ | ||
| Ligne 150: | Ligne 149: | ||
| Explication simple | Explication simple | ||
| - | J'ai défini les champs pour un jeu « go » pour inclure un Titre (par ex., Lucas vs Georges), la date du jeu (actuellement définie comme une chaîne, car je n'ai pas encore réussi à faire fonctionner correctement les dates), | + | J'ai défini les champs pour un jeu « go » pour inclure un Titre (par ex., Lucas vs Georges), la date du jeu (actuellement définie comme une chaîne, car je n'ai pas encore réussi à faire fonctionner correctement les dates), le serveur sur lequel le jeu a eu lieu (KGS, IGS, FGS, online-go, etc), le nom des joueurs Noir et Blanc, le Komi (les points attribués à Blanc s'il est second), le Résultat dans la notation traditionnelle - par ex., B+Res, et MyWin qui enregistre si j'ai gagné ce jeu (pour des statistiques ultérieures). Si j' |
| **The collection defines what I want the collection to be called in mongodb (currently, the collection does not exist - so I could have chosen anything here). You then apply the schema to a model, and export the resulting variable to use later on. | **The collection defines what I want the collection to be called in mongodb (currently, the collection does not exist - so I could have chosen anything here). You then apply the schema to a model, and export the resulting variable to use later on. | ||
| Ligne 158: | Ligne 157: | ||
| Once we’ve defined our mongodb server, we need to define our GraphQL schema. You should base the schema off your database definition, but it does not have to be a one-to-one match.** | Once we’ve defined our mongodb server, we need to define our GraphQL schema. You should base the schema off your database definition, but it does not have to be a one-to-one match.** | ||
| - | La collection définit | + | La collection définit |
| - | Étape 2 Schéma de GraphQL | + | Étape 2 - Schéma de GraphQL |
| - | Une fois que nous avons défini notre serveur mongodb, nous avons besoin de définir notre schéma GraphQL. Vous devriez baser votre schéma sur la définition de votre base de données, mais il n'a pas à correspondre | + | Une fois que nous avons défini notre serveur mongodb, nous devons |
| **The GraphQL Schema I defined looks like this: | **The GraphQL Schema I defined looks like this: | ||
| Ligne 170: | Ligne 169: | ||
| The GoGame type is a match for the mongoose Schema, and the createGoGame mutation takes pretty much all the fields.** | The GoGame type is a match for the mongoose Schema, and the createGoGame mutation takes pretty much all the fields.** | ||
| - | Le schéma GraphQL que j'ai défini ressemble à cela : | + | Le schéma GraphQL que j'ai défini ressemble à ceci : |
| / | / | ||
| Ligne 178: | Ligne 177: | ||
| **The queries, however, are specialized. The first query (goGame) can only be filtered by ID and/or title, as it returns a single instance it makes sense to be as restrictive as possible to avoid weird results. The allGoGames query can be filtered using pretty much all fields except Komi and Result. As my goal for this API is to track my own games, I’m more likely to search for games where I was black or white, and perhaps define if it was a win or a loss. I don’t think I’ll ever search for all games where Komi was 0.5, for example. If I end up needing this, I can simply add it in as an option. Similarly, I won’t necessarily be filtering by result, as I’ll never (at that point) know which player was which. The field is important for a quick overview, but shouldn’t be very useful when filtering what I want to see. I also added a Limit field to the allGoGames, to limit the number of results returned.** | **The queries, however, are specialized. The first query (goGame) can only be filtered by ID and/or title, as it returns a single instance it makes sense to be as restrictive as possible to avoid weird results. The allGoGames query can be filtered using pretty much all fields except Komi and Result. As my goal for this API is to track my own games, I’m more likely to search for games where I was black or white, and perhaps define if it was a win or a loss. I don’t think I’ll ever search for all games where Komi was 0.5, for example. If I end up needing this, I can simply add it in as an option. Similarly, I won’t necessarily be filtering by result, as I’ll never (at that point) know which player was which. The field is important for a quick overview, but shouldn’t be very useful when filtering what I want to see. I also added a Limit field to the allGoGames, to limit the number of results returned.** | ||
| - | Cependant, les requêtes sont spécialisées. La première requête (GoGame) ne peut être filtrée que par l' | + | Cependant, les requêtes sont spécialisées. La première requête (GoGame) ne peut être filtrée que par l' |
| **Step 3 Resolvers | **Step 3 Resolvers | ||
| Ligne 188: | Ligne 187: | ||
| Admittedly, almost all my resolvers look like this, with the only difference being variable names and the models used. The goGame resolver is the simplest - I take any of the args passed through (Title or _id), and then run a findOne on the collection.** | Admittedly, almost all my resolvers look like this, with the only difference being variable names and the models used. The goGame resolver is the simplest - I take any of the args passed through (Title or _id), and then run a findOne on the collection.** | ||
| - | Étape 3 Les résolveurs | + | Étape 3 - Les résolveurs |
| - | Bon ! Nous avons maintenant défini nos schémas et donné quelques éléments de réflexion sur les options disponibles dans une requête. Néanmoins, jusqu' | + | Bon ! Nous avons maintenant défini nos schémas et donné quelques éléments de réflexion sur les options disponibles dans une requête. Néanmoins, jusqu' |
| / | / | ||
| - | J'admets | + | J'avoue que tous mes résolveurs ressemblent à ça, à la seule différence des noms de variable et des modèles utilisés. Le résolveur GoGame est le plus simple |
| **The allGoGames resolver is more complicated. I pass in all the args, including a field called Limit. The idea behind ‘limit’ is to set a maximum number of results (ie. if I want a top 10). As this field doesn’t exist in the mongodb document, it will never yield results if it’s just passed in that way. Instead, I check if args has a property ‘Limit’. If it does, I create a copy of the object and delete the ‘Limit’ property. I then adjust the mongodb command to pass in the remaining arguments and use args.Limit in the .limit() function. If args.Limit doesn’t exist, I just run a find() on all the args. | **The allGoGames resolver is more complicated. I pass in all the args, including a field called Limit. The idea behind ‘limit’ is to set a maximum number of results (ie. if I want a top 10). As this field doesn’t exist in the mongodb document, it will never yield results if it’s just passed in that way. Instead, I check if args has a property ‘Limit’. If it does, I create a copy of the object and delete the ‘Limit’ property. I then adjust the mongodb command to pass in the remaining arguments and use args.Limit in the .limit() function. If args.Limit doesn’t exist, I just run a find() on all the args. | ||
| Ligne 200: | Ligne 199: | ||
| The createGoGame resolver takes all the arguments I specified in the GraphQL Schema. However, it also needs an id. Instead of forcing the user or client to generate one, I instead add an _id field to the object using mongoose.Types.ObjectId() before creating the item.** | The createGoGame resolver takes all the arguments I specified in the GraphQL Schema. However, it also needs an id. Instead of forcing the user or client to generate one, I instead add an _id field to the object using mongoose.Types.ObjectId() before creating the item.** | ||
| - | Le résolveur allGoGames est plus compliqué. Je passe tous les arguments, y compris un champ appelé Limit. L' | + | Le résolveur allGoGames est plus compliqué. Je passe tous les arguments, y compris un champ appelé Limit. L' |
| - | Le résolveur de CreateGoGame | + | Le résolveur de createGoGame |
| **Step 4 - Putting it all together | **Step 4 - Putting it all together | ||
| Ligne 214: | Ligne 213: | ||
| Étape 4 - Regrouper tout ça | Étape 4 - Regrouper tout ça | ||
| - | La première chose que je vous recommande est de créer un fichier index.js à la fois dans / | + | La première chose que je vous recommande |
| / | / | ||
| Ligne 230: | Ligne 229: | ||
| / | / | ||
| - | Assurez-vous de remplacer {MONGO_URL} par votre vraie chaîne de connexion à mongodb (en général du genre mongodb:// | + | Assurez-vous de remplacer {MONGO_URL} par votre vraie chaîne de connexion à mongodb (en général du genre mongodb:// |
| **Step 5 - Trying it out | **Step 5 - Trying it out | ||
| Ligne 245: | Ligne 244: | ||
| }** | }** | ||
| - | Étape 5 - test | + | Étape 5 - Test |
| - | Une fois que vous avez démarré le serveur avec yarn dev, le serveur devrait fonctionner à localhost: | + | Une fois que vous aurez démarré le serveur avec yarn dev, le serveur devrait fonctionner à localhost: |
| Pour créer des éléments : | Pour créer des éléments : | ||
| Ligne 276: | Ligne 275: | ||
| }** | }** | ||
| - | La commande ci-dessus | + | La commande ci-dessus |
| Pour requêter des éléments : | Pour requêter des éléments : | ||
| Ligne 296: | Ligne 295: | ||
| **So, I hope this last article has gotten you enthused for GraphQL. To all my avid readers - thank you for your time and interest over these years! As always, if you want to send me a message you can reach me at lswest34+fcm@gmail.com. Especially if you happen to have a good list of my articles and what issues they appeared in!** | **So, I hope this last article has gotten you enthused for GraphQL. To all my avid readers - thank you for your time and interest over these years! As always, if you want to send me a message you can reach me at lswest34+fcm@gmail.com. Especially if you happen to have a good list of my articles and what issues they appeared in!** | ||
| - | Bien ! J' | + | Bien ! J' |
issue152/c_c.1578040122.txt.gz · Dernière modification : 2020/01/03 09:28 de d52fr
