{"id":13546906,"url":"https://github.com/Illuday/fireQL","last_synced_at":"2025-04-02T19:31:59.321Z","repository":{"id":217216326,"uuid":"217141295","full_name":"Illuday/fireQL","owner":"Illuday","description":"FireQL - GraphQL API for Firestore - Boilerplate plug and play","archived":false,"fork":false,"pushed_at":"2021-10-15T11:04:13.000Z","size":338,"stargazers_count":76,"open_issues_count":0,"forks_count":5,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-11-03T15:38:16.220Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Illuday.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-10-23T19:51:39.000Z","updated_at":"2023-03-18T21:49:04.000Z","dependencies_parsed_at":null,"dependency_job_id":"e0e21e50-cfdd-441c-a874-43d820cc8f4c","html_url":"https://github.com/Illuday/fireQL","commit_stats":null,"previous_names":["illuday/fireql"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Illuday%2FfireQL","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Illuday%2FfireQL/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Illuday%2FfireQL/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Illuday%2FfireQL/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Illuday","download_url":"https://codeload.github.com/Illuday/fireQL/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246880090,"owners_count":20848812,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T12:00:47.612Z","updated_at":"2025-04-02T19:31:59.310Z","avatar_url":"https://github.com/Illuday.png","language":"JavaScript","funding_links":[],"categories":["Libraries"],"sub_categories":["JavaScript Libraries"],"readme":"\r\n\r\n\u003cp align=\"center\"\u003e\u003cimg align=\"center\" src=\"/.github/logo.gif\"/\u003e\u003c/p\u003e\r\n\u003cp align=\"center\"\u003e\u003cimg align=\"center\" width=\"300\"src=\"/.github/typo.svg\"/\u003e\u003c/p\u003e\r\n\u003cbr\u003e\u003cbr\u003e\r\n\r\n# \u003cp align=\"center\"\u003eWarning\u003c/p\u003e\r\n\r\n\u003e 🛑🛑 This repository is no longer maintained due to my lack of interest today for this technology. I'm now working on the Napi technology - https://getnapi.com. I added all the sources of the NPM library by the way. Feel free to do whatever you want with it. See you soon! 🛑🛑\r\n\r\n\r\n\u003cbr/\u003e\u003cp align=\"center\"\u003e\u003cimg align=\"center\" src=\"/.github/badge.png\"/\u003e\u003c/p\u003e\u003cbr/\u003e\r\n\r\n\r\n\u003e FireQL is a GraphQL connector for Firestore (Firebase database). This repository offer a boilerplate to auto-host a GraphQL server on your Firebase Project (hosting part) connecting to Firestore on the same project.\r\n\r\n\u003e **At the moment, use this repository at your own risk, I can't assure the continuity of this project. It's more an experiment for my personnals works than a real technology for en every day use. I'll make it more usable depending of its popularity.**\r\n\r\n# \u003cp align=\"center\"\u003eSummary\u003c/p\u003e\r\n\r\n- **[#](#1) Getting started** – *Create project, environment, clone repository, initialize, run playground*\r\n- **[#](#2) Create a first type**\r\n- **[#](#3) Add documents** – *Adding a mutation to our schema, to our resolvers, execute it*\r\n- **[#](#4) Get documents** – *Adding a query to our schema, to our resolvers, execute it*\r\n- **[#](#5) Update documents** – *Adding a mutation to our schema, to our resolvers, execute it*\r\n- **[#](#6) Remove documents** – *Adding a mutation to our schema, to our resolvers, execute it* - (in development)\r\n- **[#](#7) Working with relations** – *Updating our type, adding inputs, execute fun queries \u0026 mutations*\r\n- **[#](#8) Query your API from your application**\r\n- **[#](#9) What's next?**\r\n\r\n\u003cbr/\u003e\u003cp align=\"center\"\u003e\u003cimg align=\"center\" src=\"/.github/badge.png\"/\u003e\u003c/p\u003e\r\n\r\n\r\n## \u003ca name=\"1\"\u003e\u003c/a\u003eGetting started\r\n\r\n### Create your Firebase project \u0026 your Firestore database\r\n***Note:** Free projects (spark) works with FireQL!*\r\n\r\nNo specifical needs here. Just be sure to create a **Firestore database** and not a realtime one.\r\n\r\n### Prepare your environment\r\n\r\nExecute these commands in order to install firebase CLI and to login with your Firebase account (Obviously, you need one). Just follow steps.\r\n\r\n```sh\r\n$ npm install -g firebase-tools\r\n$ firebase login\r\n```\r\n\r\n### Clone this repository\r\n\r\nGit clone it or just download zip.\r\n```sh\r\n$ git clone https://github.com/Illuday/fireQL.git\r\n```\r\n\r\n### Init Firebase project\r\n\r\nInitialise the firebase project : \r\n\r\n```sh\r\n$ firebase init\r\n# Select \"Functions\" \u0026 \"Hosting\"\r\n# Choose your previously created project\r\n# Use Javascript\r\n# Say \"no\" to ESlint (You'll be able to install it later.)\r\n# Don't override index.js \u0026 packages.json\r\n# Say Yes to dependencies\r\n# Use public directory\r\n# Don't create SPA\r\n# Done!\r\n```\r\n### Open GraphQL playground with function emulating\r\n\r\nSetup your Google credentials : https://firebase.google.com/docs/functions/local-emulator#set_up_admin_credentials_optional\r\n\r\n```sh\r\n firebase emulators:start\r\n```\r\n\r\n***Note:** On some systems, emulators doesn't seams to work using this last command. You can downgrade firebase-tools to **6.8.0**, then run :*\r\n\r\n\r\n\r\n```sh\r\n firebase serve\r\n```\r\n\r\nAccess your playground on:\r\n\u003ehttp://localhost:5001/YOU_PROJECT_ID/us-central1/api (Given in the console)\r\n\r\nPlayground is running! **You have to copy/paste your api link (url above) in the upper field inside the playground in order to make it work**.\r\n\r\n### Open GraphQL playground on Firebase Hosting\r\n\r\n```sh\r\n firebase deploy\r\n```\r\n\r\nThen go to Firebase console, section \"Functions\", you should find your url: \r\n\r\n\u003e https://us-central1-YOU_PROJECT_ID.cloudfunctions.net/api\r\n\r\nPlayground is running! **You have to copy/paste your api link (url above) in the upper field inside the playground in order to make it work**.\r\n\r\n### Deploy for production\r\n\r\nTodo.\r\n\r\n\u003cbr/\u003e\u003cp align=\"center\"\u003e\u003cimg align=\"center\" src=\"/.github/badge.png\"/\u003e\u003c/p\u003e\r\n\r\n## \u003ca name=\"2\"\u003e\u003c/a\u003eCreate a first type\r\n\r\n***For non GQL user:** A **type** is a collection / table in your firestore database.*\r\n\r\nTo create a type, just add it in the schema. You can add as much type you need. **We'll come back on relations later**.\r\n\r\n```javascript\r\ntype Artist {\r\n    id: ID\r\n    name: String!\r\n    age: Int!\r\n}\r\n```\r\n###### \u003cp align=\"center\"\u003efunctions/graphql/types/artistType.graphql\u003c/p\u003e\u003cbr\u003e\r\n\r\n\u003cp align=\"center\"\u003e\u003cimg align=\"center\" src=\"/.github/badge.png\"/\u003e\u003c/p\u003e\r\n\r\n## \u003ca name=\"3\"\u003e\u003c/a\u003eAdd document to our type\r\n\r\n***For non GQL user:** Compare to a restAPI, a resolver is a GraphQL \"route\", a mutation will represent a put/patch route with parameters.*\r\n\r\n### 1 - Adding the mutation to our schema\r\n\r\n```javascript\r\ntype Mutation {\r\n    addArtist(name: String!, age: Int!): Artist\r\n}\r\n```\r\n###### \u003cp align=\"center\"\u003efunctions/graphql/types/artistType.graphql\u003c/p\u003e\r\n\r\n### 2 - Adding the mutation to our resolvers\r\n\r\nFireQL is my magical library to connect our graphQL server to our firestore. FireQL.add() will automatically add the new artist to our firestore collection \"artists\".\r\n\r\n```javascript\r\nconst resolverFunctions = {\r\n  Query: {},\r\n  Mutation: {\r\n    addArtist: (parent, document) =\u003e fireQL.add({ collectionName: 'artists', document }),\r\n  },\r\n};\r\n```\r\n###### \u003cp align=\"center\"\u003efunctions/graphql/resolvers.js\u003c/p\u003e\r\n\r\n### 3 - Executing mutation\r\n\r\nGo to your GQL playground and execute your mutation. There, we want to add an artist named \"illuday\", and get his id and his name (probably illuday...).\r\n\r\n***For non GQL user:** GraphQL allows you to get only fields you want as result of any queries or mutations.*\r\n\r\n#### \u003cp align=\"center\"\u003eADDING AN ARTIST\u003c/p\u003e\r\n\r\n```javascript\r\nmutation {\r\n  addArtist (name: \"illuday\", age: \"28\") {\r\n    id\r\n    name\r\n  }\r\n}\r\n```\r\n###### \u003cp align=\"center\"\u003eMutation - Playground\u003c/p\u003e\r\n\r\n\u003cp align=\"center\"\u003e:arrow_down:\u003c/p\u003e\u003cbr\u003e\r\n\r\n```json\r\n{\r\n  \"data\": {\r\n    \"addArtist\": {\r\n      \"id\": \"BsuNNpRQqFbgWME1RIZ4\",\r\n      \"name\": \"illuday\"\r\n    }\r\n  }\r\n}\r\n```\r\n\r\n###### \u003cp align=\"center\"\u003eMutation result - Playground\u003c/p\u003e\r\n\r\nIn firestore, you can see that you have your document, added to artists collection with \"illuday\" as name and 28 as age.\r\n\r\n***Note:** We havn't age in result because we didn't ask for it.*\r\n\r\nMagic.\r\n\r\n#### We'll come back later on adding, with more powerful add!\r\n\r\n\u003cbr/\u003e\u003cp align=\"center\"\u003e\u003cimg align=\"center\" src=\"/.github/badge.png\"/\u003e\u003c/p\u003e\r\n\r\n## \u003ca name=\"4\"\u003e\u003c/a\u003eGet documents\r\n\r\n### 1 - Adding the query to our schema\u003c/span\u003e\r\n\r\n```javascript\r\ntype Query {\r\n    getArtists(where: WhereInput): [Artist]\r\n}\r\n```\r\n###### \u003cp align=\"center\"\u003efunctions/graphql/types/artistType.graphql\u003c/p\u003e\r\n\r\n**The result value of this query is [Artist], it'll return an Array of Artist type.**\r\n\r\n**WhereInput** is an **helper** that provide the **structure for querying firestore**. The object needed here is:\r\n\r\n```javascript\r\n{\r\n  field: 'nameOfYourField'\r\n  operator: 'enum: EQ (==), GT (\u003e), GTE (\u003e=), LE (\u003c), LTE (\u003c=), INARRAY'\r\n  value: { // One of\r\n    intValue: intValue\r\n    stringValue: stringValue\r\n  }\r\n}\r\n```\r\n\r\n***Note:** This helper is already provide in your schema from this repository.*\r\n\r\n### 2 - Adding the query to our resolvers\r\n\r\nFireQL.get() will automatically get artists from our firestore collection \"artists\".\r\n\r\n```javascript\r\nconst resolverFunctions = {\r\n  Query: {\r\n    getArtists: (parent, { where }) =\u003e FireQL.get({ collectionName: 'artists', where }),\r\n  },\r\n  Mutation: {\r\n    ...\r\n  },\r\n};\r\n```\r\n\r\n###### \u003cp align=\"center\"\u003efunctions/graphql/resolvers.js\u003c/p\u003e\r\n\r\n### 3 - Executing query\r\n\r\nBefore executing this query, I seed my database to have more artists.\r\n\r\n- illuday: 28y/o\r\n- Anna Dittmann: 26y/o\r\n- Ilya Kuvshinov: 29y/o\r\n- Shayline: 27y/o\r\n\r\nLet's make some tries in our GraphQL playground.\r\n\r\n_**Note:** I named my queries (in playground) to be able to save them all._\r\n\r\n#### \u003cp align=\"center\"\u003eGET ALL ARTISTS\u003c/p\u003e\r\n\r\n```javascript\r\nquery getAllArtists { # \u003c-- This is just a name for GQL playground\r\n  getArtists {\r\n    id\r\n    name\r\n    age\r\n  }\r\n}\r\n```\r\n\u003cp align=\"center\"\u003e:arrow_down:\u003c/p\u003e\u003cbr\u003e\r\n\r\n```javascript\r\n{\r\n  \"data\": {\r\n    \"getArtists\": [\r\n      {\r\n        \"id\": \"GF0ihzKePxeKZMRTjY7A\",\r\n        \"name\": \"illuday\",\r\n        \"age\": 28\r\n      },\r\n      {\r\n        \"id\": \"NVLWsTYEq6GgqvoCvU6W\",\r\n        \"name\": \"Shayline\",\r\n        \"age\": 27\r\n      },\r\n      {\r\n        \"id\": \"TgI9PYG4p7OKzrOBmzmD\",\r\n        \"name\": \"Anna Dittmann\",\r\n        \"age\": 26\r\n      },\r\n      {\r\n        \"id\": \"mPXsd1tkYRfSxN0UW1aQ\",\r\n        \"name\": \"Ilya Kuvshinov\",\r\n        \"age\": 29\r\n      }\r\n    ]\r\n  }\r\n}\r\n```\r\n\r\n\u003chr\u003e\r\n\r\n#### \u003cp align=\"center\"\u003eGET ARTIST BY ID\u003c/p\u003e\r\n\r\n```javascript\r\nquery getArtistById { # \u003c-- This is just a name for GQL playground\r\n  getArtists (where: { field: \"id\", value: { stringValue: \"TgI9PYG4p7OKzrOBmzmD\" } }){\r\n    id\r\n    name\r\n    age\r\n  }\r\n}\r\n```\r\n\r\n\u003cp align=\"center\"\u003e:arrow_down:\u003c/p\u003e\u003cbr\u003e\r\n\r\n```javascript\r\n{\r\n  \"data\": {\r\n    \"getArtists\": [\r\n      {\r\n        \"id\": \"TgI9PYG4p7OKzrOBmzmD\",\r\n        \"name\": \"Anna Dittmann\",\r\n        \"age\": 26\r\n      }\r\n    ]\r\n  }\r\n}\r\n```\r\n\r\n\u003chr\u003e\r\n\r\n#### \u003cp align=\"center\"\u003eGET ARTISTS BY AGE\u003c/p\u003e\r\n\r\n```javascript\r\nquery getArtistsByAge { # \u003c-- This is just a name for GQL playground\r\n  getArtists (where: { field: \"age\", operator: LT, value: { intValue: 28 } }){\r\n    name\r\n    age\r\n  }\r\n}\r\n```\r\n\r\n\u003cp align=\"center\"\u003e:arrow_down:\u003c/p\u003e\u003cbr\u003e\r\n\r\n```javascript\r\n{\r\n  \"data\": {\r\n    \"getArtists\": [\r\n      {\r\n        \"name\": \"Anna Dittmann\",\r\n        \"age\": 26\r\n      },\r\n      {\r\n        \"name\": \"Shayline\",\r\n        \"age\": 27\r\n      }\r\n    ]\r\n  }\r\n}\r\n```\r\n\r\n\u003cbr/\u003e\u003cp align=\"center\"\u003e\u003cimg align=\"center\" src=\"/.github/badge.png\"/\u003e\u003c/p\u003e\r\n\r\n## \u003ca name=\"5\"\u003e\u003c/a\u003eUpdate document\r\n\r\n### 1 - Adding the mutation to our schema\u003c/span\u003e\r\n\r\n```javascript\r\ntype Mutation {\r\n    ...,\r\n    updateArtist(id: ID!, name: String, age: Int): Artist\r\n}\r\n```\r\n\r\n###### \u003cp align=\"center\"\u003efunctions/graphql/types/artistType.graphql\u003c/p\u003e\r\n\r\n### 2 - Adding the mutation to our resolvers\r\n\r\nFireQL.update() will automatically update the artist in our firestore collection \"artists\".\r\n\r\n```javascript\r\nconst resolverFunctions = {\r\n  Query: {\r\n\t...\r\n  },\r\n  Mutation: {\r\n    ...,\r\n    updateArtist: (parent, document) =\u003e FireQL.update({ collectionName: 'artists', document }),\r\n  },\r\n};\r\n```\r\n\r\n###### \u003cp align=\"center\"\u003efunctions/graphql/resolvers.js\u003c/p\u003e\r\n\r\n### 3 - Executing mutation\r\n\r\nLet's say we want to modify \"illuday\" age.\r\n\r\n#### \u003cp align=\"center\"\u003eUPDATE ILLUDAY AGE\u003c/p\u003e\r\n\r\n```javascript\r\nmutation updateIlludayAge { # \u003c-- This is just a name for GQL playground\r\n  updateArtist(id: \"GF0ihzKePxeKZMRTjY7A\", age: 38) {\r\n    id\r\n    name\r\n    age\r\n  }\r\n}\r\n```\r\n\r\n\u003cp align=\"center\"\u003e:arrow_down:\u003c/p\u003e\u003cbr\u003e\r\n\r\n```javascript\r\n{\r\n  \"data\": {\r\n    \"updateArtist\": {\r\n      \"id\": \"GF0ihzKePxeKZMRTjY7A\",\r\n      \"name\": \"illuday\",\r\n      \"age\": 38\r\n    }\r\n  }\r\n}\r\n```\r\n\r\n#### \u003cp align=\"center\"\u003e\u003cimg align=\"center\" src=\"/.github/badge.png\"/\u003e\u003c/p\u003e\r\n\r\n## \u003ca name=\"6\"\u003e\u003c/a\u003eRemoving document - (in development)\r\n\r\n### 1 - Adding the mutation to our schema\u003c/span\u003e\r\n\r\n```javascript\r\ntype Mutation {\r\n    ...,\r\n    removeArtist(id: ID!): Artist\r\n}\r\n```\r\n\r\n###### \u003cp align=\"center\"\u003efunctions/graphql/types/artistType.graphql\u003c/p\u003e\r\n\r\n### 2 - Adding the mutation to our resolvers\r\n\r\nFireQL.remove() will automatically remove the artist in our firestore collection \"artists\".\r\n\r\n```javascript\r\nconst resolverFunctions = {\r\n  Query: {\r\n\t...\r\n  },\r\n  Mutation: {\r\n    ...,\r\n    removeArtist: (parent, document) =\u003e FireQL.remove({ collectionName: 'artists', document }),\r\n  },\r\n};\r\n```\r\n\r\n###### \u003cp align=\"center\"\u003efunctions/graphql/resolvers.js\u003c/p\u003e\r\n\r\n### 3 - Executing mutation\r\n\r\n#### \u003cp align=\"center\"\u003eREMOVE ILLUDAY\u003c/p\u003e\r\n\r\n```javascript\r\nmutation removeIlluday { # \u003c-- This is just a name for GQL playground\r\n  removeArtist(id: \"GF0ihzKePxeKZMRTjY7A\") {\r\n    id\r\n  }\r\n}\r\n```\r\n\r\n\u003cp align=\"center\"\u003e:arrow_down:\u003c/p\u003e\u003cbr\u003e\r\n\r\n```javascript\r\n{\r\n  \"data\": {\r\n    \"removeArtist\": {\r\n      \"id\": \"GF0ihzKePxeKZMRTjY7A\"\r\n    }\r\n  }\r\n}\r\n```\r\n\r\n\r\n#### \u003cp align=\"center\"\u003e\u003cimg align=\"center\" src=\"/.github/badge.png\"/\u003e\u003c/p\u003e\r\n\r\n## \u003ca name=\"7\"\u003e\u003c/a\u003eWorking with relations\r\n\r\n***Note:** in FireQL, all relations must be bi-directionnal.*\r\n\r\n### 1 - Adding a new type and create a relation\r\n\r\nArtists have **MANY** artworks, artworks have **ONE** artist.\r\n\r\n```javascript\r\ntype Artwork {\r\n    id: ID\r\n    name: String\r\n    artist: Artist\r\n}\r\n\r\ntype Artist {\r\n    id: ID\r\n    name: String!\r\n    age: Int!\r\n    artworks: [Artwork]\r\n}\r\n```\r\n\r\n###### \u003cp align=\"center\"\u003efunctions/graphql/types/artistType.graphql \u0026 types/artworkType.graphql\u003c/p\u003e\r\n\r\n**Follow steps above to create basics queries \u0026 mutations for the new type**\r\n\r\n### 2 - Modifying Artwork mutation to handle relation management\r\n\r\nWe need to create our **inputs** before modifying our addArtist \u0026 updateArtist mutations. They'll allows those things:\r\n\r\n- Add **artworks** when we add an **artist**\r\n- Update / Remove **artworks** when we update **artist**\r\n\r\n```javascript\r\ninput ArtworkInput {\r\n    name: String\r\n}\r\n\r\ninput AddArtworkInput {\r\n    collection: String = \"artworks\"\r\n    on: String = \"artist\"\r\n\r\n    connect: ID\r\n    create: ArtworkInput\r\n}\r\n\r\ninput UpdateArtworkInput {\r\n    collection: String = \"artworks\"\r\n    on: String = \"artist\"\r\n\r\n    connect: ID\r\n    remove: ID\r\n    create: ArtworkInput\r\n}\r\n```\r\n\r\n###### \u003cp align=\"center\"\u003efunctions/graphql/types/artworkType.graphql\u003c/p\u003e\r\n\r\nBack to these inputs:\r\n\r\n- **ArtworkInput**: Represent fields we can fill when we create an artwork\r\n\r\n- **AddArtworkInput**:\r\n\r\n  | Argument   | Value               | Description                                                  |\r\n  | ---------- | ------------------- | ------------------------------------------------------------ |\r\n  | collection | String = \"artworks\" | Name of the collection linked, set **artworks by default**. You'll never have to change that. |\r\n  | on         | String = \"artist\"   | Foreign field for our relation, set **artwork by default**. You'll never have to change that. ***Note**: In case of a One to Many or Many to Many relations you'll have to write [String] = ['artists'].* |\r\n  | connect*   | ID                  | The id of artwork you want to connect with.                  |\r\n  | create*    | ArtworkInput        | The input of artwork you want to create then link.           |\r\n\r\n  *one of these must be fill when you execute the mutation\r\n\r\n- **UpdateArtworkInput**:\r\n\r\n  | Argument   | Value               | Description                                                  |\r\n  | ---------- | ------------------- | ------------------------------------------------------------ |\r\n  | collection | String = \"artworks\" | Name of the collection linked, set **artworks by default**. You'll never have to change that. |\r\n  | on         | String = \"artist\"   | Foreign field for our relation, set **artwork by default**. You'll never have to change that. ***Note**: In case of a One to Many or Many to Many relations you'll have to write [String] = ['artists'].* |\r\n  | connect*   | ID                  | The id of an artwork you want to connect with.               |\r\n  | remove*    | ID                  | The id of an artwork you want to remove. ***Note**: In case of a Many to One or One to one relations, the artwork will be removed from the database* |\r\n  | create*    | ArtworkInput        | The input of artwork you want to create then link.           |\r\n\r\n  *one of these must be fill when you execute the mutation\r\n\r\nNow that we have inputs, we can adjust our mutations \"addArtist\" and \"updateArtist\".\r\n\r\n```javascript\r\n type Mutation {\r\n    addArtist(name: String!, age: Int!, artworks: [AddArtworkInput]): Artist\r\n    updateArtist(id: ID!, name: String, age: Int, artworks: [UpdateArtworkInput]): Artist\r\n    ...\r\n }\r\n```\r\n\r\n###### \u003cp align=\"center\"\u003efunctions/graphql/types/artistType.graphql\u003c/p\u003e\r\n\r\nThat's it! Let's play with it.\r\n\r\n### 3 - Executing mutations\r\n\r\n#### \u003cp align=\"center\"\u003eADD AN ARTIST AND CREATE ARTWORKS AT THE SAME TIME\u003c/p\u003e\r\n\r\n```javascript\r\nmutation addAnArtistWithArtworks {\r\n  addArtist(\r\n    name: \"illuday\", \r\n    age: 28, \r\n    artworks: [\r\n      { create: { name: \"MIRAMARKA\" } }, # NEW ARTWORK\r\n      { create: { name: \"BLACKLIST\" } }, # NEW ARTWORK\r\n      { connect: \"WDwGd4LwjZGfsFEALOi7\" } # EXISTING ARTWORK\r\n    ]\r\n  ) {\r\n    id\r\n    name\r\n    artworks { id name } # WAIT WHAT ?\r\n  }\r\n}\r\n```\r\n\r\n\u003cp align=\"center\"\u003e:arrow_down:\u003c/p\u003e\u003cbr\u003e\r\n\r\n```javascript\r\n{\r\n  \"data\": {\r\n    \"addArtist\": {\r\n      \"id\": \"xyseptoQ7WBBRr8XAl4U\",\r\n      \"name\": \"illuday\",\r\n      \"artworks\": [\r\n        {\r\n          \"id\": \"NmgdsLrNgzIiIUaRFkef\",\r\n          \"name\": \"MIRAMARKA\"\r\n        },\r\n        {\r\n          \"id\": \"W7rgj1Lkc4HAruuMMmX2\",\r\n          \"name\": \"BLACKLIST\"\r\n        },\r\n        {\r\n          \"id\": \"WDwGd4LwjZGfsFEALOi7\",\r\n          \"name\": \"NYNDOR\"\r\n        }\r\n      ]\r\n    }\r\n  }\r\n}\r\n```\r\n\r\n**So, what happens there ?** We inserted an new artist in our database, named illuday, we decided to create at the same time two new artworks and connect an already existing one. References between the artist and artworks are automatically set by FireQL.\r\n\r\n**And the result ?** You can see that as we added relations in our **artist** types, we can query directly its **artworks** on results (queries, mutations). Yeah!\r\n\r\n#### \u003cp align=\"center\"\u003eUPDATE AN ARTIST AND REMOVE ONE ARTWORK\u003c/p\u003e\r\n\r\n***Note:** Due to a Firebase limitation (arrayUnion / arrayRemove), you can't add and remove at the same time.*\r\n\r\n\r\n```javascript\r\nmutation updateAnArtistWithArtworks {\r\n  updateArtist(\r\n    id: \"xyseptoQ7WBBRr8XAl4U\", # illuday\r\n    artworks: [\r\n      { remove: \"W7rgj1Lkc4HAruuMMmX2\" }, # BLACKLIST\r\n    ]\r\n  ) {\r\n    id\r\n    name\r\n    artworks { id name }\r\n  }\r\n}\r\n```\r\n\r\n\u003cp align=\"center\"\u003e:arrow_down:\u003c/p\u003e\u003cbr\u003e\r\n\r\n```javascript\r\n{\r\n  \"data\": {\r\n    \"updateArtist\": {\r\n      \"id\": \"xyseptoQ7WBBRr8XAl4U\",\r\n      \"name\": \"illuday\",\r\n      \"artworks\": [\r\n        {\r\n          \"id\": \"NmgdsLrNgzIiIUaRFkef\",\r\n          \"name\": \"MIRAMARKA\"\r\n        },\r\n        {\r\n          \"id\": \"WDwGd4LwjZGfsFEALOi7\",\r\n          \"name\": \"NYNDOR\"\r\n        }\r\n      ]\r\n    }\r\n  }\r\n}\r\n```\r\n\r\n#### \u003cp align=\"center\"\u003eQUERYING OUR FINAL ARTIST\u003c/p\u003e\r\n\r\n```javascript\r\nquery getIlluday {\r\n  getArtists(where: {field: \"id\", value: {stringValue: \"xyseptoQ7WBBRr8XAl4U\"}}) {\r\n    id\r\n    name\r\n    age\r\n    artworks {\r\n      id\r\n      name\r\n    }\r\n  }\r\n}\r\n```\r\n\r\n\u003cp align=\"center\"\u003e:arrow_down:\u003c/p\u003e\u003cbr\u003e\r\n\r\n```javascript\r\n{\r\n  \"data\": {\r\n    \"getArtists\": [\r\n      {\r\n        \"id\": \"xyseptoQ7WBBRr8XAl4U\",\r\n        \"name\": \"illuday\",\r\n        \"age\": 28,\r\n        \"artworks\": [\r\n            {\r\n          \t\t\"id\": \"NmgdsLrNgzIiIUaRFkef\",\r\n          \t\t\"name\": \"MIRAMARKA\"\r\n        \t},\r\n        \t{\r\n         \t \t\"id\": \"WDwGd4LwjZGfsFEALOi7\",\r\n          \t\t\"name\": \"NYNDOR\"\r\n        \t},\r\n        \t{\r\n          \t\t\"id\": \"nTTtND8HyktG30IQzO5M\",\r\n          \t\t\"name\": \"ACTIVITOUR\"\r\n        \t}\r\n        ]\r\n      }\r\n    ]\r\n  }\r\n}\r\n```\r\n\r\n\u003cbr/\u003e\u003cp align=\"center\"\u003e\u003cimg align=\"center\" src=\"/.github/badge.png\"/\u003e\u003c/p\u003e\r\n\r\n## \u003ca name=\"8\"\u003e\u003c/a\u003eQuery your API from your application\r\n\r\nYou just have to use a GQL client (it's like an axios for restAPI), here are some :\r\n\r\n- Flutter: https://github.com/zino-app/graphql-flutter\r\n- VueJS: https://github.com/vuejs/vue-apollo\r\n- Nuxt: https://github.com/nuxt-community/apollo-module\r\n- ReactJS: https://github.com/apollographql/react-apollo\r\n- React Native: https://github.com/apollographql/apollo-client\r\n\r\nOr for React, Angular, Vue, Ember, Web Components, Meteor, Blaze, Vanilla JS, Next.js and I assume every javascript based framework: https://github.com/apollographql/apollo-client\r\n\r\n\u003cbr/\u003e\u003cp align=\"center\"\u003e\u003cimg align=\"center\" src=\"/.github/badge.png\"/\u003e\u003c/p\u003e\r\n\r\n## \u003ca name=\"9\"\u003e\u003c/a\u003eWhat's next?\r\n\r\n- [x] Connection to Firestore\r\n- [x] Hosting on Firebase cloud functions\r\n- [x] Playgrounds local \u0026 online\r\n- [x] Get documents\r\n- [x] Get documents with their relations\r\n- [x] Add documents\r\n- [x] Add documents and relation (create, connect)\r\n- [x] Update documents\r\n- [x] Update documents and their relations (create, connect, remove)\r\n- [ ] Remove documents\r\n- [ ] Remove documents and their relations\r\n- [ ] Handle authentication (Anonymous, phone, e-mail, Facebook, Google)\r\n- [ ] Simple security rules for queries \u0026 mutations\r\n- [ ] Subscriptions (for realtime data)\r\n- [ ] File upload to Firebase storage\r\n\r\n#### You can choose the feature you need the most:\r\n\r\n[![](https://api.gh-polls.com/poll/01DR6Y6WSZEMT0SCH1DT0TEM2K/Authentication%20%26%20Security)](https://api.gh-polls.com/poll/01DR6Y6WSZEMT0SCH1DT0TEM2K/Authentication%20%26%20Security/vote)\r\n[![](https://api.gh-polls.com/poll/01DR6Y6WSZEMT0SCH1DT0TEM2K/Subscriptions)](https://api.gh-polls.com/poll/01DR6Y6WSZEMT0SCH1DT0TEM2K/Subscriptions/vote)\r\n[![](https://api.gh-polls.com/poll/01DR6Y6WSZEMT0SCH1DT0TEM2K/File%20upload)](https://api.gh-polls.com/poll/01DR6Y6WSZEMT0SCH1DT0TEM2K/File%20upload/vote)\r\n\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FIlluday%2FfireQL","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FIlluday%2FfireQL","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FIlluday%2FfireQL/lists"}