From 0683b822c30751d0a608736a72282cffe71e9459 Mon Sep 17 00:00:00 2001 From: Ilya Semenov Date: Fri, 8 Jan 2021 12:54:12 +0700 Subject: [PATCH] refactor: full rewrite - Support pagination - Support per-field cleaners for sensitive data BREAKING CHANGE: - rename npm package - Completely different usage API. Please refer to the updated README. - Drop support for `graphql.*` model modifiers (use ModelResolver/FieldResolver API) - Nested filters are taken from nested fields args, not from root args subfields --- .editorconfig | 2 +- README.md | 502 +++---- docs/filters.md | 96 ++ docs/pagination.md | 117 ++ docs/relations.md | 95 ++ docs/virtual-attributes.md | 87 ++ package.json | 20 +- rollup.config.js | 7 +- src/filter.ts | 69 + src/helpers/is_plain_object.ts | 3 + src/helpers/run_after.ts | 19 + src/index.ts | 204 +-- src/paginators/cursor.ts | 112 ++ src/paginators/index.ts | 6 + src/resolver/field.ts | 58 + src/resolver/graph.ts | 85 ++ src/resolver/model.ts | 183 +++ src/tests/fixtures.ts | 35 + src/tests/graph.ts | 7 + src/tests/main.test.ts | 551 ++++---- src/tests/migrations.ts | 25 + src/tests/model_resolvers/post.ts | 10 + src/tests/model_resolvers/section.ts | 25 + src/tests/model_resolvers/user.ts | 34 + src/tests/models.ts | 149 --- src/tests/models/post.ts | 56 + src/tests/models/section.ts | 27 + src/tests/models/user.ts | 29 + src/tests/resolvers.ts | 52 +- src/tests/schema.ts | 38 +- src/tests/server.ts | 29 + src/tests/setup.ts | 16 +- src/types.d.ts | 17 - .../src-tests-main.test.ts-TAP.test.js | 458 ++++--- tsconfig.json | 2 +- yarn.lock | 1154 ++++++++--------- 36 files changed, 2751 insertions(+), 1628 deletions(-) create mode 100644 docs/filters.md create mode 100644 docs/pagination.md create mode 100644 docs/relations.md create mode 100644 docs/virtual-attributes.md create mode 100644 src/filter.ts create mode 100644 src/helpers/is_plain_object.ts create mode 100644 src/helpers/run_after.ts create mode 100644 src/paginators/cursor.ts create mode 100644 src/paginators/index.ts create mode 100644 src/resolver/field.ts create mode 100644 src/resolver/graph.ts create mode 100644 src/resolver/model.ts create mode 100644 src/tests/fixtures.ts create mode 100644 src/tests/graph.ts create mode 100644 src/tests/migrations.ts create mode 100644 src/tests/model_resolvers/post.ts create mode 100644 src/tests/model_resolvers/section.ts create mode 100644 src/tests/model_resolvers/user.ts delete mode 100644 src/tests/models.ts create mode 100644 src/tests/models/post.ts create mode 100644 src/tests/models/section.ts create mode 100644 src/tests/models/user.ts create mode 100644 src/tests/server.ts delete mode 100644 src/types.d.ts diff --git a/.editorconfig b/.editorconfig index 4683a32..b056ad1 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,5 +7,5 @@ charset = utf-8 indent_style = tab indent_size = 2 -[{package.json,*.md,*.yml}] +[{*.json,*.md,*.yml}] indent_style = space diff --git a/README.md b/README.md index 9c0552e..3b8ae65 100644 --- a/README.md +++ b/README.md @@ -1,250 +1,249 @@ -# objection-fetch-graphql +# objection-graphql-resolver -A helper library to resolve GraphQL queries directly with objection.js models/relations. +A helper library to resolve GraphQL queries directly with [Objection.js](https://vincit.github.io/objection.js/) models and relations. -- Effective: selects only requested fields and relations (using fine-tuned `withGraphFetched`) -- Unlimited nested resolvers (traversing `relationMappings`) -- Virtual attributes -- Dynamic filters like `{ date: "2020-10-01", category__in: ["News", "Politics"] }` +- Highly effective: selects only requested fields and relations (using fine-tuned `withGraphFetched`) +- Support unlimited nested resolvers (traversing `relationMappings`) +- Support pagination +- Support virtual attributes +- Support filters like `{ date: "2020-10-01", category__in: ["News", "Politics"] }` - Hook into subqueries with query modifiers +- Hook into field results to restrict access to sensitive information + +## History + +Before 3.0.0, this library used to be named `objection-fetch-graphql`. ## Install ``` -yarn add objection-fetch-graphql +yarn add objection-graphql-resolver ``` -## Use - -Create GraphQL schema: - -```graphql -type Post { - id: ID - title: String - text: String -} - -type Query { - posts: [Post!]! -} -``` +## Minimal all-in-one example -Create objection.js model: +Run GraphQL server: ```ts +// Everything is put into a single file for demonstration purposes. +// +// In real projects, you will want to separate models, typedefs, +// model resolvers, and the server into their own modules. + +import { ApolloServer } from "apollo-server" +import gql from "graphql-tag" import { Model } from "objection" +import { + CursorPaginator, + GraphResolver, + ModelResolver, +} from "objection-graphql-resolver" -export class PostModel extends Model { +class PostModel extends Model { static tableName = "posts" + + declare id: number + declare text: string } -``` -Import `objection-fetch-graphql` somewhere in entry point: +const typeDefs = gql` + type Post { + id: ID! + text: String! + } -```ts -// Somewhere in entry point: it monkey-patches objection.js -import "objection-fetch-graphql" -``` + # Simplified paginator + # Relay-style pagination is also supported. + type PostPage { + nodes: [PostPage]! + cursor: String + } -Define resolver: + type Query { + posts: PostPage! + } +` + +const resolveGraph = GraphResolver({ + // Map GraphQL types to model resolvers + Post: ModelResolver(PostModel, { + // List fields that can be accessed via GraphQL + fields: { + id: true, + text: true, + }, + }), +}) -```ts -export const resolvers = { +const resolvers = { Query: { - posts: (parent, args, ctx, info) => { - return PostModel.query().withGraphQL(info) + posts: async (parent, args, ctx, info) => { + const page = await resolveGraph(ctx, info, Post.query(), { + paginate: CursorPaginator({ take: 10, fields: ["-id"] }), + }) + return page }, }, } -``` -Run GraphQL server: - -```ts new ApolloServer({ typeDefs, resolvers }).listen({ port: 4000 }) ``` -Define GraphQL query: - -```graphql -query get_all_posts { - posts { - id - title - # text is not requested, and will not be selected from DB - } -} -``` - -Execute it: +Query it with GraphQL client: ```ts -// Using @graphql-codegen/typescript-graphql-request -const sdk = getSdk(new GraphQLClient("http://127.0.0.1:4000")) -await sdk.get_all_posts() +import { GraphQLClient } from "graphql-request" +import gql from "graphql-tag" + +const client = new GraphQLClient("http://127.0.0.1:4000") + +await client.request( + gql` + query get_all_posts { + posts { + nodes { + id + text + } + cursor + } + } + `, +) ``` -### Relations - -Relations will be fetched automatically using `withGraphFetched()` for the nested fields. - -Consider schema: +## Relations -```graphql -type Post { - id: ID - text: String - author: User -} -``` +Relations will be fetched automatically using `withGraphFetched()` when resolving nested fields. -Model: +Example: ```ts -export class PostModel extends Model { - static tableName = "posts" - static get relationMappings() { - return { - author: { - relation: Model.BelongsToOneRelation, - modelClass: UserModel, - join: { from: "posts.author_id", to: "users.id" }, - }, - } - } -} +const resolveGraph = GraphResolver({ + User: ModelResolver(UserModel, { + fields: { + id: true, + name: true, + // will use withGraphFetched("posts") + // and process subquery with Post model resolver defined below + posts: true, + }, + }), + // No resolver options = access to all fields + Post: ModelResolver(PostModel), +}) ``` -Query: - ```graphql query posts_with_author { - posts { - id - text - author { - name - } - } + posts { + id + text + author { + name + } + } +} + +query user_with_posts { + user(id: ID!) { + name + posts { + id + text + } + } } ``` -Resolver: +[More details and examples for relations.](docs/relations.md) -```ts -// for the query above, will pull posts with related author object -PostModel.query().withGraphQL(info) -``` +## Pagination -### Filters +Root queries and one-to-many nested relations can be paginated. -Queries can be filtered like this: +Example: ```ts -PostModel.query().withGraphQL(info, { - filter: { - date: "2020-10-01", - // Only pull posts where author_id is 123 or 456. - author_id__in: [123, 456], - }, +const resolveGraph = GraphResolver({ + User: ModelResolver(UserModel, { + fields: { + id: true, + name: true, + posts: FieldResolver({ + paginate: CursorPaginage({ take: 10, fields: ["-id"] }), + }), + }, + }), + Post: ModelResolver(PostModel), }) ``` -which adds `WHERE date='2020-10-01' AND author.id IN (123, 456)`. - -The suggested workflow is using a dedicated untyped GraphQL query arg to pass filters: - -```graphql -scalar Filter - -type Query { - posts(filter: Filter): [Post!]! -} -``` - -and then in resolver: +To paginate root query, use: ```ts -export const resolvers = { +const resolvers = { Query: { - posts: (parent, { filter }, ctx, info) => { - return PostModel.query().withGraphQL(info, { filter }) + posts: async (parent, args, ctx, info) => { + const page = await resolveGraph(ctx, info, Post.query(), { + paginate: CursorPaginator({ take: 10, fields: ["-id"] }), + }) + return page }, }, } ``` -Supported operators: - -- `exact` -- `in` -- TODO: `lt`, `gt`, `lte`, `gte`, `like`, `ilike`, `contains`, `icontains` - -#### Filtering nested relations - -You can filter nested relations with a nested filter: - -```ts -UserModel.query().withGraphQL(info, { - filter: { - id: 123, - posts: { - date: "2020-10-01", - }, - }, -}) -``` - -Note that it only works reasonably for one-to-many relations, as in the example above. +[More details and examples for pagination.](docs/pagination.md) -For instance, filtering posts with `{ author: { name: "John" } }` will not work as expected. +## Filters -#### Filtering with model modifiers +Both root and nested queries can be filtered with GraphQL arguments: -If you define modifiers on a model class: - -```ts -export class PostModel extends Model { - static modifiers = { - public: (query) => query.whereNull("delete_time"), - search: (query, term) => query.where("text", "ilike", `%${term}%`), +```graphql +query get_all_posts { + posts(filter: { date: "2020-10-01", author_id__in: [123, 456] }) { + nodes { + id + text + } + cursor } } ``` -then you can filter results with: +Filters will run against database fields, or call model modifiers. -```ts -UserModel.query().withGraphQL(info, { - filter: { - public: true, // even though the actual value is ignored, sending true is a reasonable convention - search: "hello", - }, -}) -``` - -Modifier filters take precedence over raw field filters. - -### Query model modifiers - -All models can be filtered using query-level modifiers: +To enable filters, use: ```ts -PostModel.query().withGraphQL(info, { - modifiers: { - User: (query) => query.where("active", true), - }, +const resolveGraph = GraphResolver({ + Post: ModelResolver(PostModel, { + // enable all filters for all fields + filter: true, + // TODO: granular access + filter: { + date: true, + author_id: true, + published: true, // where published is a model modifier + }, + }), }) ``` -### Virtual attributes +[More details and examples for filters.](docs/filters.md) -Virtual attributes (getters on models) can be accessed as usual: +## Virtual attributes + +Virtual attributes (getters on models) can be accessed the same way as database fields: ```ts export class PostModel extends Model { + declare id: number + declare title: string + get url() { + assert(this.id) return `/${this.id}.html` } } @@ -260,62 +259,129 @@ query get_all_posts { } ``` -#### Virtual attribute dependencies +[More details and examples for virtual attributes.](docs/virtual-attributes.md) -If a getter relies on certain model fields (such as if `url` needs `title`), you will need to select all of them in the query. +## API -Alternatively, you can setup getter dependencies with `select.${field}` modifier, like this: +The following functions are exported: ```ts -export class PostModel extends Model { - static modifiers = { - "graphql.select.url": (query) => query.select(ref("title")), - } - - get url() { - assert(this.title !== undefined) - return `/${urlencode(this.title)}-${this.id}.html` - } -} +import { + GraphResolver, + ModuleResolver, + FieldResolver, + CursorPaginator, +} from "objection-graphql-resolver" ``` -#### Virtual attributes provided by the database - -`select.${field}` modifier can also be used to fill the virtual attribute with a raw subquery: - -```graphql -type Post { - id: ID - title: String - upper_title: String -} -``` +### Arguments reference ```ts -export class PostModel extends Model { - static modifiers = { - "graphql.select.upper_title": (query) => - query.select(raw("upper(title) as upper_title")), - } - - // Optionally for Typescript - declare readonly upper_title: string -} -``` - -### Global model modifiers - -The following model modifiers, when exist, are automatically applied on each query (including when resolving nested relations): +const resolveGraph = GraphResolver( + // Map GraphQL types to model resolvers (required) + { + Post: ModelResolver( + // Required: Objection.js model class + PostModel, + // Default: { fields: true } + { + // List fields that can be accessed via GraphQL, + // or true = all fields can be accessed + fields: { + // Select field from database + id: true, + // Call model getter with this name + url: true, + // Descend into relation + // (related model must be also registered in this graph resolver) + author: true, + // Modify query when this field is resolved + preview: (query) => + query.select(raw("substr(text,1,100) as preview")), + // Same as text: true + text: FieldResolver(), + // Custom field resolver + text2: FieldResolver({ + // Source database field + modelField: "text", + }), + preview2: FieldResolver({ + // Modify query + select: (query) => + query.select(raw("substr(text,1,100) as preview2")), + // Post-process selected value + clean( + // Selected value + preview, + // Current instance + post, + // Query context + context, + ) { + if (preview.length < 100) { + return preview + } else { + return preview + "..." + } + }, + }), + // Select all objects in one-to-many relation + comments: true, + comments: FieldResolver({ + // Paginate subquery in one-to-many relation + paginate: CursorPaginator( + // Pagination options + // Default: { take: 10, fields: ["id"] } + { + // How many object to take per page + take: 10, + // Which fields to use for ordering + // Prefix with - for descending sort + fields: ["name", "-id"], + }, + ), + // Enable filters on one-to-many relation + filters: true, + }), + }, + // Modify all queries to this model + modifier: (query) => query.orderBy("id", "desc"), + }, + ), + }, + // Options (default: empty) + { + // Callback: convert RequestContext into query context + // Default: merge RequestContext into query context as is + context(ctx) { + return { userId: ctx.passport.user.id } + }, + }, +) -```ts -export class PostModel extends Model { - static modifiers = { - // Applied on each query - graphql: (query) => query.where("is_hidden", false), - // Applied on each query that is returning an array (not a single object) - "graphql.many": (query) => query.orderBy("publish_time", "desc"), - // Applied on each top-level query (not nested relation) - "graphql.top": (query) => query.where("is_top", true), - } +const resolvers = { + Query: { + posts: async (parent, args, context, info) => { + const page = await resolveGraph( + // Resolver context (required) + // Will be merged into query context, + // possibly converted with GraphResolver's options.context callback + context, + // GraphQLResolveInfo object, as passed by GraphQL executor (required) + info, + // Root query (required) + Post.query(), + // Default: empty + { + // Paginator (only works for list queries) + // Default: resolve list query as is + paginate: CursorPaginator({ take: 10, fields: ["-id"] }), + // Enable filters + filters: true, + }, + ) + return page + }, + }, } ``` diff --git a/docs/filters.md b/docs/filters.md new file mode 100644 index 0000000..51d8ba6 --- /dev/null +++ b/docs/filters.md @@ -0,0 +1,96 @@ +# Filters + +Both root and nested queries can be filtered with GraphQL arguments: + +```graphql +scalar Filter + +type Query { + posts(filter: Filter): [Post!]! +} + +query get_all_posts { + posts(filter: { date: "2020-10-01", author_id__in: [123, 456] }) { + id + text + } +} +``` + +The above generates: + +```sql +SELECT id, text FROM posts WHERE date='2020-10-01' AND author_id IN (123, 456) +``` + +For security purposes, filters are disabled by default. To enable filters, use: + +```ts +const resolveGraph = GraphResolver({ + Post: ModelResolver(PostModel, { + // enable all filters for all fields + filter: true, + // TODO: granular access + filter: { + date: true, + author_id: true, + }, + }), +}) +``` + +To filter root query, use: + +```ts +const resolvers = { + Query: { + posts: async (parent, args, ctx, info) => { + const posts = await resolveGraph(ctx, info, Post.query(), { + filter: true, + }) + return posts + }, + }, +} +``` + +## Syntax + +```js +{ + field: value, + field__operator: value, +} +``` + +Supported operators: + +- `exact` +- `in` +- TODO: `lt`, `gt`, `lte`, `gte`, `like`, `ilike`, `contains`, `icontains` + +## Filtering with model modifiers + +Define modifiers on a model class: + +```ts +export class PostModel extends Model { + static modifiers = { + public: (query) => query.whereNull("delete_time"), + search: (query, term) => query.where("text", "ilike", `%${term}%`), + } +} +``` + +Then you can filter results with: + +```graphql +query get_all_posts { + posts(filter: { public: true, search: "hello" }) { + id + text + } +} +``` + +Modifier filters take precedence over database field filters. diff --git a/docs/pagination.md b/docs/pagination.md new file mode 100644 index 0000000..e7d7eed --- /dev/null +++ b/docs/pagination.md @@ -0,0 +1,117 @@ +# Pagination + +Root queries and one-to-many nested relations can be paginated. + +## Paginators + +The specific shape of the page object and the pagination logic is decoupled and is fully defined by a _paginator_. + +The library includes simple `CursorPaginator` implementation which traverses ordered rows with the following shape of the page object: + +```json +{ + "nodes": [ + { "id": 1, "foo": "bar" }, + { "id": 2, "foo": "baz" } + ], + "cursor": "xyzzy" +} +``` + +Different paginators such as providing Relay-style pagination can be implemented similarly. + +## Example + +This example demonstrates both root query and relation pagination. + +```graphql +type Post { + id: ID! + text: String! + author: User +} + +type User { + id: ID! + name: String! + posts: PostPage! + all_posts: [Post!]! +} + +type PostPage { + nodes: [Post!]! + cursor: String +} + +type Query { + user(id: ID!): User! + posts: PostPage! +} +``` + +```ts +class PostModel extends Model { + static tableName = "posts" + static get relationMappings() { + return { + author: { + relation: Model.BelongsToOneRelation, + modelClass: UserModel, + join: { from: "posts.author_id", to: "users.id" }, + }, + } + } +} + +class UserModel extends Model { + static tableName = "users" + static get relationMappings() { + return { + posts: { + relation: Model.HasManyRelation, + modelClass: PostModel, + join: { from: "posts.author_id", to: "users.id" }, + }, + } + } +} + +const resolveGraph = GraphResolver({ + User: ModelResolver(UserModel, { + fields: { + id: true, + name: true, + // If it were posts: true, all posts will be returned. + // Instead, return a page of posts + posts: FieldResolver({ + paginate: CursorPaginage({ take: 10, fields: ["-id"] }), + }), + // Should you want this, it's still possible to pull all posts (non-paginated) + // under a different GraphQL field + all_posts: FieldResolver({ modelField: "posts" }), + }, + }), + Post: ModelResolver(PostModel, { + fields: { + id: true, + text: true, + author: true, + }, + }), +}) + +const resolvers = { + Query: { + user: async (parent, args, ctx, info) => { + const user = await resolveGraph(ctx, info, User.query().findById(args.id)) + return user + }, + posts: async (parent, args, ctx, info) => { + const page = await resolveGraph(ctx, info, Post.query(), { + paginate: CursorPaginator({ take: 10, fields: ["-id"] }), + }) + return page + }, + }, +} +``` diff --git a/docs/relations.md b/docs/relations.md new file mode 100644 index 0000000..aeedf4d --- /dev/null +++ b/docs/relations.md @@ -0,0 +1,95 @@ +# Relations + +Relations will be fetched automatically using `withGraphFetched()` when resolving nested fields. + +Example: + +```graphql +type User { + id: ID! + name: String! + posts: [Post!]! +} + +type Post { + id: ID! + text: String! + author: User +} + +type Query { + user(id: ID!): User! + posts: [Post!]! +} + +query posts_with_author { + posts { + id + text + author { + name + } + } +} + +query user_with_posts { + user(id: ID!) { + name + posts { + id + title + } + } +} +``` + +```ts +const resolveGraph = GraphResolver({ + User: ModelResolver(UserModel, { + fields: { + id: true, + name: true, + // will use withGraphFetched("posts") + // and process subquery with Post model resolver defined below + posts: true, + }, + }), + // No resolver options = access to all fields + Post: ModelResolver(PostModel), +}) + +const resolvers = { + Query: { + user: async (parent, args, ctx, info) => { + const user = await resolveGraph(ctx, info, User.query().findById(args.id)) + return user + }, + posts: async (parent, args, ctx, info) => { + const page = await resolveGraph(ctx, info, Post.query(), { + paginate: CursorPaginator({ take: 10, fields: ["-id"] }), + }) + return page + }, + }, +} +``` + +Internally, this traverses `Model.relationMappings` and can handle unlimited nesting levels. Using the graph above, one could run a request like: + +```graphql +query deep_nesting { + posts { + id + text + author { + name + posts { + id + author { + name + } + } + } + } +} +``` diff --git a/docs/virtual-attributes.md b/docs/virtual-attributes.md new file mode 100644 index 0000000..ece25d7 --- /dev/null +++ b/docs/virtual-attributes.md @@ -0,0 +1,87 @@ +# Virtual attributes + +## Model getters + +Getters on objection.js instances can be pulled the same way as database fields: + +```ts +class PostModel extends Model { + get url() { + assert(this.id) + return `/${this.id}.html` + } +} + +const resolveGraph = GraphResolver({ + Post: ModelResolver(PostModel, { + fields: { + id: true, + title: true, + url: true, + }, + // or simply `fields: true` to allow all fields and getters + }), +}) +``` + +```graphql +query get_all_posts { + posts { + # Pull from database + id + title + # Use instance getter + url + } +} +``` + +## Virtual attribute dependencies + +If a getter relies on certain model fields (such as if `url` needs `slug`), you will need to select all of them in the query. + +You can automate this with: + +```ts +class PostModel extends Model { + get url() { + assert(this.slug) + return `/${this.slug}.html` + } +} + +const resolveGraph = GraphResolver({ + Post: ModelResolver(PostModel, { + fields: { + id: true, + slug: true, + text: true, + url: (query) => query.select("slug"), + }, + }), +}) +``` + +## Virtual attributes provided by the database + +Similarly, you can pull virtual attributes directly from the database: + +```graphql +type Post { + id: ID + title: String + upper_title: String +} +``` + +```ts +const resolveGraph = GraphResolver({ + Post: ModelResolver(PostModel, { + fields: { + id: true, + title: true, + upper_title: (query) => query.select(raw("upper(title) as upper_title")), + }, + }), +}) +``` diff --git a/package.json b/package.json index e98b90d..30f2c46 100644 --- a/package.json +++ b/package.json @@ -1,15 +1,15 @@ { - "name": "objection-fetch-graphql", - "description": "objection.js plugin: resolve GraphQL query using fetchGraph", + "name": "objection-graphql-resolver", + "description": "objection.js plugin: resolve GraphQL query using withGraphFetched", "version": "0.0.0-development", "repository": { "type": "git", - "url": "https://github.com/IlyaSemenov/objection-fetch-graphql.git" + "url": "https://github.com/IlyaSemenov/objection-graphql-resolver.git" }, "author": "Ilya Semenov", "license": "MIT", "main": "dist/index.js", - "types": "dist/types.d.ts", + "types": "dist/index.d.ts", "files": [ "dist" ], @@ -36,7 +36,10 @@ ] }, "dependencies": { - "graphql-parse-resolve-info": "^4.9.0" + "graphql-parse-resolve-info": "^4.10.0" + }, + "peerDependencies": { + "objection": "^2" }, "devDependencies": { "@commitlint/cli": "^11.0.0", @@ -50,16 +53,15 @@ "eslint-plugin-prettier": "^3.1.4", "eslint-plugin-simple-import-sort": "^5.0.3", "graphql": "^15.4.0", - "graphql-request": "^3.3.0", + "graphql-request": "^3.4.0", "graphql-tag": "^2.11.0", "husky": "^4.3.0", - "knex": "^0.21.12", + "knex": "^0.21.14", "lint-staged": "^10.5.1", - "objection": "^2.2.3", + "objection": "^2.2.5", "prettier": "^2.1.2", "rollup": "^2.33.1", "rollup-plugin-cleaner": "^1.0.0", - "rollup-plugin-copy": "^3.3.0", "rollup-plugin-typescript2": "^0.29.0", "semantic-release": "^17.2.2", "sqlite3": "^5.0.0", diff --git a/rollup.config.js b/rollup.config.js index eced013..da9c5af 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,5 +1,4 @@ import cleaner from "rollup-plugin-cleaner" -import copy from "rollup-plugin-copy" import typescript from "rollup-plugin-typescript2" export default { @@ -13,11 +12,7 @@ export default { plugins: [ cleaner({ targets: ["./dist/"] }), typescript({ - tsconfigOverride: { exclude: ["**/*.test.ts"] }, - }), - copy({ - // I didn't manage to setup rollup-plugin-typescript2 to work with .d.ts - targets: [{ src: "src/types.d.ts", dest: "dist" }], + tsconfigOverride: { exclude: ["**/*.test.ts", "src/tests"] }, }), ], external: ["graphql-parse-resolve-info", "objection"], diff --git a/src/filter.ts b/src/filter.ts new file mode 100644 index 0000000..3f3e6dc --- /dev/null +++ b/src/filter.ts @@ -0,0 +1,69 @@ +import { AnyQueryBuilder } from "objection" + +import { is_plain_object } from "./helpers/is_plain_object" + +// TODO: per-field definitions +export type FiltersDef = boolean + +export type FilterScalarValue = null | string | number | boolean +export type FilterValue = FilterScalarValue | Exclude[] +export type Filter = { [property: string]: FilterValue } + +export function apply_filter({ + query, + filter, + args, +}: { + query: AnyQueryBuilder + filter: FiltersDef + args?: Record +}) { + if (!filter) { + return + } + const filter_obj = args?.filter + if (!filter_obj) { + return + } + if (!is_plain_object(filter_obj)) { + throw new Error(`Invalid filter: ${filter}, must be object.`) + } + const ThisModel = query.modelClass() + const table_name = ThisModel.tableName + for (const [field, value] of Object.entries(filter_obj)) { + if (ThisModel.modifiers?.[field]) { + // Call modifier + query.modify(field, value) + } else { + // Normal filter + const [dbfield, op] = field.split("__") + if (!op || op === "exact") { + if ( + !( + value === null || + typeof value === "string" || + typeof value === "number" + ) + ) { + throw new Error(`Unsupported filter value for ${table_name}.${field}`) + } + if (value !== null) { + query.where(dbfield, value) + } else { + query.whereNull(dbfield) + } + } else if (op === "in") { + if (!Array.isArray(value)) { + throw new Error( + `Invalid filter value for ${table_name}.${field}: must be an array.`, + ) + } + query.whereIn(dbfield, value) + } else { + throw new Error( + `Invalid filter ${table_name}.${field}: unsupported operator ${op}.`, + ) + } + } + } +} diff --git a/src/helpers/is_plain_object.ts b/src/helpers/is_plain_object.ts new file mode 100644 index 0000000..e289ca3 --- /dev/null +++ b/src/helpers/is_plain_object.ts @@ -0,0 +1,3 @@ +export function is_plain_object(obj: any): obj is Record { + return typeof obj === "object" && !Array.isArray(obj) +} diff --git a/src/helpers/run_after.ts b/src/helpers/run_after.ts new file mode 100644 index 0000000..df2145a --- /dev/null +++ b/src/helpers/run_after.ts @@ -0,0 +1,19 @@ +export function run_after(callback: (instance: any) => void) { + return (result: any) => { + if (Array.isArray(result)) { + return result.map(callback) + } else { + return callback(result) + } + } +} + +export function async_run_after(callback: (instance: any) => Promise) { + return (result: any) => { + if (Array.isArray(result)) { + return Promise.all(result.map(callback)) + } else { + return callback(result) + } + } +} diff --git a/src/index.ts b/src/index.ts index d2afcc8..0033fbc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,200 +1,4 @@ -import { GraphQLResolveInfo } from "graphql" -import { parseResolveInfo, ResolveTree } from "graphql-parse-resolve-info" -import { - AnyQueryBuilder, - QueryBuilder, - RelationMappings, - RelationType, -} from "objection" - -export type FilterNonNullScalarValue = string | number | boolean -export type FilterScalarValue = null | FilterNonNullScalarValue -export type FilterValue = - | FilterScalarValue - | FilterNonNullScalarValue[] - | Filter -export type Filter = { [property: string]: FilterValue } - -export type QueryModifier = QueryBuilder> = ( - qb: QB, -) => QB | void - -export type Modifiers = { - [type_name: string]: QueryModifier -} - -export interface FetchOptions { - filter?: Filter - modifiers?: Modifiers -} - -QueryBuilder.prototype.withGraphQL = function ( - this: QB, - info: GraphQLResolveInfo, - options?: FetchOptions, -) { - const resolve_tree = parseResolveInfo(info) as ResolveTree - return process_resolve_tree_node({ - ...options, - query: this, - resolve_tree, - }) -} - -function process_resolve_tree_node({ - query, - resolve_tree, - filter, - modifiers, - relation, -}: { - query: QB - resolve_tree: ResolveTree - filter?: Filter - modifiers?: Modifiers - relation?: RelationType -}) { - const Model = query.modelClass() - - const type_name = Object.keys(resolve_tree.fieldsByTypeName)[0] - - const type_query_modifier = modifiers?.[type_name] - if (type_query_modifier) { - type_query_modifier(query) - } - - if (filter !== undefined && !isFilterObject(filter)) { - throw Model.createValidationError({ - type: "InvalidFilter", - message: `Invalid filter ${type_name}: must be an object.`, - }) - } - - // Pull the list of getters from Model - // see https://stackoverflow.com/a/39310917/189806 - const getters = new Set( - Object.entries(Object.getOwnPropertyDescriptors(Model.prototype)) - .filter(([, descriptor]) => typeof descriptor.get === "function") - .map(([key]) => key), - ) - - // List of relation mappings - // Static-cast them to RelationMappings, because thunk has already been resolved by now. - const relations = Model.relationMappings as RelationMappings - - // Run select() and withGraphFetched() for fields requested in GraphQL query - let has_selected_id = false - for (const resolve_subtree of Object.values( - resolve_tree.fieldsByTypeName[type_name], - )) { - const field = resolve_subtree.name - const modifier_name = `graphql.select.${field}` - const has_modifier = Model.modifiers?.[modifier_name] - - if (relations[field]) { - // Nested relation - query.withGraphFetched(`${field}(${field})`).modifiers({ - [field]: (subquery) => - process_resolve_tree_node({ - query: subquery, - resolve_tree: resolve_subtree, - filter: filter?.[field] as Filter, - modifiers, - relation: relations[field].relation, - }), - }) - } else if (getters.has(field) || has_modifier) { - // Getter - do nothing, it will be pulled by the external graphql resolver runner - // Modifier - do nothing, it's supposed to fill this.field - } else { - // Normal field - select() it - query.select(field) - if (field === Model.idColumn) { - has_selected_id = true - } - } - - // Call field modifier - if (has_modifier) { - query.modify(modifier_name) - } - } - - if (!has_selected_id) { - // Always select ID: - // 1. This is useful for potential $query() - // 2. This avoid automatic "select *" when not a single normal field is selected - query.select(Model.idColumn) - } - - // Add where() clauses based on the provided filter object - if (filter) { - for (const [field, value] of Object.entries(filter)) { - if (value === undefined) { - throw Model.createValidationError({ - type: "InvalidFilter", - message: `Invalid filter ${type_name}.${field}: undefined.`, - }) - } - if (relations[field]) { - // Nested field filter - // Ignore - processed above - } else if (Model.modifiers?.[field]) { - // Call modifier - query.modify(field, value) - } else { - // Normal filter - if (isFilterObject(value)) { - throw Model.createValidationError({ - type: "InvalidFilter", - message: `Invalid filter ${type_name}.${field}: must not be an object.`, - }) - } - const [dbfield, op] = field.split("__") - if (!op || op === "exact") { - if (Array.isArray(value)) { - throw Model.createValidationError({ - type: "InvalidFilter", - message: `Invalid filter ${type_name}.${field}: must not be an array.`, - }) - } - if (value !== null) { - query.where(dbfield, value) - } else { - query.whereNull(dbfield) - } - } else if (op === "in") { - if (!Array.isArray(value)) { - throw Model.createValidationError({ - type: "InvalidFilter", - message: `Invalid filter ${type_name}.${field}: must be an array.`, - }) - } - query.whereIn(dbfield, value) - } else { - throw Model.createValidationError({ - type: "InvalidFilter", - message: `Invalid filter ${type_name}.${field}: unsupported operator ${op}.`, - }) - } - } - } - } - - if (Model.modifiers?.graphql) { - query.modify("graphql") - } - if (Model.modifiers?.["graphql.many"] && !query.has("first")) { - // TODO: exclude XxxOne relations? - query.modify("graphql.many") - } - if (!relation && Model.modifiers?.["graphql.top"]) { - query.modify("graphql.top") - } - - return query -} - -function isFilterObject(obj: any): obj is Filter { - return typeof obj === "object" && !Array.isArray(obj) -} +export { FieldResolver } from "./resolver/field" +export { ModelResolver } from "./resolver/model" +export { GraphResolver } from "./resolver/graph" +export { CursorPaginator } from "./paginators/cursor" diff --git a/src/paginators/cursor.ts b/src/paginators/cursor.ts new file mode 100644 index 0000000..4b45ce0 --- /dev/null +++ b/src/paginators/cursor.ts @@ -0,0 +1,112 @@ +import { Model, QueryBuilder, raw } from "objection" + +import { PaginatorFn } from "." + +export interface CursorPaginatorOptions { + fields: string[] + take: number +} + +export interface CursorPaginatorArgs { + cursor?: string + take?: number +} + +export interface CursorPaginatorPage { + nodes: M[] + cursor?: string +} + +export function CursorPaginator( + options?: Partial, +): PaginatorFn> { + const paginator_options: CursorPaginatorOptions = { + fields: ["id"], + take: 10, + ...options, + } + + const fields: Array<{ + name: string + desc: boolean + }> = paginator_options.fields.map((field) => { + if (field.startsWith("-")) { + return { name: field.slice(1), desc: true } + } else { + return { name: field, desc: false } + } + }) + + const create_cursor = (instance: any) => { + return JSON.stringify( + fields.map((field) => { + const value = instance[field.name] + if (value === undefined) { + throw new Error( + `Unable to create cursor: undefined field ${field.name}`, + ) + } + return String(value) + }), + ) + } + + const set_query_cursor = (query: QueryBuilder, cursor: string) => { + const values = JSON.parse(cursor) + type P = [string, any] + const left: P[] = [] + const right: P[] = [] + for (let i = 0; i < fields.length; ++i) { + const field = fields[i] + const field_part = field.desc ? right : left + const value_part = field.desc ? left : right + field_part.push(["??", field.name]) + value_part.push(["?", values[i]]) + } + const get_placeholders = (pairs: P[]) => pairs.map(([p]) => p) + const get_values = (pairs: P[]) => pairs.map(([, v]) => v) + const cond = raw( + `(${get_placeholders(left).join(",")}) > (${get_placeholders(right).join( + ",", + )})`, + ...get_values(left), + ...get_values(right), + ) + query.where(cond) + } + + const paginate: PaginatorFn> = ( + query: QueryBuilder, + args?: CursorPaginatorArgs, + ): QueryBuilder> => { + const take = Number(args?.take) || paginator_options.take + const cursor = args?.cursor + + // Set query order + query.clearOrder() + fields.forEach((field) => + query.orderBy(field.name, field.desc ? "desc" : "asc"), + ) + + if (cursor) { + set_query_cursor(query, cursor) + } + query.limit(take + 1) + + query.runAfter((nodes) => { + if (!Array.isArray(nodes)) { + throw new Error(`Paginator called for single result query.`) + } + let cursor: string | undefined + if (nodes.length > take) { + cursor = create_cursor(nodes[take - 1]) + nodes = nodes.slice(0, take) + } + return { nodes, cursor } + }) + return (query as unknown) as QueryBuilder> + } + + paginate.path = ["nodes"] + return paginate +} diff --git a/src/paginators/index.ts b/src/paginators/index.ts new file mode 100644 index 0000000..f57888e --- /dev/null +++ b/src/paginators/index.ts @@ -0,0 +1,6 @@ +import { Model, QueryBuilder } from "objection" + +export type PaginatorFn = { + (query: QueryBuilder, args?: any): QueryBuilder + path: [string] +} diff --git a/src/resolver/field.ts b/src/resolver/field.ts new file mode 100644 index 0000000..e82372e --- /dev/null +++ b/src/resolver/field.ts @@ -0,0 +1,58 @@ +import { Model, QueryBuilder } from "objection" + +import { FiltersDef } from "../filter" +import { async_run_after } from "../helpers/run_after" +import { PaginatorFn } from "../paginators" +import { AnyContext } from "./graph" +import { ModelFieldResolverFn } from "./model" + +export interface FieldResolverOptions { + modelField?: string + select?: FieldResolverFn + filter?: FiltersDef + paginate?: PaginatorFn + clean?(value: any, instance: M, context: AnyContext): any +} + +export type FieldResolverFn = ( + query: QueryBuilder, + field: string, + resolve_model_field: ModelFieldResolverFn, +) => void + +export function FieldResolver( + options?: FieldResolverOptions, +): FieldResolverFn { + const field_options: FieldResolverOptions = { ...options } + + const clean_field = field_options.clean + + return function resolve(query, field, resolve_model_field) { + if (field_options.select) { + field_options.select(query, field, resolve_model_field) + } else { + resolve_model_field({ + model_field: field_options.modelField || field, + filter: field_options.filter, + paginate: field_options.paginate, + }) + } + if (clean_field) { + const context = query.context() + query.runAfter( + async_run_after(async (instance: any) => { + if (!instance) { + // Supposedly, single query builder returning NULL + return instance + } + instance[field] = await clean_field( + instance[field], + instance, + context, + ) + return instance + }), + ) + } + } +} diff --git a/src/resolver/graph.ts b/src/resolver/graph.ts new file mode 100644 index 0000000..d5e4464 --- /dev/null +++ b/src/resolver/graph.ts @@ -0,0 +1,85 @@ +import { GraphQLResolveInfo } from "graphql" +import { parseResolveInfo, ResolveTree } from "graphql-parse-resolve-info" +import { Model, ModelType, QueryBuilder } from "objection" + +import { apply_filter, FiltersDef } from "../filter" +import { PaginatorFn } from "../paginators" +import { ModelResolverFn } from "./model" + +export type AnyContext = Record + +export interface GraphResolverOptions { + context?: (context: AnyContext) => AnyContext +} + +export interface QueryOptions { + filter?: FiltersDef + paginate?: PaginatorFn +} + +export type ResolveTreeFn = (args: { + tree: ResolveTree + query: QueryBuilder + filter?: FiltersDef + paginate?: PaginatorFn +}) => void + +export function GraphResolver( + model_resolvers: Record>, + options?: GraphResolverOptions, +) { + const graph_options: GraphResolverOptions = { ...options } + + return function resolve< + QB extends QueryBuilder, + O extends QueryOptions> + >( + context: AnyContext, + info: GraphQLResolveInfo, + query: QB, + options?: O, + ): O extends { + paginate: PaginatorFn + } + ? ReturnType + : QB { + const query_options: QueryOptions> = { ...options } + if (context) { + query.context( + graph_options.context ? graph_options.context(context) : context, + ) + } + + const resolve_tree: ResolveTreeFn = ({ tree, query, filter, paginate }) => { + const { args } = tree + let type = Object.keys(tree.fieldsByTypeName)[0] + if (paginate) { + // Skip page subtree(s) + for (const field of paginate.path) { + tree = tree.fieldsByTypeName[type][field] + type = Object.keys(tree.fieldsByTypeName)[0] + } + } + const resolve_model = model_resolvers[type] + if (!resolve_model) { + throw new Error(`Model resolver not found for type ${type}`) + } + resolve_model({ tree, type, query, resolve_tree }) + if (filter) { + apply_filter({ query, filter, args }) + } + if (paginate) { + paginate(query, args) + } + } + + resolve_tree({ + tree: parseResolveInfo(info) as ResolveTree, + query, + filter: query_options.filter, + paginate: query_options.paginate, + }) + + return query as any // I have no idea how to cast this properly. + } +} diff --git a/src/resolver/model.ts b/src/resolver/model.ts new file mode 100644 index 0000000..7f0efd6 --- /dev/null +++ b/src/resolver/model.ts @@ -0,0 +1,183 @@ +import { ResolveTree } from "graphql-parse-resolve-info" +import { + Model, + ModelClass, + ModelConstructor, + QueryBuilder, + ref, + RelationMappings, +} from "objection" + +import { FiltersDef } from "../filter" +import { run_after } from "../helpers/run_after" +import { PaginatorFn } from "../paginators" +import { FieldResolver, FieldResolverFn } from "./field" +import { ResolveTreeFn } from "./graph" + +export interface ModelResolverOptions { + modifier?: Modifier + fields?: Record> | true +} + +export type Modifier = (qb: QueryBuilder) => void + +export type SimpleFieldResolver = + | true + | string + | FieldResolverFn + +export type ModelResolverFn = (args: { + tree: ResolveTree + type: string + query: QueryBuilder + resolve_tree: ResolveTreeFn +}) => void + +export type ModelFieldResolverFn = (args: { + model_field: string + filter?: FiltersDef + paginate?: PaginatorFn +}) => void + +export function ModelResolver( + model_class: ModelConstructor, + options?: ModelResolverOptions, +): ModelResolverFn { + const model_options: ModelResolverOptions = { + // inject defaults here + fields: true, + ...options, + } + + const ThisModel = model_class as ModelClass + + // Pull the list of getter names from Model + // see https://stackoverflow.com/a/39310917/189806 + const getter_names = new Set( + Object.entries(Object.getOwnPropertyDescriptors(ThisModel.prototype)) + .filter(([, descriptor]) => typeof descriptor.get === "function") + .map(([key]) => key), + ) + + // List of model relations + // Static-cast the value to RelationMappings, because if it was a thunk, it has been already resolved by now. + const relations = ThisModel.relationMappings as RelationMappings + + // Default field resolver + const resolve_field: FieldResolverFn = FieldResolver() + + // Per-field resolvers + const field_resolvers: Record> | null = + model_options.fields === true ? null : {} + if (field_resolvers) { + const fields = model_options.fields as Record> + for (const field of Object.keys(fields)) { + const r0 = fields[field] + let r: FieldResolverFn + if (typeof r0 === "function") { + r = r0 + } else if (r0 === true) { + r = resolve_field + } else if (typeof r0 === "string") { + r = FieldResolver({ modelField: r0 }) + } else { + throw new Error( + `Field resolver must be a function, string, or true; found ${r0}`, + ) + } + field_resolvers[field] = r + } + } + + return function resolve({ tree, type, query, resolve_tree }) { + const ThisModel = query.modelClass() + if (model_class !== (ThisModel as ModelConstructor)) { + throw new Error( + `Mismatching query model for ${type} model resolver (expected ${model_class}, found ${ThisModel})`, + ) + } + + if (model_options.modifier) { + model_options.modifier(query) + } + + for (const subtree of Object.values(tree.fieldsByTypeName[type])) { + const field = subtree.name + const r = field_resolvers ? field_resolvers[field] : resolve_field + if (!r) { + throw new Error(`No field resolver defined for field ${type}.${field}`) + } + + // Base model field resolver + const resolve_model_field: ModelFieldResolverFn = ({ + model_field, + filter, + paginate, + }) => { + if (getter_names.has(field)) { + // Do nothing + } else if (relations[model_field]) { + // Nested relation + if (paginate) { + // withGraphFetched will disregard paginator's runAfter callback (which converts object list into cursor and nodes) + // Save it locally and then re-inject + let paginated_results: any + query + .withGraphFetched(`${model_field}(${field}) as ${field}`, { + joinOperation: "leftJoin", // Remove after https://github.com/Vincit/objection.js/issues/1954 is fixed + maxBatchSize: 1, + }) + .modifiers({ + [field]: (subquery) => { + resolve_tree({ + tree: subtree, + query: subquery, + filter, + paginate, + }) + subquery.runAfter((results) => { + // Save paginated results + paginated_results = results + }) + }, + }) + query.runAfter( + // Re-inject paginated results + // They have been overwritten by objection.js by now + run_after((instance) => { + instance[field] = paginated_results + return instance + }), + ) + } else { + query + .withGraphFetched(`${model_field}(${field}) as ${field}`) + .modifiers({ + [field]: (subquery) => + resolve_tree({ tree: subtree, query: subquery, filter }), + }) + } + } else { + // Normal field - select() it + query.select( + field === model_field ? field : ref(model_field).as(field), + ) + } + } + + r(query, field, resolve_model_field) + } + + if ( + !query.has( + ((op: any) => + op.name === "select" && op.args[0] === ThisModel.idColumn) as any, + ) + ) { + // Always select ID: + // 1. This is useful for potential $query() + // 2. This avoid automatic "select *" when not a single normal field was selected + query.select(ThisModel.idColumn) + } + } +} diff --git a/src/tests/fixtures.ts b/src/tests/fixtures.ts new file mode 100644 index 0000000..6e71dd3 --- /dev/null +++ b/src/tests/fixtures.ts @@ -0,0 +1,35 @@ +import { PostModel } from "./models/post" +import { SectionModel } from "./models/section" +import { UserModel } from "./models/user" + +export async function create_objects() { + await SectionModel.query().insertGraph([ + { id: 1, slug: "news", name: "News" }, + { id: 2, slug: "editorial", name: "Editorial" }, + { id: 3, slug: "covid", name: "COVID-19" }, + ]) + + await UserModel.query().insertGraph([ + { id: 1, name: "John", password: "secret", default_section_id: 1 }, + { id: 2, name: "Mary", password: "mary123" }, + ]) + + await PostModel.query().insertGraph( + [ + { id: 1, author_id: 1, section_id: 1, text: "Oil price rising." }, + { id: 2, author_id: 1, section_id: 2, text: "Is communism dead yet?" }, + { id: 3, author_id: 2, section_id: 3, text: "Latest COVID figures." }, + { id: 4, author_id: 2, section_id: 1, text: "Good news from China." }, + { id: 5, author_id: 2, section_id: 1, text: "More good news!" }, + { id: 6, author_id: 1, section_id: 3, text: "COVID vs Flu?" }, + { + id: 7, + author_id: 1, + section_id: 1, + text: "This is a draft", + is_published: false, + }, + ], + { relate: true }, + ) +} diff --git a/src/tests/graph.ts b/src/tests/graph.ts new file mode 100644 index 0000000..6ff4020 --- /dev/null +++ b/src/tests/graph.ts @@ -0,0 +1,7 @@ +import { GraphResolver } from "objection-graphql-resolver" + +import { Post } from "./model_resolvers/post" +import { Section } from "./model_resolvers/section" +import { User } from "./model_resolvers/user" + +export const resolve_graph = GraphResolver({ User, Section, Post }) diff --git a/src/tests/main.test.ts b/src/tests/main.test.ts index e163bd4..ef984eb 100644 --- a/src/tests/main.test.ts +++ b/src/tests/main.test.ts @@ -1,275 +1,380 @@ import gql from "graphql-tag" import tap from "tap" -import { PostModel, SectionModel, UserModel } from "./models" +import { create_objects } from "./fixtures" import { use_client, use_db } from "./setup" tap.test("Main", async (tap) => { await use_db(tap) + await create_objects() const client = await use_client(tap) - await SectionModel.query().insertGraph([ - { id: 1, slug: "test", name: "Test" }, - { id: 2, slug: "news", name: "News" }, - { id: 3, slug: "hidden", name: "Hidden", is_hidden: true }, - ]) - - await UserModel.query().insertGraph( - [ - { id: 1, name: "John", password: "secret", default_section: { id: 1 } }, - { id: 2, name: "Mary" }, - ], - { relate: true }, - ) - - await PostModel.query().insertGraph( - [ - { - id: 1, - author: { id: 1 }, - section: { id: 1 }, - title: "Hello", - text: "Hello, world!", - }, - { id: 2, author: { id: 1 }, title: "Bye", text: "Bye-bye, cruel world!" }, - { id: 3, author: { id: 2 }, section: { id: 3 }, title: "Foo" }, - { id: 4, author: { id: 2 }, section: { id: 1 }, title: "Bar" }, - ], - { relate: true }, - ) - - tap.matchSnapshot( - await client.request( - gql` - { - user(id: 1) { - id - name - posts { + await tap.test("fetch existing object", async (tap) => { + tap.matchSnapshot( + await client.request( + gql` + { + user(id: 1) { id - title - text + name } } - } - `, - ), - "User with id 1 and his posts", - ) + `, + ), + ) + }) - tap.same( - await client.request( - gql` - { - user(id: 800) { - id - name + await tap.test("fetch missing object", async (tap) => { + tap.same( + await client.request( + gql` + { + user(id: 9562876) { + id + name + } } - } - `, - ), - { user: null }, - ) + `, + ), + { user: null }, + ) + }) - tap.matchSnapshot( - await client.request( - gql` - { - posts(filter: { author_id: 2 }) { - id - title - author { + await tap.test("model getter", async (tap) => { + tap.matchSnapshot( + await client.request( + gql` + { + section(slug: "news") { + id name + url } } - } - `, - ), - "Posts where author_id=2", - ) + `, + ), + ) + }) - tap.matchSnapshot( - await client.request( - gql` - { - posts(filter: { title__in: ["Hello", "Foo"] }) { - id - title + await tap.test("raw SQL selector", async (tap) => { + tap.matchSnapshot( + await client.request( + gql` + { + section(slug: "news") { + id + slug + upper_slug + } } - } - `, - ), - "Posts where title is Hello or Foo", - ) + `, + ), + ) + }) - tap.matchSnapshot( - await client.request( - gql` - { - posts(filter: { section_id: 1 }) { - id - title - author { + await tap.test("field cleaner", async (tap) => { + tap.matchSnapshot( + await client.request( + gql` + { + user(id: 1) { + id name } - section { - slug - } } - } - `, - ), - "Posts with both author and section (multiple relations)", - ) - - tap.matchSnapshot( - await client.request( - gql` - { - posts { - url + `, + ), + "public fields", + ) + tap.matchSnapshot( + await client.request( + gql` + { + user(id: 1) { + id + name + password + } } - } - `, - ), - "Posts with url only (test fields dependency)", - ) - - tap.matchSnapshot( - await client.request( - gql` - { - posts { - url - section { + `, + ), + "reject password to public", + ) + tap.matchSnapshot( + await client.request( + gql` + { + user(id: 1) { + id name + password } } - } - `, - ), - "Posts with url and section without slug (test nested fields dependency)", - ) - - tap.rejects( - client.request( - gql` - { - user(id: 1) { - name - password + `, + undefined, + { user_id: "2" }, + ), + "reject password to other users", + ) + tap.matchSnapshot( + await client.request( + gql` + { + user(id: 1) { + id + name + password + } } - } - `, - ), - "Reject retrieving user password (field not defined in schema)", - ) + `, + undefined, + { user_id: "1" }, + ), + "return own password to user", + ) + }) - tap.matchSnapshot( - await client.request( - gql` - { - user(id: 1) { - user_name: name + await tap.test("root pagination", async (tap) => { + tap.matchSnapshot( + await client.request( + gql` + { + sections { + nodes { + id + slug + name + } + cursor + } } - } - `, - ), - "User with name->user_name (field alias)", - ) + `, + ), + ) + }) - tap.matchSnapshot( - await client.request( + await tap.test("root pagination with arguments", async (tap) => { + const { sections } = await client.request( gql` { - posts(filter: { published: true }) { - id - title - section { + sections(take: 1) { + nodes { + id slug + name } + cursor } } `, - ), - "Published posts (filter modifier)", - ) - - tap.matchSnapshot( - await client.request( - gql` - { - posts(filter: { search: "Bye" }) { - id - title - } - } - `, - ), - "Posts with 'Bye' in title (parameterized filter modifier)", - ) - - tap.matchSnapshot( - await client.request( - gql` - { - sections { - id - name + ) + tap.matchSnapshot(sections, "take 1") + tap.matchSnapshot( + await client.request( + gql` + query more_sections($cursor: String) { + sections(take: 100, cursor: $cursor) { + nodes { + id + slug + name + } + cursor + } } - } - `, - ), - "All sections, ordered, excluding hidden (test both global model modifiers)", - ) + `, + { cursor: sections.cursor }, + ), + "take 100 with cursor", + ) + }) - tap.matchSnapshot( - await client.request( - gql` - { - posts(filter: { section_id: 3 }) { - id - title - section { + tap.test("nested pagination", async (tap) => { + tap.matchSnapshot( + await client.request( + gql` + { + user(id: 1) { + id name + posts { + nodes { + id + text + section { + url + } + url + } + cursor + } } } - } - `, - ), - "Find post under Hidden section (test global model modifier)", - ) + `, + ), + ) + }) - tap.matchSnapshot( - await client.request( - gql` - { - posts(filter: { under_default_section: { user_id: 1 } }) { - id - title - section { + tap.test("double nested pagination", async (tap) => { + tap.matchSnapshot( + await client.request( + gql` + { + user(id: 1) { id name + posts { + nodes { + id + text + author { + name + } + url + section { + url + name + posts { + nodes { + text + url + author { + name + } + section { + url + } + } + cursor + } + } + } + cursor + } } } - } - `, - ), - "Find post under User ID=1's default section (test async model modifier)", - ) + `, + ), + ) + }) - tap.matchSnapshot( - await client.request( - gql` - { - user(id: 1) { - id - name - upper_name + tap.test("root filter", async (tap) => { + tap.test("by field", async (tap) => { + tap.matchSnapshot( + await client.request( + gql` + { + posts(filter: { author_id: 2 }, take: 10) { + nodes { + id + text + author { + id + name + } + } + } + } + `, + ), + "author_id: 2", + ) + }) + tap.test("__in", async (tap) => { + tap.matchSnapshot( + await client.request( + gql` + { + posts(filter: { id__in: [3, 5] }, take: 10) { + nodes { + id + text + } + } + } + `, + ), + "id__in: [3, 5]", + ) + }) + tap.test("by modifier", async (tap) => { + tap.matchSnapshot( + await client.request( + gql` + { + posts(filter: { is_draft: true }, take: 10) { + nodes { + id + text + } + } + } + `, + ), + "is_draft", + ) + }) + tap.test("filter by parametrized modifier", async (tap) => { + tap.matchSnapshot( + await client.request( + gql` + { + posts(filter: { search: "news" }, take: 10) { + nodes { + id + text + } + } + } + `, + ), + 'search: "news"', + ) + }) + }) + + tap.test("root filter when filters not enabled", async (tap) => { + tap.matchSnapshot( + await client.request( + gql` + { + sections(filter: { slug: "news" }) { + nodes { + id + name + } + } } - } - `, - ), - "User with id 1 with his upper_name", - ) + `, + ), + "all sections, not only news", + ) + }) + + tap.test("nested filter", async (tap) => { + tap.matchSnapshot( + await client.request( + gql` + { + section(slug: "news") { + posts(filter: { author_id: 2 }, take: 10) { + nodes { + id + text + author { + id + name + } + section { + slug + } + } + } + } + } + `, + ), + "section slug, author_id: 2", + ) + }) }) diff --git a/src/tests/migrations.ts b/src/tests/migrations.ts new file mode 100644 index 0000000..6e56c76 --- /dev/null +++ b/src/tests/migrations.ts @@ -0,0 +1,25 @@ +import Knex from "knex" + +export async function create_tables(knex: Knex) { + await knex.schema.createTable("users", function (table) { + table.integer("id").primary() + table.string("name").notNullable() + table.string("password").notNullable() + table.integer("default_section_id") + table.foreign("default_section_id").references("id").inTable("sections") + }) + await knex.schema.createTable("sections", function (table) { + table.integer("id").primary() + table.string("slug").notNullable().unique() + table.string("name").notNullable() + }) + await knex.schema.createTable("posts", function (table) { + table.integer("id").primary() + table.string("text").notNullable() + table.boolean("is_published").notNullable().defaultTo(true) + table.integer("author_id").notNullable() + table.foreign("author_id").references("id").inTable("users") + table.integer("section_id").notNullable() + table.foreign("section_id").references("id").inTable("sections") + }) +} diff --git a/src/tests/model_resolvers/post.ts b/src/tests/model_resolvers/post.ts new file mode 100644 index 0000000..c000f9c --- /dev/null +++ b/src/tests/model_resolvers/post.ts @@ -0,0 +1,10 @@ +import { ModelResolver } from "objection-graphql-resolver" + +import { PostModel } from "../models/post" + +export const Post = ModelResolver(PostModel, { + modifier: (query) => { + query.orderBy("id", "desc") + }, + // No fields = all allowed +}) diff --git a/src/tests/model_resolvers/section.ts b/src/tests/model_resolvers/section.ts new file mode 100644 index 0000000..dec8e52 --- /dev/null +++ b/src/tests/model_resolvers/section.ts @@ -0,0 +1,25 @@ +import { raw } from "objection" +import { + CursorPaginator, + FieldResolver, + ModelResolver, +} from "objection-graphql-resolver" + +import { SectionModel } from "../models/section" + +export const Section = ModelResolver(SectionModel, { + modifier: (query) => { + query.orderBy("name") + }, + fields: { + id: true, + name: true, + slug: true, + url: (query) => query.select("slug"), + upper_slug: (query) => query.select(raw("upper(slug) as upper_slug")), + posts: FieldResolver({ + filter: true, + paginate: CursorPaginator({ take: 2 }), + }), + }, +}) diff --git a/src/tests/model_resolvers/user.ts b/src/tests/model_resolvers/user.ts new file mode 100644 index 0000000..1946785 --- /dev/null +++ b/src/tests/model_resolvers/user.ts @@ -0,0 +1,34 @@ +import { + CursorPaginator, + FieldResolver, + ModelResolver, +} from "objection-graphql-resolver" + +import { UserModel } from "../models/user" + +export const User = ModelResolver(UserModel, { + fields: { + id: true, + name: true, + password: FieldResolver({ + clean(password, user, context) { + if (context.user_id && context.user_id === user.id) { + return password + } else { + return undefined + } + }, + }), + posts: FieldResolver({ paginate: CursorPaginator({ take: 2 }) }), + posts_page: FieldResolver({ + modelField: "posts", + paginate: CursorPaginator({ take: 2 }), + }), + posts_by_one: FieldResolver({ + modelField: "posts", + paginate: CursorPaginator({ take: 1 }), + }), + all_posts: "posts", + all_posts_verbose: FieldResolver({ modelField: "posts" }), + }, +}) diff --git a/src/tests/models.ts b/src/tests/models.ts deleted file mode 100644 index 5ed2262..0000000 --- a/src/tests/models.ts +++ /dev/null @@ -1,149 +0,0 @@ -import Knex from "knex" -import { Model, QueryBuilder, raw } from "objection" -import { assert } from "tap" - -export class UserModel extends Model { - static tableName = "users" - static get relationMappings() { - return { - posts: { - relation: Model.HasManyRelation, - modelClass: PostModel, - join: { from: "posts.author_id", to: "users.id" }, - }, - default_section: { - relation: Model.BelongsToOneRelation, - modelClass: SectionModel, - join: { from: "users.default_section_id", to: "sections.id" }, - }, - } - } - - static modifiers = { - "graphql.select.upper_name": (query: QueryBuilder) => - query.select(raw("upper(name) as upper_name")), - } - - declare id: number - declare name: string - declare readonly upper_name: string - declare password: string - declare posts: PostModel[] - declare default_section_id: number - declare default_section: SectionModel -} - -export class SectionModel extends Model { - static tableName = "sections" - static get relationMappings() { - return { - posts: { - relation: Model.HasManyRelation, - modelClass: PostModel, - join: { from: "posts.section_id", to: "sections.id" }, - }, - } - } - - static modifiers = { - "graphql.top": (query: QueryBuilder) => - query.where("is_hidden", false), - "graphql.many": (query: QueryBuilder) => query.orderBy("name"), - } - - declare id: number - declare slug: string - declare name: string - declare is_hidden: boolean - declare posts: PostModel[] -} - -export class PostModel extends Model { - static tableName = "posts" - static get relationMappings() { - return { - author: { - relation: Model.BelongsToOneRelation, - modelClass: UserModel, - join: { from: "posts.author_id", to: "users.id" }, - }, - section: { - relation: Model.BelongsToOneRelation, - modelClass: SectionModel, - join: { from: "posts.section_id", to: "sections.id" }, - }, - } - } - - static modifiers = { - published(query: QueryBuilder) { - query.whereNotNull("section_id") - }, - search(query: QueryBuilder, term: string) { - query.where("title", "like", `%${term}%`) - }, - under_default_section( - query: QueryBuilder, - { user_id }: { user_id: string }, - ) { - query.runBefore(async function () { - const { default_section_id } = await UserModel.query( - this.context().transaction, - ).findById(user_id) - this.where("section_id", default_section_id) - }) - }, - "graphql.select.url": (query: QueryBuilder) => - query - .select("title") - .withGraphFetched("section(section_slug)") - .modifiers({ - section_slug: (query) => query.select("slug"), - }), - } - - declare id: number - declare title: string | null - declare text: string | null - declare author: UserModel - declare section: SectionModel - - get url() { - assert( - this.id !== undefined && - this.title !== undefined && - (this.section === null || this.section?.slug !== undefined), - ) - return ( - (this.section ? `/${this.section.slug}` : "") + - `/${this.title}-${this.id}` - ) - } -} - -export async function create_tables(knex: Knex) { - await knex.schema.createTable("users", function (table) { - table.integer("id").primary() - table.string("name") - table.string("password") - }) - await knex.schema.createTable("sections", function (table) { - table.integer("id").primary() - table.string("slug").notNullable().unique() - table.string("name") - table.boolean("is_hidden").notNullable().defaultTo(false) - }) - await knex.schema.alterTable("users", function (table) { - table.integer("default_section_id") - table.foreign("default_section_id").references("id").inTable("sections") - }) - await knex.schema.createTable("posts", function (table) { - table.integer("id").primary() - table.string("title") - table.string("text") - table.integer("author_id").notNullable() - table.foreign("author_id").references("id").inTable("users") - table.integer("section_id") - table.foreign("section_id").references("id").inTable("sections") - }) -} diff --git a/src/tests/models/post.ts b/src/tests/models/post.ts new file mode 100644 index 0000000..baa43c0 --- /dev/null +++ b/src/tests/models/post.ts @@ -0,0 +1,56 @@ +import assert from "assert" +import { Model, QueryBuilder } from "objection" + +import { SectionModel } from "./section" +import { UserModel } from "./user" + +export class PostModel extends Model { + static tableName = "posts" + static get relationMappings() { + return { + author: { + relation: Model.BelongsToOneRelation, + modelClass: UserModel, + join: { from: "posts.author_id", to: "users.id" }, + }, + section: { + relation: Model.BelongsToOneRelation, + modelClass: SectionModel, + join: { from: "posts.section_id", to: "sections.id" }, + }, + } + } + + static modifiers = { + is_draft(query: QueryBuilder) { + query.where("is_published", false) + }, + search(query: QueryBuilder, term: string) { + query.where("text", "like", `%${term}%`) + }, + under_default_section( + query: QueryBuilder, + { user_id }: { user_id: string }, + ) { + query.runBefore(async function () { + const { default_section_id } = await UserModel.query( + this.context().transaction, + ).findById(user_id) + this.where("section_id", default_section_id) + }) + }, + } + + declare id: number + declare is_published: boolean + declare text: string + declare author_id: number + declare author: UserModel + declare section_id: number + declare section: SectionModel + + get url() { + assert(this.id !== undefined && this.section?.slug !== undefined) + return `/${this.section.slug}/${this.id}` + } +} diff --git a/src/tests/models/section.ts b/src/tests/models/section.ts new file mode 100644 index 0000000..029dda9 --- /dev/null +++ b/src/tests/models/section.ts @@ -0,0 +1,27 @@ +import assert from "assert" +import { Model } from "objection" + +import { PostModel } from "./post" + +export class SectionModel extends Model { + static tableName = "sections" + static get relationMappings() { + return { + posts: { + relation: Model.HasManyRelation, + modelClass: PostModel, + join: { from: "posts.section_id", to: "sections.id" }, + }, + } + } + + declare id: number + declare slug: string + declare name: string + declare posts: PostModel[] + + get url() { + assert(this.slug !== undefined) + return `/${this.slug}` + } +} diff --git a/src/tests/models/user.ts b/src/tests/models/user.ts new file mode 100644 index 0000000..6bd344f --- /dev/null +++ b/src/tests/models/user.ts @@ -0,0 +1,29 @@ +import { Model } from "objection" + +import { PostModel } from "./post" +import { SectionModel } from "./section" + +export class UserModel extends Model { + static tableName = "users" + static get relationMappings() { + return { + posts: { + relation: Model.HasManyRelation, + modelClass: PostModel, + join: { from: "posts.author_id", to: "users.id" }, + }, + default_section: { + relation: Model.BelongsToOneRelation, + modelClass: SectionModel, + join: { from: "users.default_section_id", to: "sections.id" }, + }, + } + } + + declare id: number + declare name: string + declare password: string + declare posts: PostModel[] + declare default_section_id: number | null + declare default_section: SectionModel | null +} diff --git a/src/tests/resolvers.ts b/src/tests/resolvers.ts index 271a98d..978c9eb 100644 --- a/src/tests/resolvers.ts +++ b/src/tests/resolvers.ts @@ -1,24 +1,44 @@ -import { GraphQLResolveInfo } from "graphql" +import { CursorPaginator } from "objection-graphql-resolver" -import { PostModel, SectionModel, UserModel } from "./models" +import { resolve_graph } from "./graph" +import { PostModel } from "./models/post" +import { SectionModel } from "./models/section" +import { UserModel } from "./models/user" +import { Resolvers } from "./server" -type Resolver = ( - parent: unknown, - args: A, - ctx: unknown, - info: GraphQLResolveInfo, -) => any - -export const resolvers: Record>> = { +export const resolvers: Resolvers = { Query: { - user: (parent, { id }, ctx: unknown, info) => { - return UserModel.query().findById(id).withGraphQL(info) + user: async (_parent, { id }, ctx, info) => { + const user = await resolve_graph( + ctx, + info, + UserModel.query().findById(id), + ) + return user + }, + section: async (parent, { slug }, ctx, info) => { + const section = await resolve_graph( + ctx, + info, + SectionModel.query().findOne({ slug }), + ) + return section }, - sections: async (parent, { filter }, ctx, info) => { - return SectionModel.query().withGraphQL(info, { filter }) + sections: async (parent, args, ctx, info) => { + const page = await resolve_graph(ctx, info, SectionModel.query(), { + paginate: CursorPaginator({ + take: 2, + fields: ["name", "-id"], + }), + }) + return page }, - posts: async (parent, { filter }, ctx, info) => { - return PostModel.query().withGraphQL(info, { filter }) + posts: async (parent, args, ctx, info) => { + const page = await resolve_graph(ctx, info, PostModel.query(), { + paginate: CursorPaginator({ take: 2, fields: ["-id"] }), + filter: true, + }) + return page }, }, } diff --git a/src/tests/schema.ts b/src/tests/schema.ts index 0a5a003..cfe8e94 100644 --- a/src/tests/schema.ts +++ b/src/tests/schema.ts @@ -1,33 +1,51 @@ import gql from "graphql-tag" export const schema = gql` + scalar Filter + type User { id: ID! - name: String - upper_name: String - posts: [Post!]! + name: String! + # empty if not allowed + password: String + posts(filter: Filter, cursor: String, take: Int): PostPage! + posts_page(filter: Filter, cursor: String, take: Int): PostPage! + posts_by_one(filter: Filter, cursor: String, take: Int): PostPage! + all_posts(filter: Filter): [Post!]! + all_posts_verbose(filter: Filter): [Post!]! } type Section { id: ID! + name: String! slug: String! - name: String + upper_slug: String! + url: String! + posts(filter: Filter, cursor: String, take: Int): PostPage! + } + + type SectionPage { + nodes: [Section!]! + cursor: String } type Post { id: ID! author: User! - section: Section - title: String - text: String + section: Section! + text: String! url: String! } - scalar Filter + type PostPage { + nodes: [Post!]! + cursor: String + } type Query { user(id: ID!): User - sections(filter: Filter): [Section!]! - posts(filter: Filter): [Post!]! + section(slug: String!): Section + sections(filter: Filter, cursor: String, take: Int): SectionPage! + posts(filter: Filter, cursor: String, take: Int): PostPage! } ` diff --git a/src/tests/server.ts b/src/tests/server.ts new file mode 100644 index 0000000..a45c344 --- /dev/null +++ b/src/tests/server.ts @@ -0,0 +1,29 @@ +import { ApolloServer } from "apollo-server" +import { GraphQLResolveInfo } from "graphql" + +import { resolvers } from "./resolvers" +import { schema } from "./schema" + +export interface ResolverContext { + user_id: number | null +} + +export type Resolver = ( + parent: unknown, + args: A, + ctx: ResolverContext, + info: GraphQLResolveInfo, +) => any + +export type Resolvers = Record<"Query", Record>> + +export function create_server() { + return new ApolloServer({ + typeDefs: schema, + resolvers, + context: ({ req }): ResolverContext => { + const user_id = Number(req.headers.user_id) || null + return { user_id } + }, + }) +} diff --git a/src/tests/setup.ts b/src/tests/setup.ts index 8dcfe71..56a0bd4 100644 --- a/src/tests/setup.ts +++ b/src/tests/setup.ts @@ -1,19 +1,19 @@ -import "objection-fetch-graphql" - -import { ApolloServer } from "apollo-server" import { GraphQLClient } from "graphql-request" import Knex from "knex" import { Model } from "objection" import tap from "tap" -import { create_tables } from "./models" -import { resolvers } from "./resolvers" -import { schema } from "./schema" +import { create_tables } from "./migrations" +import { create_server } from "./server" type Test = typeof tap.Test.prototype export async function use_db(tap: Test) { - const knex = Knex({ client: "sqlite3", connection: ":memory:" }) + const knex = Knex({ + client: "sqlite3", + connection: ":memory:", + useNullAsDefault: true, + }) tap.tearDown(async () => { await knex.destroy() }) @@ -22,7 +22,7 @@ export async function use_db(tap: Test) { } export async function use_client(tap: Test) { - const server = new ApolloServer({ typeDefs: schema, resolvers }) + const server = create_server() tap.tearDown(async () => { await server.stop() }) diff --git a/src/types.d.ts b/src/types.d.ts deleted file mode 100644 index aaa4021..0000000 --- a/src/types.d.ts +++ /dev/null @@ -1,17 +0,0 @@ -// I had to move this to a separate .d.ts file -// When placed in a .ts file, extending QueryBuilder emits error: -// Type parameter 'M' of exported interface has or is using private name 'Model'. ts(4004) - -import { GraphQLResolveInfo } from "graphql" - -import { FetchOptions } from "." - -// Export other types, so that it's possible to refer to this file in package.json types -export * from "." - -declare module "objection" { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - export interface QueryBuilder { - withGraphQL(info: GraphQLResolveInfo, options?: FetchOptions): this - } -} diff --git a/tap-snapshots/src-tests-main.test.ts-TAP.test.js b/tap-snapshots/src-tests-main.test.ts-TAP.test.js index d796358..ad0109a 100644 --- a/tap-snapshots/src-tests-main.test.ts-TAP.test.js +++ b/tap-snapshots/src-tests-main.test.ts-TAP.test.js @@ -5,243 +5,361 @@ * Make sure to inspect the output below. Do not ignore changes! */ 'use strict' -exports[`src/tests/main.test.ts TAP Main > All sections, ordered, excluding hidden (test both global model modifiers) 1`] = ` +exports[`src/tests/main.test.ts TAP Main double nested pagination > must match snapshot 1`] = ` Object { - "sections": Array [ - Object { - "id": "2", - "name": "News", - }, - Object { - "id": "1", - "name": "Test", + "user": Object { + "id": "1", + "name": "John", + "posts": Object { + "cursor": "[\\"2\\"]", + "nodes": Array [ + Object { + "author": Object { + "name": "John", + }, + "id": "1", + "section": Object { + "name": "News", + "posts": Object { + "cursor": "[\\"4\\"]", + "nodes": Array [ + Object { + "author": Object { + "name": "John", + }, + "section": Object { + "url": "/news", + }, + "text": "Oil price rising.", + "url": "/news/1", + }, + Object { + "author": Object { + "name": "Mary", + }, + "section": Object { + "url": "/news", + }, + "text": "Good news from China.", + "url": "/news/4", + }, + ], + }, + "url": "/news", + }, + "text": "Oil price rising.", + "url": "/news/1", + }, + Object { + "author": Object { + "name": "John", + }, + "id": "2", + "section": Object { + "name": "Editorial", + "posts": Object { + "cursor": null, + "nodes": Array [ + Object { + "author": Object { + "name": "John", + }, + "section": Object { + "url": "/editorial", + }, + "text": "Is communism dead yet?", + "url": "/editorial/2", + }, + ], + }, + "url": "/editorial", + }, + "text": "Is communism dead yet?", + "url": "/editorial/2", + }, + ], }, - ], + }, } ` -exports[`src/tests/main.test.ts TAP Main > Find post under Hidden section (test global model modifier) 1`] = ` +exports[`src/tests/main.test.ts TAP Main fetch existing object > must match snapshot 1`] = ` Object { - "posts": Array [ - Object { - "id": "3", - "section": Object { - "name": "Hidden", - }, - "title": "Foo", - }, - ], + "user": Object { + "id": "1", + "name": "John", + }, } ` -exports[`src/tests/main.test.ts TAP Main > Find post under User ID=1's default section (test async model modifier) 1`] = ` +exports[`src/tests/main.test.ts TAP Main field cleaner > public fields 1`] = ` Object { - "posts": Array [ - Object { - "id": "1", - "section": Object { - "id": "1", - "name": "Test", - }, - "title": "Hello", - }, - Object { - "id": "4", - "section": Object { - "id": "1", - "name": "Test", - }, - "title": "Bar", - }, - ], + "user": Object { + "id": "1", + "name": "John", + }, } ` -exports[`src/tests/main.test.ts TAP Main > Posts where author_id=2 1`] = ` +exports[`src/tests/main.test.ts TAP Main field cleaner > reject password to other users 1`] = ` Object { - "posts": Array [ - Object { - "author": Object { - "name": "Mary", - }, - "id": "3", - "title": "Foo", - }, - Object { - "author": Object { - "name": "Mary", - }, - "id": "4", - "title": "Bar", - }, - ], + "user": Object { + "id": "1", + "name": "John", + "password": null, + }, } ` -exports[`src/tests/main.test.ts TAP Main > Posts where title is Hello or Foo 1`] = ` +exports[`src/tests/main.test.ts TAP Main field cleaner > reject password to public 1`] = ` Object { - "posts": Array [ - Object { - "id": "1", - "title": "Hello", - }, - Object { - "id": "3", - "title": "Foo", - }, - ], + "user": Object { + "id": "1", + "name": "John", + "password": null, + }, } ` -exports[`src/tests/main.test.ts TAP Main > Posts with 'Bye' in title (parameterized filter modifier) 1`] = ` +exports[`src/tests/main.test.ts TAP Main field cleaner > return own password to user 1`] = ` Object { - "posts": Array [ - Object { - "id": "2", - "title": "Bye", + "user": Object { + "id": "1", + "name": "John", + "password": "secret", + }, +} +` + +exports[`src/tests/main.test.ts TAP Main model getter > must match snapshot 1`] = ` +Object { + "section": Object { + "id": "1", + "name": "News", + "url": "/news", + }, +} +` + +exports[`src/tests/main.test.ts TAP Main nested filter > section slug, author_id: 2 1`] = ` +Object { + "section": Object { + "posts": Object { + "nodes": Array [ + Object { + "author": Object { + "id": "2", + "name": "Mary", + }, + "id": "4", + "section": Object { + "slug": "news", + }, + "text": "Good news from China.", + }, + Object { + "author": Object { + "id": "2", + "name": "Mary", + }, + "id": "5", + "section": Object { + "slug": "news", + }, + "text": "More good news!", + }, + ], }, - ], + }, } ` -exports[`src/tests/main.test.ts TAP Main > Posts with both author and section (multiple relations) 1`] = ` +exports[`src/tests/main.test.ts TAP Main nested pagination > must match snapshot 1`] = ` Object { - "posts": Array [ - Object { - "author": Object { - "name": "John", - }, - "id": "1", - "section": Object { - "slug": "test", - }, - "title": "Hello", + "user": Object { + "id": "1", + "name": "John", + "posts": Object { + "cursor": "[\\"2\\"]", + "nodes": Array [ + Object { + "id": "1", + "section": Object { + "url": "/news", + }, + "text": "Oil price rising.", + "url": "/news/1", + }, + Object { + "id": "2", + "section": Object { + "url": "/editorial", + }, + "text": "Is communism dead yet?", + "url": "/editorial/2", + }, + ], }, - Object { - "author": Object { - "name": "Mary", + }, +} +` + +exports[`src/tests/main.test.ts TAP Main raw SQL selector > must match snapshot 1`] = ` +Object { + "section": Object { + "id": "1", + "slug": "news", + "upper_slug": "NEWS", + }, +} +` + +exports[`src/tests/main.test.ts TAP Main root filter __in > id__in: [3, 5] 1`] = ` +Object { + "posts": Object { + "nodes": Array [ + Object { + "id": "5", + "text": "More good news!", }, - "id": "4", - "section": Object { - "slug": "test", + Object { + "id": "3", + "text": "Latest COVID figures.", }, - "title": "Bar", - }, - ], + ], + }, } ` -exports[`src/tests/main.test.ts TAP Main > Posts with url and section without slug (test nested fields dependency) 1`] = ` +exports[`src/tests/main.test.ts TAP Main root filter by field > author_id: 2 1`] = ` Object { - "posts": Array [ - Object { - "section": Object { - "name": "Test", + "posts": Object { + "nodes": Array [ + Object { + "author": Object { + "id": "2", + "name": "Mary", + }, + "id": "5", + "text": "More good news!", }, - "url": "/test/Hello-1", - }, - Object { - "section": null, - "url": "/Bye-2", - }, - Object { - "section": Object { - "name": "Hidden", + Object { + "author": Object { + "id": "2", + "name": "Mary", + }, + "id": "4", + "text": "Good news from China.", }, - "url": "/hidden/Foo-3", - }, - Object { - "section": Object { - "name": "Test", + Object { + "author": Object { + "id": "2", + "name": "Mary", + }, + "id": "3", + "text": "Latest COVID figures.", }, - "url": "/test/Bar-4", - }, - ], + ], + }, } ` -exports[`src/tests/main.test.ts TAP Main > Posts with url only (test fields dependency) 1`] = ` +exports[`src/tests/main.test.ts TAP Main root filter by modifier > is_draft 1`] = ` Object { - "posts": Array [ - Object { - "url": "/test/Hello-1", - }, - Object { - "url": "/Bye-2", - }, - Object { - "url": "/hidden/Foo-3", - }, - Object { - "url": "/test/Bar-4", - }, - ], + "posts": Object { + "nodes": Array [ + Object { + "id": "7", + "text": "This is a draft", + }, + ], + }, } ` -exports[`src/tests/main.test.ts TAP Main > Published posts (filter modifier) 1`] = ` +exports[`src/tests/main.test.ts TAP Main root filter filter by parametrized modifier > search: "news" 1`] = ` Object { - "posts": Array [ - Object { - "id": "1", - "section": Object { - "slug": "test", - }, - "title": "Hello", - }, - Object { - "id": "3", - "section": Object { - "slug": "hidden", + "posts": Object { + "nodes": Array [ + Object { + "id": "5", + "text": "More good news!", }, - "title": "Foo", - }, - Object { - "id": "4", - "section": Object { - "slug": "test", + Object { + "id": "4", + "text": "Good news from China.", }, - "title": "Bar", - }, - ], + ], + }, } ` -exports[`src/tests/main.test.ts TAP Main > User with id 1 and his posts 1`] = ` +exports[`src/tests/main.test.ts TAP Main root filter when filters not enabled > all sections, not only news 1`] = ` Object { - "user": Object { - "id": "1", - "name": "John", - "posts": Array [ + "sections": Object { + "nodes": Array [ Object { - "id": "1", - "text": "Hello, world!", - "title": "Hello", + "id": "3", + "name": "COVID-19", }, Object { "id": "2", - "text": "Bye-bye, cruel world!", - "title": "Bye", + "name": "Editorial", }, ], }, } ` -exports[`src/tests/main.test.ts TAP Main > User with id 1 with his upper_name 1`] = ` +exports[`src/tests/main.test.ts TAP Main root pagination > must match snapshot 1`] = ` Object { - "user": Object { - "id": "1", - "name": "John", - "upper_name": "JOHN", + "sections": Object { + "cursor": "[\\"Editorial\\",\\"2\\"]", + "nodes": Array [ + Object { + "id": "3", + "name": "COVID-19", + "slug": "covid", + }, + Object { + "id": "2", + "name": "Editorial", + "slug": "editorial", + }, + ], }, } ` -exports[`src/tests/main.test.ts TAP Main > User with name->user_name (field alias) 1`] = ` +exports[`src/tests/main.test.ts TAP Main root pagination with arguments > take 1 1`] = ` Object { - "user": Object { - "user_name": "John", + "cursor": "[\\"COVID-19\\",\\"3\\"]", + "nodes": Array [ + Object { + "id": "3", + "name": "COVID-19", + "slug": "covid", + }, + ], +} +` + +exports[`src/tests/main.test.ts TAP Main root pagination with arguments > take 100 with cursor 1`] = ` +Object { + "sections": Object { + "cursor": null, + "nodes": Array [ + Object { + "id": "2", + "name": "Editorial", + "slug": "editorial", + }, + Object { + "id": "1", + "name": "News", + "slug": "news", + }, + ], }, } ` diff --git a/tsconfig.json b/tsconfig.json index a368fe8..276f6a4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,7 +8,7 @@ "target": "ES2018", "baseUrl": ".", "paths": { - "objection-fetch-graphql": ["./src"] + "objection-graphql-resolver": ["./src"] } }, "include": ["src"] diff --git a/yarn.lock b/yarn.lock index 1c04e8e..9112c6e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -36,58 +36,57 @@ xss "^1.0.6" "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" - integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" + integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== dependencies: "@babel/highlight" "^7.10.4" "@babel/core@^7.5.5": - version "7.12.3" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.3.tgz#1b436884e1e3bff6fb1328dc02b208759de92ad8" - integrity sha512-0qXcZYKZp3/6N2jKYVxZv0aNCsxTSVCiK72DTiTYZAu7sjg73W0/aynWjMbiGd87EQL4WyA8reiJVh92AVla9g== + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.10.tgz#b79a2e1b9f70ed3d84bbfb6d8c4ef825f606bccd" + integrity sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w== dependencies: "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.12.1" + "@babel/generator" "^7.12.10" "@babel/helper-module-transforms" "^7.12.1" - "@babel/helpers" "^7.12.1" - "@babel/parser" "^7.12.3" - "@babel/template" "^7.10.4" - "@babel/traverse" "^7.12.1" - "@babel/types" "^7.12.1" + "@babel/helpers" "^7.12.5" + "@babel/parser" "^7.12.10" + "@babel/template" "^7.12.7" + "@babel/traverse" "^7.12.10" + "@babel/types" "^7.12.10" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.1" json5 "^2.1.2" lodash "^4.17.19" - resolve "^1.3.2" semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.12.1", "@babel/generator@^7.12.5", "@babel/generator@^7.4.0": - version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.5.tgz#a2c50de5c8b6d708ab95be5e6053936c1884a4de" - integrity sha512-m16TQQJ8hPt7E+OS/XVQg/7U184MLXtvuGbCdA7na61vha+ImkyyNM/9DDA0unYCVZn3ZOhng+qz48/KBOT96A== +"@babel/generator@^7.12.10", "@babel/generator@^7.4.0": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.11.tgz#98a7df7b8c358c9a37ab07a24056853016aba3af" + integrity sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA== dependencies: - "@babel/types" "^7.12.5" + "@babel/types" "^7.12.11" jsesc "^2.5.1" source-map "^0.5.0" -"@babel/helper-annotate-as-pure@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz#5bf0d495a3f757ac3bda48b5bf3b3ba309c72ba3" - integrity sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA== +"@babel/helper-annotate-as-pure@^7.10.4", "@babel/helper-annotate-as-pure@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.10.tgz#54ab9b000e60a93644ce17b3f37d313aaf1d115d" + integrity sha512-XplmVbC1n+KY6jL8/fgLVXXUauDIB+lD5+GsQEh6F6GBF1dq1qy4DP4yXWzDKcoqXB3X58t61e85Fitoww4JVQ== dependencies: - "@babel/types" "^7.10.4" + "@babel/types" "^7.12.10" -"@babel/helper-builder-react-jsx-experimental@^7.12.1": - version "7.12.4" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.12.4.tgz#55fc1ead5242caa0ca2875dcb8eed6d311e50f48" - integrity sha512-AjEa0jrQqNk7eDQOo0pTfUOwQBMF+xVqrausQwT9/rTKy0g04ggFNaJpaE09IQMn9yExluigWMJcj0WC7bq+Og== +"@babel/helper-builder-react-jsx-experimental@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.12.11.tgz#a39616d7e4cf8f9da1f82b5fc3ee1f7406beeb11" + integrity sha512-4oGVOekPI8dh9JphkPXC68iIuP6qp/RPbaPmorRmEFbRAHZjSqxPjqHudn18GVDPgCuFM/KdFXc63C17Ygfa9w== dependencies: - "@babel/helper-annotate-as-pure" "^7.10.4" - "@babel/helper-module-imports" "^7.12.1" - "@babel/types" "^7.12.1" + "@babel/helper-annotate-as-pure" "^7.12.10" + "@babel/helper-module-imports" "^7.12.5" + "@babel/types" "^7.12.11" "@babel/helper-builder-react-jsx@^7.10.4": version "7.10.4" @@ -98,29 +97,29 @@ "@babel/types" "^7.10.4" "@babel/helper-function-name@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a" - integrity sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ== + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz#1fd7738aee5dcf53c3ecff24f1da9c511ec47b42" + integrity sha512-AtQKjtYNolKNi6nNNVLQ27CP6D9oFR6bq/HPYSizlzbp7uC1M59XJe8L+0uXjbIaZaUJF99ruHqVGiKXU/7ybA== dependencies: - "@babel/helper-get-function-arity" "^7.10.4" - "@babel/template" "^7.10.4" - "@babel/types" "^7.10.4" + "@babel/helper-get-function-arity" "^7.12.10" + "@babel/template" "^7.12.7" + "@babel/types" "^7.12.11" -"@babel/helper-get-function-arity@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2" - integrity sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A== +"@babel/helper-get-function-arity@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz#b158817a3165b5faa2047825dfa61970ddcc16cf" + integrity sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag== dependencies: - "@babel/types" "^7.10.4" + "@babel/types" "^7.12.10" -"@babel/helper-member-expression-to-functions@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.1.tgz#fba0f2fcff3fba00e6ecb664bb5e6e26e2d6165c" - integrity sha512-k0CIe3tXUKTRSoEx1LQEPFU9vRQfqHtl+kf8eNnDqb4AUJEy5pz6aIiog+YWtVm2jpggjS1laH68bPsR+KWWPQ== +"@babel/helper-member-expression-to-functions@^7.12.7": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz#aa77bd0396ec8114e5e30787efa78599d874a855" + integrity sha512-DCsuPyeWxeHgh1Dus7APn7iza42i/qXqiFPWyBDdOFtvS581JQePsc1F/nD+fHrcswhLlRc2UpYS1NwERxZhHw== dependencies: - "@babel/types" "^7.12.1" + "@babel/types" "^7.12.7" -"@babel/helper-module-imports@^7.12.1": +"@babel/helper-module-imports@^7.12.1", "@babel/helper-module-imports@^7.12.5": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz#1bfc0229f794988f76ed0a4d4e90860850b54dfb" integrity sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA== @@ -142,12 +141,12 @@ "@babel/types" "^7.12.1" lodash "^4.17.19" -"@babel/helper-optimise-call-expression@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz#50dc96413d594f995a77905905b05893cd779673" - integrity sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg== +"@babel/helper-optimise-call-expression@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.10.tgz#94ca4e306ee11a7dd6e9f42823e2ac6b49881e2d" + integrity sha512-4tpbU0SrSTjjt65UMWSrUOPZTsgvPgGG4S8QSTNHacKzpS51IVWGDj0yCwyeZND/i+LSN2g/O63jEXEWm49sYQ== dependencies: - "@babel/types" "^7.10.4" + "@babel/types" "^7.12.10" "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.8.0": version "7.10.4" @@ -155,14 +154,14 @@ integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== "@babel/helper-replace-supers@^7.12.1": - version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.12.5.tgz#f009a17543bbbbce16b06206ae73b63d3fca68d9" - integrity sha512-5YILoed0ZyIpF4gKcpZitEnXEJ9UoDRki1Ey6xz46rxOzfNMAhVIJMoune1hmPVxh40LRv1+oafz7UsWX+vyWA== + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.12.11.tgz#ea511658fc66c7908f923106dd88e08d1997d60d" + integrity sha512-q+w1cqmhL7R0FNzth/PLLp2N+scXEK/L2AHbXUyydxp828F4FEa5WcVoqui9vFRiHDQErj9Zof8azP32uGVTRA== dependencies: - "@babel/helper-member-expression-to-functions" "^7.12.1" - "@babel/helper-optimise-call-expression" "^7.10.4" - "@babel/traverse" "^7.12.5" - "@babel/types" "^7.12.5" + "@babel/helper-member-expression-to-functions" "^7.12.7" + "@babel/helper-optimise-call-expression" "^7.12.10" + "@babel/traverse" "^7.12.10" + "@babel/types" "^7.12.11" "@babel/helper-simple-access@^7.12.1": version "7.12.1" @@ -172,18 +171,18 @@ "@babel/types" "^7.12.1" "@babel/helper-split-export-declaration@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f" - integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg== + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz#1b4cc424458643c47d37022223da33d76ea4603a" + integrity sha512-LsIVN8j48gHgwzfocYUSkO/hjYAOJqlpJEc7tGXcIm4cubjVUf8LGW6eWRyxEu7gA25q02p0rQUWoCI33HNS5g== dependencies: - "@babel/types" "^7.11.0" + "@babel/types" "^7.12.11" -"@babel/helper-validator-identifier@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" - integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== +"@babel/helper-validator-identifier@^7.10.4", "@babel/helper-validator-identifier@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" + integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== -"@babel/helpers@^7.12.1": +"@babel/helpers@^7.12.5": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.12.5.tgz#1a1ba4a768d9b58310eda516c449913fe647116e" integrity sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA== @@ -201,10 +200,10 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.10.4", "@babel/parser@^7.12.3", "@babel/parser@^7.12.5", "@babel/parser@^7.4.3": - version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.5.tgz#b4af32ddd473c0bfa643bd7ff0728b8e71b81ea0" - integrity sha512-FVM6RZQ0mn2KCf1VUED7KepYeUWoVShczewOCfm3nzoBybaih51h+sYVVGthW9M6lPByEPTQf+xm27PBdlpwmQ== +"@babel/parser@^7.12.10", "@babel/parser@^7.12.7", "@babel/parser@^7.4.3": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.11.tgz#9ce3595bcd74bc5c466905e86c535b8b25011e79" + integrity sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg== "@babel/plugin-proposal-object-rest-spread@^7.5.5": version "7.12.1" @@ -244,12 +243,12 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-react-jsx@^7.3.0": - version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.5.tgz#39ede0e30159770561b6963be143e40af3bde00c" - integrity sha512-2xkcPqqrYiOQgSlM/iwto1paPijjsDbUynN13tI6bosDz/jOW3CRzYguIE8wKX32h+msbBM22Dv5fwrFkUOZjQ== + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.11.tgz#09a7319195946b0ddc09f9a5f01346f2cb80dfdd" + integrity sha512-5nWOw6mTylaFU72BdZfa0dP1HsGdY3IMExpxn8LBE8dNmkQjB+W+sR+JwIdtbzkPvVuFviT3zyNbSUkuVTVxbw== dependencies: "@babel/helper-builder-react-jsx" "^7.10.4" - "@babel/helper-builder-react-jsx-experimental" "^7.12.1" + "@babel/helper-builder-react-jsx-experimental" "^7.12.11" "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-jsx" "^7.12.1" @@ -260,36 +259,36 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/template@^7.10.4", "@babel/template@^7.4.0": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" - integrity sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA== +"@babel/template@^7.10.4", "@babel/template@^7.12.7", "@babel/template@^7.4.0": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.7.tgz#c817233696018e39fbb6c491d2fb684e05ed43bc" + integrity sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow== dependencies: "@babel/code-frame" "^7.10.4" - "@babel/parser" "^7.10.4" - "@babel/types" "^7.10.4" + "@babel/parser" "^7.12.7" + "@babel/types" "^7.12.7" -"@babel/traverse@^7.12.1", "@babel/traverse@^7.12.5", "@babel/traverse@^7.4.3": - version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.5.tgz#78a0c68c8e8a35e4cacfd31db8bb303d5606f095" - integrity sha512-xa15FbQnias7z9a62LwYAA5SZZPkHIXpd42C6uW68o8uTuua96FHZy1y61Va5P/i83FAAcMpW8+A/QayntzuqA== +"@babel/traverse@^7.12.1", "@babel/traverse@^7.12.10", "@babel/traverse@^7.12.5", "@babel/traverse@^7.4.3": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.10.tgz#2d1f4041e8bf42ea099e5b2dc48d6a594c00017a" + integrity sha512-6aEtf0IeRgbYWzta29lePeYSk+YAFIC3kyqESeft8o5CkFlYIMX+EQDDWEiAQ9LHOA3d0oHdgrSsID/CKqXJlg== dependencies: "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.12.5" + "@babel/generator" "^7.12.10" "@babel/helper-function-name" "^7.10.4" "@babel/helper-split-export-declaration" "^7.11.0" - "@babel/parser" "^7.12.5" - "@babel/types" "^7.12.5" + "@babel/parser" "^7.12.10" + "@babel/types" "^7.12.10" debug "^4.1.0" globals "^11.1.0" lodash "^4.17.19" -"@babel/types@^7.10.4", "@babel/types@^7.11.0", "@babel/types@^7.12.1", "@babel/types@^7.12.5", "@babel/types@^7.4.0": - version "7.12.6" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.6.tgz#ae0e55ef1cce1fbc881cd26f8234eb3e657edc96" - integrity sha512-hwyjw6GvjBLiyy3W0YQf0Z5Zf4NpYejUnKFcfcUhZCSffoBBp30w6wP2Wn6pk31jMYZvcOrB/1b7cGXvEoKogA== +"@babel/types@^7.10.4", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.11", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.4.0": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.11.tgz#a86e4d71e30a9b6ee102590446c98662589283ce" + integrity sha512-ukA9SQtKThINm++CX1CwmliMrE54J6nIYB5XTwL5f/CLFW9owfls+YSU8tVW15RQ2w+a3fSbPjC6HdQNtWZkiA== dependencies: - "@babel/helper-validator-identifier" "^7.10.4" + "@babel/helper-validator-identifier" "^7.12.11" lodash "^4.17.19" to-fast-properties "^2.0.0" @@ -429,10 +428,10 @@ resolved "https://registry.yarnpkg.com/@commitlint/types/-/types-11.0.0.tgz#719cf05fcc1abb6533610a2e0f5dd1e61eac14fe" integrity sha512-VoNqai1vR5anRF5Tuh/+SWDFk7xi7oMwHrHrbm1BprYXjB2RJsWLhUrStMssDxEl5lW/z3EUdg8RvH/IUBccSQ== -"@eslint/eslintrc@^0.2.1": - version "0.2.1" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.2.1.tgz#f72069c330461a06684d119384435e12a5d76e3c" - integrity sha512-XRUeBZ5zBWLYgSANMpThFddrZZkEbGHgUdt5UJjZfnlN9BGCiUBrf+nvbRupSjMvqzwnQN0qwCmOxITt1cfywA== +"@eslint/eslintrc@^0.2.2": + version "0.2.2" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.2.2.tgz#d01fc791e2fc33e88a29d6f3dc7e93d0cd784b76" + integrity sha512-EfB5OHNYp1F4px/LI/FEnGylop7nOqkQ1LRzCM0KccA2U8tvV8w01KBv37LbO7nW4H+YhKyo2LcJhRwjjV17QQ== dependencies: ajv "^6.12.4" debug "^4.1.1" @@ -475,108 +474,107 @@ "@nodelib/fs.scandir" "2.1.3" fastq "^1.6.0" -"@octokit/auth-token@^2.4.0": - version "2.4.3" - resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-2.4.3.tgz#b868b5f2366533a7e62933eaa1181a8924228cc4" - integrity sha512-fdGoOQ3kQJh+hrilc0Plg50xSfaCKOeYN9t6dpJKXN9BxhhfquL0OzoQXg3spLYymL5rm29uPeI3KEXRaZQ9zg== +"@octokit/auth-token@^2.4.4": + version "2.4.4" + resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-2.4.4.tgz#ee31c69b01d0378c12fd3ffe406030f3d94d3b56" + integrity sha512-LNfGu3Ro9uFAYh10MUZVaT7X2CnNm2C8IDQmabx+3DygYIQjs9FwzFAHN/0t6mu5HEPhxcb1XOuxdpY82vCg2Q== dependencies: - "@octokit/types" "^5.0.0" + "@octokit/types" "^6.0.0" -"@octokit/core@^2.4.3": - version "2.5.4" - resolved "https://registry.yarnpkg.com/@octokit/core/-/core-2.5.4.tgz#f7fbf8e4f86c5cc2497a8887ba2561ec8d358054" - integrity sha512-HCp8yKQfTITYK+Nd09MHzAlP1v3Ii/oCohv0/TW9rhSLvzb98BOVs2QmVYuloE6a3l6LsfyGIwb6Pc4ycgWlIQ== +"@octokit/core@^3.2.3": + version "3.2.4" + resolved "https://registry.yarnpkg.com/@octokit/core/-/core-3.2.4.tgz#5791256057a962eca972e31818f02454897fd106" + integrity sha512-d9dTsqdePBqOn7aGkyRFe7pQpCXdibSJ5SFnrTr0axevObZrpz3qkWm7t/NjYv5a66z6vhfteriaq4FRz3e0Qg== dependencies: - "@octokit/auth-token" "^2.4.0" - "@octokit/graphql" "^4.3.1" - "@octokit/request" "^5.4.0" - "@octokit/types" "^5.0.0" + "@octokit/auth-token" "^2.4.4" + "@octokit/graphql" "^4.5.8" + "@octokit/request" "^5.4.12" + "@octokit/types" "^6.0.3" before-after-hook "^2.1.0" - universal-user-agent "^5.0.0" + universal-user-agent "^6.0.0" "@octokit/endpoint@^6.0.1": - version "6.0.9" - resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-6.0.9.tgz#c6a772e024202b1bd19ab69f90e0536a2598b13e" - integrity sha512-3VPLbcCuqji4IFTclNUtGdp9v7g+nspWdiCUbK3+iPMjJCZ6LEhn1ts626bWLOn0GiDb6j+uqGvPpqLnY7pBgw== + version "6.0.10" + resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-6.0.10.tgz#741ce1fa2f4fb77ce8ebe0c6eaf5ce63f565f8e8" + integrity sha512-9+Xef8nT7OKZglfkOMm7IL6VwxXUQyR7DUSU0LH/F7VNqs8vyd7es5pTfz9E7DwUIx7R3pGscxu1EBhYljyu7Q== dependencies: - "@octokit/types" "^5.0.0" + "@octokit/types" "^6.0.0" is-plain-object "^5.0.0" universal-user-agent "^6.0.0" -"@octokit/graphql@^4.3.1": - version "4.5.7" - resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-4.5.7.tgz#f4562dcd9e80ea94602068e85aefac19a88f8578" - integrity sha512-Gk0AR+DcwIK/lK/GX+OQ99UqtenQhcbrhHHfOYlrCQe17ADnX3EKAOKRsAZ9qZvpi5MuwWm/Nm+9aO2kTDSdyA== +"@octokit/graphql@^4.5.8": + version "4.5.8" + resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-4.5.8.tgz#d42373633c3015d0eafce64a8ce196be167fdd9b" + integrity sha512-WnCtNXWOrupfPJgXe+vSmprZJUr0VIu14G58PMlkWGj3cH+KLZEfKMmbUQ6C3Wwx6fdhzVW1CD5RTnBdUHxhhA== dependencies: "@octokit/request" "^5.3.0" - "@octokit/types" "^5.0.0" + "@octokit/types" "^6.0.0" universal-user-agent "^6.0.0" -"@octokit/plugin-paginate-rest@^2.2.0": - version "2.6.0" - resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.6.0.tgz#03416396e7a227b268c5b827365238f620a9c5c1" - integrity sha512-o+O8c1PqsC5++BHXfMZabRRsBIVb34tXPWyQLyp2IXq5MmkxdipS7TXM4Y9ldL1PzY9CTrCsn/lzFFJGM3oRRA== +"@octokit/openapi-types@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-2.0.1.tgz#7453d8281ce66b8ed1607f7ac7d751c3baffd2cc" + integrity sha512-9AuC04PUnZrjoLiw3uPtwGh9FE4Q3rTqs51oNlQ0rkwgE8ftYsOC+lsrQyvCvWm85smBbSc0FNRKKumvGyb44Q== + +"@octokit/plugin-paginate-rest@^2.6.2": + version "2.6.2" + resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.6.2.tgz#45d13dbf5ff8aed54f1a3716b1d57fdc62720c5f" + integrity sha512-3Dy7/YZAwdOaRpGQoNHPeT0VU1fYLpIUdPyvR37IyFLgd6XSij4j9V/xN/+eSjF2KKvmfIulEh9LF1tRPjIiDA== dependencies: - "@octokit/types" "^5.5.0" + "@octokit/types" "^6.0.1" -"@octokit/plugin-request-log@^1.0.0": +"@octokit/plugin-request-log@^1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.2.tgz#394d59ec734cd2f122431fbaf05099861ece3c44" integrity sha512-oTJSNAmBqyDR41uSMunLQKMX0jmEXbwD1fpz8FG27lScV3RhtGfBa1/BBLym+PxcC16IBlF7KH9vP1BUYxA+Eg== -"@octokit/plugin-rest-endpoint-methods@3.17.0": - version "3.17.0" - resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-3.17.0.tgz#d8ba04eb883849dd98666c55bf49d8c9fe7be055" - integrity sha512-NFV3vq7GgoO2TrkyBRUOwflkfTYkFKS0tLAPym7RNpkwLCttqShaEGjthOsPEEL+7LFcYv3mU24+F2yVd3npmg== +"@octokit/plugin-rest-endpoint-methods@4.4.1": + version "4.4.1" + resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-4.4.1.tgz#105cf93255432155de078c9efc33bd4e14d1cd63" + integrity sha512-+v5PcvrUcDeFXf8hv1gnNvNLdm4C0+2EiuWt9EatjjUmfriM1pTMM+r4j1lLHxeBQ9bVDmbywb11e3KjuavieA== dependencies: - "@octokit/types" "^4.1.6" + "@octokit/types" "^6.1.0" deprecation "^2.3.1" "@octokit/request-error@^2.0.0": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-2.0.3.tgz#b51b200052bf483f6fa56c9e7e3aa51ead36ecd8" - integrity sha512-GgD5z8Btm301i2zfvJLk/mkhvGCdjQ7wT8xF9ov5noQY8WbKZDH9cOBqXzoeKd1mLr1xH2FwbtGso135zGBgTA== + version "2.0.4" + resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-2.0.4.tgz#07dd5c0521d2ee975201274c472a127917741262" + integrity sha512-LjkSiTbsxIErBiRh5wSZvpZqT4t0/c9+4dOe0PII+6jXR+oj/h66s7E4a/MghV7iT8W9ffoQ5Skoxzs96+gBPA== dependencies: - "@octokit/types" "^5.0.1" + "@octokit/types" "^6.0.0" deprecation "^2.0.0" once "^1.4.0" -"@octokit/request@^5.3.0", "@octokit/request@^5.4.0": - version "5.4.10" - resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.4.10.tgz#402d2c53768bde12b99348329ba4129746aebb9c" - integrity sha512-egA49HkqEORVGDZGav1mh+VD+7uLgOxtn5oODj6guJk0HCy+YBSYapFkSLFgeYj3Fr18ZULKGURkjyhkAChylw== +"@octokit/request@^5.3.0", "@octokit/request@^5.4.12": + version "5.4.12" + resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.4.12.tgz#b04826fa934670c56b135a81447be2c1723a2ffc" + integrity sha512-MvWYdxengUWTGFpfpefBBpVmmEYfkwMoxonIB3sUGp5rhdgwjXL1ejo6JbgzG/QD9B/NYt/9cJX1pxXeSIUCkg== dependencies: "@octokit/endpoint" "^6.0.1" "@octokit/request-error" "^2.0.0" - "@octokit/types" "^5.0.0" + "@octokit/types" "^6.0.3" deprecation "^2.0.0" is-plain-object "^5.0.0" node-fetch "^2.6.1" once "^1.4.0" universal-user-agent "^6.0.0" -"@octokit/rest@^17.0.0": - version "17.11.2" - resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-17.11.2.tgz#f3dbd46f9f06361c646230fd0ef8598e59183ead" - integrity sha512-4jTmn8WossTUaLfNDfXk4fVJgbz5JgZE8eCs4BvIb52lvIH8rpVMD1fgRCrHbSd6LRPE5JFZSfAEtszrOq3ZFQ== - dependencies: - "@octokit/core" "^2.4.3" - "@octokit/plugin-paginate-rest" "^2.2.0" - "@octokit/plugin-request-log" "^1.0.0" - "@octokit/plugin-rest-endpoint-methods" "3.17.0" - -"@octokit/types@^4.1.6": - version "4.1.10" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-4.1.10.tgz#e4029c11e2cc1335051775bc1600e7e740e4aca4" - integrity sha512-/wbFy1cUIE5eICcg0wTKGXMlKSbaAxEr00qaBXzscLXpqhcwgXeS6P8O0pkysBhRfyjkKjJaYrvR1ExMO5eOXQ== +"@octokit/rest@^18.0.0": + version "18.0.12" + resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-18.0.12.tgz#278bd41358c56d87c201e787e8adc0cac132503a" + integrity sha512-hNRCZfKPpeaIjOVuNJzkEL6zacfZlBPV8vw8ReNeyUkVvbuCvvrrx8K8Gw2eyHHsmd4dPlAxIXIZ9oHhJfkJpw== dependencies: - "@types/node" ">= 8" + "@octokit/core" "^3.2.3" + "@octokit/plugin-paginate-rest" "^2.6.2" + "@octokit/plugin-request-log" "^1.0.2" + "@octokit/plugin-rest-endpoint-methods" "4.4.1" -"@octokit/types@^5.0.0", "@octokit/types@^5.0.1", "@octokit/types@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-5.5.0.tgz#e5f06e8db21246ca102aa28444cdb13ae17a139b" - integrity sha512-UZ1pErDue6bZNjYOotCNveTXArOMZQFG6hKJfOnGnulVCMcVVi7YIIuuR4WfBhjo7zgpmzn/BkPDnUXtNx+PcQ== +"@octokit/types@^6.0.0", "@octokit/types@^6.0.1", "@octokit/types@^6.0.3", "@octokit/types@^6.1.0": + version "6.1.2" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.1.2.tgz#2b3a6ae0b8b71c27c770b4ff3e9ad8f1f538af58" + integrity sha512-LPCpcLbcky7fWfHCTuc7tMiSHFpFlrThJqVdaHgowBTMS0ijlZFfonQC/C1PrZOjD4xRCYgBqH9yttEATGE/nw== dependencies: + "@octokit/openapi-types" "^2.0.1" "@types/node" ">= 8" "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": @@ -660,11 +658,11 @@ integrity sha512-9Tj/qn+y2j+sjCI3Jd+qseGtHjOAeg7dU2/lVcqIQ9TV3QDaDXDYXcoOHU+7o2Hwh8L8ymL4gfuO7KxDs3q2zg== "@semantic-release/github@^7.0.0": - version "7.1.1" - resolved "https://registry.yarnpkg.com/@semantic-release/github/-/github-7.1.1.tgz#e998aa9a9cd770838d9f27c64f060c2b686b9d95" - integrity sha512-w8CLCvGVKNe2FPOYQ68OFxFVNNha7YRzptnwTZYdjXYtgTDKw0XVfnMSd9NlJeQPYGfQmIhIVPNBU/cA6zUY0A== + version "7.2.0" + resolved "https://registry.yarnpkg.com/@semantic-release/github/-/github-7.2.0.tgz#925f3efd91adabfc4bbe0de24b79fe1a8a38b4e2" + integrity sha512-tMRnWiiWb43whRHvbDGXq4DGEbKRi56glDpXDJZit4PIiwDPX7Kx3QzmwRtDOcG+8lcpGjpdPabYZ9NBxoI2mw== dependencies: - "@octokit/rest" "^17.0.0" + "@octokit/rest" "^18.0.0" "@semantic-release/error" "^2.2.0" aggregate-error "^3.0.0" bottleneck "^2.18.1" @@ -682,23 +680,23 @@ url-join "^4.0.0" "@semantic-release/npm@^7.0.0": - version "7.0.6" - resolved "https://registry.yarnpkg.com/@semantic-release/npm/-/npm-7.0.6.tgz#1301bd57d246eae048d7104a735467bb0829f3d8" - integrity sha512-F4judxdeLe8f7+vDva1TkqNc5Tb2tcltZYW0tLtvP2Xt7CD/gGiz7UxAWEOPsXBvIqAP+uTidvGLPl9U3/uRoQ== + version "7.0.9" + resolved "https://registry.yarnpkg.com/@semantic-release/npm/-/npm-7.0.9.tgz#a49d80d0f96a52cd70f9ce4e78fac5be70f24844" + integrity sha512-VsmmQF3/n7mDbm6AGL0yPD3QNTGsHdinBtkyyerN1eLgvhdGJ/vEeAvmDMARiuf5Ev9cFeCheF0wLyUZNlAkeA== dependencies: "@semantic-release/error" "^2.2.0" aggregate-error "^3.0.0" - execa "^4.0.0" + execa "^5.0.0" fs-extra "^9.0.0" lodash "^4.17.15" nerf-dart "^1.0.0" normalize-url "^5.0.0" - npm "^6.13.0" + npm "^6.14.8" rc "^1.2.8" read-pkg "^5.0.0" registry-auth-token "^4.0.0" semver "^7.1.2" - tempy "^0.5.0" + tempy "^1.0.0" "@semantic-release/release-notes-generator@^9.0.0": version "9.0.1" @@ -737,9 +735,9 @@ "@types/node" "*" "@types/connect@*": - version "3.4.33" - resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.33.tgz#31610c901eca573b8713c3330abc6e6b9f588546" - integrity sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A== + version "3.4.34" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.34.tgz#170a40223a6d666006d93ca128af2beb1d9b1901" + integrity sha512-ePPA/JuI+X0vb+gSWlPKOY0NdNAie/rPUqX2GUPpbZwiKTkSPhjXWuee47E4MtE54QVzGCQMQkAL6JhV2E1+cQ== dependencies: "@types/node" "*" @@ -770,7 +768,16 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== -"@types/express-serve-static-core@*", "@types/express-serve-static-core@4.17.13": +"@types/express-serve-static-core@*": + version "4.17.17" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.17.tgz#6ba02465165b6c9c3d8db3a28def6b16fc9b70f5" + integrity sha512-YYlVaCni5dnHc+bLZfY908IG1+x5xuibKZMGv8srKkvtul3wUuanYvpIj9GXXoWkQbaAdR+kgX46IETKUALWNQ== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + +"@types/express-serve-static-core@4.17.13": version "4.17.13" resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.13.tgz#d9af025e925fc8b089be37423b8d1eac781be084" integrity sha512-RgDi5a4nuzam073lRGKTUIaL3eF2+H7LJvJ8eUnCI0wA6SNjXc44DCmWNiTLs/AZ7QlsFWZiw/gTG3nSQGL0fA== @@ -780,9 +787,9 @@ "@types/range-parser" "*" "@types/express@*": - version "4.17.8" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.8.tgz#3df4293293317e61c60137d273a2e96cd8d5f27a" - integrity sha512-wLhcKh3PMlyA2cNAB9sjM1BntnhPMiM0JOBwPBqttjHev2428MLEB4AYVN+d8s2iyCVZac+o41Pflm/ZH5vLXQ== + version "4.17.9" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.9.tgz#f5f2df6add703ff28428add52bdec8a1091b0a78" + integrity sha512-SDzEIZInC4sivGIFY4Sz1GG6J9UObPwCInYJjko2jzOf/Imx/dlpume6Xxwj1ORL82tBbmN4cPDIDkLbWHk9hw== dependencies: "@types/body-parser" "*" "@types/express-serve-static-core" "*" @@ -806,21 +813,6 @@ dependencies: "@types/node" "*" -"@types/fs-extra@^8.0.1": - version "8.1.1" - resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-8.1.1.tgz#1e49f22d09aa46e19b51c0b013cb63d0d923a068" - integrity sha512-TcUlBem321DFQzBNuz8p0CLLKp0VvF/XH9E4KHNmgwyp4E3AfgI5cjiIVZWlbfThBop2qxFIh4+LeY6hVWWZ2w== - dependencies: - "@types/node" "*" - -"@types/glob@^7.1.1": - version "7.1.3" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183" - integrity sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w== - dependencies: - "@types/minimatch" "*" - "@types/node" "*" - "@types/graphql-upload@^8.0.0": version "8.0.4" resolved "https://registry.yarnpkg.com/@types/graphql-upload/-/graphql-upload-8.0.4.tgz#23a8ffb3d2fe6e0ee07e6f16ee9d9d5e995a2f4f" @@ -887,15 +879,10 @@ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.3.tgz#c893b73721db73699943bfc3653b1deb7faa4a3a" integrity sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q== -"@types/minimatch@*": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" - integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== - "@types/minimist@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.0.tgz#69a23a3ad29caf0097f06eda59b361ee2f0639f6" - integrity sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY= + version "1.2.1" + resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.1.tgz#283f669ff76d7b8260df8ab7a4262cc83d988256" + integrity sha512-fZQQafSREFyuZcdWFAExYjBiCL7AUCdgsk80iO0q4yihYYdcIiH28CcuPTGFgLOCC8RlW49GSQxdHwZP+I7CNg== "@types/node-fetch@2.5.7": version "2.5.7" @@ -906,14 +893,14 @@ form-data "^3.0.0" "@types/node@*", "@types/node@>= 8": - version "14.14.6" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.6.tgz#146d3da57b3c636cc0d1769396ce1cfa8991147f" - integrity sha512-6QlRuqsQ/Ox/aJEQWBEJG7A9+u7oSYl3mem/K8IzxXG/kAGbV1YPD9Bg9Zw3vyxC/YP+zONKwy8hGkSt1jxFMw== + version "14.14.14" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.14.tgz#f7fd5f3cc8521301119f63910f0fb965c7d761ae" + integrity sha512-UHnOPWVWV1z+VV8k6L1HhG7UbGBgIdghqF3l9Ny9ApPghbjICXkUJSd/b9gOgQfjM1r+37cipdw/HJ3F6ICEnQ== "@types/node@^10.1.0": - version "10.17.44" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.44.tgz#3945e6b702cb6403f22b779c8ea9e5c3f44ead40" - integrity sha512-vHPAyBX1ffLcy4fQHmDyIUMUb42gHZjPHU66nhvbMzAWJqHnySGZ6STwN3rwrnSd1FHB0DI/RWgGELgKSYRDmw== + version "10.17.49" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.49.tgz#ecf0b67bab4b84d0ec9b0709db4aac3824a51c4a" + integrity sha512-PGaJNs5IZz5XgzwJvL/1zRfZB7iaJ5BydZ8/Picm+lUNYoNO9iVTQkVy5eUh0dZDrx3rBOIs3GCbCRmMuYyqwg== "@types/normalize-package-data@^2.4.0": version "2.4.0" @@ -941,9 +928,9 @@ integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA== "@types/react@^16.9.16": - version "16.9.56" - resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.56.tgz#ea25847b53c5bec064933095fc366b1462e2adf0" - integrity sha512-gIkl4J44G/qxbuC6r2Xh+D3CGZpJ+NdWTItAPmZbR5mUS+JQ8Zvzpl0ea5qT/ZT3ZNTUcDKUVqV3xBE8wv/DyQ== + version "16.14.2" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.14.2.tgz#85dcc0947d0645349923c04ccef6018a1ab7538c" + integrity sha512-BzzcAlyDxXl2nANlabtT4thtvbbnhee8hMmH/CcJrISDBVcJS1iOsP1f0OAgSdGE0MsY9tqcrb9YoZcOFv9dbQ== dependencies: "@types/prop-types" "*" csstype "^3.0.2" @@ -954,9 +941,9 @@ integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== "@types/serve-static@*": - version "1.13.6" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.6.tgz#866b1b8dec41c36e28c7be40ac725b88be43c5c1" - integrity sha512-nuRJmv7jW7VmCVTn+IgYDkkbbDGyIINOeu/G0d74X3lm6E5KfMeQPJhxIt1ayQeQB3cSxvYs1RA/wipYoFB4EA== + version "1.13.8" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.8.tgz#851129d434433c7082148574ffec263d58309c46" + integrity sha512-MoJhSQreaVoL+/hurAZzIm8wafFR6ajiTM1m4A0kv6AGeVBl4r4pOV8bGFrjjq1sGxDTnCoF8i22o0/aE5XCyA== dependencies: "@types/mime" "*" "@types/node" "*" @@ -969,9 +956,9 @@ "@types/node" "*" "@types/ws@^7.0.0": - version "7.2.9" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.2.9.tgz#cadfac473acfab192678a487c3ecbb13a503547f" - integrity sha512-gmXYAXr7G4BrRMnkGQGkGonc3ArVro9VZd//C1uns/qqsJyl2dxaJdlPMhZbcq5MTxFFC+ttFWtHSfVW5+hlRA== + version "7.4.0" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.0.tgz#499690ea08736e05a8186113dac37769ab251a0e" + integrity sha512-Y29uQ3Uy+58bZrFLhX36hcI3Np37nqWE7ky5tjiDoy1GDZnIwVxS0CgF+s+1bXMzjKBFy+fqaRfb708iNzdinw== dependencies: "@types/node" "*" @@ -981,60 +968,60 @@ integrity sha512-S9q47ByT2pPvD65IvrWp7qppVMpk9WGMbVq9wbWZOHg6tnXSD4vyhao6nOSBwwfDdV2p3Kx9evA9vI+XWTfDvw== "@typescript-eslint/eslint-plugin@^4.6.1": - version "4.6.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.6.1.tgz#99d77eb7a016fd5a5e749d2c44a7e4c317eb7da3" - integrity sha512-SNZyflefTMK2JyrPfFFzzoy2asLmZvZJ6+/L5cIqg4HfKGiW2Gr1Go1OyEVqne/U4QwmoasuMwppoBHWBWF2nA== + version "4.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.11.0.tgz#bc6c1e4175c0cf42083da4314f7931ad12f731cc" + integrity sha512-x4arJMXBxyD6aBXLm3W7mSDZRiABzy+2PCLJbL7OPqlp53VXhaA1HKK7R2rTee5OlRhnUgnp8lZyVIqjnyPT6g== dependencies: - "@typescript-eslint/experimental-utils" "4.6.1" - "@typescript-eslint/scope-manager" "4.6.1" + "@typescript-eslint/experimental-utils" "4.11.0" + "@typescript-eslint/scope-manager" "4.11.0" debug "^4.1.1" functional-red-black-tree "^1.0.1" regexpp "^3.0.0" semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/experimental-utils@4.6.1": - version "4.6.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.6.1.tgz#a9c691dfd530a9570274fe68907c24c07a06c4aa" - integrity sha512-qyPqCFWlHZXkEBoV56UxHSoXW2qnTr4JrWVXOh3soBP3q0o7p4pUEMfInDwIa0dB/ypdtm7gLOS0hg0a73ijfg== +"@typescript-eslint/experimental-utils@4.11.0": + version "4.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.11.0.tgz#d1a47cc6cfe1c080ce4ead79267574b9881a1565" + integrity sha512-1VC6mSbYwl1FguKt8OgPs8xxaJgtqFpjY/UzUYDBKq4pfQ5lBvN2WVeqYkzf7evW42axUHYl2jm9tNyFsb8oLg== dependencies: "@types/json-schema" "^7.0.3" - "@typescript-eslint/scope-manager" "4.6.1" - "@typescript-eslint/types" "4.6.1" - "@typescript-eslint/typescript-estree" "4.6.1" + "@typescript-eslint/scope-manager" "4.11.0" + "@typescript-eslint/types" "4.11.0" + "@typescript-eslint/typescript-estree" "4.11.0" eslint-scope "^5.0.0" eslint-utils "^2.0.0" "@typescript-eslint/parser@^4.6.1": - version "4.6.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.6.1.tgz#b801bff67b536ecc4a840ac9289ba2be57e02428" - integrity sha512-lScKRPt1wM9UwyKkGKyQDqf0bh6jm8DQ5iN37urRIXDm16GEv+HGEmum2Fc423xlk5NUOkOpfTnKZc/tqKZkDQ== + version "4.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.11.0.tgz#1dd3d7e42708c10ce9f3aa64c63c0ab99868b4e2" + integrity sha512-NBTtKCC7ZtuxEV5CrHUO4Pg2s784pvavc3cnz6V+oJvVbK4tH9135f/RBP6eUA2KHiFKAollSrgSctQGmHbqJQ== dependencies: - "@typescript-eslint/scope-manager" "4.6.1" - "@typescript-eslint/types" "4.6.1" - "@typescript-eslint/typescript-estree" "4.6.1" + "@typescript-eslint/scope-manager" "4.11.0" + "@typescript-eslint/types" "4.11.0" + "@typescript-eslint/typescript-estree" "4.11.0" debug "^4.1.1" -"@typescript-eslint/scope-manager@4.6.1": - version "4.6.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.6.1.tgz#21872b91cbf7adfc7083f17b8041149148baf992" - integrity sha512-f95+80r6VdINYscJY1KDUEDcxZ3prAWHulL4qRDfNVD0I5QAVSGqFkwHERDoLYJJWmEAkUMdQVvx7/c2Hp+Bjg== +"@typescript-eslint/scope-manager@4.11.0": + version "4.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.11.0.tgz#2d906537db8a3a946721699e4fc0833810490254" + integrity sha512-6VSTm/4vC2dHM3ySDW9Kl48en+yLNfVV6LECU8jodBHQOhO8adAVizaZ1fV0QGZnLQjQ/y0aBj5/KXPp2hBTjA== dependencies: - "@typescript-eslint/types" "4.6.1" - "@typescript-eslint/visitor-keys" "4.6.1" + "@typescript-eslint/types" "4.11.0" + "@typescript-eslint/visitor-keys" "4.11.0" -"@typescript-eslint/types@4.6.1": - version "4.6.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.6.1.tgz#d3ad7478f53f22e7339dc006ab61aac131231552" - integrity sha512-k2ZCHhJ96YZyPIsykickez+OMHkz06xppVLfJ+DY90i532/Cx2Z+HiRMH8YZQo7a4zVd/TwNBuRCdXlGK4yo8w== +"@typescript-eslint/types@4.11.0": + version "4.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.11.0.tgz#86cf95e7eac4ccfd183f9fcf1480cece7caf4ca4" + integrity sha512-XXOdt/NPX++txOQHM1kUMgJUS43KSlXGdR/aDyEwuAEETwuPt02Nc7v+s57PzuSqMbNLclblQdv3YcWOdXhQ7g== -"@typescript-eslint/typescript-estree@4.6.1": - version "4.6.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.6.1.tgz#6025cce724329413f57e4959b2d676fceeca246f" - integrity sha512-/J/kxiyjQQKqEr5kuKLNQ1Finpfb8gf/NpbwqFFYEBjxOsZ621r9AqwS9UDRA1Rrr/eneX/YsbPAIhU2rFLjXQ== +"@typescript-eslint/typescript-estree@4.11.0": + version "4.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.11.0.tgz#1144d145841e5987d61c4c845442a24b24165a4b" + integrity sha512-eA6sT5dE5RHAFhtcC+b5WDlUIGwnO9b0yrfGa1mIOIAjqwSQCpXbLiFmKTdRbQN/xH2EZkGqqLDrKUuYOZ0+Hg== dependencies: - "@typescript-eslint/types" "4.6.1" - "@typescript-eslint/visitor-keys" "4.6.1" + "@typescript-eslint/types" "4.11.0" + "@typescript-eslint/visitor-keys" "4.11.0" debug "^4.1.1" globby "^11.0.1" is-glob "^4.0.1" @@ -1042,12 +1029,12 @@ semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/visitor-keys@4.6.1": - version "4.6.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.6.1.tgz#6b125883402d8939df7b54528d879e88f7ba3614" - integrity sha512-owABze4toX7QXwOLT3/D5a8NecZEjEWU1srqxENTfqsY3bwVnl3YYbOh6s1rp2wQKO9RTHFGjKes08FgE7SVMw== +"@typescript-eslint/visitor-keys@4.11.0": + version "4.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.11.0.tgz#906669a50f06aa744378bb84c7d5c4fdbc5b7d51" + integrity sha512-tRYKyY0i7cMk6v4UIOCjl1LhuepC/pc6adQqJk4Is3YcC6k46HvsV9Wl7vQoLbm9qADgeujiT7KdLrylvFIQ+A== dependencies: - "@typescript-eslint/types" "4.6.1" + "@typescript-eslint/types" "4.11.0" eslint-visitor-keys "^2.0.0" "@wry/equality@^0.1.2": @@ -1078,7 +1065,7 @@ accepts@^1.3.5, accepts@~1.3.7: mime-types "~2.1.24" negotiator "0.6.2" -acorn-jsx@^5.2.0: +acorn-jsx@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== @@ -1124,7 +1111,7 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.0, ajv@^6.12.3, ajv@^6.12.4: +ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.6: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -1863,7 +1850,7 @@ chalk@4.1.0, chalk@^4.0.0, chalk@^4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.2: +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.2, chalk@^2.4.1: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -1970,11 +1957,12 @@ cli-table3@^0.5.0, cli-table3@^0.5.1: colors "^1.1.2" cli-table@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/cli-table/-/cli-table-0.3.1.tgz#f53b05266a8b1a0b934b3d0821e6e2dc5914ae23" - integrity sha1-9TsFJmqLGguTSz0IIebi3FkUriM= + version "0.3.4" + resolved "https://registry.yarnpkg.com/cli-table/-/cli-table-0.3.4.tgz#5b37fd723751f1a6e9e70d55953a75e16eab958e" + integrity sha512-1vinpnX/ZERcmE443i3SZTmU5DF0rPO9DrL4I2iVAllhxzCM9SzPlHnz19fsZB78htkKZvYBvj6SZ6vXnaxmTA== dependencies: - colors "1.0.3" + chalk "^2.4.1" + string-width "^4.2.0" cli-truncate@^2.1.0: version "2.1.0" @@ -2075,16 +2063,11 @@ color-support@^1.1.0: resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== -colorette@1.2.1, colorette@^1.1.0: +colorette@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b" integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw== -colors@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" - integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs= - colors@^1.1.2: version "1.4.0" resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" @@ -2110,15 +2093,10 @@ commander@^2.20.3: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== -commander@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" - integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== - commander@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.0.tgz#b990bfb8ac030aedc6d11bc04d1488ffef56db75" - integrity sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q== + version "6.2.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" + integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== commondir@^1.0.1: version "1.0.1" @@ -2284,9 +2262,9 @@ copy-descriptor@^0.1.0: integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= core-js@^3.0.1, core-js@^3.6.1: - version "3.7.0" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.7.0.tgz#b0a761a02488577afbf97179e4681bf49568520f" - integrity sha512-NwS7fI5M5B85EwpWuIwJN4i/fbisQUwLwiSNUWeXlkAZ0sbBjLEvLvFLf1uzAUV66PcEPt4xCGCmOZSxVf3xzA== + version "3.8.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.8.1.tgz#f51523668ac8a294d1285c3b9db44025fda66d47" + integrity sha512-9Id2xHY1W7m8hCl8NkhQn5CufmF/WuR30BTRewvCXc1aZd3kMECwNZ69ndLbekKfakw9Rf2Xyc+QR6E7Gg+obg== core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" @@ -2376,7 +2354,7 @@ cross-spawn@^5.0.1: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^6.0.0, cross-spawn@^6.0.5: +cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== @@ -2387,7 +2365,7 @@ cross-spawn@^6.0.0, cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^7.0.0, cross-spawn@^7.0.2: +cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -2412,9 +2390,9 @@ cssfilter@0.0.10: integrity sha1-xtJnJjKi5cg+AT5oZKQs6N79IK4= csstype@^3.0.2: - version "3.0.4" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.4.tgz#b156d7be03b84ff425c9a0a4b1e5f4da9c5ca888" - integrity sha512-xc8DUsCLmjvCfoD7LTGE0ou2MIWLx0K9RCZwSHMOdynqRsP4MtUcLeqh1HcQ2dInwDTqn+3CE0/FZh1et+p4jA== + version "3.0.5" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.5.tgz#7fdec6a28a67ae18647c51668a9ff95bb2fa7bb8" + integrity sha512-uVDi8LpBUKQj6sdxNaTetL6FpeCqTjOvAQuQUa/qAqq8oOd4ivkbhgnqayl0dnPal8Tb/yB1tF+gOvCBiicaiQ== cyclist@^1.0.1: version "1.0.1" @@ -2457,24 +2435,17 @@ debug@3.1.0: dependencies: ms "2.0.0" -debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" - integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== +debug@4, debug@4.3.1, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0: + version "4.3.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" + integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== dependencies: ms "2.1.2" -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" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== dependencies: ms "^2.1.1" @@ -2559,6 +2530,20 @@ define-property@^2.0.2: is-descriptor "^1.0.2" isobject "^3.0.1" +del@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/del/-/del-6.0.0.tgz#0b40d0332cea743f1614f818be4feb717714c952" + integrity sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ== + dependencies: + globby "^11.0.1" + graceful-fs "^4.2.4" + is-glob "^4.0.1" + is-path-cwd "^2.2.0" + is-path-inside "^3.0.2" + p-map "^4.0.0" + rimraf "^3.0.2" + slash "^3.0.0" + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -2762,9 +2747,9 @@ err-code@^1.0.0: integrity sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA= errno@~0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" - integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== + version "0.1.8" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" + integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== dependencies: prr "~1.0.1" @@ -2775,7 +2760,7 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.17.0-next.1, es-abstract@^1.17.2: +es-abstract@^1.17.2: version "1.17.7" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.7.tgz#a4de61b2f66989fc7421676c1cb9787573ace54c" integrity sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g== @@ -2859,9 +2844,9 @@ eslint-config-prettier@^6.15.0: get-stdin "^6.0.0" eslint-plugin-prettier@^3.1.4: - version "3.1.4" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.4.tgz#168ab43154e2ea57db992a2cd097c828171f75c2" - integrity sha512-jZDa8z76klRqo+TdGDTFJSavwbnWK2ZpqGKNZ+VvweMW516pDUMmQ2koXvxEE4JhzNvTv+radye/bWGBmA6jmg== + version "3.3.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.0.tgz#61e295349a65688ffac0b7808ef0a8244bdd8d40" + integrity sha512-tMTwO8iUWlSRZIwS9k7/E4vrTsfvsrcM5p1eftyuqWH25nKsz/o6/54I7jwQ/3zobISyC7wMy9ZsFwgTxOcOpQ== dependencies: prettier-linter-helpers "^1.0.0" @@ -2896,12 +2881,12 @@ eslint-visitor-keys@^2.0.0: integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== eslint@^7.12.1: - version "7.13.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.13.0.tgz#7f180126c0dcdef327bfb54b211d7802decc08da" - integrity sha512-uCORMuOO8tUzJmsdRtrvcGq5qposf7Rw0LwkTJkoDbOycVQtQjmnhZSuLQnozLE4TmAzlMVV45eCHmQ1OpDKUQ== + version "7.16.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.16.0.tgz#a761605bf9a7b32d24bb7cde59aeb0fd76f06092" + integrity sha512-iVWPS785RuDA4dWuhhgXTNrGxHHK3a8HLSMBgbbU59ruJDubUraXN8N5rn7kb8tG6sjg74eE0RA3YWT51eusEw== dependencies: "@babel/code-frame" "^7.0.0" - "@eslint/eslintrc" "^0.2.1" + "@eslint/eslintrc" "^0.2.2" ajv "^6.10.0" chalk "^4.0.0" cross-spawn "^7.0.2" @@ -2911,10 +2896,10 @@ eslint@^7.12.1: eslint-scope "^5.1.1" eslint-utils "^2.1.0" eslint-visitor-keys "^2.0.0" - espree "^7.3.0" + espree "^7.3.1" esquery "^1.2.0" esutils "^2.0.2" - file-entry-cache "^5.0.1" + file-entry-cache "^6.0.0" functional-red-black-tree "^1.0.1" glob-parent "^5.0.0" globals "^12.1.0" @@ -2934,7 +2919,7 @@ eslint@^7.12.1: semver "^7.2.1" strip-ansi "^6.0.0" strip-json-comments "^3.1.0" - table "^5.2.3" + table "^6.0.4" text-table "^0.2.0" v8-compile-cache "^2.0.3" @@ -2943,13 +2928,13 @@ esm@^3.2.25: resolved "https://registry.yarnpkg.com/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10" integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA== -espree@^7.3.0: - version "7.3.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.0.tgz#dc30437cf67947cf576121ebd780f15eeac72348" - integrity sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw== +espree@^7.3.0, espree@^7.3.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" + integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g== dependencies: acorn "^7.4.0" - acorn-jsx "^5.2.0" + acorn-jsx "^5.3.1" eslint-visitor-keys "^1.3.0" esprima@^4.0.0, esprima@~4.0.0: @@ -3019,19 +3004,6 @@ execa@^0.7.0: signal-exit "^3.0.0" strip-eof "^1.0.0" -execa@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" - integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== - dependencies: - cross-spawn "^6.0.0" - get-stream "^4.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - execa@^4.0.0, execa@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" @@ -3047,6 +3019,21 @@ execa@^4.0.0, execa@^4.1.0: signal-exit "^3.0.2" strip-final-newline "^2.0.0" +execa@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.0.0.tgz#4029b0007998a841fbd1032e5f4de86a3c1e3376" + integrity sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" @@ -3162,7 +3149,7 @@ fast-diff@^1.1.2: resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== -fast-glob@^3.0.3, fast-glob@^3.1.1: +fast-glob@^3.1.1: version "3.2.4" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.4.tgz#d20aefbf99579383e7f3cc66529158c9b98554d3" integrity sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ== @@ -3185,9 +3172,9 @@ fast-levenshtein@^2.0.6: integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= fastq@^1.6.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.9.0.tgz#e16a72f338eaca48e91b5c23593bcc2ef66b7947" - integrity sha512-i7FVWL8HhVY+CTkwFxkN2mk3h+787ixS5S63eb78diVRc1MCssarHq3W5cj0av7YDSwmaV928RNag+U1etRQ7w== + version "1.10.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.10.0.tgz#74dbefccade964932cdf500473ef302719c652bb" + integrity sha512-NL2Qc5L3iQEsyYzweq7qfgy5OtXCmGzGvhElGEd/SoFWEMOEczNh5s5ocaF01HDetxz+p8ecjNPA6cZxxIHmzA== dependencies: reusify "^1.0.4" @@ -3210,12 +3197,12 @@ figures@^3.0.0, figures@^3.2.0: dependencies: escape-string-regexp "^1.0.5" -file-entry-cache@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" - integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== +file-entry-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.0.tgz#7921a89c391c6d93efec2169ac6bf300c527ea0a" + integrity sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA== dependencies: - flat-cache "^2.0.1" + flat-cache "^3.0.4" fill-range@^4.0.0: version "4.0.0" @@ -3338,31 +3325,30 @@ flagged-respawn@^1.0.0: resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-1.0.1.tgz#e7de6f1279ddd9ca9aac8a5971d618606b3aab41" integrity sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q== -flat-cache@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" - integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== dependencies: - flatted "^2.0.0" - rimraf "2.6.3" - write "1.0.3" + flatted "^3.1.0" + rimraf "^3.0.2" -flatted@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" - integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== +flatted@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.0.tgz#a5d06b4a8b01e3a63771daa5cb7a1903e2e57067" + integrity sha512-tW+UkmtNg/jv9CSofAKvgVcO7c2URjhTdW1ZTkcAritblu8tajiYy7YisnIflEwtKssCtOxpnBRoCB7iap0/TA== -flow-parser@^0.137.0: - version "0.137.0" - resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.137.0.tgz#8c05612ff9344648d8bcdeaa4c58d131e875d842" - integrity sha512-i3KXJZ8lhlQI0n+BoZzIeH/rv+fNvAiu1i9/s64MklBV+HuhFbycUML7367J2eng0gapLnwvYPFNaPZys8POsA== +flow-parser@^0.141.0: + version "0.141.0" + resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.141.0.tgz#b9e176e54dd204b2375e35df10caf6607c3d09a1" + integrity sha512-WKdBiR9sDfkgEyPGhIgldUrVM08D57CgHLgd0FOXbhcVYXNfw+eHSApQ8SdcdQQoqrOvhlcVRB8lsn9bD5GQOw== flow-remove-types@^2.112.0: - version "2.137.0" - resolved "https://registry.yarnpkg.com/flow-remove-types/-/flow-remove-types-2.137.0.tgz#4653035c04de03a9177e85e5d09391fd14e703e9" - integrity sha512-Ubj3M8kKv6rA5mxy9qVxKoZZ8COcFknUvwjUb1uxObrOLOhhZYeIrs//P6EUzd14cVKzhxPQ2Ey7b0DESq7VcA== + version "2.141.0" + resolved "https://registry.yarnpkg.com/flow-remove-types/-/flow-remove-types-2.141.0.tgz#2f9d0339bf8e94dbf50c2b5e76efb82be679949d" + integrity sha512-N5t55GrD3VgzgwWSOja6IULbz/W1HkmPKwwic+zsYhpW1UfLBwsO4y0j+P5J+wr0a/xdm2rH1dBLpKiRPQDBIw== dependencies: - flow-parser "^0.137.0" + flow-parser "^0.141.0" pirates "^3.0.2" vlq "^0.2.1" @@ -3460,7 +3446,7 @@ fs-exists-cached@^1.0.0: resolved "https://registry.yarnpkg.com/fs-exists-cached/-/fs-exists-cached-1.0.0.tgz#cf25554ca050dc49ae6656b41de42258989dcbce" integrity sha1-zyVVTKBQ3EmuZla0HeQiWJidy84= -fs-extra@8.1.0, fs-extra@^8.1.0: +fs-extra@8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== @@ -3592,9 +3578,9 @@ get-caller-file@^2.0.1: integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== get-intrinsic@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.1.tgz#94a9768fcbdd0595a1c9273aacf4c89d075631be" - integrity sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg== + version "1.0.2" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.2.tgz#6820da226e50b24894e08859469dc68361545d49" + integrity sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg== dependencies: function-bind "^1.1.1" has "^1.0.3" @@ -3634,6 +3620,11 @@ get-stream@^5.0.0: dependencies: pump "^3.0.0" +get-stream@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.0.tgz#3e0012cb6827319da2706e601a1583e8629a6718" + integrity sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg== + get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" @@ -3732,20 +3723,6 @@ globals@^12.1.0: dependencies: type-fest "^0.8.1" -globby@10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.1.tgz#4782c34cb75dd683351335c5829cc3420e606b22" - integrity sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A== - dependencies: - "@types/glob" "^7.1.1" - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.0.3" - glob "^7.1.3" - ignore "^5.1.1" - merge2 "^1.2.3" - slash "^3.0.0" - globby@^11.0.0, globby@^11.0.1: version "11.0.1" resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.1.tgz#9a2bf107a068f3ffeabc49ad702c79ede8cfd357" @@ -3789,18 +3766,18 @@ graphql-extensions@^0.12.6: apollo-server-env "^2.4.5" apollo-server-types "^0.6.1" -graphql-parse-resolve-info@^4.9.0: - version "4.9.0" - resolved "https://registry.yarnpkg.com/graphql-parse-resolve-info/-/graphql-parse-resolve-info-4.9.0.tgz#e2a7f3b6c328aaf1c0b867102bb7207e03a98ef3" - integrity sha512-tJqpmG+t5e68ZUjlbNzZ6O6kjzULeVBa+2KOC0IwwxaajtnKpp1bzaZxteOvWATdPwuASfOFJA1epYiva6/ztQ== +graphql-parse-resolve-info@^4.10.0: + version "4.10.0" + resolved "https://registry.yarnpkg.com/graphql-parse-resolve-info/-/graphql-parse-resolve-info-4.10.0.tgz#3f61fa4bcbcad65d017f503fac4075f07624a69f" + integrity sha512-4KWA4oiVnC1bduPZzmuUsTT9SZf/sbdrOAtOsHz747H6Azs4xPgj7/DPXCgdYvKrd4Ci9fNDcem4mOVV2Lct1w== dependencies: debug "^4.1.1" tslib "^2.0.1" -graphql-request@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-3.3.0.tgz#1b9003f34b73cd40d691803d2d422fde5c713af3" - integrity sha512-NHj65WSIUh8j7TBYgzWU0fqvLfxrqFDrLG8nZUh+IREZw50ljR6JXlXRkr52/fL/46wpItiQNLDrG+UZI+KmzA== +graphql-request@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-3.4.0.tgz#3a400cd5511eb3c064b1873afb059196bbea9c2b" + integrity sha512-acrTzidSlwAj8wBNO7Q/UQHS8T+z5qRGquCQRv9J1InwR01BBWV9ObnoE+JS5nCCEj8wSGS0yrDXVDoRiKZuOg== dependencies: cross-fetch "^3.0.6" extract-files "^9.0.0" @@ -4053,6 +4030,11 @@ human-signals@^1.1.1: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + humanize-ms@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" @@ -4061,9 +4043,9 @@ humanize-ms@^1.2.1: ms "^2.0.0" husky@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/husky/-/husky-4.3.0.tgz#0b2ec1d66424e9219d359e26a51c58ec5278f0de" - integrity sha512-tTMeLCLqSBqnflBZnlVDhpaIMucSGaYyX6855jM4AguGeWCeSzNdb1mfyWduTZ3pe3SJVvVWGL0jO1iKZVPfTA== + version "4.3.6" + resolved "https://registry.yarnpkg.com/husky/-/husky-4.3.6.tgz#ebd9dd8b9324aa851f1587318db4cccb7665a13c" + integrity sha512-o6UjVI8xtlWRL5395iWq9LKDyp/9TE7XMOTvIpEVzW638UcGxTmV5cfel6fsk/jbZSTlvfGVJf2svFtybcIZag== dependencies: chalk "^4.0.0" ci-info "^2.0.0" @@ -4112,15 +4094,15 @@ ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.1.1, ignore@^5.1.4: +ignore@^5.1.4: version "5.1.8" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1: - version "3.2.2" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.2.tgz#fc129c160c5d68235507f4331a6baad186bdbc3e" - integrity sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw== + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== dependencies: parent-module "^1.0.0" resolve-from "^4.0.0" @@ -4183,9 +4165,9 @@ inherits@2.0.3: integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== init-package-json@^1.10.3: version "1.10.3" @@ -4323,10 +4305,10 @@ is-cidr@^3.0.0: dependencies: cidr-regex "^2.0.10" -is-core-module@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.1.0.tgz#a4cc031d9b1aca63eecbd18a650e13cb4eeab946" - integrity sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA== +is-core-module@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.2.0.tgz#97037ef3d52224d85163f5597b2b63d9afed981a" + integrity sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ== dependencies: has "^1.0.3" @@ -4417,9 +4399,9 @@ is-installed-globally@^0.1.0: is-path-inside "^1.0.0" is-negative-zero@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.0.tgz#9553b121b0fac28869da9ed459e20c7543788461" - integrity sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE= + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" + integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== is-npm@^1.0.0: version "1.0.0" @@ -4448,6 +4430,11 @@ is-obj@^2.0.0: resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== +is-path-cwd@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" + integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== + 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" @@ -4455,6 +4442,11 @@ is-path-inside@^1.0.0: dependencies: path-is-inside "^1.0.1" +is-path-inside@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.2.tgz#f5220fc82a3e233757291dddc9c5877f2a1f3017" + integrity sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg== + is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" @@ -4467,11 +4459,6 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" -is-plain-object@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-3.0.1.tgz#662d92d24c0aa4302407b0d45d21f2251c85f85b" - integrity sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g== - is-plain-object@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" @@ -4676,9 +4663,9 @@ java-properties@^1.0.0: integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-yaml@^3.13.1: - version "3.14.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" - integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A== + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== dependencies: argparse "^1.0.7" esprima "^4.0.0" @@ -4792,20 +4779,20 @@ kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== -knex@^0.21.12: - version "0.21.12" - resolved "https://registry.yarnpkg.com/knex/-/knex-0.21.12.tgz#961bdb484311eb853030f6f49bd5bf9eca89dc51" - integrity sha512-AEyyiTM9p/x/Pb38TPZkvphKPmn8UWxP7MdIphzjAOielOfFFeU6pjP6y3M7UJ7rxrQsCrAYHwdonLQ3l1JCDw== +knex@^0.21.14: + version "0.21.14" + resolved "https://registry.yarnpkg.com/knex/-/knex-0.21.14.tgz#ac1e0b51c599be9e65e77df682bbecefabad99ad" + integrity sha512-UKoRtSzeSlm4Fi/jcFZ+NNmwYPnLADKy3u7Wm8WFhhFlv/I9RXf6TrTHNeE9hjIK1hCUz2yn4PeXagvjArTPUg== dependencies: colorette "1.2.1" - commander "^5.1.0" - debug "4.1.1" + commander "^6.2.0" + debug "4.3.1" esm "^3.2.25" getopts "2.2.5" interpret "^2.2.0" liftoff "3.1.0" lodash "^4.17.20" - pg-connection-string "2.3.0" + pg-connection-string "2.4.0" tarn "^3.0.1" tildify "2.0.0" v8flags "^3.2.0" @@ -4996,9 +4983,9 @@ lines-and-columns@^1.1.6: integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= lint-staged@^10.5.1: - version "10.5.1" - resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-10.5.1.tgz#901e915c2360072dded0e7d752a0d9a49e079daa" - integrity sha512-fTkTGFtwFIJJzn/PbUO3RXyEBHIhbfYBE7+rJyLcOXabViaO/h6OslgeK6zpeUtzkDrzkgyAYDTLAwx6JzDTHw== + version "10.5.3" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-10.5.3.tgz#c682838b3eadd4c864d1022da05daa0912fb1da5" + integrity sha512-TanwFfuqUBLufxCc3RUtFEkFraSPNR3WzWcGF39R3f2J7S9+iF9W0KTVLfSy09lYGmZS5NDCxjNvhGMSJyFCWg== dependencies: chalk "^4.1.0" cli-truncate "^2.1.0" @@ -5017,9 +5004,9 @@ lint-staged@^10.5.1: stringify-object "^3.3.0" listr2@^3.2.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/listr2/-/listr2-3.2.2.tgz#d20feb75015e506992b55af40722ba1af168b8f1" - integrity sha512-AajqcZEUikF2ioph6PfH3dIuxJclhr3i3kHgTOP0xeXdWQohrvJAAmqVcV43/GI987HFY/vzT73jYXoa4esDHg== + version "3.2.3" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-3.2.3.tgz#ef9e0d790862f038dde8a9837be552b1adfd1c07" + integrity sha512-vUb80S2dSUi8YxXahO8/I/s29GqnOL8ozgHVLjfWQXa03BNEeS1TpBLjh2ruaqq5ufx46BRGvfymdBSuoXET5w== dependencies: chalk "^4.1.0" cli-truncate "^2.1.0" @@ -5204,7 +5191,7 @@ lodash.without@~4.4.0: resolved "https://registry.yarnpkg.com/lodash.without/-/lodash.without-4.4.0.tgz#3cd4574a00b67bae373a94b748772640507b7aac" integrity sha1-PNRXSgC2e643OpS3SHcmQFB7eqw= -lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.4: +lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.4: version "4.17.20" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== @@ -5241,9 +5228,9 @@ log-update@^4.0.0: wrap-ansi "^6.2.0" loglevel@^1.6.7: - version "1.7.0" - resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.0.tgz#728166855a740d59d38db01cf46f042caa041bb0" - integrity sha512-i2sY04nal5jDcagM3FMfG++T69GEEM8CYuOfeOIvmXzOIcwE9a/CJPR0MFM97pYMj/u10lzz7/zd7+qwhrBTqQ== + version "1.7.1" + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.1.tgz#005fde2f5e6e47068f935ff28573e125ef72f197" + integrity sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw== long@^4.0.0: version "4.0.0" @@ -5284,11 +5271,6 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -macos-release@^2.2.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.4.1.tgz#64033d0ec6a5e6375155a74b1a1eba8e509820ac" - integrity sha512-H/QHeBIN1fIGJX517pvK8IEK53yQOW7YcEI55oYtgjDdoCQQz7eJS94qt5kNrscReEyuD/JcdFCm2XBEcGOITg== - make-dir@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" @@ -5375,14 +5357,14 @@ marked-terminal@^4.0.0: supports-hyperlinks "^2.1.0" marked@^1.0.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/marked/-/marked-1.2.3.tgz#58817ba348a7c9398cb94d40d12e0d08df83af57" - integrity sha512-RQuL2i6I6Gn+9n81IDNGbL0VHnta4a+8ZhqvryXEniTb/hQNtf3i26hi1XWUhzb9BgVyWHKR3UO8MaHtKoYibw== + version "1.2.7" + resolved "https://registry.yarnpkg.com/marked/-/marked-1.2.7.tgz#6e14b595581d2319cdcf033a24caaf41455a01fb" + integrity sha512-No11hFYcXr/zkBvL6qFmAp1z6BKY3zqLMHny/JN/ey+al7qwCM2+CMBL9BOgqMxZU36fz4cCWfn2poWIf7QRXA== meant@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/meant/-/meant-1.0.2.tgz#5d0c78310a3d8ae1408a16be0fe0bd42a969f560" - integrity sha512-KN+1uowN/NK+sT/Lzx7WSGIj2u+3xe5n2LbwObfjOhPZiA+cCfCm6idVl0RkEfjThkw5XJ96CyRcanq6GmKtUg== + version "1.0.3" + resolved "https://registry.yarnpkg.com/meant/-/meant-1.0.3.tgz#67769af9de1d158773e928ae82c456114903554c" + integrity sha512-88ZRGcNxAq4EH38cQ4D85PM57pikCwS8Z99EWHODxN7KBY+UuPiqzRTtZzS8KTXO/ywSWbdjjJST2Hly/EQxLw== media-typer@0.3.0: version "0.3.0" @@ -5430,7 +5412,7 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -merge2@^1.2.3, merge2@^1.3.0: +merge2@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== @@ -5485,9 +5467,9 @@ mime@1.6.0: integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== mime@^2.4.3: - version "2.4.6" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.6.tgz#e5b407c90db442f2beb5b162373d07b69affa4d1" - integrity sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA== + version "2.4.7" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.7.tgz#962aed9be0ed19c91fd7dc2ece5d7f4e89a90d74" + integrity sha512-dhNd1uA2u397uQk3Nv5LM4lm93WYDUXFn3Fu291FJerns4jyTudqhIWe4W04YLy7Uk1tm1Ore04NpjRvQp/NPA== mimic-fn@^1.0.0: version "1.2.0" @@ -5605,11 +5587,16 @@ 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.1.2, ms@^2.0.0, ms@^2.1.1, ms@^2.1.2: +ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +ms@^2.0.0, ms@^2.1.1, ms@^2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + mute-stream@~0.0.4: version "0.0.8" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" @@ -5906,22 +5893,22 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" -npm-run-path@^4.0.0: +npm-run-path@^4.0.0, npm-run-path@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== dependencies: path-key "^3.0.0" -npm-user-validate@~1.0.0: +npm-user-validate@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/npm-user-validate/-/npm-user-validate-1.0.1.tgz#31428fc5475fe8416023f178c0ab47935ad8c561" integrity sha512-uQwcd/tY+h1jnEaze6cdX/LrhWhoBxfSknxentoqmIuStxUExxjWd3ULMLFPiFUrZKbOVMowH6Jq2FRWfmhcEw== -npm@^6.13.0: - version "6.14.8" - resolved "https://registry.yarnpkg.com/npm/-/npm-6.14.8.tgz#64ef754345639bc035982ec3f609353c8539033c" - integrity sha512-HBZVBMYs5blsj94GTeQZel7s9odVuuSUHy1+AlZh7rPVux1os2ashvEGLy/STNK7vUjbrCg5Kq9/GXisJgdf6A== +npm@^6.14.8: + version "6.14.10" + resolved "https://registry.yarnpkg.com/npm/-/npm-6.14.10.tgz#f45c8e4244294ba793770f2ab0e9ce2d0b93fd29" + integrity sha512-FT23Qy/JMA+qxEYReMOr1MY7642fKn8Onn+72LASPi872Owvmw0svm+/DXTHOC3yO9CheEO+EslyXEpdBdRtIA== dependencies: JSONStream "^1.3.5" abbrev "~1.1.1" @@ -5995,10 +5982,10 @@ npm@^6.13.0: npm-pick-manifest "^3.0.2" npm-profile "^4.0.4" npm-registry-fetch "^4.0.7" - npm-user-validate "~1.0.0" + npm-user-validate "^1.0.1" npmlog "~4.1.2" once "~1.4.0" - opener "^1.5.1" + opener "^1.5.2" osenv "^0.1.5" pacote "^9.5.12" path-is-inside "~1.0.2" @@ -6105,9 +6092,9 @@ object-copy@^0.1.0: kind-of "^3.0.3" object-inspect@^1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0" - integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA== + version "1.9.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.9.0.tgz#c90521d74e1127b67266ded3394ad6116986533a" + integrity sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw== object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" @@ -6147,12 +6134,13 @@ object.defaults@^1.1.0: isobject "^3.0.0" object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649" - integrity sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg== + version "2.1.1" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.1.tgz#0dfda8d108074d9c563e80490c883b6661091544" + integrity sha512-6DtXgZ/lIZ9hqx4GtZETobXLR/ZLaa0aqV0kzbn80Rf8Z2e/XFnhA0I7p07N2wH8bBBltr2xQPi6sbKWAY2Eng== dependencies: + call-bind "^1.0.0" define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" + es-abstract "^1.18.0-next.1" object.map@^1.0.0: version "1.0.1" @@ -6169,12 +6157,12 @@ object.pick@^1.2.0, object.pick@^1.3.0: dependencies: isobject "^3.0.1" -objection@^2.2.3: - version "2.2.3" - resolved "https://registry.yarnpkg.com/objection/-/objection-2.2.3.tgz#7509620b75a6907227cfb6a3fc4135222bb2e749" - integrity sha512-uNya9GuHlNeix7H0URthVE3+CmAlXmxkU69LAcRnncLjujJ8l1YX8JCB2GVSErTYS3Oc2xneF1ZWaR/MS8r63g== +objection@^2.2.5: + version "2.2.5" + resolved "https://registry.yarnpkg.com/objection/-/objection-2.2.5.tgz#ecbe46ea118b94fff5853aa9b225b88fb2527cb8" + integrity sha512-17VDi2txhQAn2/G0JnNy2C6WfM2Zo03/8tyvoNMg7n/qv3uf+hetFuLjg5FxD0ZxeB69kuX/k7l2UsGboPdnFA== dependencies: - ajv "^6.12.0" + ajv "^6.12.6" db-errors "^0.2.3" on-finished@~2.3.0: @@ -6198,7 +6186,7 @@ onetime@^2.0.0: dependencies: mimic-fn "^1.0.0" -onetime@^5.1.0: +onetime@^5.1.0, onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== @@ -6210,7 +6198,7 @@ opencollective-postinstall@^2.0.2: resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259" integrity sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q== -opener@^1.5.1: +opener@^1.5.1, opener@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== @@ -6241,14 +6229,6 @@ os-locale@^2.0.0: lcid "^1.0.0" mem "^1.1.0" -os-name@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/os-name/-/os-name-3.1.0.tgz#dec19d966296e1cd62d701a5a66ee1ddeae70801" - integrity sha512-h8L+8aNjNcMpo/mAIBPn5PXCM16iyPGjHNWo6U1YO8sJTMHtEtyczI6QJnLoplswm6goopQkqc7OAnjhWcugVg== - dependencies: - macos-release "^2.2.0" - windows-release "^3.1.0" - os-tmpdir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" @@ -6275,9 +6255,9 @@ own-or@^1.0.0: integrity sha1-Tod/vtqaLsgAD7wLyuOWRe6L+Nw= p-each-series@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.1.0.tgz#961c8dd3f195ea96c747e636b262b800a6b1af48" - integrity sha512-ZuRs1miPT4HrjFa+9fRfOFXxGJfORgelKV9f9nNOWw2gl6gVsRaVDOQP0+MI0G0wGKns1Yacsu0GjOFbTK0JFQ== + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.2.0.tgz#105ab0357ce72b202a8a8b94933672657b5e2a9a" + integrity sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA== p-filter@^2.0.0: version "2.1.0" @@ -6311,11 +6291,11 @@ p-limit@^2.0.0, p-limit@^2.2.0: p-try "^2.0.0" p-limit@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.0.2.tgz#1664e010af3cadc681baafd3e2a437be7b0fb5fe" - integrity sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg== + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== dependencies: - p-try "^2.0.0" + yocto-queue "^0.1.0" p-locate@^2.0.0: version "2.0.0" @@ -6577,10 +6557,10 @@ performance-now@^2.1.0: resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= -pg-connection-string@2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.3.0.tgz#c13fcb84c298d0bfa9ba12b40dd6c23d946f55d6" - integrity sha512-ukMTJXLI7/hZIwTW7hGMZJ0Lj0S2XQBCJ4Shv4y1zgQ/vqVea+FLhzywvPj0ujSuofu+yA4MYHGZPTsgjBgJ+w== +pg-connection-string@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.4.0.tgz#c979922eb47832999a204da5dbe1ebf2341b6a10" + integrity sha512-3iBXuv7XKvxeMrIgym7njT+HlZkwZqqGX4Bu9cci8xHZNT+Um1gWKqCsAzcC0d95rcKMU5WBg6YRUcHyV0HZKQ== picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1, picomatch@^2.2.2: version "2.2.2" @@ -6661,9 +6641,9 @@ prettier-linter-helpers@^1.0.0: fast-diff "^1.1.2" prettier@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.1.2.tgz#3050700dae2e4c8b67c4c3f666cdb8af405e1ce5" - integrity sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg== + version "2.2.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.2.1.tgz#795a1a78dd52f073da0cd42b21f9c91381923ff5" + integrity sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q== process-nextick-args@~2.0.0: version "2.0.1" @@ -7055,9 +7035,9 @@ registry-auth-token@^3.0.1: safe-buffer "^5.0.1" registry-auth-token@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.0.tgz#1d37dffda72bbecd0f581e4715540213a65eb7da" - integrity sha512-P+lWzPrsgfN+UEpDS3U8AQKg/UjZX6mQSJueZj3EK+vNESoqBSpBUD3gmu4sF9lOsjXWjF11dQKUqemf3veq1w== + version "4.2.1" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.1.tgz#6d7b4006441918972ccd5fedcd41dc322c79b250" + integrity sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw== dependencies: rc "^1.2.8" @@ -7168,12 +7148,12 @@ resolve@1.17.0: dependencies: path-parse "^1.0.6" -resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.17.0, resolve@^1.3.2: - version "1.18.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.18.1.tgz#018fcb2c5b207d2a6424aee361c5a266da8f4130" - integrity sha512-lDfCPaMKfOJXjy0dPayzPdF1phampNWr3qFCjAu+rw/qbQmr5jWH5xN2hwh9QKfw9E5v4hwV7A+jrCmL8yjjqA== +resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.17.0: + version "1.19.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" + integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== dependencies: - is-core-module "^2.0.0" + is-core-module "^2.1.0" path-parse "^1.0.6" restore-cursor@^2.0.0: @@ -7219,10 +7199,10 @@ rimraf@2, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2. dependencies: glob "^7.1.3" -rimraf@2.6.3: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== dependencies: glob "^7.1.3" @@ -7233,17 +7213,6 @@ rollup-plugin-cleaner@^1.0.0: dependencies: rimraf "^2.6.3" -rollup-plugin-copy@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/rollup-plugin-copy/-/rollup-plugin-copy-3.3.0.tgz#5ba230047f86b9f703a29288f242948a5580e7b9" - integrity sha512-euDjCUSBXZa06nqnwCNADbkAcYDfzwowfZQkto9K/TFhiH+QG7I4PUsEMwM9tDgomGWJc//z7KLW8t+tZwxADA== - dependencies: - "@types/fs-extra" "^8.0.1" - colorette "^1.1.0" - fs-extra "^8.1.0" - globby "10.0.1" - is-plain-object "^3.0.0" - rollup-plugin-typescript2@^0.29.0: version "0.29.0" resolved "https://registry.yarnpkg.com/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.29.0.tgz#b7ad83f5241dbc5bdf1e98d9c3fca005ffe39e1a" @@ -7256,9 +7225,9 @@ rollup-plugin-typescript2@^0.29.0: tslib "2.0.1" rollup@^2.33.1: - version "2.33.1" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.33.1.tgz#802795164164ee63cd47769d8879c33ec8ae0c40" - integrity sha512-uY4O/IoL9oNW8MMcbA5hcOaz6tZTMIh7qJHx/tzIJm+n1wLoY38BLn6fuy7DhR57oNFLMbDQtDeJoFURt5933w== + version "2.35.1" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.35.1.tgz#e6bc8d10893556a638066f89e8c97f422d03968c" + integrity sha512-q5KxEyWpprAIcainhVy6HfRttD9kutQpHbeqDTWnqAFNJotiojetK6uqmcydNMymBEtC4I8bCYR+J3mTMqeaUA== optionalDependencies: fsevents "~2.1.2" @@ -7317,9 +7286,9 @@ scheduler@^0.18.0: object-assign "^4.1.1" semantic-release@^17.2.2: - version "17.2.2" - resolved "https://registry.yarnpkg.com/semantic-release/-/semantic-release-17.2.2.tgz#520dae9cd188c7cdcc5216a7aad131548fc5cec7" - integrity sha512-LNU68ud3a3oU46H11OThXaKAK430jGGGTIF4VsiP843kRmS6s8kVCceLRdi7yWWz/sCCMD0zygPTQV2Jw79J5g== + version "17.3.0" + resolved "https://registry.yarnpkg.com/semantic-release/-/semantic-release-17.3.0.tgz#121252b5bb6acc1048d7657111173b03d47502c5" + integrity sha512-enhDayMZRP4nWcWAMBFHHB7THRaIcRdUAZv3lxd65pXs2ttzay7IeCvRRrGayRWExtnY0ulwRz5Ycp88Dv/UeQ== dependencies: "@semantic-release/commit-analyzer" "^8.0.0" "@semantic-release/error" "^2.2.0" @@ -7379,7 +7348,7 @@ semver-regex@^2.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@7.3.2, semver@^7.1.2, semver@^7.2.1, semver@^7.3.2: +semver@7.3.2: version "7.3.2" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== @@ -7389,6 +7358,13 @@ semver@^6.0.0, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^7.1.2, semver@^7.2.1, semver@^7.3.2: + version "7.3.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97" + integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw== + dependencies: + lru-cache "^6.0.0" + semver@~5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" @@ -7487,7 +7463,7 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -signal-exit@^3.0.0, signal-exit@^3.0.2: +signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== @@ -7506,15 +7482,6 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -slice-ansi@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" - integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== - dependencies: - ansi-styles "^3.2.0" - astral-regex "^1.0.0" - is-fullwidth-code-point "^2.0.0" - slice-ansi@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" @@ -7675,9 +7642,9 @@ spdx-expression-parse@^3.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.6" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz#c80757383c28abf7296744998cbc106ae8b854ce" - integrity sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw== + version "3.0.7" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz#e9c18a410e5ed7e12442a549fbd8afa767038d65" + integrity sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ== split-on-first@^1.0.0: version "1.1.0" @@ -7749,10 +7716,12 @@ ssri@^6.0.0, ssri@^6.0.1: dependencies: figgy-pudding "^3.5.1" -stack-utils@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8" - integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA== +stack-utils@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.4.tgz#4b600971dcfc6aed0cbdf2a8268177cc916c87c8" + integrity sha512-IPDJfugEGbfizBwBZRZ3xpccMdRyP5lqsBWXGQWimVjua/ccLCeMOAVjlc1R7LxFjo5sEDhyNIXd8mo/AiDS9w== + dependencies: + escape-string-regexp "^2.0.0" static-extend@^0.1.1: version "0.1.2" @@ -7855,20 +7824,20 @@ string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0: strip-ansi "^6.0.0" string.prototype.trimend@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.2.tgz#6ddd9a8796bc714b489a3ae22246a208f37bfa46" - integrity sha512-8oAG/hi14Z4nOVP0z6mdiVZ/wqjDtWSLygMigTzAb+7aPEDTleeFf+WrF+alzecxIRkckkJVn+dTlwzJXORATw== + version "1.0.3" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz#a22bd53cca5c7cf44d7c9d5c732118873d6cd18b" + integrity sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw== dependencies: + call-bind "^1.0.0" define-properties "^1.1.3" - es-abstract "^1.18.0-next.1" string.prototype.trimstart@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.2.tgz#22d45da81015309cd0cdd79787e8919fc5c613e7" - integrity sha512-7F6CdBTl5zyu30BJFdzSTlSlLPwODC23Od+iLoVH8X6+3fvDPPuBVVj9iaB1GOsSTSIgVfsfm27R2FGrAPznWg== + version "1.0.3" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz#9b4cb590e123bb36564401d59824298de50fd5aa" + integrity sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg== dependencies: + call-bind "^1.0.0" define-properties "^1.1.3" - es-abstract "^1.18.0-next.1" string_decoder@^1.1.1: version "1.3.0" @@ -8008,15 +7977,15 @@ symbol-observable@^1.0.4: resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== -table@^5.2.3: - version "5.4.6" - resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" - integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== +table@^6.0.4: + version "6.0.4" + resolved "https://registry.yarnpkg.com/table/-/table-6.0.4.tgz#c523dd182177e926c723eb20e1b341238188aa0d" + integrity sha512-sBT4xRLdALd+NFBvwOz8bw4b15htyythha+q+DVZqy2RS08PPC8O2sZFgJYEY7bJvbCFKccs+WIZ/cd+xxTWCw== dependencies: - ajv "^6.10.2" - lodash "^4.17.14" - slice-ansi "^2.1.0" - string-width "^3.0.0" + ajv "^6.12.4" + lodash "^4.17.20" + slice-ansi "^4.0.0" + string-width "^4.2.0" tap-mocha-reporter@^5.0.0: version "5.0.1" @@ -8049,9 +8018,9 @@ tap-yaml@^1.0.0: yaml "^1.5.0" tap@^14.10.8: - version "14.10.8" - resolved "https://registry.yarnpkg.com/tap/-/tap-14.10.8.tgz#3c9ce79519acca2f40e57350513b2aa51c6e57c2" - integrity sha512-aamkWefJ0G8GGf9t5LWFtrNF5tfVd8ut/tDUianLF6N4621ERITIl0qkocWCVEnsM6hZnaMKa+SggSAaBlC2tA== + version "14.11.0" + resolved "https://registry.yarnpkg.com/tap/-/tap-14.11.0.tgz#64f1f50b10280d5149690c9a7059d859f2bbcd24" + integrity sha512-z8qnNFVyIjLh/bNoTLFRkEk09XZUDAZbCkz/BjvHHly3ao5H+y60gPnedALfheEjA6dA4tpp/mrKq2NWlMuq0A== dependencies: "@types/react" "^16.9.16" async-hook-domain "^1.1.3" @@ -8083,7 +8052,7 @@ tap@^14.10.8: rimraf "^2.7.1" signal-exit "^3.0.0" source-map-support "^0.5.16" - stack-utils "^1.0.2" + stack-utils "^1.0.3" tap-mocha-reporter "^5.0.0" tap-parser "^10.0.1" tap-yaml "^1.0.0" @@ -8136,14 +8105,15 @@ temp-dir@^2.0.0: resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-2.0.0.tgz#bde92b05bdfeb1516e804c9c00ad45177f31321e" integrity sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg== -tempy@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/tempy/-/tempy-0.5.0.tgz#2785c89df39fcc4d1714fc554813225e1581d70b" - integrity sha512-VEY96x7gbIRfsxqsafy2l5yVxxp3PhwAGoWMyC2D2Zt5DmEv+2tGiPOrquNRpf21hhGnKLVEsuqleqiZmKG/qw== +tempy@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/tempy/-/tempy-1.0.0.tgz#4f192b3ee3328a2684d0e3fc5c491425395aab65" + integrity sha512-eLXG5B1G0mRPHmgH2WydPl5v4jH35qEn3y/rA/aahKhIa91Pn119SsU7n7v/433gtT9ONzC8ISvNHIh2JSTm0w== dependencies: + del "^6.0.0" is-stream "^2.0.0" temp-dir "^2.0.0" - type-fest "^0.12.0" + type-fest "^0.16.0" unique-string "^2.0.0" term-size@^1.2.0: @@ -8366,15 +8336,15 @@ type-fest@^0.11.0: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1" integrity sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ== -type-fest@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.12.0.tgz#f57a27ab81c68d136a51fd71467eff94157fa1ee" - integrity sha512-53RyidyjvkGpnWPMF9bQgFtWp+Sl8O2Rp13VavmJgfAP9WWG6q6TkrKU8iyJdnwnfgHI6k2hTlgqH4aSdjoTbg== +type-fest@^0.16.0: + version "0.16.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.16.0.tgz#3240b891a78b0deae910dbeb86553e552a148860" + integrity sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg== type-fest@^0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.0.tgz#2edfa6382d48653707344f7fccdb0443d460e8d6" - integrity sha512-fbDukFPnJBdn2eZ3RR+5mK2slHLFd6gYHY7jna1KWWy4Yr4XysHuCdXRzy+RiG/HwG4WJat00vdC2UHky5eKiQ== + version "0.18.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f" + integrity sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw== type-fest@^0.6.0: version "0.6.0" @@ -8407,14 +8377,14 @@ typedarray@^0.0.6: integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= typescript@^3.7.2, typescript@^4, typescript@^4.0.5: - version "4.0.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.5.tgz#ae9dddfd1069f1cb5beb3ef3b2170dd7c1332389" - integrity sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ== + version "4.1.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.3.tgz#519d582bd94cba0cf8934c7d8e8467e473f53bb7" + integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg== uglify-js@^3.1.4: - version "3.11.5" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.11.5.tgz#d6788bc83cf35ff18ea78a65763e480803409bc6" - integrity sha512-btvv/baMqe7HxP7zJSF7Uc16h1mSfuuSplT0/qdjxseesDU+yYzH33eHBH+eMdeRXwujXspaCTooWHQVVBh09w== + version "3.12.2" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.12.2.tgz#c7ae89da0ed1bb58999c7fce07190b347fdbdaba" + integrity sha512-rWYleAvfJPjduYCt+ELvzybNah/zIkRteGXIBO8X0lteRZPGladF61hFi8tU7qKTsF7u6DUQCtT9k00VlFOgkg== uid-number@0.0.6: version "0.0.6" @@ -8477,13 +8447,6 @@ unique-string@^2.0.0: dependencies: crypto-random-string "^2.0.0" -universal-user-agent@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-5.0.0.tgz#a3182aa758069bf0e79952570ca757de3579c1d9" - integrity sha512-B5TPtzZleXyPrUMKCpEHFmVhMN6EhmJYjG5PQna9s7mXeSqGTLap4OpqLl5FCEFUI3UBmllkETwKf/db66Y54Q== - dependencies: - os-name "^3.1.0" - universal-user-agent@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee" @@ -8605,9 +8568,9 @@ uuid@^3.1.0, uuid@^3.3.2, uuid@^3.3.3: integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== uuid@^8.0.0: - version "8.3.1" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.1.tgz#2ba2e6ca000da60fce5a196954ab241131e05a31" - integrity sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg== + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== v8-compile-cache@^2.0.3: version "2.2.0" @@ -8707,13 +8670,6 @@ widest-line@^3.1.0: dependencies: string-width "^4.0.0" -windows-release@^3.1.0: - version "3.3.3" - resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-3.3.3.tgz#1c10027c7225743eec6b89df160d64c2e0293999" - integrity sha512-OSOGH1QYiW5yVor9TtmXKQvt2vjQqbYS+DqmsZw+r7xDwLXEeT3JGW0ZppFmHx4diyXmxt238KFR3N9jzevBRg== - dependencies: - execa "^1.0.0" - word-wrap@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" @@ -8781,13 +8737,6 @@ write-file-atomic@^3.0.1: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" -write@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" - integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== - dependencies: - mkdirp "^0.5.1" - ws@^5.2.0: version "5.2.2" resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f" @@ -8826,9 +8775,9 @@ y18n@^3.2.1: integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= y18n@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" - integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== + version "4.0.1" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.1.tgz#8db2b83c31c5d75099bb890b23f3094891e247d4" + integrity sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ== yallist@^2.1.2: version "2.1.2" @@ -8880,9 +8829,9 @@ yargs-parser@^18.1.2: decamelize "^1.2.0" yargs-parser@^20.2.3: - version "20.2.3" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.3.tgz#92419ba867b858c868acf8bae9bf74af0dd0ce26" - integrity sha512-emOFRT9WVHw03QSvN5qor9QQT9+sw5vwxfYweivSMHTcAXPefwVae2FjO7JJjj8hCE4CzPOPeFM83VwT29HCww== + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== yargs-parser@^7.0.0: version "7.0.0" @@ -8965,6 +8914,11 @@ yn@3.1.1: resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + yoga-layout-prebuilt@^1.9.3: version "1.10.0" resolved "https://registry.yarnpkg.com/yoga-layout-prebuilt/-/yoga-layout-prebuilt-1.10.0.tgz#2936fbaf4b3628ee0b3e3b1df44936d6c146faa6"