From b0266628952c42b2b25d566e673dee9ab355fe0e Mon Sep 17 00:00:00 2001 From: alexlbr Date: Tue, 18 Jun 2019 15:37:38 +0100 Subject: [PATCH 01/16] upddates solution relay --- src/index.js | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/index.js b/src/index.js index 60bdf7b..946e4c9 100644 --- a/src/index.js +++ b/src/index.js @@ -11,10 +11,9 @@ const CHARACTER_TYPE = "Character"; const EPISODE_TYPE = "Episode"; const typeDefs = gql` - # do I need this? - # interface Node { - # id: ID! - # } + interface INode { + id: ID! + } union Node = Character | Episode @@ -37,8 +36,8 @@ const typeDefs = gql` edges: [CharacterEdge] } - type Character { - id: ID + type Character implements INode { + id: ID! name: String status: String episodes: [Episode] @@ -67,10 +66,7 @@ const typeDefs = gql` const resolvers = { Query: { charactersConnection: async (_, args) => { - // give this to students - // const pageInfo = {}; - // const edges = []; - // solution first part + // partial solution // const characters = await fetchCharactersData(); // const pageInfo = { // hasNextPage: characters.info.next, From ceb75cc61cebaaf94561e66cdbb280df261ff251 Mon Sep 17 00:00:00 2001 From: alexlbr Date: Tue, 18 Jun 2019 20:37:37 +0100 Subject: [PATCH 02/16] adds INode __resolveType --- src/index.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/index.js b/src/index.js index 946e4c9..02912ea 100644 --- a/src/index.js +++ b/src/index.js @@ -114,6 +114,11 @@ const resolvers = { return EPISODE_TYPE; } + return null; + } + }, + INode: { + __resolveType() { return null; } } From 66b7899324c22c666ddf005ed5a007a40e1e449a Mon Sep 17 00:00:00 2001 From: alexlbr Date: Mon, 1 Jul 2019 19:17:27 +0200 Subject: [PATCH 03/16] udpates solution --- src/index.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/index.js b/src/index.js index 02912ea..f6e2794 100644 --- a/src/index.js +++ b/src/index.js @@ -43,8 +43,8 @@ const typeDefs = gql` episodes: [Episode] } - type Episode { - id: ID + type Episode implements INode { + id: ID! name: String characters: [Character] } @@ -59,6 +59,7 @@ const typeDefs = gql` ): CharactersConnection character(id: Int): Character episodes: [Episode] + characters: [Character] episode(id: Int): Episode } `; @@ -87,8 +88,10 @@ const resolvers = { } }; }, + // TODO Ad a comment we'll use the toGlobalId in the nex step node: (_, { id }) => getObjectById(fromGlobalId(id)), character: (_, args) => fetchCharacterById(args.id), + characters: (_, args) => fetchCharacters(), episodes: () => fetchEpisodes(), episode: (_, args) => fetchEpisodeById(args.id) }, @@ -132,7 +135,7 @@ server.listen().then(({ url }) => { function getObjectById({ type, id }) { const types = { - Character: fetchCharacterById + [CHARACTER_TYPE]: fetchCharacterById }; return types[type](id); @@ -162,6 +165,12 @@ function fetchCharactersData() { ); } +function fetchCharacters() { + return fetch("https://rickandmortyapi.com/api/character/") + .then(res => res.json()) + .then(json => json.results); +} + function fetchCharacterById(id) { return fetch("https://rickandmortyapi.com/api/character/" + id) .then(res => res.json()) From cd0048f4a3dd0efab71266f6109f277613b7da24 Mon Sep 17 00:00:00 2001 From: alexlbr Date: Sun, 29 Mar 2020 22:50:42 +0100 Subject: [PATCH 04/16] add solution fundamentals --- README.md | 256 +++++++++++++++++++++---- package.json | 5 +- src/index.js | 240 +++++++++-------------- src/index_exercise.js | 102 ---------- yarn.lock | 435 +++++++++++++++++++++++++++--------------- 5 files changed, 603 insertions(+), 435 deletions(-) delete mode 100644 src/index_exercise.js diff --git a/README.md b/README.md index cc00fda..53d4e8d 100644 --- a/README.md +++ b/README.md @@ -1,77 +1,263 @@ -# Thinking in GraphQL exercise +# GraphQL API Fundamentals This exercise is part of the [React GraphQL Academy](http://reactgraphql.academy) learning material. The goal of the exercise is to help you get started transitioning from REST to GraphQL. ## Learning objectives -- Thinking in Graphs -- Learn how to connect resolvers to a REST API -- Understand Schema Design principles +- Understand the main functionalities and responsibilities of a GraphQL server +- Learn how to migrate an existing REST API to GraphQL and start “thinking in graphs” +- Start identifying potential problems when running real-world GraphQL APIs ## Exercise part 1 -[https://rickandmortyapi.com/graphql/](https://rickandmortyapi.com/graphql/) +[](TODO DEPLOY URL) -- Query a list with all the character names -- Query how many characters are in the system -- Query a single characther by id (try id equals 1) and get its name +- Query a list with all the training titles +- Query how many training are in the system? +- Query a single training by id (try id equals TODO ADD ONE????????) and get its name - How many types do we have in the system? ## Exercise part 2 ### To get started -We are going to create our own GraphQL API on top of this [Rick and Morty API](https://rickandmortyapi.com/documentation/#rest) +We are going to create our own GraphQL API on top of this [REST API](https://mockedrestapi.reactgraphql.academy/) -- `git clone git@github.com:reactgraphqlacademy/rest-to-graphql-workshop.git` -- `cd rest-to-graphql-workshop` +- `git clone https://github.com/reactgraphqlacademy/graphql-api-training.git` +- `cd graphql-api-training` - `yarn install` or `npm install` - `yarn start` or `npm start` +### Before we start + +- Clone the repo, git checkout the `fundamentals` branch, install the dependencies and let me walk you through the code meanwhile. +- We use nodemon in the `start` script, so every time you save the server will restart automatically. +- The `src/index.js` is the [getting started tutorial](https://www.apollographql.com/docs/apollo-server/getting-started/) from Apollo. +- Let's replace the schema: + +```graphql +type Query { + books: [Book] +} +``` + +with + +```graphql +type Query { + avocados: [Book] +} +``` + +What do we need to change so the field avocados returns the array of books when we run the query? I'll give you 2 minutes to fix it :) + ### Tasks -- [ ] 1. Create a `Character` type in your schema. Use the [documentation of the character endpoint](https://rickandmortyapi.com/documentation/#character-schema) to define the shape of the `Character` type. +⚠️ Some info before you start the tasks: +1- You can define an array using square brackets and the type, example `[Book]` +2- You can use the type `ID` for ids. +3- In GraphQL types are nullable by default. If you want to make a type non-nullable use `!` (excalmation mark). Example: - - [ ] 1.1. Add a `characters` field to the `Query` type. You can replace the `books` field from Query type on line 32 with `characters` since we won't use books. The `characters` field in the `Query` type should return an array of [Character]. - - [ ] 1.2. Add a `characters` resolver to the Query's resolvers. You can replace the `books` field from Query type on line 40 with `characters` since we won't use books. You can return the mock characters array (which is in the scope and defined at the bottom of the file index.js) in the resolver function. - - [ ] 1.3 You should be able to manually test the `characters` query in Playground at [http://localhost:4000/](http://localhost:4000/) +```graphql +type Book { + id: ID! +} +``` -- [ ] 2. Create an `Episode` type in your schema. Use the [documentation of the episode endpoint](https://rickandmortyapi.com/documentation/#episode-schema) to define the shape of the `Episode` type. Here you are practicing what you've learned on the previous task (1). +To complete the tasks you'll use the mock data and helper functions that are at the bottom of the file `src/index.js`. - - [ ] 2.1. Add an `episodes` field to the `Query` type. The `episodes` field should return an array of [Episode] - - [ ] 2.2. Add an `episodes` resolver to the Query's resolvers. You can return the mock episodes array (which is in the scope and defined at the bottom of the file index.js) in the resolver function. - - [ ] 2.3 You should be able to manually test the `episodes` query in Playground at [http://localhost:4000/](http://localhost:4000/) +- [ ] 1. Create a `Training` type in your schema. Define the following fields `title`, `id`, `objectives`, `curriculum`. Have a look at the mock training data in `src/index.js` to identify the types of each field. -- [ ] 3. Replace the mock data using https://rickandmortyapi.com/documentation/#rest. + - [ ] 1.1. Add a `trainings` field to the `Query` type. You can replace the `books` field from Query type with `trainings` since we won't use books. The `trainings` field in the `Query` type should return an array of training. . + - [ ] 1.2. Add a `trainings` resolver to the Query's resolvers. You can replace the `books` field from Query type with `trainings` since we won't use books. You can return the trainingMockData array (which is in the scope and defined at the bottom of the file index.js) in the resolver function. + - [ ] 1.3 You should be able to manually test the `trainings` query in Playground at [http://localhost:4000/](http://localhost:4000/) - - You can use the `fetchEpisodes` and `fetchCharacters` defined at the bottom of this file `src/index.js` - - You'll need to replace mock data in 2 different places: - - Query characters - - Query episodes +- [ ] 2. Create a `Discount` type in your schema. Define only the fields `code`, `id`, and `discountPercentage`. Have a look at the discount mock data in `src/index.js` to identify the types of each field. -- [ ] 4. Create a relationship between Episode type and Character type in your schema. Please have a look at the [documentation of the episode endpoint](https://rickandmortyapi.com/documentation/#episode-schema) to see how to get the episodes of a given character (heads up! we are calling the field in our Characters `episodes` but the REST API is calling the field that returns an array of episodes as `episode` - singular!). Hints: + - [ ] 2.1. Add an `discounts` field to the `Query` type. The `discounts` field should return an array of discounts. + - [ ] 2.2. Add an `discounts` resolver to the Query's resolvers. You can return the mock discounts array (which is in the scope and defined at the bottom of the file index.js) in the resolver function. + - [ ] 2.3 You should be able to manually test the `discounts` query in Playground at [http://localhost:4000/](http://localhost:4000/) - - You need to add a `Character` key in the resolvers object and an object with an `episodes` key in `Character`. Similar to the Author type and books field in the [Apollo documentation](https://www.apollographql.com/docs/apollo-server/essentials/data#resolver-map). Hint: The first argument of the resolver is the 'parent' type, in this case, the parent of the `episodes` field is the `Character`. parent.episode gives you the array of episodes returned from the REST API. - - You can use the helper fetch functions defined at the bottom of this file `src/index.js`. +- [ ] 3. Replace the mock data with real data using the following endpoints: + - [https://mockedrestapi.reactgraphql.academy/v1/trainings](https://mockedrestapi.reactgraphql.academy/v1/trainings) + - [https://mockedrestapi.reactgraphql.academy/v1/discounts](https://mockedrestapi.reactgraphql.academy/v1/discounts) -- [ ] 5. Create a query that returns a single Character given an id. You need to fetch the character using `https://rickandmortyapi.com/documentation/#get-a-single-character`. Hint, you need to use [arguments](https://graphql.org/graphql-js/passing-arguments/) +Hint. You can use the `fetchTrainings` and `fetchDiscounts` defined at the bottom of this file `src/index.js` -### Bonus +- You'll need to replace mock data in 2 different places: + - Query discounts + - Query trainings -- Create the types and resolvers so the following query works: +Note on mocking. In the next session we'll use the automocking feature of Apollo Server. The only thing you need to do is `mocks:true` in your Apollo Server configuration. More info [here](https://www.apollographql.com/docs/apollo-server/testing/mocking/). +```js +const server = new ApolloServer({ + typeDefs, + mocks: true // ⬅️⬅️⬅️⬅️ +}); ``` -query episode { - episode(id: 1) { + +#### 🏋️‍♀️ Bonus exercise part 2 + +Congratulations, you've completed part 2! You've learned how to create object types in GraphQL and add fields to them using scalar types (`String`,`Int`, `ID`) or your own object types (`Training`, `Discount`). You've also learned how to create a relationship between two object types. + +In GraphQL you can also create your custom scalars types, like [Date](https://graphql.org/learn/schema/#scalar-types). + +Bonus task, add a field called `startDate` to the `Training` object type using a `DateTime` scalar type. GraphQL doesn't provide a DateTime type. Instead of creating a custom `DateTime` scalar type you are going to use [https://github.com/excitement-engineer/graphql-iso-date](https://github.com/excitement-engineer/graphql-iso-date). Note, the package is already installed in package.json. + +## Exercise part 3 + +### Before we start + +Resolvers are functions that have 4 arguments `(parent, args, context, info)`. In this exercise, we are only going to use the first 2 arguments: `parent` and `args`. + +#### The first argument of the resolver + +The first argument, often called `parent`, points to the parent object. For instance, we could override the default resolver of the title field in the Training and return an upper case version of the title. + +⚠️ Trainer implements: + +```js +const resolvers = { + Query: { + //... + }, + Training: { + title: (parent) { + return parent.title.toUpperCase() + } + } +}; +``` + +We could also create a new field that returns the upper case version of the title without changing the title field. Example: + +⚠️ Learners implement (only 5 minutes to implement and write a query to test it!): + +```graphql +type Training { + title: String! + upperCaseTitle: String! + # the rest remains the same +} +``` + +```js +const resolvers = { + Query: { + //... + }, + Training: { + upperCaseTitle: (parent) { + return parent.title.toUpperCase() + } + } +}; +``` + +🏋️‍♀️Bonus exercise, return all the URLs of the discounts field in upper case. + +#### The second argument of the resolver + +The second argument of the resolver (we are calling it `args`) points to the arguments passed to the field. In the following example `args` contains `id`: + +```js +const schema = gql` + type Query { + author(id: ID!): Author + } +`; +const resolvers = { + Query: { + author(parent, args) { + console.log(args); // { id: 3 } based on the query below + } + } +}; +``` + +```graphql +query authorName { + author(id: 3) { name - characters { - name + } +} +``` + +### Tasks + +To complete the tasks you'll use the helper functions that are at the bottom of the file `src/index.js` + +- [ ] 4. Implement a new field in the `Query` type that returns a single training given an id. You need to fetch the training from this endpoint `https://restapi.reactgraphql.academy/v1/trainings/` + `id`. Hint, you need to pass [arguments](https://graphql.org/graphql-js/passing-arguments/) to the field, and then use the second argument in the resolver. There is a helper function at the bottom of `src/index.js`. + +Once implemented you should be able to run the following query: + +```graphql +query getTraining { + training(id: "tra:22") { + title + } +} +``` + +- [ ] 5. Create the following relationship between the Training type and the Discount type in your schema. + +```graphql +type Training { + discounts: [Discount] + # the rest of the fields remain the same +} +``` + +- You need to add a `Training` key in the resolvers object and an object with an `discounts` key in `Training`. Similar to the Author type and books field in the [Apollo documentation](https://www.apollographql.com/docs/apollo-server/essentials/data#resolver-map) +- You need to use the **first argument of the resolver**: the 'parent'. In this case, the parent of the `discounts` field is the `Training`. `parent.discounts` gives you the array of URLs that you can use to fetch each discount from the REST API. +- You can use the helper function `fetchDiscountByUrl` defined at the bottom of this file `src/index.js`. +- Heads up! We want our Training type to have a field called `discounts` that returns an array of `Discount` types not an array of `String` +- Once implemented, you should be able to run the following query: + +```graphql +query getTraining { + training(id: "tra:22") { + title + discounts { + code } } } ``` -- Once implemented, do you see any vulnerability issues on that query? +#### 🏋️‍♀️ Bonus exercise part 3 + +- Create the types and resolvers so the following query works: + +```graphql +query getDangerousDiscount { + discount(id: "dis:421") { + code + training { + title + discounts { + code + # why this query could be dangerous? + } + } + } +} +``` + +Once implemented, do you see any problems/ vulnerability issues on that query? + +## Homework + +You are going to build a GraphQL API on top of an existing REST API. Steps: + +1- Choose a public API. You have a list of public APIs [here](https://github.com/public-apis/public-apis). Suggestion, choose an API that doesn't require authentication and has decent documentation. + +2- Create a GraphQL server to validate and execute the GraphQL queries. You can get started using the [getting started tutorial](https://www.apollographql.com/docs/apollo-server/getting-started/) from Apollo Server. + +3- Create the GraphQL schema using the [Schema Definition Language (SDL)](https://www.prisma.io/blog/graphql-sdl-schema-definition-language-6755bcb9ce51) . You'll define types and relationships between those types. + +4- Add the resolvers to your schema. We are following a SDL-first approach to build our schema. It's the most popular approach in the GraphQL JavaScript community, but be aware that it's not the only one. You can read more about it and other alternatives in this [article](https://www.prisma.io/blog/the-problems-of-schema-first-graphql-development-x1mn4cb0tyl3). ## Articles and links diff --git a/package.json b/package.json index f8b3f41..1a87e64 100644 --- a/package.json +++ b/package.json @@ -18,8 +18,9 @@ }, "homepage": "https://github.com/reactgraphqlacademy/rest-to-graphql-workshop#readme", "dependencies": { - "apollo-server": "^2.5.0", - "graphql": "^14.3.1", + "apollo-server": "^2.11.0", + "graphql": "^14.6.0", + "graphql-iso-date": "^3.6.1", "graphql-relay": "^0.6.0", "node-fetch": "^2.6.0" }, diff --git a/src/index.js b/src/index.js index f6e2794..9284212 100644 --- a/src/index.js +++ b/src/index.js @@ -1,184 +1,130 @@ const fetch = require("node-fetch"); const { ApolloServer, gql } = require("apollo-server"); -const { - fromGlobalId, - toGlobalId, - connectionFromArray -} = require("graphql-relay"); -const mockedCharacters = require("../mocks/characters.json"); - -const CHARACTER_TYPE = "Character"; -const EPISODE_TYPE = "Episode"; - -const typeDefs = gql` - interface INode { - id: ID! - } - - union Node = Character | Episode - - type PageInfo { - # https://facebook.github.io/relay/graphql/connections.htm#sec-undefined.PageInfo.Fields - hasNextPage: Boolean! - hasPreviousPage: Boolean! - totalCount: Int # this is not part of the Relay specification but it's widely used - } - - type CharacterEdge { - # https://facebook.github.io/relay/graphql/connections.htm#sec-Edge-Types - cursor: String! - node: Character +const { GraphQLDateTime } = require("graphql-iso-date"); + +const trainingMockData = [ + { + id: "tra:1", + title: "React Fundamentals", + objectives: "learning basics of react", + curriculum: + "-Thinking in React, Modern JavaScript, Routing & Data Fetching\n-Forms, Authentication, and Hooks\n-Redux Fundamentals, deployment to production" + }, + { + id: "tra:2", + title: "Advanced React", + objectives: "master react", + curriculum: + "-Advanced React patterns and performance.\n-GraphQL 101 & Real-World Testing in React.\n-Building a UI component library" } - - type CharactersConnection { - # https://facebook.github.io/relay/graphql/connections.htm#sec-Connection-Types.Fields - pageInfo: PageInfo! - edges: [CharacterEdge] +]; + +const discountMockData = [ + { + id: "dis:1", + code: "sweetpotato60", + discountPercentage: 60, + description: null + }, + { + id: "dis:2", + code: "garlic20", + discountPercentage: 20, + description: null + }, + { + id: "dis:3", + code: "onion50", + discountPercentage: 50, + description: null } +]; - type Character implements INode { +const typeDefs = gql` + type Training { id: ID! - name: String - status: String - episodes: [Episode] + title: String! + objectives: String! + curriculum: String! + overview: String + discounts: [Discount] + startDate: DateTime } - type Episode implements INode { + type Discount { id: ID! - name: String - characters: [Character] + training: Training + code: String! + discountPercentage: Int! + description: String } + scalar DateTime + type Query { - node(id: String!): Node - charactersConnection( - first: Int - after: String - last: Int - before: String - ): CharactersConnection - character(id: Int): Character - episodes: [Episode] - characters: [Character] - episode(id: Int): Episode + trainings: [Training!] + training(id: ID!): Training + discounts: [Discount!] + discount(id: ID!): Discount } `; const resolvers = { Query: { - charactersConnection: async (_, args) => { - // partial solution - // const characters = await fetchCharactersData(); - // const pageInfo = { - // hasNextPage: characters.info.next, - // hasPreviousPage: characters.info.prev, - // totalCount: characters.info.count - // }; - // const edges = characters.results.map(node => ({ - // node, - // cursor: "" // current page + id + next page - // })); - // return { edges, pageInfo }; - const characters = connectionFromArray(mockedCharacters, args); - return { - ...characters, - pageInfo: { - ...characters.pageInfo, - totalCount: mockedCharacters.length - } - }; - }, - // TODO Ad a comment we'll use the toGlobalId in the nex step - node: (_, { id }) => getObjectById(fromGlobalId(id)), - character: (_, args) => fetchCharacterById(args.id), - characters: (_, args) => fetchCharacters(), - episodes: () => fetchEpisodes(), - episode: (_, args) => fetchEpisodeById(args.id) - }, - Episode: { - characters: parent => { - const { characters = [] } = parent; - return characters.map(fetchCharacterByUrl); - } + trainings: () => fetchTrainings(), + discounts: () => fetchDiscounts(), + training: (_, { id }) => fetchTrainingById(id), + discount: (_, { id }) => fetchDiscountById(id) }, - Character: { - id: parent => toGlobalId(CHARACTER_TYPE, parent.id), - episodes: parent => { - const characterEpisodes = parent.episode || []; - return characterEpisodes.map(fetchEpisodeByUrl); - } + Discount: { + training: parent => fetchTrainingByUrl(parent.training) }, - Node: { - __resolveType(obj) { - if (obj.episode) { - return CHARACTER_TYPE; - } - if (obj.character) { - return EPISODE_TYPE; - } - - return null; - } + Training: { + discounts: ({ discounts }) => discounts.map(fetchDiscountByUrl) }, - INode: { - __resolveType() { - return null; - } - } + DateTime: GraphQLDateTime }; -const server = new ApolloServer({ typeDefs, resolvers }); - -server.listen().then(({ url }) => { - console.log(`🚀 Server ready at ${url}`); -}); - -function getObjectById({ type, id }) { - const types = { - [CHARACTER_TYPE]: fetchCharacterById - }; - - return types[type](id); -} - -function fetchEpisodesData() { - return fetch("https://rickandmortyapi.com/api/episode/").then(res => +function fetchTrainings() { + // More info about the fetch function? https://github.com/bitinn/node-fetch#json + return fetch("https://restapi.reactgraphql.academy/v1/trainings/").then(res => res.json() ); } -function fetchEpisodeById(id) { - return fetch("https://rickandmortyapi.com/api/episode/" + id) - .then(res => res.json()) - .then(json => json); +function fetchTrainingById(id) { + return fetch( + `https://restapi.reactgraphql.academy/v1/trainings/${id}` + ).then(res => res.json()); } -function fetchEpisodeByUrl(url) { - return fetch(url) - .then(res => res.json()) - .then(json => json); -} - -function fetchCharactersData() { - return fetch("https://rickandmortyapi.com/api/character/").then(res => +function fetchDiscounts() { + return fetch("https://restapi.reactgraphql.academy/v1/discounts/").then(res => res.json() ); } -function fetchCharacters() { - return fetch("https://rickandmortyapi.com/api/character/") - .then(res => res.json()) - .then(json => json.results); +function fetchTrainingByUrl(url) { + return fetch(url).then(res => res.json()); } -function fetchCharacterById(id) { - return fetch("https://rickandmortyapi.com/api/character/" + id) - .then(res => res.json()) - .then(json => json); +function fetchDiscountById(id) { + return fetch( + `https://restapi.reactgraphql.academy/v1/discounts/${id}` + ).then(res => res.json()); } -function fetchCharacterByUrl(url) { - return fetch(url) - .then(res => res.json()) - .then(json => json); +function fetchDiscountByUrl(url) { + return fetch(url).then(res => res.json()); } + +// In the most basic sense, the ApolloServer can be started +// by passing type definitions (typeDefs) and the resolvers +// responsible for fetching the data for those types. +const server = new ApolloServer({ typeDefs, resolvers }); + +// This `listen` method launches a web-server. Existing apps +// can utilize middleware options, which we'll discuss later. +server.listen().then(({ url }) => { + console.log(`🚀 Server ready at ${url}`); +}); diff --git a/src/index_exercise.js b/src/index_exercise.js deleted file mode 100644 index 90675d9..0000000 --- a/src/index_exercise.js +++ /dev/null @@ -1,102 +0,0 @@ -const fetch = require("node-fetch"); -const { ApolloServer, gql } = require("apollo-server"); - -// Type definitions define the "shape" of your data and specify -// which ways the data can be fetched from the GraphQL server. -const typeDefs = gql` - # Comments in GraphQL are defined with the hash (#) symbol. - - # This "Book" type can be used in other type declarations. - type Book { - title: String - author: String - } - - # The "Query" type is the root of all GraphQL queries. - # (A "Mutation" type will be covered later on.) - type Query { - books: [Book] - } -`; - -// Resolvers define the technique for fetching the types in the -// schema. We'll retrieve books from the "books" array above. -const resolvers = { - Query: { - books: () => books - } -}; - -// In the most basic sense, the ApolloServer can be started -// by passing type definitions (typeDefs) and the resolvers -// responsible for fetching the data for those types. -const server = new ApolloServer({ typeDefs, resolvers }); - -// This `listen` method launches a web-server. Existing apps -// can utilize middleware options, which we'll discuss later. -server.listen().then(({ url }) => { - console.log(`🚀 Server ready at ${url}`); -}); - -// mock data for characters -const characters = [ - { - name: "Rick Sanchez", - id: 1, - status: "Alive", - episodes: [ - "https://rickandmortyapi.com/api/episode/1", - "https://rickandmortyapi.com/api/episode/2" - ] - }, - { - name: "Morty Smith", - id: 2, - status: "Alive", - episodes: [ - "https://rickandmortyapi.com/api/episode/1", - "https://rickandmortyapi.com/api/episode/3" - ] - } -]; - -// mock data for episodes -const episodes = [ - { - name: "Pilot", - id: 1 - }, - { - name: "Lawnmower Dog", - id: 2 - } -]; - -function getEpisodeIdFromUrl(url) { - return url && url.split("/").pop(); -} - -function mapEpisodeUrlToEpisode(episodes, episodeUrl) { - return episodes.find(e => e.id == getEpisodeIdFromUrl(episodeUrl)); -} - -function fetchEpisodes() { - // More info about the fetch function? https://github.com/bitinn/node-fetch#json - return fetch("https://rickandmortyapi.com/api/episode/") - .then(res => res.json()) - .then(json => json.results); -} - -function fetchCharacters() { - // More info about the fetch function? https://github.com/bitinn/node-fetch#json - return fetch("https://rickandmortyapi.com/api/character/") - .then(res => res.json()) - .then(json => json.results); -} - -function fetchCharacter(id) { - // More info about the fetch function? https://github.com/bitinn/node-fetch#json - return fetch("https://rickandmortyapi.com/api/character/" + id) - .then(res => res.json()) - .then(json => json); -} diff --git a/yarn.lock b/yarn.lock index afc2ff7..0dbed5f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,17 +2,36 @@ # yarn lockfile v1 -"@apollographql/apollo-tools@^0.3.6-alpha.1": - version "0.3.7" - resolved "https://registry.yarnpkg.com/@apollographql/apollo-tools/-/apollo-tools-0.3.7.tgz#3bc9c35b9fff65febd4ddc0c1fc04677693a3d40" - integrity sha512-+ertvzAwzkYmuUtT8zH3Zi6jPdyxZwOgnYaZHY7iLnMVJDhQKWlkyjLMF8wyzlPiEdDImVUMm5lOIBZo7LkGlg== +"@apollo/protobufjs@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@apollo/protobufjs/-/protobufjs-1.0.3.tgz#02c655aedd4ba7c7f64cbc3d2b1dd9a000a391ba" + integrity sha512-gqeT810Ect9WIqsrgfUvr+ljSB5m1PyBae9HGdrRyQ3HjHjTcjVvxpsMYXlUk4rUHnrfUqyoGvLSy2yLlRGEOw== + dependencies: + "@protobufjs/aspromise" "^1.1.2" + "@protobufjs/base64" "^1.1.2" + "@protobufjs/codegen" "^2.0.4" + "@protobufjs/eventemitter" "^1.1.0" + "@protobufjs/fetch" "^1.1.0" + "@protobufjs/float" "^1.0.2" + "@protobufjs/inquire" "^1.1.0" + "@protobufjs/path" "^1.1.2" + "@protobufjs/pool" "^1.1.0" + "@protobufjs/utf8" "^1.1.0" + "@types/long" "^4.0.0" + "@types/node" "^10.1.0" + long "^4.0.0" + +"@apollographql/apollo-tools@^0.4.3": + version "0.4.4" + resolved "https://registry.yarnpkg.com/@apollographql/apollo-tools/-/apollo-tools-0.4.4.tgz#e2564c35b22536de1e4a633b2fdea219583d082c" + integrity sha512-kldvB9c+vzimel4yEktlkB08gaJ5DQn9ZuIfFf1kpAw+++5hFwYRWTyKgOhF9LbOWNWGropesYC7WwLja2erhQ== dependencies: - apollo-env "0.5.1" + apollo-env "^0.6.2" -"@apollographql/graphql-playground-html@^1.6.6": - version "1.6.19" - resolved "https://registry.yarnpkg.com/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.19.tgz#6d63dc5f3d85e939a79c78fcb905f72e592e0ecc" - integrity sha512-KMS/2kAh6KaZXN5QE5VjLoZRMY3ivSnZD/5Ua150kJKQZTMjJ/ZDlBTj5hJeJ+QAiPwcCpJgQ1lyAcxpAT5VEA== +"@apollographql/graphql-playground-html@1.6.24": + version "1.6.24" + resolved "https://registry.yarnpkg.com/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.24.tgz#3ce939cb127fb8aaa3ffc1e90dff9b8af9f2e3dc" + integrity sha512-8GqG48m1XqyXh4mIZrtB5xOhUwSsh1WsrrsaZQOEYYql3YN9DEu9OOSg0ILzXHZo/h2Q74777YE4YzlArQzQEQ== "@babel/code-frame@^7.0.0": version "7.0.0" @@ -216,14 +235,14 @@ resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA= -"@types/accepts@^1.3.5": +"@types/accepts@*", "@types/accepts@^1.3.5": version "1.3.5" resolved "https://registry.yarnpkg.com/@types/accepts/-/accepts-1.3.5.tgz#c34bec115cfc746e04fe5a059df4ce7e7b391575" integrity sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ== dependencies: "@types/node" "*" -"@types/body-parser@*", "@types/body-parser@1.17.0": +"@types/body-parser@*": version "1.17.0" resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.17.0.tgz#9f5c9d9bd04bb54be32d5eb9fc0d8c974e6cf58c" integrity sha512-a2+YeUjPkztKJu5aIF2yArYFQQp8d51wZ7DavSHjFuY1mqVgidGyzEQ41JIVNy82fXj8yPgy2vJmfIywgESW6w== @@ -231,6 +250,14 @@ "@types/connect" "*" "@types/node" "*" +"@types/body-parser@1.19.0": + version "1.19.0" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.0.tgz#0685b3c47eb3006ffed117cdd55164b61f80538f" + integrity sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ== + dependencies: + "@types/connect" "*" + "@types/node" "*" + "@types/connect@*": version "3.4.32" resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.32.tgz#aa0e9616b9435ccad02bc52b5b454ffc2c70ba28" @@ -238,6 +265,21 @@ dependencies: "@types/node" "*" +"@types/content-disposition@*": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@types/content-disposition/-/content-disposition-0.5.2.tgz#18ccb0fd126808e498a820cb8149c0072a2b9066" + integrity sha1-GMyw/RJoCOSYqCDLgUnAByorkGY= + +"@types/cookies@*": + version "0.7.4" + resolved "https://registry.yarnpkg.com/@types/cookies/-/cookies-0.7.4.tgz#26dedf791701abc0e36b5b79a5722f40e455f87b" + integrity sha512-oTGtMzZZAVuEjTwCjIh8T8FrC8n/uwy+PG0yTvQcdZ7etoel7C7/3MSd7qrukENTgQtotG7gvBlBojuVs7X5rw== + dependencies: + "@types/connect" "*" + "@types/express" "*" + "@types/keygrip" "*" + "@types/node" "*" + "@types/cors@^2.8.4": version "2.8.5" resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.5.tgz#c0c54c4e643e1d943d447292f2baf9dc82cfc8ec" @@ -258,7 +300,7 @@ "@types/node" "*" "@types/range-parser" "*" -"@types/express@*", "@types/express@4.16.1": +"@types/express@*": version "4.16.1" resolved "https://registry.yarnpkg.com/@types/express/-/express-4.16.1.tgz#d756bd1a85c34d87eaf44c888bad27ba8a4b7cf0" integrity sha512-V0clmJow23WeyblmACoxbHBu2JKlE5TiIme6Lem14FnPW9gsttyHtk6wq7njcdIWH1njAaFgR8gW09lgY98gQg== @@ -267,6 +309,62 @@ "@types/express-serve-static-core" "*" "@types/serve-static" "*" +"@types/express@4.17.2": + version "4.17.2" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.2.tgz#a0fb7a23d8855bac31bc01d5a58cadd9b2173e6c" + integrity sha512-5mHFNyavtLoJmnusB8OKJ5bshSzw+qkMIBAobLrIM48HJvunFva9mOa6aBwh64lBFyNwBbs0xiEFuj4eU/NjCA== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "*" + "@types/serve-static" "*" + +"@types/fs-capacitor@*": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@types/fs-capacitor/-/fs-capacitor-2.0.0.tgz#17113e25817f584f58100fb7a08eed288b81956e" + integrity sha512-FKVPOCFbhCvZxpVAMhdBdTfVfXUpsh15wFHgqOKxh9N9vzWZVuWCSijZ5T4U34XYNnuj2oduh6xcs1i+LPI+BQ== + dependencies: + "@types/node" "*" + +"@types/graphql-upload@^8.0.0": + version "8.0.3" + resolved "https://registry.yarnpkg.com/@types/graphql-upload/-/graphql-upload-8.0.3.tgz#b371edb5f305a2a1f7b7843a890a2a7adc55c3ec" + integrity sha512-hmLg9pCU/GmxBscg8GCr1vmSoEmbItNNxdD5YH2TJkXm//8atjwuprB+xJBK714JG1dkxbbhp5RHX+Pz1KsCMA== + dependencies: + "@types/express" "*" + "@types/fs-capacitor" "*" + "@types/koa" "*" + graphql "^14.5.3" + +"@types/http-assert@*": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@types/http-assert/-/http-assert-1.5.1.tgz#d775e93630c2469c2f980fc27e3143240335db3b" + integrity sha512-PGAK759pxyfXE78NbKxyfRcWYA/KwW17X290cNev/qAsn9eQIxkH4shoNBafH37wewhDG/0p1cHPbK6+SzZjWQ== + +"@types/keygrip@*": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/keygrip/-/keygrip-1.0.2.tgz#513abfd256d7ad0bf1ee1873606317b33b1b2a72" + integrity sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw== + +"@types/koa-compose@*": + version "3.2.5" + resolved "https://registry.yarnpkg.com/@types/koa-compose/-/koa-compose-3.2.5.tgz#85eb2e80ac50be95f37ccf8c407c09bbe3468e9d" + integrity sha512-B8nG/OoE1ORZqCkBVsup/AKcvjdgoHnfi4pZMn5UwAPCbhk/96xyv284eBYW8JlQbQ7zDmnpFr68I/40mFoIBQ== + dependencies: + "@types/koa" "*" + +"@types/koa@*": + version "2.11.3" + resolved "https://registry.yarnpkg.com/@types/koa/-/koa-2.11.3.tgz#540ece376581b12beadf9a417dd1731bc31c16ce" + integrity sha512-ABxVkrNWa4O/Jp24EYI/hRNqEVRlhB9g09p48neQp4m3xL1TJtdWk2NyNQSMCU45ejeELMQZBYyfstyVvO2H3Q== + dependencies: + "@types/accepts" "*" + "@types/content-disposition" "*" + "@types/cookies" "*" + "@types/http-assert" "*" + "@types/keygrip" "*" + "@types/koa-compose" "*" + "@types/node" "*" + "@types/long@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.0.tgz#719551d2352d301ac8b81db732acb6bdc28dbdef" @@ -277,6 +375,14 @@ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.1.tgz#dc488842312a7f075149312905b5e3c0b054c79d" integrity sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw== +"@types/node-fetch@2.5.5": + version "2.5.5" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.5.tgz#cd264e20a81f4600a6c52864d38e7fef72485e92" + integrity sha512-IWwjsyYjGw+em3xTvWVQi5MgYKbRs0du57klfTaZkv/B24AEQ/p/IopNeqIYNy3EsfHOpg8ieQSDomPcsYMHpA== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + "@types/node@*": version "12.0.3" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.0.3.tgz#5d8d24e0033fc6393efadc85cb59c1f638095c9a" @@ -353,65 +459,59 @@ anymatch@^2.0.0: micromatch "^3.1.4" normalize-path "^2.1.1" -apollo-cache-control@0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/apollo-cache-control/-/apollo-cache-control-0.6.0.tgz#df22db28f850ea90a5722f5e92654d30c96e7f91" - integrity sha512-66aCF6MHe0/FdD3knphwTv6CCIdb1ZxrMsiRpxP474qqyYVe2jAwBu6aJBn4emffZHZ7i6gp9dY6cPHThjnbKA== +apollo-cache-control@^0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/apollo-cache-control/-/apollo-cache-control-0.9.0.tgz#43d2eec16d40248683f46b9b28937a89ad3b5c54" + integrity sha512-iLT6IT4Ul5cMfBcJAvhpk3a7AD6fXqvFxNmJEPVapVJHbSKYIjra4PTis13sOyN5Y3WQS6a+NRFxAW8+hL3q3Q== dependencies: - apollo-server-env "2.3.0" - graphql-extensions "0.6.0" + apollo-server-env "^2.4.3" + graphql-extensions "^0.11.0" -apollo-datasource@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/apollo-datasource/-/apollo-datasource-0.4.0.tgz#f042641fd2593fa5f4f002fc30d1fb1a20284df8" - integrity sha512-6QkgnLYwQrW0qv+yXIf617DojJbGmza2XJXUlgnzrGGhxzfAynzEjaLyYkc8rYS1m82vjrl9EOmLHTcnVkvZAQ== - dependencies: - apollo-server-caching "0.4.0" - apollo-server-env "2.3.0" - -apollo-engine-reporting-protobuf@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/apollo-engine-reporting-protobuf/-/apollo-engine-reporting-protobuf-0.3.0.tgz#2c764c054ff9968387cf16115546e0d5b04ee9f1" - integrity sha512-PYowpx/E+TJT/8nKpp3JmJuKh3x1SZcxDF6Cquj0soV205TUpFFCZQMi91i5ACiEp2AkYvM/GDBIrw+rfIwzTg== - dependencies: - protobufjs "^6.8.6" - -apollo-engine-reporting@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/apollo-engine-reporting/-/apollo-engine-reporting-1.1.0.tgz#10def3d3bf3f11ddb24765c19d9c81e30cb9d55c" - integrity sha512-Dj0BwgcluHL0QVUaquhAoYoLX9Z4DRP/n2REcIwO8d2iy52r+1wN5QqZLx97dEFh7CjhNjTWeysJzc8XMWKa1Q== - dependencies: - apollo-engine-reporting-protobuf "0.3.0" - apollo-graphql "^0.2.1-alpha.1" - apollo-server-core "2.5.0" - apollo-server-env "2.3.0" +apollo-datasource@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/apollo-datasource/-/apollo-datasource-0.7.0.tgz#2a6d82edb2eba21b4ddf21877009ba39ff821945" + integrity sha512-Yja12BgNQhzuFGG/5Nw2MQe0hkuQy2+9er09HxeEyAf2rUDIPnhPrn1MDoZTB8MU7UGfjwITC+1ofzKkkrZobA== + dependencies: + apollo-server-caching "^0.5.1" + apollo-server-env "^2.4.3" + +apollo-engine-reporting-protobuf@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/apollo-engine-reporting-protobuf/-/apollo-engine-reporting-protobuf-0.4.4.tgz#73a064f8c9f2d6605192d1673729c66ec47d9cb7" + integrity sha512-SGrIkUR7Q/VjU8YG98xcvo340C4DaNUhg/TXOtGsMlfiJDzHwVau/Bv6zifAzBafp2lj0XND6Daj5kyT/eSI/w== + dependencies: + "@apollo/protobufjs" "^1.0.3" + +apollo-engine-reporting@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/apollo-engine-reporting/-/apollo-engine-reporting-1.7.0.tgz#34a54ef96da5cfe1dea3a4fdf02768d1cc7e154f" + integrity sha512-jsjSnoHrRmk4XXK4aFU17YSJILmWsilKRwIeN74QJsSxjn5SCVF4EI/ebf/MNrTHpft8EhShx+wdkAcOD9ivqA== + dependencies: + apollo-engine-reporting-protobuf "^0.4.4" + apollo-graphql "^0.4.0" + apollo-server-caching "^0.5.1" + apollo-server-env "^2.4.3" + apollo-server-errors "^2.4.0" + apollo-server-types "^0.3.0" async-retry "^1.2.1" - graphql-extensions "0.6.0" + graphql-extensions "^0.11.0" -apollo-env@0.4.1-register.1: - version "0.4.1-register.1" - resolved "https://registry.yarnpkg.com/apollo-env/-/apollo-env-0.4.1-register.1.tgz#e8c94e21a5b3f9c45088dec47862dfe2026111c2" - integrity sha512-fg1US7YZ6yW1N0tFq8g4HpCR3eJZmI+rIiHDiknYN9D1MTjvwYdmXYhi7VaPvQ21hV5nMRvfBUMqYXjP+6FsGQ== - dependencies: - core-js "3.0.0-beta.13" - node-fetch "^2.2.0" - sha.js "^2.4.11" - -apollo-env@0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/apollo-env/-/apollo-env-0.5.1.tgz#b9b0195c16feadf0fe9fd5563edb0b9b7d9e97d3" - integrity sha512-fndST2xojgSdH02k5hxk1cbqA9Ti8RX4YzzBoAB4oIe1Puhq7+YlhXGXfXB5Y4XN0al8dLg+5nAkyjNAR2qZTw== +apollo-env@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/apollo-env/-/apollo-env-0.6.2.tgz#7d456cf3f36e410ce5e7b5f81506efd15095aadf" + integrity sha512-Vb/doL1ZbzkNDJCQ6kYGOrphRx63rMERYo3MT2pzm2pNEdm6AK60InMgJaeh3RLK3cjGllOXFAgP8IY+m+TaEg== dependencies: + "@types/node-fetch" "2.5.5" core-js "^3.0.1" node-fetch "^2.2.0" sha.js "^2.4.11" -apollo-graphql@^0.2.1-alpha.1: - version "0.2.1-register.1" - resolved "https://registry.yarnpkg.com/apollo-graphql/-/apollo-graphql-0.2.1-register.1.tgz#941dd165a9428c2ea3407ab410f842c4050cea28" - integrity sha512-Z2LOuvYomC9CN9K+mpFVcVQu6Ml5PIJlV+YOkGzFq73xeqWg1InxHqI3eEdCEhxTJq6H8rlWT8ATrMS+4sIhqw== +apollo-graphql@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/apollo-graphql/-/apollo-graphql-0.4.1.tgz#c9470b11cf29f046f6e9b747034417c200222e91" + integrity sha512-dz2wtGeCqUDAKAj4KXLKLZiFY791aoXduul3KcLo8/6SwqWlsuZiPe0oB8mENHZZc/EchCpTMTJZX2ZENsOt2A== dependencies: - apollo-env "0.4.1-register.1" + apollo-env "^0.6.2" lodash.sortby "^4.7.0" apollo-link@^1.2.3: @@ -424,32 +524,33 @@ apollo-link@^1.2.3: tslib "^1.9.3" zen-observable-ts "^0.8.18" -apollo-server-caching@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/apollo-server-caching/-/apollo-server-caching-0.4.0.tgz#e82917590d723c0adc1fa52900e79e93ad65e4d9" - integrity sha512-GTOZdbLhrSOKYNWMYgaqX5cVNSMT0bGUTZKV8/tYlyYmsB6ey7l6iId3Q7UpHS6F6OR2lstz5XaKZ+T3fDfPzQ== +apollo-server-caching@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/apollo-server-caching/-/apollo-server-caching-0.5.1.tgz#5cd0536ad5473abb667cc82b59bc56b96fb35db6" + integrity sha512-L7LHZ3k9Ao5OSf2WStvQhxdsNVplRQi7kCAPfqf9Z3GBEnQ2uaL0EgO0hSmtVHfXTbk5CTRziMT1Pe87bXrFIw== dependencies: lru-cache "^5.0.0" -apollo-server-core@2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-2.5.0.tgz#89fc28ba1018ebf9240bc3cc0c103fe705309023" - integrity sha512-7hyQ/Rt0hC38bUfxMQmLNHDBIGEBykFWo9EO0W+3o/cno/SqBKd1KKichrABVv+v+SCvZAUutX6gYS5l3G+ULQ== +apollo-server-core@^2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-2.11.0.tgz#91a055ce6cf12a8b43e8a4811d465d97fa324eac" + integrity sha512-jHLOqwTRlyWzqWNRlwr2M/xfrt+lw2pHtKYyxUGRjWFo8EM5TX1gDcTKtbtvx9p5m+ZBDAhcWp/rpq0vSz4tqg== dependencies: - "@apollographql/apollo-tools" "^0.3.6-alpha.1" - "@apollographql/graphql-playground-html" "^1.6.6" + "@apollographql/apollo-tools" "^0.4.3" + "@apollographql/graphql-playground-html" "1.6.24" + "@types/graphql-upload" "^8.0.0" "@types/ws" "^6.0.0" - apollo-cache-control "0.6.0" - apollo-datasource "0.4.0" - apollo-engine-reporting "1.1.0" - apollo-server-caching "0.4.0" - apollo-server-env "2.3.0" - apollo-server-errors "2.3.0" - apollo-server-plugin-base "0.4.0" - apollo-tracing "0.6.0" + apollo-cache-control "^0.9.0" + apollo-datasource "^0.7.0" + apollo-engine-reporting "^1.7.0" + apollo-server-caching "^0.5.1" + apollo-server-env "^2.4.3" + apollo-server-errors "^2.4.0" + apollo-server-plugin-base "^0.7.0" + apollo-server-types "^0.3.0" + apollo-tracing "^0.9.0" fast-json-stable-stringify "^2.0.0" - graphql-extensions "0.6.0" - graphql-subscriptions "^1.0.0" + graphql-extensions "^0.11.0" graphql-tag "^2.9.2" graphql-tools "^4.0.0" graphql-upload "^8.0.2" @@ -457,60 +558,75 @@ apollo-server-core@2.5.0: subscriptions-transport-ws "^0.9.11" ws "^6.0.0" -apollo-server-env@2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/apollo-server-env/-/apollo-server-env-2.3.0.tgz#f0bf4484a6cc331a8c13763ded56e91beb16ba17" - integrity sha512-WIwlkCM/gir0CkoYWPMTCH8uGCCKB/aM074U1bKayvkFOBVO2VgG5x2kgsfkyF05IMQq2/GOTsKhNY7RnUEhTA== +apollo-server-env@^2.4.3: + version "2.4.3" + resolved "https://registry.yarnpkg.com/apollo-server-env/-/apollo-server-env-2.4.3.tgz#9bceedaae07eafb96becdfd478f8d92617d825d2" + integrity sha512-23R5Xo9OMYX0iyTu2/qT0EUb+AULCBriA9w8HDfMoChB8M+lFClqUkYtaTTHDfp6eoARLW8kDBhPOBavsvKAjA== dependencies: node-fetch "^2.1.2" util.promisify "^1.0.0" -apollo-server-errors@2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/apollo-server-errors/-/apollo-server-errors-2.3.0.tgz#700622b66a16dffcad3b017e4796749814edc061" - integrity sha512-rUvzwMo2ZQgzzPh2kcJyfbRSfVKRMhfIlhY7BzUfM4x6ZT0aijlgsf714Ll3Mbf5Fxii32kD0A/DmKsTecpccw== +apollo-server-errors@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/apollo-server-errors/-/apollo-server-errors-2.4.0.tgz#3096db02b6ae8d434a6b2678f74eddaad8b98452" + integrity sha512-ZouZfr2sGavvI18rgdRcyY2ausRAlVtWNOax9zca8ZG2io86dM59jXBmUVSNlVZSmBsIh45YxYC0eRvr2vmRdg== -apollo-server-express@2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-2.5.0.tgz#ff6cbd3fcb8933f6316c5a5edd4db12d9a56fa65" - integrity sha512-2gd3VWIqji2jyDYMTTqKzVU4/znjEjugtLUmPgVl5SoBvJSMTsO7VgJv+roBubZGDK8jXXUEXr2a33RtIeHe4g== +apollo-server-express@^2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-2.11.0.tgz#ef59a15f6f9ba8a8fb90cfa8b7c4c436be6e84c0" + integrity sha512-9bbiD+zFAx+xyurc9lxYmNa9y79k/gsA1vEyPFVcv7jxzCFC5wc0tcbV7NPX2qi1Nn7K76fxo2fPNYbPFX/y0g== dependencies: - "@apollographql/graphql-playground-html" "^1.6.6" + "@apollographql/graphql-playground-html" "1.6.24" "@types/accepts" "^1.3.5" - "@types/body-parser" "1.17.0" + "@types/body-parser" "1.19.0" "@types/cors" "^2.8.4" - "@types/express" "4.16.1" + "@types/express" "4.17.2" accepts "^1.3.5" - apollo-server-core "2.5.0" + apollo-server-core "^2.11.0" + apollo-server-types "^0.3.0" body-parser "^1.18.3" cors "^2.8.4" + express "^4.17.1" graphql-subscriptions "^1.0.0" graphql-tools "^4.0.0" + parseurl "^1.3.2" + subscriptions-transport-ws "^0.9.16" type-is "^1.6.16" -apollo-server-plugin-base@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/apollo-server-plugin-base/-/apollo-server-plugin-base-0.4.0.tgz#38a3c37767043873dd1b07143d4e70eecbb09562" - integrity sha512-iD7ARNtwnvHGd1EMPK0CuodM8d8hgDvFwTfIDzJY04QIQ6/KrBFaWhnCXJsy+HMb47GovwBbq67IK6eb2WJgBg== +apollo-server-plugin-base@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/apollo-server-plugin-base/-/apollo-server-plugin-base-0.7.0.tgz#5c52ee311c8ef884b8b17be1b7e9d4597966dae1" + integrity sha512-//xgYrBYLQSr92W0z3mYsFGoVz3wxKNsv3KcOUBhbOCGTbjZgP7vHOE1vhHhRcpZKKXmjXTVONdrnNJ+XVGi6A== + dependencies: + apollo-server-types "^0.3.0" -apollo-server@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/apollo-server/-/apollo-server-2.5.0.tgz#a88a550dbc5ff0c6713142d1cab3b61b4a36e483" - integrity sha512-85A3iAnXVP5QiXc0xvAJRyGsoxov06+8AzttKqehR4Q50UC1Is62xY5WZk58oW7fm+awpqh+sXB2F2E6tObSmg== +apollo-server-types@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/apollo-server-types/-/apollo-server-types-0.3.0.tgz#01732e5fc6c4a2a522f051d5685c57a8e3dc620e" + integrity sha512-FMo7kbTkhph9dfIQ3xDbRLObqmdQH9mwSjxhGsX+JxGMRPPXgd3+GZvCeVKOi/udxh//w1otSeAqItjvbj0tfQ== + dependencies: + apollo-engine-reporting-protobuf "^0.4.4" + apollo-server-caching "^0.5.1" + apollo-server-env "^2.4.3" + +apollo-server@^2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/apollo-server/-/apollo-server-2.11.0.tgz#f901f820716716e8693be8b0e234849f5819a4ae" + integrity sha512-UhW6RHPBMWZy1v7KhzssUnxPBxpu9fGFajtqP68vtvvP3+xa2Y2GUg0594bHcUcLK+BjdMBQQSW27i0yQ/Fz9g== dependencies: - apollo-server-core "2.5.0" - apollo-server-express "2.5.0" + apollo-server-core "^2.11.0" + apollo-server-express "^2.11.0" express "^4.0.0" graphql-subscriptions "^1.0.0" graphql-tools "^4.0.0" -apollo-tracing@0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/apollo-tracing/-/apollo-tracing-0.6.0.tgz#afc2b9cbea173dc4c315a5d98053797469518083" - integrity sha512-OpYPHVBgcQ/HT2WLXJQWwhilzR1rrl01tZeMU2N7yinsp/oyKngF5aUSMtuvX1k/T3abilQo+w10oAQlBCGdPA== +apollo-tracing@^0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/apollo-tracing/-/apollo-tracing-0.9.0.tgz#673916ae674b9a8d72603f73af0b8561dfd38306" + integrity sha512-oqspTrf4BLGbKkIk1vF+I31C2v7PPJmF36TFpT/+zJxNvJw54ji4ZMhtytgVqbVldQEintJmdHQIidYBGKmu+g== dependencies: - apollo-server-env "2.3.0" - graphql-extensions "0.6.0" + apollo-server-env "^2.4.3" + graphql-extensions "^0.11.0" apollo-utilities@^1.0.1, apollo-utilities@^1.2.1: version "1.3.0" @@ -581,6 +697,11 @@ async-retry@^1.2.1: dependencies: retry "0.12.0" +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + atob@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" @@ -787,6 +908,13 @@ color-name@1.1.3: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + commander@^2.8.1: version "2.20.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" @@ -858,11 +986,6 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= -core-js@3.0.0-beta.13: - version "3.0.0-beta.13" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.0.0-beta.13.tgz#7732c69be5e4758887917235fe7c0352c4cb42a1" - integrity sha512-16Q43c/3LT9NyePUJKL8nRIQgYWjcBhjJSMWg96PVSxoS0PeE0NHitPI3opBrs9MGGHjte1KoEVr9W63YKlTXQ== - core-js@^2.6.5: version "2.6.9" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2" @@ -967,6 +1090,11 @@ define-property@^2.0.2: is-descriptor "^1.0.2" isobject "^3.0.1" +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" @@ -1093,7 +1221,7 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -express@^4.0.0: +express@^4.0.0, express@^4.17.1: version "4.17.1" resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== @@ -1207,6 +1335,15 @@ for-in@^1.0.2: resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= +form-data@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.0.tgz#31b7e39c85f1355b7139ee0c647cf0de7f83c682" + integrity sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + forwarded@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" @@ -1332,12 +1469,19 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== -graphql-extensions@0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/graphql-extensions/-/graphql-extensions-0.6.0.tgz#3ee3aa57fe213f90aec5cd31275f6d04767c6a23" - integrity sha512-SshzmbD68fHXRv2q3St29olMOxHDLQ5e9TOh+Tz2BYxinrfhjFaPNcEefiK/vF295wW827Y58bdO11Xmhf8J+Q== +graphql-extensions@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/graphql-extensions/-/graphql-extensions-0.11.0.tgz#2923b06f7452dad186d835327974b6c3ebb9c58f" + integrity sha512-zd4qfUiJoYBx2MwJusM36SEJ+YmJ1ki8YF8nlm9mgaPDUzsnmFq4lxULxUfhLAXFwZw7MbEN2vV4V6WiNgSJLg== dependencies: - "@apollographql/apollo-tools" "^0.3.6-alpha.1" + "@apollographql/apollo-tools" "^0.4.3" + apollo-server-env "^2.4.3" + apollo-server-types "^0.3.0" + +graphql-iso-date@^3.6.1: + version "3.6.1" + resolved "https://registry.yarnpkg.com/graphql-iso-date/-/graphql-iso-date-3.6.1.tgz#bd2d0dc886e0f954cbbbc496bbf1d480b57ffa96" + integrity sha512-AwFGIuYMJQXOEAgRlJlFL4H1ncFM8n8XmoVDTNypNOZyQ8LFDG2ppMFlsS862BSTCDcSUfHp8PD3/uJhv7t59Q== graphql-relay@^0.6.0: version "0.6.0" @@ -1379,10 +1523,10 @@ graphql-upload@^8.0.2: http-errors "^1.7.2" object-path "^0.11.4" -graphql@^14.3.1: - version "14.3.1" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.3.1.tgz#b3aa50e61a841ada3c1f9ccda101c483f8e8c807" - integrity sha512-FZm7kAa3FqKdXy8YSSpAoTtyDFMIYSpCDOr+3EqlI1bxmtHu+Vv/I2vrSeT1sBOEnEniX3uo4wFhFdS/8XN6gA== +graphql@^14.5.3, graphql@^14.6.0: + version "14.6.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.6.0.tgz#57822297111e874ea12f5cd4419616930cd83e49" + integrity sha512-VKzfvHEKybTKjQVpTFrA5yUq2S9ihcZvfJAtsDBBCuV6wauPu1xl/f9ehgVf0FcEJJs4vz6ysb/ZMkGigQZseg== dependencies: iterall "^1.2.2" @@ -1884,6 +2028,18 @@ mime-db@1.40.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32" integrity sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA== +mime-db@1.43.0: + version "1.43.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58" + integrity sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ== + +mime-types@^2.1.12: + version "2.1.26" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.26.tgz#9c921fc09b7e149a65dfdc0da4d20997200b0a06" + integrity sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ== + dependencies: + mime-db "1.43.0" + mime-types@~2.1.24: version "2.1.24" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.24.tgz#b6f8d0b3e951efb77dedeca194cff6d16f676f81" @@ -2218,7 +2374,7 @@ parse-passwd@^1.0.0: resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= -parseurl@~1.3.3: +parseurl@^1.3.2, parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== @@ -2307,25 +2463,6 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== -protobufjs@^6.8.6: - version "6.8.8" - resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.8.8.tgz#c8b4f1282fd7a90e6f5b109ed11c84af82908e7c" - integrity sha512-AAmHtD5pXgZfi7GMpllpO3q1Xw1OYldr+dMUlAnffGTAhqkg72WdmSY71uKBF/JuyiKs8psYbtKrhi0ASCD8qw== - dependencies: - "@protobufjs/aspromise" "^1.1.2" - "@protobufjs/base64" "^1.1.2" - "@protobufjs/codegen" "^2.0.4" - "@protobufjs/eventemitter" "^1.1.0" - "@protobufjs/fetch" "^1.1.0" - "@protobufjs/float" "^1.0.2" - "@protobufjs/inquire" "^1.1.0" - "@protobufjs/path" "^1.1.2" - "@protobufjs/pool" "^1.1.0" - "@protobufjs/utf8" "^1.1.0" - "@types/long" "^4.0.0" - "@types/node" "^10.1.0" - long "^4.0.0" - proxy-addr@~2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.5.tgz#34cbd64a2d81f4b1fd21e76f9f06c8a45299ee34" @@ -2723,7 +2860,7 @@ strip-json-comments@~2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= -subscriptions-transport-ws@^0.9.11: +subscriptions-transport-ws@^0.9.11, subscriptions-transport-ws@^0.9.16: version "0.9.16" resolved "https://registry.yarnpkg.com/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.16.tgz#90a422f0771d9c32069294c08608af2d47f596ec" integrity sha512-pQdoU7nC+EpStXnCfh/+ho0zE0Z+ma+i7xvj7bkXKb1dvYHSZxgRPaU6spRP+Bjzow67c/rRDoix5RT0uU9omw== From 1297d5cd58f8ec7e7bdccf9e842484ac7d5c9e6e Mon Sep 17 00:00:00 2001 From: alexlbr Date: Sun, 29 Mar 2020 23:05:37 +0100 Subject: [PATCH 05/16] fixes typos readme --- README.md | 19 ++++++++++--------- src/index.js | 38 -------------------------------------- 2 files changed, 10 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index 53d4e8d..f08139f 100644 --- a/README.md +++ b/README.md @@ -21,16 +21,17 @@ This exercise is part of the [React GraphQL Academy](http://reactgraphql.academy ### To get started -We are going to create our own GraphQL API on top of this [REST API](https://mockedrestapi.reactgraphql.academy/) +We are going to create our own GraphQL API on top of this [REST API](https://restapi.reactgraphql.academy/v1/trainings) - `git clone https://github.com/reactgraphqlacademy/graphql-api-training.git` - `cd graphql-api-training` +- `git checkout fundamentals-v2` - `yarn install` or `npm install` - `yarn start` or `npm start` ### Before we start -- Clone the repo, git checkout the `fundamentals` branch, install the dependencies and let me walk you through the code meanwhile. +- Don't forget to checkout the `fundamentals` branch, install the dependencies, and let me walk you through the code meanwhile. - We use nodemon in the `start` script, so every time you save the server will restart automatically. - The `src/index.js` is the [getting started tutorial](https://www.apollographql.com/docs/apollo-server/getting-started/) from Apollo. - Let's replace the schema: @@ -55,8 +56,8 @@ What do we need to change so the field avocados returns the array of books when ⚠️ Some info before you start the tasks: 1- You can define an array using square brackets and the type, example `[Book]` -2- You can use the type `ID` for ids. -3- In GraphQL types are nullable by default. If you want to make a type non-nullable use `!` (excalmation mark). Example: +2- You can use the scalar type `ID` for ids. +3- In GraphQL types are nullable by default. If you want to make a type non-nullable use `!` (exclamation mark). Example: ```graphql type Book { @@ -74,8 +75,8 @@ To complete the tasks you'll use the mock data and helper functions that are at - [ ] 2. Create a `Discount` type in your schema. Define only the fields `code`, `id`, and `discountPercentage`. Have a look at the discount mock data in `src/index.js` to identify the types of each field. - - [ ] 2.1. Add an `discounts` field to the `Query` type. The `discounts` field should return an array of discounts. - - [ ] 2.2. Add an `discounts` resolver to the Query's resolvers. You can return the mock discounts array (which is in the scope and defined at the bottom of the file index.js) in the resolver function. + - [ ] 2.1. Add a `discounts` field to the `Query` type. The `discounts` field should return an array of discounts. + - [ ] 2.2. Add a `discounts` resolver to the Query's resolvers. You can return the mock discounts array (which is in the scope and defined at the bottom of the file index.js) in the resolver function. - [ ] 2.3 You should be able to manually test the `discounts` query in Playground at [http://localhost:4000/](http://localhost:4000/) - [ ] 3. Replace the mock data with real data using the following endpoints: @@ -88,7 +89,7 @@ Hint. You can use the `fetchTrainings` and `fetchDiscounts` defined at the botto - Query discounts - Query trainings -Note on mocking. In the next session we'll use the automocking feature of Apollo Server. The only thing you need to do is `mocks:true` in your Apollo Server configuration. More info [here](https://www.apollographql.com/docs/apollo-server/testing/mocking/). +Note on mocking. In the next session, we'll use the automocking feature of Apollo Server. The only thing you need to do is `mocks:true` in your Apollo Server configuration. More info [here](https://www.apollographql.com/docs/apollo-server/testing/mocking/). ```js const server = new ApolloServer({ @@ -200,7 +201,7 @@ query getTraining { } ``` -- [ ] 5. Create the following relationship between the Training type and the Discount type in your schema. +- [ ] 5. Create the following relationship between the Training type and the Discount type in your schema: ```graphql type Training { @@ -209,7 +210,7 @@ type Training { } ``` -- You need to add a `Training` key in the resolvers object and an object with an `discounts` key in `Training`. Similar to the Author type and books field in the [Apollo documentation](https://www.apollographql.com/docs/apollo-server/essentials/data#resolver-map) +- You need to add a `Training` key in the resolvers object and an object with a `discounts` key in `Training`. Similar to the Author type and books field in the [Apollo documentation](https://www.apollographql.com/docs/apollo-server/essentials/data#resolver-map) - You need to use the **first argument of the resolver**: the 'parent'. In this case, the parent of the `discounts` field is the `Training`. `parent.discounts` gives you the array of URLs that you can use to fetch each discount from the REST API. - You can use the helper function `fetchDiscountByUrl` defined at the bottom of this file `src/index.js`. - Heads up! We want our Training type to have a field called `discounts` that returns an array of `Discount` types not an array of `String` diff --git a/src/index.js b/src/index.js index 9284212..88c8556 100644 --- a/src/index.js +++ b/src/index.js @@ -2,44 +2,6 @@ const fetch = require("node-fetch"); const { ApolloServer, gql } = require("apollo-server"); const { GraphQLDateTime } = require("graphql-iso-date"); -const trainingMockData = [ - { - id: "tra:1", - title: "React Fundamentals", - objectives: "learning basics of react", - curriculum: - "-Thinking in React, Modern JavaScript, Routing & Data Fetching\n-Forms, Authentication, and Hooks\n-Redux Fundamentals, deployment to production" - }, - { - id: "tra:2", - title: "Advanced React", - objectives: "master react", - curriculum: - "-Advanced React patterns and performance.\n-GraphQL 101 & Real-World Testing in React.\n-Building a UI component library" - } -]; - -const discountMockData = [ - { - id: "dis:1", - code: "sweetpotato60", - discountPercentage: 60, - description: null - }, - { - id: "dis:2", - code: "garlic20", - discountPercentage: 20, - description: null - }, - { - id: "dis:3", - code: "onion50", - discountPercentage: 50, - description: null - } -]; - const typeDefs = gql` type Training { id: ID! From 3522aedeb8a041656e0d43949f58e494e72df94c Mon Sep 17 00:00:00 2001 From: alexlbr Date: Mon, 30 Mar 2020 09:12:38 +0100 Subject: [PATCH 06/16] update fetch helper functions --- src/index.js | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/index.js b/src/index.js index 88c8556..9fc4154 100644 --- a/src/index.js +++ b/src/index.js @@ -49,31 +49,33 @@ const resolvers = { function fetchTrainings() { // More info about the fetch function? https://github.com/bitinn/node-fetch#json - return fetch("https://restapi.reactgraphql.academy/v1/trainings/").then(res => - res.json() - ); + return fetch("https://restapi.reactgraphql.academy/v1/trainings/") + .then(res => res.json()) + .catch(error => console.log(error)); } function fetchTrainingById(id) { - return fetch( - `https://restapi.reactgraphql.academy/v1/trainings/${id}` - ).then(res => res.json()); + return fetch(`https://restapi.reactgraphql.academy/v1/trainings/${id}`) + .then(res => res.json()) + .catch(error => console.log(error)); } function fetchDiscounts() { - return fetch("https://restapi.reactgraphql.academy/v1/discounts/").then(res => - res.json() - ); + return fetch("https://restapi.reactgraphql.academy/v1/discounts/") + .then(res => res.json()) + .catch(error => console.log(error)); } function fetchTrainingByUrl(url) { - return fetch(url).then(res => res.json()); + return fetch(url) + .then(res => res.json()) + .catch(error => console.log(error)); } function fetchDiscountById(id) { - return fetch( - `https://restapi.reactgraphql.academy/v1/discounts/${id}` - ).then(res => res.json()); + return fetch(`https://restapi.reactgraphql.academy/v1/discounts/${id}`) + .then(res => res.json()) + .catch(error => console.log(error)); } function fetchDiscountByUrl(url) { From 1c73d41f5cf4b9fbf70af18149bc91362a429833 Mon Sep 17 00:00:00 2001 From: alexlbr Date: Mon, 30 Mar 2020 09:14:18 +0100 Subject: [PATCH 07/16] update fetch helper functions --- src/index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index 9fc4154..ccc7810 100644 --- a/src/index.js +++ b/src/index.js @@ -79,7 +79,9 @@ function fetchDiscountById(id) { } function fetchDiscountByUrl(url) { - return fetch(url).then(res => res.json()); + return fetch(url) + .then(res => res.json()) + .catch(error => console.log(error)); } // In the most basic sense, the ApolloServer can be started From a43fb286460ea320f67e498a0580c2ca9a387d9e Mon Sep 17 00:00:00 2001 From: alexlbr Date: Tue, 31 Mar 2020 00:38:19 +0100 Subject: [PATCH 08/16] add cloud function --- .firebaserc | 5 + README.md | 10 +- firebase.json | 13 + index-dev.js | 9 + index.js | 7 + package.json | 10 +- src/{index.js => server.js} | 45 +- yarn.lock | 1098 ++++++++++++++++++++++++++++++++++- 8 files changed, 1162 insertions(+), 35 deletions(-) create mode 100644 .firebaserc create mode 100644 firebase.json create mode 100644 index-dev.js create mode 100644 index.js rename src/{index.js => server.js} (69%) diff --git a/.firebaserc b/.firebaserc new file mode 100644 index 0000000..f36caa4 --- /dev/null +++ b/.firebaserc @@ -0,0 +1,5 @@ +{ + "projects": { + "default": "rga-mocked-apis" + } +} diff --git a/README.md b/README.md index f08139f..c919507 100644 --- a/README.md +++ b/README.md @@ -10,11 +10,11 @@ This exercise is part of the [React GraphQL Academy](http://reactgraphql.academy ## Exercise part 1 -[](TODO DEPLOY URL) +Given the following [GraphQL API](https://us-central1-rga-mocked-apis.cloudfunctions.net/graphql) / https://api.reactgraphql.academy/graphql: -- Query a list with all the training titles -- Query how many training are in the system? -- Query a single training by id (try id equals TODO ADD ONE????????) and get its name +- Query a list with all the training and retrieve the title and language for each +- Query a single discount by id (try id equals `dis:422`) and get its name +- Query how many languages are in the system? - How many types do we have in the system? ## Exercise part 2 @@ -248,6 +248,8 @@ query getDangerousDiscount { Once implemented, do you see any problems/ vulnerability issues on that query? +🤸🏾Do you want some extra workout? Create an [enumeration](https://graphql.org/learn/schema/#enumeration-types) for the languages. Add field language to the Training object type that uses the language enum. + ## Homework You are going to build a GraphQL API on top of an existing REST API. Steps: diff --git a/firebase.json b/firebase.json new file mode 100644 index 0000000..7680f86 --- /dev/null +++ b/firebase.json @@ -0,0 +1,13 @@ +{ + "functions": { + "source": "." + }, + "hosting": { + "rewrites": [ + { + "source": "/graphql", + "function": "graphql" + } + ] + } +} diff --git a/index-dev.js b/index-dev.js new file mode 100644 index 0000000..29a77ac --- /dev/null +++ b/index-dev.js @@ -0,0 +1,9 @@ +const { createServer } = require("./src/server"); + +const server = createServer({ playground: true, introspection: true }).listen( + 4000, + () => { + const { address, port } = server.address(); + console.log(`🚀 Server ready at ${address}:${port}`); + } +); diff --git a/index.js b/index.js new file mode 100644 index 0000000..f4c8278 --- /dev/null +++ b/index.js @@ -0,0 +1,7 @@ +const functions = require("firebase-functions"); +const { createServer } = require("./src/server"); + +// Set up the server and export it for the GCF API (it requires an endpoint to be exported; in this case, 'api') +exports.graphql = functions.https.onRequest( + createServer({ playground: true, introspection: true }) +); diff --git a/package.json b/package.json index 1a87e64..6d20ee0 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,8 @@ "version": "1.0.0", "description": "", "scripts": { - "start": "node_modules/.bin/nodemon src/index.js", + "start": "node_modules/.bin/nodemon index-dev.js", + "deploy": "firebase deploy --only functions", "start-babel": "node_modules/.bin/nodemon -- node_modules/.bin/babel-node src/index.js", "test": "echo \"Error: no test specified\" && exit 1" }, @@ -19,6 +20,10 @@ "homepage": "https://github.com/reactgraphqlacademy/rest-to-graphql-workshop#readme", "dependencies": { "apollo-server": "^2.11.0", + "apollo-server-express": "^2.11.0", + "express": "^4.17.1", + "firebase-admin": "^8.10.0", + "firebase-functions": "^3.5.0", "graphql": "^14.6.0", "graphql-iso-date": "^3.6.1", "graphql-relay": "^0.6.0", @@ -28,5 +33,8 @@ "@babel/core": "^7.4.5", "@babel/node": "^7.4.5", "nodemon": "^1.19.1" + }, + "engines": { + "node": "8" } } diff --git a/src/index.js b/src/server.js similarity index 69% rename from src/index.js rename to src/server.js index ccc7810..358065a 100644 --- a/src/index.js +++ b/src/server.js @@ -1,5 +1,6 @@ +const express = require("express"); const fetch = require("node-fetch"); -const { ApolloServer, gql } = require("apollo-server"); +const { ApolloServer, gql } = require("apollo-server-express"); const { GraphQLDateTime } = require("graphql-iso-date"); const typeDefs = gql` @@ -11,6 +12,7 @@ const typeDefs = gql` overview: String discounts: [Discount] startDate: DateTime + language: Language } type Discount { @@ -23,6 +25,19 @@ const typeDefs = gql` scalar DateTime + enum Language { + EN + ES + FR + IT + PT + NL + DE + ZH + JA + RU + } + type Query { trainings: [Training!] training(id: ID!): Training @@ -49,19 +64,19 @@ const resolvers = { function fetchTrainings() { // More info about the fetch function? https://github.com/bitinn/node-fetch#json - return fetch("https://restapi.reactgraphql.academy/v1/trainings/") + return fetch("https://api.reactgraphql.academy/api/rest/trainings/") .then(res => res.json()) .catch(error => console.log(error)); } function fetchTrainingById(id) { - return fetch(`https://restapi.reactgraphql.academy/v1/trainings/${id}`) + return fetch(`https://api.reactgraphql.academy/api/rest/trainings/${id}`) .then(res => res.json()) .catch(error => console.log(error)); } function fetchDiscounts() { - return fetch("https://restapi.reactgraphql.academy/v1/discounts/") + return fetch("https://api.reactgraphql.academy/api/rest/discounts/") .then(res => res.json()) .catch(error => console.log(error)); } @@ -73,7 +88,7 @@ function fetchTrainingByUrl(url) { } function fetchDiscountById(id) { - return fetch(`https://restapi.reactgraphql.academy/v1/discounts/${id}`) + return fetch(`https://api.reactgraphql.academy/api/rest/discounts/${id}`) .then(res => res.json()) .catch(error => console.log(error)); } @@ -84,13 +99,15 @@ function fetchDiscountByUrl(url) { .catch(error => console.log(error)); } -// In the most basic sense, the ApolloServer can be started -// by passing type definitions (typeDefs) and the resolvers -// responsible for fetching the data for those types. -const server = new ApolloServer({ typeDefs, resolvers }); +module.exports = { + createServer: options => { + const app = express(); + const apollo = new ApolloServer({ typeDefs, resolvers, ...options }); + apollo.applyMiddleware({ + app, + path: `/` + }); -// This `listen` method launches a web-server. Existing apps -// can utilize middleware options, which we'll discuss later. -server.listen().then(({ url }) => { - console.log(`🚀 Server ready at ${url}`); -}); + return app; + } +}; diff --git a/yarn.lock b/yarn.lock index 0dbed5f..c2cdbe2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -182,6 +182,143 @@ lodash "^4.17.11" to-fast-properties "^2.0.0" +"@firebase/app-types@0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@firebase/app-types/-/app-types-0.6.0.tgz#8dcc3e793c6983e9d54f7eb623a7618c05f2d94c" + integrity sha512-ld6rzjXk/SUauHiQZJkeuSJpxIZ5wdnWuF5fWBFQNPaxsaJ9kyYg9GqEvwZ1z2e6JP5cU9gwRBlfW1WkGtGDYA== + +"@firebase/auth-interop-types@0.1.4": + version "0.1.4" + resolved "https://registry.yarnpkg.com/@firebase/auth-interop-types/-/auth-interop-types-0.1.4.tgz#e81589f58508630a5bffa604d7c949a0d01ea97b" + integrity sha512-CLKNS84KGAv5lRnHTQZFWoR11Ti7gIPFirDDXWek/fSU+TdYdnxJFR5XSD4OuGyzUYQ3Dq7aVj5teiRdyBl9hA== + +"@firebase/component@0.1.8": + version "0.1.8" + resolved "https://registry.yarnpkg.com/@firebase/component/-/component-0.1.8.tgz#3a5753493ba65c85c9c09e2707be44d73e0a456c" + integrity sha512-kzuCF+NVympQk3gcsHldOmDRVPVndECi6O9Wvd47HTEQYO9HsZWfOM1fHUvvHAijSzNi16p4NSM7UziuBQBL4w== + dependencies: + "@firebase/util" "0.2.43" + tslib "1.11.1" + +"@firebase/database-types@0.4.14": + version "0.4.14" + resolved "https://registry.yarnpkg.com/@firebase/database-types/-/database-types-0.4.14.tgz#181e10c1d1ae64fd0a080f6e0369cec115c51d70" + integrity sha512-+D41HWac0HcvwMi+0dezEdSOZHpVjPKPNmpQiW2GDuS5kk27/v1jxc9v7F4ALLtpxbVcn16UZl5PqEkcS9H2Xg== + dependencies: + "@firebase/app-types" "0.6.0" + +"@firebase/database@^0.5.17": + version "0.5.24" + resolved "https://registry.yarnpkg.com/@firebase/database/-/database-0.5.24.tgz#548b2030def35a7b6f4d71a4b2d1a67499d1eef3" + integrity sha512-9whAQzU8cxDUKGBWCT/aHVmqfyzCP2RkGhbZi2oHpMrmvht7cuBtXtUbDD5R8WomniCOUP8rtQfmCFI7V9ehYw== + dependencies: + "@firebase/auth-interop-types" "0.1.4" + "@firebase/component" "0.1.8" + "@firebase/database-types" "0.4.14" + "@firebase/logger" "0.2.0" + "@firebase/util" "0.2.43" + faye-websocket "0.11.3" + tslib "1.11.1" + +"@firebase/logger@0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@firebase/logger/-/logger-0.2.0.tgz#d40149b8a33bca3dfbfb5b4a63e06b3ffa193157" + integrity sha512-qOMnAh1JY9NkYUEy3iFviiFq0dCvk6qN2DsRy2Y7eAhHR6RqwA47l1kI+0MIXmSzlJ9akXjWAXxV5ijzr68Big== + +"@firebase/util@0.2.43": + version "0.2.43" + resolved "https://registry.yarnpkg.com/@firebase/util/-/util-0.2.43.tgz#551728e1f6deb3a3709c2e9dc60dbb7c1a423fd4" + integrity sha512-4gGlvcoOJ48xO6PH59UOHLjvImdYXANF/1d0ao60fbiJDIKxJqMksXw3UF2zsUrRkyCOqIDLeiVuF18vffXP+g== + dependencies: + tslib "1.11.1" + +"@google-cloud/common@^2.1.1": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@google-cloud/common/-/common-2.4.0.tgz#2783b7de8435024a31453510f2dab5a6a91a4c82" + integrity sha512-zWFjBS35eI9leAHhjfeOYlK5Plcuj/77EzstnrJIZbKgF/nkqjcQuGiMCpzCwOfPyUbz8ZaEOYgbHa759AKbjg== + dependencies: + "@google-cloud/projectify" "^1.0.0" + "@google-cloud/promisify" "^1.0.0" + arrify "^2.0.0" + duplexify "^3.6.0" + ent "^2.2.0" + extend "^3.0.2" + google-auth-library "^5.5.0" + retry-request "^4.0.0" + teeny-request "^6.0.0" + +"@google-cloud/firestore@^3.0.0": + version "3.7.2" + resolved "https://registry.yarnpkg.com/@google-cloud/firestore/-/firestore-3.7.2.tgz#e5a55bd765b291ce38376b8fb699212fae8770ba" + integrity sha512-oMqJhrsZzPyY0DDgkvJLt90x6bgmUbXOLTNcAVtF6mPdiOp0L6nA3NSx4KYNYEPLNynG6yl9JsRIaJcZm77flw== + dependencies: + deep-equal "^2.0.0" + functional-red-black-tree "^1.0.1" + google-gax "^1.13.0" + readable-stream "^3.4.0" + through2 "^3.0.0" + +"@google-cloud/paginator@^2.0.0": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@google-cloud/paginator/-/paginator-2.0.3.tgz#c7987ad05d1c3ebcef554381be80e9e8da4e4882" + integrity sha512-kp/pkb2p/p0d8/SKUu4mOq8+HGwF8NPzHWkj+VKrIPQPyMRw8deZtrO/OcSiy9C/7bpfU5Txah5ltUNfPkgEXg== + dependencies: + arrify "^2.0.0" + extend "^3.0.2" + +"@google-cloud/projectify@^1.0.0": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@google-cloud/projectify/-/projectify-1.0.4.tgz#28daabebba6579ed998edcadf1a8f3be17f3b5f0" + integrity sha512-ZdzQUN02eRsmTKfBj9FDL0KNDIFNjBn/d6tHQmA/+FImH5DO6ZV8E7FzxMgAUiVAUq41RFAkb25p1oHOZ8psfg== + +"@google-cloud/promisify@^1.0.0": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@google-cloud/promisify/-/promisify-1.0.4.tgz#ce86ffa94f9cfafa2e68f7b3e4a7fad194189723" + integrity sha512-VccZDcOql77obTnFh0TbNED/6ZbbmHDf8UMNnzO1d5g9V0Htfm4k5cllY8P1tJsRKC3zWYGRLaViiupcgVjBoQ== + +"@google-cloud/storage@^4.1.2": + version "4.7.0" + resolved "https://registry.yarnpkg.com/@google-cloud/storage/-/storage-4.7.0.tgz#a7466086a83911c7979cc238d00a127ffb645615" + integrity sha512-f0guAlbeg7Z0m3gKjCfBCu7FG9qS3M3oL5OQQxlvGoPtK7/qg3+W+KQV73O2/sbuS54n0Kh2mvT5K2FWzF5vVQ== + dependencies: + "@google-cloud/common" "^2.1.1" + "@google-cloud/paginator" "^2.0.0" + "@google-cloud/promisify" "^1.0.0" + arrify "^2.0.0" + compressible "^2.0.12" + concat-stream "^2.0.0" + date-and-time "^0.13.0" + duplexify "^3.5.0" + extend "^3.0.2" + gaxios "^3.0.0" + gcs-resumable-upload "^2.2.4" + hash-stream-validation "^0.2.2" + mime "^2.2.0" + mime-types "^2.0.8" + onetime "^5.1.0" + p-limit "^2.2.0" + pumpify "^2.0.0" + readable-stream "^3.4.0" + snakeize "^0.1.0" + stream-events "^1.0.1" + through2 "^3.0.0" + xdg-basedir "^4.0.0" + +"@grpc/grpc-js@^0.6.18": + version "0.6.18" + resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-0.6.18.tgz#ba3b3dfef869533161d192a385412a4abd0db127" + integrity sha512-uAzv/tM8qpbf1vpx1xPMfcUMzbfdqJtdCYAqY/LsLeQQlnTb4vApylojr+wlCyr7bZeg3AFfHvtihnNOQQt/nA== + dependencies: + semver "^6.2.0" + +"@grpc/proto-loader@^0.5.1": + version "0.5.3" + resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.5.3.tgz#a233070720bf7560c4d70e29e7950c72549a132c" + integrity sha512-8qvUtGg77G2ZT2HqdqYoM/OY97gQd/0crSG34xNmZ4ZOsv3aQT/FQV9QfZPazTGna6MIoyUd+u6AxsoZjJ/VMQ== + dependencies: + lodash.camelcase "^4.3.0" + protobufjs "^6.8.6" + "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" @@ -235,6 +372,11 @@ resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA= +"@tootallnate/once@1": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.0.0.tgz#9c13c2574c92d4503b005feca8f2e16cc1611506" + integrity sha512-KYyTT/T6ALPkIRd2Ge080X/BsXvy9O0hcWTtMWkPvwAwF99+vn6Dv4GzrFT/Nn1LePr+FFDbRXXlqmsy9lw2zA== + "@types/accepts@*", "@types/accepts@^1.3.5": version "1.3.5" resolved "https://registry.yarnpkg.com/@types/accepts/-/accepts-1.3.5.tgz#c34bec115cfc746e04fe5a059df4ce7e7b391575" @@ -318,6 +460,15 @@ "@types/express-serve-static-core" "*" "@types/serve-static" "*" +"@types/express@^4.17.3": + version "4.17.3" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.3.tgz#38e4458ce2067873b09a73908df488870c303bd9" + integrity sha512-I8cGRJj3pyOLs/HndoP+25vOqhqWkAZsWMEmq1qXy/b/M3ppufecUwaK2/TVDVxcV61/iSdhykUjQQ2DLSrTdg== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "*" + "@types/serve-static" "*" + "@types/fs-capacitor@*": version "2.0.0" resolved "https://registry.yarnpkg.com/@types/fs-capacitor/-/fs-capacitor-2.0.0.tgz#17113e25817f584f58100fb7a08eed288b81956e" @@ -325,6 +476,13 @@ dependencies: "@types/node" "*" +"@types/fs-extra@^8.0.1": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-8.1.0.tgz#1114834b53c3914806cd03b3304b37b3bd221a4d" + integrity sha512-UoOfVEzAUpeSPmjm7h1uk5MH6KZma2z2O7a75onTGjnNvAvMVrPzPL/vBbT65iIGHWj6rokwfmYcmxmlSf2uwg== + dependencies: + "@types/node" "*" + "@types/graphql-upload@^8.0.0": version "8.0.3" resolved "https://registry.yarnpkg.com/@types/graphql-upload/-/graphql-upload-8.0.3.tgz#b371edb5f305a2a1f7b7843a890a2a7adc55c3ec" @@ -393,6 +551,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.7.tgz#1854f0a9aa8d2cd6818d607b3d091346c6730362" integrity sha512-on4MmIDgHXiuJDELPk1NFaKVUxxCFr37tm8E9yN6rAiF5Pzp/9bBfBHkoexqRiY+hk/Z04EJU9kKEb59YqJ82A== +"@types/node@^8.10.59": + version "8.10.59" + resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.59.tgz#9e34261f30183f9777017a13d185dfac6b899e04" + integrity sha512-8RkBivJrDCyPpBXhVZcjh7cQxVBSmRk9QM7hOketZzp6Tg79c0N8kkpAIito9bnJ3HCVCHVYz+KHTEbfQNfeVQ== + "@types/range-parser@*": version "1.2.3" resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c" @@ -419,6 +582,13 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + accepts@^1.3.5, accepts@~1.3.7: version "1.3.7" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" @@ -427,6 +597,13 @@ accepts@^1.3.5, accepts@~1.3.7: mime-types "~2.1.24" negotiator "0.6.2" +agent-base@6: + version "6.0.0" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.0.tgz#5d0101f19bbfaed39980b22ae866de153b93f09a" + integrity sha512-j1Q7cSCqN+AwrmDd+pzgqc0/NpC655x2bUf5ZjRIO77DcNBFmh+OgRNzF6OKdCC9RSCb19fGd99+bhXFdkRNqw== + dependencies: + debug "4" + ansi-align@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f" @@ -675,6 +852,11 @@ array-unique@^0.3.2: resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= +arrify@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" + integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== + assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" @@ -717,6 +899,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= +base64-js@^1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" + integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== + base@^0.11.1: version "0.11.2" resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" @@ -730,6 +917,11 @@ base@^0.11.1: mixin-deep "^1.2.0" pascalcase "^0.1.1" +bignumber.js@^7.0.0: + version "7.2.1" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-7.2.1.tgz#80c048759d826800807c4bfd521e50edbba57a5f" + integrity sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ== + binary-extensions@^1.0.0: version "1.13.1" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" @@ -788,6 +980,11 @@ braces@^2.3.1, braces@^2.3.2: split-string "^3.0.2" to-regex "^3.0.1" +buffer-equal-constant-time@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" + integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk= + buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" @@ -930,11 +1127,28 @@ component-emitter@^1.2.1: resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== +compressible@^2.0.12: + version "2.0.18" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" + integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== + dependencies: + mime-db ">= 1.43.0 < 2" + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= +concat-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-2.0.0.tgz#414cf5af790a48c60ab9be4527d56d5e41133cb1" + integrity sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^3.0.2" + typedarray "^0.0.6" + configstore@^3.0.0: version "3.1.2" resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.2.tgz#c6f25defaeef26df12dd33414b001fe81a543f8f" @@ -947,6 +1161,18 @@ configstore@^3.0.0: write-file-atomic "^2.0.0" xdg-basedir "^3.0.0" +configstore@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96" + integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA== + dependencies: + dot-prop "^5.2.0" + graceful-fs "^4.1.2" + make-dir "^3.0.0" + unique-string "^2.0.0" + write-file-atomic "^3.0.0" + xdg-basedir "^4.0.0" + console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" @@ -1001,7 +1227,7 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= -cors@^2.8.4: +cors@^2.8.4, cors@^2.8.5: version "2.8.5" resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== @@ -1030,6 +1256,16 @@ crypto-random-string@^1.0.0: resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" integrity sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4= +crypto-random-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" + integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== + +date-and-time@^0.13.0: + version "0.13.1" + resolved "https://registry.yarnpkg.com/date-and-time/-/date-and-time-0.13.1.tgz#d12ba07ac840d5b112dc4c83f8a03e8a51f78dd6" + integrity sha512-/Uge9DJAT+s+oAcDxtBhyR8+sKjUnZbYmyhbmWjTHNtX7B7oWD8YyYdeXcBRbwSj6hVvj+IQegJam7m7czhbFw== + debug@2.6.9, debug@^2.2.0, debug@^2.3.3: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -1037,6 +1273,13 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3: dependencies: ms "2.0.0" +debug@4, debug@^4.1.0, debug@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + dependencies: + ms "^2.1.1" + debug@^3.1.0, debug@^3.2.6: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" @@ -1044,24 +1287,35 @@ debug@^3.1.0, debug@^3.2.6: dependencies: ms "^2.1.1" -debug@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== - dependencies: - ms "^2.1.1" - decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= +deep-equal@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.0.1.tgz#fc12bbd6850e93212f21344748682ccc5a8813cf" + integrity sha512-7Et6r6XfNW61CPPCIYfm1YPGSmh6+CliYeL4km7GWJcpX5LTAflGF8drLLR+MZX+2P3NZfAfSduutBbSWqER4g== + dependencies: + es-abstract "^1.16.3" + es-get-iterator "^1.0.1" + is-arguments "^1.0.4" + is-date-object "^1.0.1" + is-regex "^1.0.4" + isarray "^2.0.5" + object-is "^1.0.1" + object-keys "^1.1.1" + regexp.prototype.flags "^1.2.0" + side-channel "^1.0.1" + which-boxed-primitive "^1.0.1" + which-collection "^1.0.0" + deep-extend@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== -define-properties@^1.1.2: +define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== @@ -1120,7 +1374,7 @@ detect-libc@^1.0.2: resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= -dicer@0.3.0: +dicer@0.3.0, dicer@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/dicer/-/dicer-0.3.0.tgz#eacd98b3bfbf92e8ab5c2fdb71aaac44bb06b872" integrity sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA== @@ -1134,11 +1388,45 @@ dot-prop@^4.1.0: dependencies: is-obj "^1.0.0" +dot-prop@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.2.0.tgz#c34ecc29556dc45f1f4c22697b6f4904e0cc4fcb" + integrity sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A== + dependencies: + is-obj "^2.0.0" + duplexer3@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= +duplexify@^3.5.0, duplexify@^3.6.0: + version "3.7.1" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" + integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== + dependencies: + end-of-stream "^1.0.0" + inherits "^2.0.1" + readable-stream "^2.0.0" + stream-shift "^1.0.0" + +duplexify@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.1.tgz#7027dc374f157b122a8ae08c2d3ea4d2d953aa61" + integrity sha512-DY3xVEmVHTv1wSzKNbwoU6nVjzI369Y6sPoqfYr0/xlx3IdX2n94xIszTcjPO8W8ZIv0Wb0PXNcjuZyT4wiICA== + dependencies: + end-of-stream "^1.4.1" + inherits "^2.0.3" + readable-stream "^3.1.1" + stream-shift "^1.0.0" + +ecdsa-sig-formatter@1.0.11, ecdsa-sig-formatter@^1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" + integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== + dependencies: + safe-buffer "^5.0.1" + ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -1149,6 +1437,35 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= +end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +ent@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" + integrity sha1-6WQhkyWiHQX0RGai9obtbOX13R0= + +es-abstract@^1.16.3, es-abstract@^1.17.0-next.1, es-abstract@^1.17.4, es-abstract@^1.17.5: + version "1.17.5" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.5.tgz#d8c9d1d66c8981fb9200e2251d799eee92774ae9" + integrity sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg== + dependencies: + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.1.5" + is-regex "^1.0.5" + object-inspect "^1.7.0" + object-keys "^1.1.1" + object.assign "^4.1.0" + string.prototype.trimleft "^2.1.1" + string.prototype.trimright "^2.1.1" + es-abstract@^1.5.1: version "1.13.0" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" @@ -1161,6 +1478,19 @@ es-abstract@^1.5.1: is-regex "^1.0.4" object-keys "^1.0.12" +es-get-iterator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.0.tgz#bb98ad9d6d63b31aacdc8f89d5d0ee57bcb5b4c8" + integrity sha512-UfrmHuWQlNMTs35e1ypnvikg6jCz3SK8v8ImvmDsh36fCVUR1MqoFDiyn0/k52C8NqO3YsO8Oe0azeesNuqSsQ== + dependencies: + es-abstract "^1.17.4" + has-symbols "^1.0.1" + is-arguments "^1.0.4" + is-map "^2.0.1" + is-set "^2.0.1" + is-string "^1.0.5" + isarray "^2.0.5" + es-to-primitive@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" @@ -1170,6 +1500,15 @@ es-to-primitive@^1.2.0: is-date-object "^1.0.1" is-symbol "^1.0.2" +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" @@ -1190,6 +1529,11 @@ etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + eventemitter3@^3.1.0: version "3.1.2" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7" @@ -1272,6 +1616,11 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: assign-symbols "^1.0.0" is-extendable "^1.0.1" +extend@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" @@ -1291,6 +1640,18 @@ fast-json-stable-stringify@^2.0.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= +fast-text-encoding@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fast-text-encoding/-/fast-text-encoding-1.0.1.tgz#4a428566f74fc55ebdd447555b1eb4d9cf514455" + integrity sha512-x4FEgaz3zNRtJfLFqJmHWxkMDDvXVtaznj2V9jiP8ACUJrUgist4bP9FmDL2Vew2Y9mEQI/tG4GqabaitYp9CQ== + +faye-websocket@0.11.3: + version "0.11.3" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.3.tgz#5c0e9a8968e8912c286639fde977a8b209f2508e" + integrity sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA== + dependencies: + websocket-driver ">=0.5.1" + fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" @@ -1330,6 +1691,31 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" +firebase-admin@^8.10.0: + version "8.10.0" + resolved "https://registry.yarnpkg.com/firebase-admin/-/firebase-admin-8.10.0.tgz#4a838aec52df49845eba07ad59a40b4df996e815" + integrity sha512-QzJZ1sBh9xzKjb44aP6m1duy0Xe1ixexwh0eaOt1CkJYCOq2b6bievK4GNWMl5yGQ7FFBEbZO6hyDi+5wrctcg== + dependencies: + "@firebase/database" "^0.5.17" + "@types/node" "^8.10.59" + dicer "^0.3.0" + jsonwebtoken "8.1.0" + node-forge "0.7.4" + optionalDependencies: + "@google-cloud/firestore" "^3.0.0" + "@google-cloud/storage" "^4.1.2" + +firebase-functions@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/firebase-functions/-/firebase-functions-3.5.0.tgz#c42accc7a965b03b00a69d230ff06eeaff9e6fe2" + integrity sha512-BnhfsMyhi2eQfKO6RlOKg7bidiIzTrKY+7qF3M02c5yCczUaSQN3TvggqxphaZPOdEdPF2OjoBBK9xO2R2RHeg== + dependencies: + "@types/express" "^4.17.3" + cors "^2.8.5" + express "^4.17.1" + jsonwebtoken "^8.5.1" + lodash "^4.17.14" + for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -1391,6 +1777,11 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" @@ -1405,6 +1796,48 @@ gauge@~2.7.3: strip-ansi "^3.0.1" wide-align "^1.1.0" +gaxios@^2.0.0, gaxios@^2.1.0: + version "2.3.4" + resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-2.3.4.tgz#eea99353f341c270c5f3c29fc46b8ead56f0a173" + integrity sha512-US8UMj8C5pRnao3Zykc4AAVr+cffoNKRTg9Rsf2GiuZCW69vgJj38VK2PzlPuQU73FZ/nTk9/Av6/JGcE1N9vA== + dependencies: + abort-controller "^3.0.0" + extend "^3.0.2" + https-proxy-agent "^5.0.0" + is-stream "^2.0.0" + node-fetch "^2.3.0" + +gaxios@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-3.0.2.tgz#ec49d0b93713d9efdc51e7a6499536854d8958fd" + integrity sha512-cLOetrsKOBLPwjzVyFzirYaGjrhtYjbKUHp6fQpsio2HH8Mil35JTFQLgkV5D3CCXV7Gnd5V69/m4C9rMBi9bA== + dependencies: + abort-controller "^3.0.0" + extend "^3.0.2" + https-proxy-agent "^5.0.0" + is-stream "^2.0.0" + node-fetch "^2.3.0" + +gcp-metadata@^3.4.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-3.5.0.tgz#6d28343f65a6bbf8449886a0c0e4a71c77577055" + integrity sha512-ZQf+DLZ5aKcRpLzYUyBS3yo3N0JSa82lNDO8rj3nMSlovLcz2riKFBsYgDzeXcv75oo5eqB2lx+B14UvPoCRnA== + dependencies: + gaxios "^2.1.0" + json-bigint "^0.3.0" + +gcs-resumable-upload@^2.2.4: + version "2.3.3" + resolved "https://registry.yarnpkg.com/gcs-resumable-upload/-/gcs-resumable-upload-2.3.3.tgz#02c616ed17eff6676e789910aeab3907d412c5f8" + integrity sha512-sf896I5CC/1AxeaGfSFg3vKMjUq/r+A3bscmVzZm10CElyRanN0XwPu/MxeIO4LSP+9uF6yKzXvNsaTsMXUG6Q== + dependencies: + abort-controller "^3.0.0" + configstore "^5.0.0" + gaxios "^2.0.0" + google-auth-library "^5.0.0" + pumpify "^2.0.0" + stream-events "^1.0.4" + get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" @@ -1447,6 +1880,49 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== +google-auth-library@^5.0.0, google-auth-library@^5.5.0: + version "5.10.1" + resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-5.10.1.tgz#504ec75487ad140e68dd577c21affa363c87ddff" + integrity sha512-rOlaok5vlpV9rSiUu5EpR0vVpc+PhN62oF4RyX/6++DG1VsaulAFEMlDYBLjJDDPI6OcNOCGAKy9UVB/3NIDXg== + dependencies: + arrify "^2.0.0" + base64-js "^1.3.0" + ecdsa-sig-formatter "^1.0.11" + fast-text-encoding "^1.0.0" + gaxios "^2.1.0" + gcp-metadata "^3.4.0" + gtoken "^4.1.0" + jws "^4.0.0" + lru-cache "^5.0.0" + +google-gax@^1.13.0: + version "1.15.1" + resolved "https://registry.yarnpkg.com/google-gax/-/google-gax-1.15.1.tgz#a1fa5448e077d94dcf643e7cb0e0cc413a328217" + integrity sha512-1T1PwSZWnbdRusA+NCZMSe56iU6swGvuZuy54eYl9vEHiRXTLYbQmUkWY2CqgYD9Fd/T4WBkUl22+rZG80unyw== + dependencies: + "@grpc/grpc-js" "^0.6.18" + "@grpc/proto-loader" "^0.5.1" + "@types/fs-extra" "^8.0.1" + "@types/long" "^4.0.0" + abort-controller "^3.0.0" + duplexify "^3.6.0" + google-auth-library "^5.0.0" + is-stream-ended "^0.1.4" + lodash.at "^4.6.0" + lodash.has "^4.5.2" + node-fetch "^2.6.0" + protobufjs "^6.8.9" + retry-request "^4.0.0" + semver "^6.0.0" + walkdir "^0.4.0" + +google-p12-pem@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/google-p12-pem/-/google-p12-pem-2.0.4.tgz#036462394e266472632a78b685f0cc3df4ef337b" + integrity sha512-S4blHBQWZRnEW44OcR7TL9WR+QCqByRvhNDZ/uuQfpxywfupikf/miba8js1jZi6ZOGv5slgSuoshCWh6EMDzg== + dependencies: + node-forge "^0.9.0" + got@^6.7.1: version "6.7.1" resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" @@ -1530,6 +2006,16 @@ graphql@^14.5.3, graphql@^14.6.0: dependencies: iterall "^1.2.2" +gtoken@^4.1.0: + version "4.1.4" + resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-4.1.4.tgz#925ff1e7df3aaada06611d30ea2d2abf60fcd6a7" + integrity sha512-VxirzD0SWoFUo5p8RDP8Jt2AGyOmyYcT/pOUgDKJCK+iSw0TMqwrVfY37RXTNmoKwrzmDHSk0GMT9FsgVmnVSA== + dependencies: + gaxios "^2.1.0" + google-p12-pem "^2.0.0" + jws "^4.0.0" + mime "^2.2.0" + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -1540,6 +2026,11 @@ has-symbols@^1.0.0: resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= +has-symbols@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" + integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== + has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" @@ -1583,6 +2074,13 @@ has@^1.0.1, has@^1.0.3: dependencies: function-bind "^1.1.1" +hash-stream-validation@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/hash-stream-validation/-/hash-stream-validation-0.2.2.tgz#6b34c4fce5e9fce265f1d3380900049d92a10090" + integrity sha512-cMlva5CxWZOrlS/cY0C+9qAzesn5srhFA8IT1VPiHc9bWWBLkJfEUIZr7MWoi89oOOGmpg8ymchaOjiArsGu5A== + dependencies: + through2 "^2.0.0" + homedir-polyfill@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" @@ -1601,6 +2099,28 @@ http-errors@1.7.2, http-errors@^1.7.2, http-errors@~1.7.2: statuses ">= 1.5.0 < 2" toidentifier "1.0.0" +"http-parser-js@>=0.4.0 <0.4.11": + version "0.4.10" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.10.tgz#92c9c1374c35085f75db359ec56cc257cbb93fa4" + integrity sha1-ksnBN0w1CF912zWexWzCV8u5P6Q= + +http-proxy-agent@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" + integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== + dependencies: + "@tootallnate/once" "1" + agent-base "6" + debug "4" + +https-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" + integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== + dependencies: + agent-base "6" + debug "4" + iconv-lite@0.4.24, iconv-lite@^0.4.4: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -1667,6 +2187,16 @@ is-accessor-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" +is-arguments@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.0.4.tgz#3faf966c7cba0ff437fb31f6250082fcf0448cf3" + integrity sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA== + +is-bigint@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.0.tgz#73da8c33208d00f130e9b5e15d23eac9215601c4" + integrity sha512-t5mGUXC/xRheCK431ylNiSkGGpBp8bHENBcENTkDT6ppwPzEVxNGZRvgvmOEfbWkFhA7D2GEuE2mmQTr78sl2g== + is-binary-path@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" @@ -1674,6 +2204,11 @@ is-binary-path@^1.0.0: dependencies: binary-extensions "^1.0.0" +is-boolean-object@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.0.1.tgz#10edc0900dd127697a92f6f9807c7617d68ac48e" + integrity sha512-TqZuVwa/sppcrhUCAYkGBk7w0yxfQQnxq28fjkO53tnK9FQXmdwz2JS5+GjsWQ6RByES1K40nI+yDic5c9/aAQ== + is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" @@ -1684,6 +2219,11 @@ is-callable@^1.1.4: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== +is-callable@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" + integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== + is-ci@^1.0.10: version "1.2.1" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c" @@ -1779,11 +2319,21 @@ is-installed-globally@^0.1.0: global-dirs "^0.1.0" is-path-inside "^1.0.0" +is-map@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.1.tgz#520dafc4307bb8ebc33b813de5ce7c9400d644a1" + integrity sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw== + is-npm@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" integrity sha1-8vtjpl5JBbQGyGBydloaTceTufQ= +is-number-object@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.4.tgz#36ac95e741cf18b283fc1ddf5e83da798e3ec197" + integrity sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw== + is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" @@ -1796,6 +2346,11 @@ is-obj@^1.0.0: resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= +is-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" + integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== + is-path-inside@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" @@ -1822,16 +2377,43 @@ is-regex@^1.0.4: dependencies: has "^1.0.1" +is-regex@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" + integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ== + dependencies: + has "^1.0.3" + is-retry-allowed@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" integrity sha1-EaBgVotnM5REAz0BJaYaINVk+zQ= +is-set@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.1.tgz#d1604afdab1724986d30091575f54945da7e5f43" + integrity sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA== + +is-stream-ended@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-stream-ended/-/is-stream-ended-0.1.4.tgz#f50224e95e06bce0e356d440a4827cd35b267eda" + integrity sha512-xj0XPvmr7bQFTvirqnFr50o0hQIh6ZItDqloxt5aJrR4NQsYeSsyFQERYGCAzfindAcnKjINnwEEgLx4IqVzQw== + is-stream@^1.0.0, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= +is-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" + integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== + +is-string@^1.0.4, is-string@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" + integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ== + is-symbol@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" @@ -1839,6 +2421,21 @@ is-symbol@^1.0.2: dependencies: has-symbols "^1.0.0" +is-typedarray@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +is-weakmap@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.1.tgz#5008b59bdc43b698201d18f62b37b2ca243e8cf2" + integrity sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA== + +is-weakset@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.1.tgz#e9a0af88dbd751589f5e50d80f4c98b780884f83" + integrity sha512-pi4vhbhVHGLxohUw7PhGsueT4vRGFoXhP7+RGN0jKIv9+8PWYCQTqtADngrxOm2g46hoH0+g8uZZBzMrvVGDmw== + is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" @@ -1849,6 +2446,11 @@ isarray@1.0.0, isarray@~1.0.0: resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= +isarray@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -1881,6 +2483,13 @@ jsesc@^2.5.1: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== +json-bigint@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/json-bigint/-/json-bigint-0.3.0.tgz#0ccd912c4b8270d05f056fbd13814b53d3825b1e" + integrity sha1-DM2RLEuCcNBfBW+9E4FLU9OCWx4= + dependencies: + bignumber.js "^7.0.0" + json5@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.0.tgz#e7a0c62c48285c628d20a10b85c89bb807c32850" @@ -1888,6 +2497,72 @@ json5@^2.1.0: dependencies: minimist "^1.2.0" +jsonwebtoken@8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.1.0.tgz#c6397cd2e5fd583d65c007a83dc7bb78e6982b83" + integrity sha1-xjl80uX9WD1lwAeoPce7eOaYK4M= + dependencies: + jws "^3.1.4" + lodash.includes "^4.3.0" + lodash.isboolean "^3.0.3" + lodash.isinteger "^4.0.4" + lodash.isnumber "^3.0.3" + lodash.isplainobject "^4.0.6" + lodash.isstring "^4.0.1" + lodash.once "^4.0.0" + ms "^2.0.0" + xtend "^4.0.1" + +jsonwebtoken@^8.5.1: + version "8.5.1" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d" + integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w== + dependencies: + jws "^3.2.2" + lodash.includes "^4.3.0" + lodash.isboolean "^3.0.3" + lodash.isinteger "^4.0.4" + lodash.isnumber "^3.0.3" + lodash.isplainobject "^4.0.6" + lodash.isstring "^4.0.1" + lodash.once "^4.0.0" + ms "^2.1.1" + semver "^5.6.0" + +jwa@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" + integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== + dependencies: + buffer-equal-constant-time "1.0.1" + ecdsa-sig-formatter "1.0.11" + safe-buffer "^5.0.1" + +jwa@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-2.0.0.tgz#a7e9c3f29dae94027ebcaf49975c9345593410fc" + integrity sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA== + dependencies: + buffer-equal-constant-time "1.0.1" + ecdsa-sig-formatter "1.0.11" + safe-buffer "^5.0.1" + +jws@^3.1.4, jws@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" + integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== + dependencies: + jwa "^1.4.1" + safe-buffer "^5.0.1" + +jws@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jws/-/jws-4.0.0.tgz#2d4e8cf6a318ffaa12615e9dec7e86e6c97310f4" + integrity sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg== + dependencies: + jwa "^2.0.0" + safe-buffer "^5.0.1" + kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" @@ -1927,6 +2602,56 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" +lodash.at@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.at/-/lodash.at-4.6.0.tgz#93cdce664f0a1994ea33dd7cd40e23afd11b0ff8" + integrity sha1-k83OZk8KGZTqM9181A4jr9EbD/g= + +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= + +lodash.has@^4.5.2: + version "4.5.2" + resolved "https://registry.yarnpkg.com/lodash.has/-/lodash.has-4.5.2.tgz#d19f4dc1095058cccbe2b0cdf4ee0fe4aa37c862" + integrity sha1-0Z9NwQlQWMzL4rDN9O4P5Ko3yGI= + +lodash.includes@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" + integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8= + +lodash.isboolean@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" + integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY= + +lodash.isinteger@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" + integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M= + +lodash.isnumber@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" + integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w= + +lodash.isplainobject@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" + integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs= + +lodash.isstring@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" + integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE= + +lodash.once@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" + integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= + lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" @@ -1937,6 +2662,11 @@ lodash@^4.17.11: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== +lodash@^4.17.14: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + long@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" @@ -1977,6 +2707,13 @@ make-dir@^2.0.0: pify "^4.0.1" semver "^5.6.0" +make-dir@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.0.2.tgz#04a1acbf22221e1d6ef43559f43e05a90dbb4392" + integrity sha512-rYKABKutXa6vXTXhoV18cBE7PaewPXHe/Bdq4v+ZLMhxbWApkFFplT0LcbMW+6BbjnQXzZ/sAvSE/JdguApG5w== + dependencies: + semver "^6.0.0" + map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" @@ -2028,12 +2765,12 @@ mime-db@1.40.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32" integrity sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA== -mime-db@1.43.0: +mime-db@1.43.0, "mime-db@>= 1.43.0 < 2": version "1.43.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58" integrity sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ== -mime-types@^2.1.12: +mime-types@^2.0.8, mime-types@^2.1.12: version "2.1.26" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.26.tgz#9c921fc09b7e149a65dfdc0da4d20997200b0a06" integrity sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ== @@ -2052,6 +2789,16 @@ mime@1.6.0: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== +mime@^2.2.0: + version "2.4.4" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5" + integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA== + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" @@ -2109,6 +2856,11 @@ ms@2.1.1, ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== +ms@^2.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + nan@^2.12.1: version "2.14.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" @@ -2153,11 +2905,21 @@ node-environment-flags@^1.0.5: object.getownpropertydescriptors "^2.0.3" semver "^5.7.0" -node-fetch@^2.1.2, node-fetch@^2.2.0, node-fetch@^2.6.0: +node-fetch@^2.1.2, node-fetch@^2.2.0, node-fetch@^2.3.0, node-fetch@^2.6.0: version "2.6.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== +node-forge@0.7.4: + version "0.7.4" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.4.tgz#8e6e9f563a1e32213aa7508cded22aa791dbf986" + integrity sha512-8Df0906+tq/omxuCZD6PqhPaQDYuyJ1d+VITgxoIA8zvQd1ru+nMJcDChHH324MWitIgbVkAkQoGEEVJNpn/PA== + +node-forge@^0.9.0: + version "0.9.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.1.tgz#775368e6846558ab6676858a4d8c6e8d16c677b5" + integrity sha512-G6RlQt5Sb4GMBzXvhfkeFmbqR6MzhtnT7VTHuLadjkii3rdYHNdw0m8zA4BTxVIh68FicCQ2NSUANpsqkr9jvQ== + node-modules-regexp@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" @@ -2271,7 +3033,17 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" -object-keys@^1.0.12: +object-inspect@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" + integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== + +object-is@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.2.tgz#6b80eb84fe451498f65007982f035a5b445edec4" + integrity sha512-Epah+btZd5wrrfjkJZq1AOB9O6OxUQto45hzFd7lXGrpHPGE0W1k+426yrZV+k6NJOzLNNW/nVsmZdIWsAqoOQ== + +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== @@ -2288,6 +3060,16 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" +object.assign@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + object.getownpropertydescriptors@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" @@ -2310,13 +3092,20 @@ on-finished@~2.3.0: dependencies: ee-first "1.1.1" -once@^1.3.0: +once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= dependencies: wrappy "1" +onetime@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" + integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== + dependencies: + mimic-fn "^2.1.0" + os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" @@ -2347,6 +3136,13 @@ p-limit@^2.0.0: dependencies: p-try "^2.0.0" +p-limit@^2.2.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.2.tgz#61279b67721f5287aa1c13a9a7fbbc48c9291b1e" + integrity sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ== + dependencies: + p-try "^2.0.0" + p-locate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" @@ -2463,6 +3259,25 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== +protobufjs@^6.8.6, protobufjs@^6.8.9: + version "6.8.9" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.8.9.tgz#0b1adbcdaa983d369c3d9108a97c814edc030754" + integrity sha512-j2JlRdUeL/f4Z6x4aU4gj9I2LECglC+5qR2TrWb193Tla1qfdaNQTZ8I27Pt7K0Ajmvjjpft7O3KWTGciz4gpw== + dependencies: + "@protobufjs/aspromise" "^1.1.2" + "@protobufjs/base64" "^1.1.2" + "@protobufjs/codegen" "^2.0.4" + "@protobufjs/eventemitter" "^1.1.0" + "@protobufjs/fetch" "^1.1.0" + "@protobufjs/float" "^1.0.2" + "@protobufjs/inquire" "^1.1.0" + "@protobufjs/path" "^1.1.2" + "@protobufjs/pool" "^1.1.0" + "@protobufjs/utf8" "^1.1.0" + "@types/long" "^4.0.0" + "@types/node" "^10.1.0" + long "^4.0.0" + proxy-addr@~2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.5.tgz#34cbd64a2d81f4b1fd21e76f9f06c8a45299ee34" @@ -2481,6 +3296,23 @@ pstree.remy@^1.1.6: resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.6.tgz#73a55aad9e2d95814927131fbf4dc1b62d259f47" integrity sha512-NdF35+QsqD7EgNEI5mkI/X+UwaxVEbQaz9f4IooEmMUv6ZPmlTQYGjBPJGgrlzNdjSvIy4MWMg6Q6vCgBO2K+w== +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pumpify@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-2.0.1.tgz#abfc7b5a621307c728b551decbbefb51f0e4aa1e" + integrity sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw== + dependencies: + duplexify "^4.1.1" + inherits "^2.0.3" + pump "^3.0.0" + qs@6.7.0: version "6.7.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" @@ -2511,6 +3343,28 @@ rc@^1.0.1, rc@^1.1.6, rc@^1.2.7: minimist "^1.2.0" strip-json-comments "~2.0.1" +"readable-stream@2 || 3", readable-stream@^3.0.2, readable-stream@^3.1.1, readable-stream@^3.4.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readable-stream@^2.0.0, readable-stream@~2.3.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + readable-stream@^2.0.2, readable-stream@^2.0.6: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" @@ -2546,6 +3400,14 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" +regexp.prototype.flags@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz#7aba89b3c13a64509dabcf3ca8d9fbb9bdf5cb75" + integrity sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + registry-auth-token@^3.0.1: version "3.4.0" resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.4.0.tgz#d7446815433f5d5ed6431cd5dca21048f66b397e" @@ -2593,6 +3455,14 @@ ret@~0.1.10: resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== +retry-request@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/retry-request/-/retry-request-4.1.1.tgz#f676d0db0de7a6f122c048626ce7ce12101d2bd8" + integrity sha512-BINDzVtLI2BDukjWmjAIRZ0oglnCAkpP2vQjM3jdLhmT62h0xnQgciPwBRDAvHqpkPT2Wo1XuUyLyn6nbGrZQQ== + dependencies: + debug "^4.1.1" + through2 "^3.0.1" + retry@0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" @@ -2610,6 +3480,11 @@ safe-buffer@5.1.2, safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, s resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== +safe-buffer@>=5.1.0, safe-buffer@~5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" + integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== + safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" @@ -2639,6 +3514,11 @@ semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semve resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== +semver@^6.0.0, semver@^6.2.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + send@0.17.1: version "0.17.1" resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" @@ -2718,11 +3598,24 @@ shebang-regex@^1.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= +side-channel@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.2.tgz#df5d1abadb4e4bf4af1cd8852bf132d2f7876947" + integrity sha512-7rL9YlPHg7Ancea1S96Pa8/QWb4BtXL/TZvS6B8XFetGBeuhAsfmUspK6DokBeZ64+Kj9TCNRD/30pVz1BvQNA== + dependencies: + es-abstract "^1.17.0-next.1" + object-inspect "^1.7.0" + signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= +snakeize@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/snakeize/-/snakeize-0.1.0.tgz#10c088d8b58eb076b3229bb5a04e232ce126422d" + integrity sha1-EMCI2LWOsHazIpu1oE4jLOEmQi0= + snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" @@ -2807,6 +3700,18 @@ static-extend@^0.1.1: resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= +stream-events@^1.0.1, stream-events@^1.0.4, stream-events@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/stream-events/-/stream-events-1.0.5.tgz#bbc898ec4df33a4902d892333d47da9bf1c406d5" + integrity sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg== + dependencies: + stubs "^3.0.0" + +stream-shift@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" + integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== + streamsearch@0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a" @@ -2829,6 +3734,47 @@ string-width@^1.0.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" +string.prototype.trimend@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.0.tgz#ee497fd29768646d84be2c9b819e292439614373" + integrity sha512-EEJnGqa/xNfIg05SxiPSqRS7S9qwDhYts1TSLR1BQfYUfPe1stofgGKvwERK9+9yf+PpfBMlpBaCHucXGPQfUA== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + +string.prototype.trimleft@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz#4408aa2e5d6ddd0c9a80739b087fbc067c03b3cc" + integrity sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + string.prototype.trimstart "^1.0.0" + +string.prototype.trimright@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz#c76f1cef30f21bbad8afeb8db1511496cfb0f2a3" + integrity sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + string.prototype.trimend "^1.0.0" + +string.prototype.trimstart@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.0.tgz#afe596a7ce9de905496919406c9734845f01a2f2" + integrity sha512-iCP8g01NFYiiBOnwG1Xc3WZLyoo+RuBymwIlWncShXDDJYWN6DbnM3odslBJdgCdRlq94B5s63NWAZlcn2CS4w== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" @@ -2860,6 +3806,11 @@ strip-json-comments@~2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= +stubs@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/stubs/-/stubs-3.0.0.tgz#e8d2ba1fa9c90570303c030b6900f7d5f89abe5b" + integrity sha1-6NK6H6nJBXAwPAMLaQD31fiavls= + subscriptions-transport-ws@^0.9.11, subscriptions-transport-ws@^0.9.16: version "0.9.16" resolved "https://registry.yarnpkg.com/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.16.tgz#90a422f0771d9c32069294c08608af2d47f596ec" @@ -2896,6 +3847,17 @@ tar@^4: safe-buffer "^5.1.2" yallist "^3.0.2" +teeny-request@^6.0.0: + version "6.0.3" + resolved "https://registry.yarnpkg.com/teeny-request/-/teeny-request-6.0.3.tgz#b617f9d5b7ba95c76a3f257f6ba2342b70228b1f" + integrity sha512-TZG/dfd2r6yeji19es1cUIwAlVD8y+/svB1kAC2Y0bjEyysrfbO8EZvJBRwIE6WkwmUoB7uvWLwTIhJbMXZ1Dw== + dependencies: + http-proxy-agent "^4.0.0" + https-proxy-agent "^5.0.0" + node-fetch "^2.2.0" + stream-events "^1.0.5" + uuid "^7.0.0" + term-size@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" @@ -2903,6 +3865,21 @@ term-size@^1.2.0: dependencies: execa "^0.7.0" +through2@^2.0.0: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +through2@^3.0.0, through2@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.1.tgz#39276e713c3302edf9e388dd9c812dd3b825bd5a" + integrity sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww== + dependencies: + readable-stream "2 || 3" + timed-out@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" @@ -2969,6 +3946,11 @@ ts-invariant@^0.4.0: dependencies: tslib "^1.9.3" +tslib@1.11.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35" + integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA== + tslib@^1.9.3: version "1.9.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" @@ -2982,6 +3964,18 @@ type-is@^1.6.16, type-is@~1.6.17, type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + undefsafe@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.2.tgz#225f6b9e0337663e0d8e7cfd686fc2836ccace76" @@ -3006,6 +4000,13 @@ unique-string@^1.0.0: dependencies: crypto-random-string "^1.0.0" +unique-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" + integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg== + dependencies: + crypto-random-string "^2.0.0" + unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" @@ -3062,7 +4063,7 @@ use@^3.1.0: resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== -util-deprecate@~1.0.1: +util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= @@ -3085,6 +4086,11 @@ uuid@^3.1.0: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== +uuid@^7.0.0: + version "7.0.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.2.tgz#7ff5c203467e91f5e0d85cfcbaaf7d2ebbca9be6" + integrity sha512-vy9V/+pKG+5ZTYKf+VcphF5Oc6EFiu3W8Nv3P3zIh0EqVI80ZxOzuPfe9EHjkFNvf8+xuTHVeei4Drydlx4zjw== + v8flags@^3.1.1: version "3.1.3" resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.1.3.tgz#fc9dc23521ca20c5433f81cc4eb9b3033bb105d8" @@ -3097,6 +4103,46 @@ vary@^1, vary@~1.1.2: resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= +walkdir@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/walkdir/-/walkdir-0.4.1.tgz#dc119f83f4421df52e3061e514228a2db20afa39" + integrity sha512-3eBwRyEln6E1MSzcxcVpQIhRG8Q1jLvEqRmCZqS3dsfXEDR/AhOF4d+jHg1qvDCpYaVRZjENPQyrVxAkQqxPgQ== + +websocket-driver@>=0.5.1: + version "0.7.3" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.3.tgz#a2d4e0d4f4f116f1e6297eba58b05d430100e9f9" + integrity sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg== + dependencies: + http-parser-js ">=0.4.0 <0.4.11" + safe-buffer ">=5.1.0" + websocket-extensions ">=0.1.1" + +websocket-extensions@>=0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29" + integrity sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg== + +which-boxed-primitive@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.1.tgz#cbe8f838ebe91ba2471bb69e9edbda67ab5a5ec1" + integrity sha512-7BT4TwISdDGBgaemWU0N0OU7FeAEJ9Oo2P1PHRm/FCWoEi2VLWC9b6xvxAA3C/NMpxg3HXVgi0sMmGbNUbNepQ== + dependencies: + is-bigint "^1.0.0" + is-boolean-object "^1.0.0" + is-number-object "^1.0.3" + is-string "^1.0.4" + is-symbol "^1.0.2" + +which-collection@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.1.tgz#70eab71ebbbd2aefaf32f917082fc62cdcb70906" + integrity sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A== + dependencies: + is-map "^2.0.1" + is-set "^2.0.1" + is-weakmap "^2.0.1" + is-weakset "^2.0.1" + which@^1.2.9: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" @@ -3132,6 +4178,16 @@ write-file-atomic@^2.0.0: imurmurhash "^0.1.4" signal-exit "^3.0.2" +write-file-atomic@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + ws@^5.2.0: version "5.2.2" resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f" @@ -3151,6 +4207,16 @@ xdg-basedir@^3.0.0: resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" integrity sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ= +xdg-basedir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" + integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== + +xtend@^4.0.1, xtend@~4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" From 88b7d76e43e659f5c764e07b5b2e9e4588feb979 Mon Sep 17 00:00:00 2001 From: alexlbr Date: Tue, 31 Mar 2020 00:41:48 +0100 Subject: [PATCH 09/16] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c919507..61a2b2d 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ We are going to create our own GraphQL API on top of this [REST API](https://res ### Before we start -- Don't forget to checkout the `fundamentals` branch, install the dependencies, and let me walk you through the code meanwhile. +- Don't forget to checkout the `fundamentals-v2` branch, install the dependencies, and let me walk you through the code meanwhile. - We use nodemon in the `start` script, so every time you save the server will restart automatically. - The `src/index.js` is the [getting started tutorial](https://www.apollographql.com/docs/apollo-server/getting-started/) from Apollo. - Let's replace the schema: From 683e9a5f8380a1c61d70726a1635b7fd13ab4a36 Mon Sep 17 00:00:00 2001 From: alexlbr Date: Tue, 31 Mar 2020 09:28:52 +0100 Subject: [PATCH 10/16] update server.js and readme.md --- README.md | 2 +- src/server.js | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 61a2b2d..878331c 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ This exercise is part of the [React GraphQL Academy](http://reactgraphql.academy ## Exercise part 1 -Given the following [GraphQL API](https://us-central1-rga-mocked-apis.cloudfunctions.net/graphql) / https://api.reactgraphql.academy/graphql: +Given the following [GraphQL API](https://us-central1-rga-mocked-apis.cloudfunctions.net/graphql): - Query a list with all the training and retrieve the title and language for each - Query a single discount by id (try id equals `dis:422`) and get its name diff --git a/src/server.js b/src/server.js index 358065a..ff4836c 100644 --- a/src/server.js +++ b/src/server.js @@ -64,19 +64,19 @@ const resolvers = { function fetchTrainings() { // More info about the fetch function? https://github.com/bitinn/node-fetch#json - return fetch("https://api.reactgraphql.academy/api/rest/trainings/") + return fetch("https://api.reactgraphql.academy/rest/trainings/") .then(res => res.json()) .catch(error => console.log(error)); } function fetchTrainingById(id) { - return fetch(`https://api.reactgraphql.academy/api/rest/trainings/${id}`) + return fetch(`https://api.reactgraphql.academy/rest/trainings/${id}`) .then(res => res.json()) .catch(error => console.log(error)); } function fetchDiscounts() { - return fetch("https://api.reactgraphql.academy/api/rest/discounts/") + return fetch("https://api.reactgraphql.academy/rest/discounts/") .then(res => res.json()) .catch(error => console.log(error)); } @@ -88,7 +88,7 @@ function fetchTrainingByUrl(url) { } function fetchDiscountById(id) { - return fetch(`https://api.reactgraphql.academy/api/rest/discounts/${id}`) + return fetch(`https://api.reactgraphql.academy/rest/discounts/${id}`) .then(res => res.json()) .catch(error => console.log(error)); } From ec5e1b210fdc71edbb15563d4cbaa1c1ff8280ec Mon Sep 17 00:00:00 2001 From: alexlbr Date: Tue, 31 Mar 2020 09:46:19 +0100 Subject: [PATCH 11/16] update readme.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 878331c..185559a 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Given the following [GraphQL API](https://us-central1-rga-mocked-apis.cloudfunct ### To get started -We are going to create our own GraphQL API on top of this [REST API](https://restapi.reactgraphql.academy/v1/trainings) +We are going to create our own GraphQL API on top of this [REST API](https://api.reactgraphql.academy/rest/trainings) - `git clone https://github.com/reactgraphqlacademy/graphql-api-training.git` - `cd graphql-api-training` @@ -29,7 +29,7 @@ We are going to create our own GraphQL API on top of this [REST API](https://res - `yarn install` or `npm install` - `yarn start` or `npm start` -### Before we start +### 🥑 Before we start - Don't forget to checkout the `fundamentals-v2` branch, install the dependencies, and let me walk you through the code meanwhile. - We use nodemon in the `start` script, so every time you save the server will restart automatically. @@ -250,7 +250,7 @@ Once implemented, do you see any problems/ vulnerability issues on that query? 🤸🏾Do you want some extra workout? Create an [enumeration](https://graphql.org/learn/schema/#enumeration-types) for the languages. Add field language to the Training object type that uses the language enum. -## Homework +## 🧘‍♀️Homework You are going to build a GraphQL API on top of an existing REST API. Steps: From 4ca714c9aa3e0f995f1388fb26e7adb979083fec Mon Sep 17 00:00:00 2001 From: alexlbr Date: Tue, 31 Mar 2020 09:59:17 +0100 Subject: [PATCH 12/16] update readme.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 185559a..a618803 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ We are going to create our own GraphQL API on top of this [REST API](https://api ### 🥑 Before we start - Don't forget to checkout the `fundamentals-v2` branch, install the dependencies, and let me walk you through the code meanwhile. -- We use nodemon in the `start` script, so every time you save the server will restart automatically. +- We use nodemon in the `start` script, so every time you save, the server will restart automatically. - The `src/index.js` is the [getting started tutorial](https://www.apollographql.com/docs/apollo-server/getting-started/) from Apollo. - Let's replace the schema: @@ -50,7 +50,7 @@ type Query { } ``` -What do we need to change so the field avocados returns the array of books when we run the query? I'll give you 2 minutes to fix it :) +What do we need to change so the field avocados returns the array of books when we run the query? ⏳I'll give you 2 minutes to fix it. ### Tasks @@ -83,7 +83,7 @@ To complete the tasks you'll use the mock data and helper functions that are at - [https://mockedrestapi.reactgraphql.academy/v1/trainings](https://mockedrestapi.reactgraphql.academy/v1/trainings) - [https://mockedrestapi.reactgraphql.academy/v1/discounts](https://mockedrestapi.reactgraphql.academy/v1/discounts) -Hint. You can use the `fetchTrainings` and `fetchDiscounts` defined at the bottom of this file `src/index.js` +🛠 Helper. You can use the `fetchTrainings` and `fetchDiscounts` defined at the bottom of this file `src/index.js` - You'll need to replace mock data in 2 different places: - Query discounts @@ -133,7 +133,7 @@ const resolvers = { We could also create a new field that returns the upper case version of the title without changing the title field. Example: -⚠️ Learners implement (only 5 minutes to implement and write a query to test it!): +⚠️ Learners implement (⏳ only 5 minutes to implement and write a query to test it!): ```graphql type Training { @@ -189,7 +189,7 @@ query authorName { To complete the tasks you'll use the helper functions that are at the bottom of the file `src/index.js` -- [ ] 4. Implement a new field in the `Query` type that returns a single training given an id. You need to fetch the training from this endpoint `https://restapi.reactgraphql.academy/v1/trainings/` + `id`. Hint, you need to pass [arguments](https://graphql.org/graphql-js/passing-arguments/) to the field, and then use the second argument in the resolver. There is a helper function at the bottom of `src/index.js`. +- [ ] 4. Implement a new field in the `Query` type that returns a single training given an id. You need to fetch the training from this endpoint `https://restapi.reactgraphql.academy/v1/trainings/` + `id`. 🕵️‍♂️ Hint, you need to pass [arguments](https://graphql.org/graphql-js/passing-arguments/) to the field, and then use the second argument in the resolver. There is a helper function at the bottom of `src/index.js`. Once implemented you should be able to run the following query: From 106211f99b4e53abb2c1f869b4c3875b3e0b715e Mon Sep 17 00:00:00 2001 From: alexlbr Date: Tue, 31 Mar 2020 10:00:49 +0100 Subject: [PATCH 13/16] update readme.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a618803..2dabbbb 100644 --- a/README.md +++ b/README.md @@ -108,7 +108,7 @@ Bonus task, add a field called `startDate` to the `Training` object type using a ## Exercise part 3 -### Before we start +### 🥑 Before we start Resolvers are functions that have 4 arguments `(parent, args, context, info)`. In this exercise, we are only going to use the first 2 arguments: `parent` and `args`. From 98c13b70b6d96d46dbcab2707879e58790123254 Mon Sep 17 00:00:00 2001 From: alexlbr Date: Tue, 31 Mar 2020 11:31:22 +0100 Subject: [PATCH 14/16] update readme --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2dabbbb..0a3e739 100644 --- a/README.md +++ b/README.md @@ -189,7 +189,7 @@ query authorName { To complete the tasks you'll use the helper functions that are at the bottom of the file `src/index.js` -- [ ] 4. Implement a new field in the `Query` type that returns a single training given an id. You need to fetch the training from this endpoint `https://restapi.reactgraphql.academy/v1/trainings/` + `id`. 🕵️‍♂️ Hint, you need to pass [arguments](https://graphql.org/graphql-js/passing-arguments/) to the field, and then use the second argument in the resolver. There is a helper function at the bottom of `src/index.js`. +- [ ] 4. Implement a new field in the `Query` type that returns a single training given an id. You need to fetch the training from this endpoint `https://api.reactgraphql.academy/rest/trainings/` + `id`. 🕵️‍♂️ Hint, you need to pass [arguments](https://graphql.org/graphql-js/passing-arguments/) to the field, and then use the second argument in the resolver. There is a helper function at the bottom of `src/index.js`. Once implemented you should be able to run the following query: @@ -229,7 +229,7 @@ query getTraining { #### 🏋️‍♀️ Bonus exercise part 3 -- Create the types and resolvers so the following query works: +Create the types and resolvers so the following query works: ```graphql query getDangerousDiscount { @@ -246,7 +246,10 @@ query getDangerousDiscount { } ``` -Once implemented, do you see any problems/ vulnerability issues on that query? +Bonus final questions: + +- Once the getDangerousDiscount query is implemented, do you see any problem/ vulnerability issues on that query? +- Should the relationship Discount to Training be non-nullable? meaning `training: Training` or `training: Training!` 🤸🏾Do you want some extra workout? Create an [enumeration](https://graphql.org/learn/schema/#enumeration-types) for the languages. Add field language to the Training object type that uses the language enum. From 8204888593343c062fc435525b9a1c7b2f769ec7 Mon Sep 17 00:00:00 2001 From: alexlbr Date: Wed, 22 Apr 2020 12:28:55 +0100 Subject: [PATCH 15/16] update README --- README.md | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 0a3e739..550480c 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,19 @@ This exercise is part of the [React GraphQL Academy](http://reactgraphql.academy) learning material. The goal of the exercise is to help you get started transitioning from REST to GraphQL. +## Our teaching method + +1. Collaborative learning environment & pair programming. + - Rooms with small groups + - Work with your peers, discuss, help each other. +2. We try to foster critical thinking. + - ⬆️ Discovery ⬇️ Instruction +3. We don’t explain everything you need to know before the exercise: + - The exercise is meant to help you come up with conclusions. + - Learn by doing and build a mental model. + +More on our [teaching method](https://reactgraphql.academy/blog/react-graphql-academy-teaching-method/) + ## Learning objectives - Understand the main functionalities and responsibilities of a GraphQL server @@ -55,9 +68,10 @@ What do we need to change so the field avocados returns the array of books when ### Tasks ⚠️ Some info before you start the tasks: -1- You can define an array using square brackets and the type, example `[Book]` -2- You can use the scalar type `ID` for ids. -3- In GraphQL types are nullable by default. If you want to make a type non-nullable use `!` (exclamation mark). Example: + +- You can define an array using square brackets and the type, example `[Book]` +- You can use the scalar type `ID` for ids. +- In GraphQL types are nullable by default. If you want to make a type non-nullable use `!` (exclamation mark). Example: ```graphql type Book { @@ -80,8 +94,8 @@ To complete the tasks you'll use the mock data and helper functions that are at - [ ] 2.3 You should be able to manually test the `discounts` query in Playground at [http://localhost:4000/](http://localhost:4000/) - [ ] 3. Replace the mock data with real data using the following endpoints: - - [https://mockedrestapi.reactgraphql.academy/v1/trainings](https://mockedrestapi.reactgraphql.academy/v1/trainings) - - [https://mockedrestapi.reactgraphql.academy/v1/discounts](https://mockedrestapi.reactgraphql.academy/v1/discounts) + - [https://api.reactgraphql.academy/rest/trainings](https://api.reactgraphql.academy/rest/trainings) + - [https://api.reactgraphql.academy/rest/discounts](https://api.reactgraphql.academy/rest/discounts) 🛠 Helper. You can use the `fetchTrainings` and `fetchDiscounts` defined at the bottom of this file `src/index.js` @@ -94,7 +108,7 @@ Note on mocking. In the next session, we'll use the automocking feature of Apoll ```js const server = new ApolloServer({ typeDefs, - mocks: true // ⬅️⬅️⬅️⬅️ + mocks: true, // ⬅️⬅️⬅️⬅️ }); ``` @@ -172,8 +186,8 @@ const resolvers = { Query: { author(parent, args) { console.log(args); // { id: 3 } based on the query below - } - } + }, + }, }; ``` @@ -249,7 +263,7 @@ query getDangerousDiscount { Bonus final questions: - Once the getDangerousDiscount query is implemented, do you see any problem/ vulnerability issues on that query? -- Should the relationship Discount to Training be non-nullable? meaning `training: Training` or `training: Training!` +- Should the relationship Discount to Training be non-nullable? Meaning `training: Training` or `training: Training!` 🤸🏾Do you want some extra workout? Create an [enumeration](https://graphql.org/learn/schema/#enumeration-types) for the languages. Add field language to the Training object type that uses the language enum. From cd924daafb20e64771ccd6a6924699dc577d01f2 Mon Sep 17 00:00:00 2001 From: alexlbr Date: Wed, 22 Apr 2020 14:51:27 +0100 Subject: [PATCH 16/16] update README and add .env to .gitignore --- .gitignore | 2 ++ README.md | 61 +++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 49 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 7b61c09..ac279e9 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,5 @@ data #build dist/ + +.env diff --git a/README.md b/README.md index 550480c..e5f04bd 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # GraphQL API Fundamentals -This exercise is part of the [React GraphQL Academy](http://reactgraphql.academy) learning material. The goal of the exercise is to help you get started transitioning from REST to GraphQL. +This exercise is part of the [React GraphQL Academy](http://reactgraphql.academy) training material. ## Our teaching method @@ -23,6 +23,8 @@ More on our [teaching method](https://reactgraphql.academy/blog/react-graphql-ac ## Exercise part 1 +🎯 The goal of this exercise it to help you get familiar with GraphQL queries and the in-browser IDE Playground. + Given the following [GraphQL API](https://us-central1-rga-mocked-apis.cloudfunctions.net/graphql): - Query a list with all the training and retrieve the title and language for each @@ -32,8 +34,6 @@ Given the following [GraphQL API](https://us-central1-rga-mocked-apis.cloudfunct ## Exercise part 2 -### To get started - We are going to create our own GraphQL API on top of this [REST API](https://api.reactgraphql.academy/rest/trainings) - `git clone https://github.com/reactgraphqlacademy/graphql-api-training.git` @@ -44,10 +44,10 @@ We are going to create our own GraphQL API on top of this [REST API](https://api ### 🥑 Before we start -- Don't forget to checkout the `fundamentals-v2` branch, install the dependencies, and let me walk you through the code meanwhile. +- Don't forget to checkout the `fundamentals-v2` branch, and install the dependencies. - We use nodemon in the `start` script, so every time you save, the server will restart automatically. -- The `src/index.js` is the [getting started tutorial](https://www.apollographql.com/docs/apollo-server/getting-started/) from Apollo. -- Let's replace the schema: +- The `src/index.js` is the [getting started tutorial](https://www.apollographql.com/docs/apollo-server/getting-started/) from Apollo. Let me walk you through our code. +- Let's do a small exercise to warm up, let's replace in the schema: ```graphql type Query { @@ -63,10 +63,12 @@ type Query { } ``` -What do we need to change so the field avocados returns the array of books when we run the query? ⏳I'll give you 2 minutes to fix it. +🏋️‍♀️ Mini exercise. What do we need to change so the field avocados returns the array of books when we run the query? ⏳ You have 2 minutes to fix it. ### Tasks +🎯 The goal of the following tasks it to help you get familiar with the Schema Definition Language (SDL) and the resolvers. + ⚠️ Some info before you start the tasks: - You can define an array using square brackets and the type, example `[Book]` @@ -147,7 +149,7 @@ const resolvers = { We could also create a new field that returns the upper case version of the title without changing the title field. Example: -⚠️ Learners implement (⏳ only 5 minutes to implement and write a query to test it!): +⚠️ Learners implement (⏳ you only 5 minutes to implement and write a query to test it!): ```graphql type Training { @@ -201,6 +203,8 @@ query authorName { ### Tasks +🎯 The goal of the following tasks it to help you understand how arguments and relationships work in GraphQL. + To complete the tasks you'll use the helper functions that are at the bottom of the file `src/index.js` - [ ] 4. Implement a new field in the `Query` type that returns a single training given an id. You need to fetch the training from this endpoint `https://api.reactgraphql.academy/rest/trainings/` + `id`. 🕵️‍♂️ Hint, you need to pass [arguments](https://graphql.org/graphql-js/passing-arguments/) to the field, and then use the second argument in the resolver. There is a helper function at the bottom of `src/index.js`. @@ -243,28 +247,53 @@ query getTraining { #### 🏋️‍♀️ Bonus exercise part 3 -Create the types and resolvers so the following query works: +- [ ] Bonus 1. Create the types and resolvers so the following query works: ```graphql -query getDangerousDiscount { +query getPotentiallyDangerousDiscount { discount(id: "dis:421") { code training { title discounts { code - # why this query could be dangerous? + # why this type of query could be potentially dangerous? } } } } ``` -Bonus final questions: - -- Once the getDangerousDiscount query is implemented, do you see any problem/ vulnerability issues on that query? +- Once the getPotentiallyDangerousDiscount query is implemented, do you see any problem/ vulnerability issues on that type of query? - Should the relationship Discount to Training be non-nullable? Meaning `training: Training` or `training: Training!` +* [ ] Bonus 2. If we run the following query, is the GraphQL Server fetching the training from the rest API (you can use a console.log in the resolver)? + +```graphql +query { + discount(id: "dis:421") { + code + # with the training field commented out, is the training resolver invoked on the API? + # training { + # title + # } + } +} +``` + +- [ ] Bonus 3. Add a `first` argument to the field discounts in the `Training` object type. The `first` argument is an integer that makes the field `discounts` return the first N discounts, being N the value of the argument. Once implemented, you should be able to run the following query + +```graphql +query getTraining { + training(id: "tra:22") { + title + discounts(first: 2) { + code + } + } +} +``` + 🤸🏾Do you want some extra workout? Create an [enumeration](https://graphql.org/learn/schema/#enumeration-types) for the languages. Add field language to the Training object type that uses the language enum. ## 🧘‍♀️Homework @@ -298,3 +327,7 @@ You are going to build a GraphQL API on top of an existing REST API. Steps: ## License This material is available for private, non-commercial use under the [GPL version 3](http://www.gnu.org/licenses/gpl-3.0-standalone.html). + +``` + +```