diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2463901a91..c37ca70a1a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,13 +6,13 @@ on: branches: - '**' env: - NODE_VERSION: 16.13.0 + NODE_VERSION: 16.14.2 PARSE_SERVER_TEST_TIMEOUT: 20000 jobs: check-ci: name: Node Engine Check timeout-minutes: 15 - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 - name: Use Node.js ${{ matrix.NODE_VERSION }} @@ -33,7 +33,7 @@ jobs: check-lint: name: Lint timeout-minutes: 15 - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 - name: Use Node.js ${{ matrix.NODE_VERSION }} @@ -53,7 +53,7 @@ jobs: check-circular: name: Circular Dependencies timeout-minutes: 5 - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 - name: Use Node.js ${{ matrix.NODE_VERSION }} @@ -73,7 +73,7 @@ jobs: check-docker: name: Docker Build timeout-minutes: 15 - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04 steps: - name: Checkout repository uses: actions/checkout@v2 @@ -90,7 +90,7 @@ jobs: check-lock-file-version: name: NPM Lock File Version timeout-minutes: 5 - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 - name: Check NPM lock file version @@ -101,51 +101,71 @@ jobs: strategy: matrix: include: + - name: MongoDB 5.2, ReplicaSet, WiredTiger + MONGODB_VERSION: 5.2.1 + MONGODB_TOPOLOGY: replicaset + MONGODB_STORAGE_ENGINE: wiredTiger + NODE_VERSION: 14.19.1 + - name: MongoDB 5.1, ReplicaSet, WiredTiger + MONGODB_VERSION: 5.1.1 + MONGODB_TOPOLOGY: replicaset + MONGODB_STORAGE_ENGINE: wiredTiger + NODE_VERSION: 14.19.1 - name: MongoDB 5.0, ReplicaSet, WiredTiger - MONGODB_VERSION: 5.0.3 + MONGODB_VERSION: 5.0.6 MONGODB_TOPOLOGY: replicaset MONGODB_STORAGE_ENGINE: wiredTiger - NODE_VERSION: 16.13.0 + NODE_VERSION: 16.14.2 - name: MongoDB 4.4, ReplicaSet, WiredTiger - MONGODB_VERSION: 4.4.10 + MONGODB_VERSION: 4.4.13 MONGODB_TOPOLOGY: replicaset MONGODB_STORAGE_ENGINE: wiredTiger - NODE_VERSION: 16.13.0 + NODE_VERSION: 16.14.2 - name: MongoDB 4.2, ReplicaSet, WiredTiger - MONGODB_VERSION: 4.2.17 + MONGODB_VERSION: 4.2.19 MONGODB_TOPOLOGY: replicaset MONGODB_STORAGE_ENGINE: wiredTiger - NODE_VERSION: 16.13.0 + NODE_VERSION: 16.14.2 - name: MongoDB 4.0, ReplicaSet, WiredTiger - MONGODB_VERSION: 4.0.27 + MONGODB_VERSION: 4.0.28 MONGODB_TOPOLOGY: replicaset MONGODB_STORAGE_ENGINE: wiredTiger - NODE_VERSION: 16.13.0 + NODE_VERSION: 16.14.2 - name: MongoDB 4.0, Standalone, MMAPv1 - MONGODB_VERSION: 4.0.27 + MONGODB_VERSION: 4.0.28 MONGODB_TOPOLOGY: standalone MONGODB_STORAGE_ENGINE: mmapv1 - NODE_VERSION: 16.13.0 + NODE_VERSION: 16.14.2 - name: Redis Cache PARSE_SERVER_TEST_CACHE: redis - MONGODB_VERSION: 4.4.10 + MONGODB_VERSION: 4.4.13 MONGODB_TOPOLOGY: standalone MONGODB_STORAGE_ENGINE: wiredTiger - NODE_VERSION: 16.13.0 + NODE_VERSION: 16.14.2 - name: Node 12 - MONGODB_VERSION: 4.4.10 + MONGODB_VERSION: 4.4.13 MONGODB_TOPOLOGY: standalone MONGODB_STORAGE_ENGINE: wiredTiger - NODE_VERSION: 12.22.7 + NODE_VERSION: 12.22.11 - name: Node 14 - MONGODB_VERSION: 4.4.10 + MONGODB_VERSION: 4.4.13 + MONGODB_TOPOLOGY: standalone + MONGODB_STORAGE_ENGINE: wiredTiger + NODE_VERSION: 14.19.1 + - name: Node 17 + MONGODB_VERSION: 4.4.13 + MONGODB_TOPOLOGY: standalone + MONGODB_STORAGE_ENGINE: wiredTiger + NODE_VERSION: 17.9.0 + - name: Node 18 + MONGODB_VERSION: 4.4.13 MONGODB_TOPOLOGY: standalone MONGODB_STORAGE_ENGINE: wiredTiger - NODE_VERSION: 14.18.1 + NODE_VERSION: 18.1.0 fail-fast: false name: ${{ matrix.name }} timeout-minutes: 15 - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04 services: redis: image: redis @@ -158,6 +178,8 @@ jobs: PARSE_SERVER_TEST_CACHE: ${{ matrix.PARSE_SERVER_TEST_CACHE }} NODE_VERSION: ${{ matrix.NODE_VERSION }} steps: + - name: Fix usage of insecure GitHub protocol + run: sudo git config --system url."https://github".insteadOf "git://github" - uses: actions/checkout@v2 - name: Use Node.js ${{ matrix.NODE_VERSION }} uses: actions/setup-node@v2 @@ -183,26 +205,26 @@ jobs: include: - name: PostgreSQL 11, PostGIS 3.0 POSTGRES_IMAGE: postgis/postgis:11-3.0 - NODE_VERSION: 16.13.0 + NODE_VERSION: 16.14.2 - name: PostgreSQL 11, PostGIS 3.1 POSTGRES_IMAGE: postgis/postgis:11-3.1 - NODE_VERSION: 16.13.0 + NODE_VERSION: 16.14.2 - name: PostgreSQL 11, PostGIS 3.2 POSTGRES_IMAGE: postgis/postgis:11-3.2 - NODE_VERSION: 16.13.0 + NODE_VERSION: 16.14.2 - name: PostgreSQL 12, PostGIS 3.2 POSTGRES_IMAGE: postgis/postgis:12-3.2 - NODE_VERSION: 16.13.0 + NODE_VERSION: 16.14.2 - name: PostgreSQL 13, PostGIS 3.2 POSTGRES_IMAGE: postgis/postgis:13-3.2 - NODE_VERSION: 16.13.0 + NODE_VERSION: 16.14.2 - name: PostgreSQL 14, PostGIS 3.2 POSTGRES_IMAGE: postgis/postgis:14-3.2 - NODE_VERSION: 16.13.0 + NODE_VERSION: 16.14.2 fail-fast: false name: ${{ matrix.name }} timeout-minutes: 15 - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04 services: redis: image: redis diff --git a/DEPRECATIONS.md b/DEPRECATIONS.md index dc913dd0e7..82aa8144a0 100644 --- a/DEPRECATIONS.md +++ b/DEPRECATIONS.md @@ -8,6 +8,9 @@ The following is a list of deprecations, according to the [Deprecation Policy](h | DEPPS2 | Config option `directAccess` defaults to `true` | [#6636](https://github.com/parse-community/parse-server/pull/6636) | 5.0.0 (2022) | 6.0.0 (2023) | deprecated | - | | DEPPS3 | Config option `enforcePrivateUsers` defaults to `true` | [#7319](https://github.com/parse-community/parse-server/pull/7319) | 5.0.0 (2022) | 6.0.0 (2023) | deprecated | - | | DEPPS4 | Remove convenience method for http request `Parse.Cloud.httpRequest` | [#7589](https://github.com/parse-community/parse-server/pull/7589) | 5.0.0 (2022) | 6.0.0 (2023) | deprecated | - | +| DEPPS5 | Config option `allowClientClassCreation` defaults to `false` | [#7925](https://github.com/parse-community/parse-server/pull/7925) | 5.3.0 (2022) | 7.0.0 (2024) | deprecated | - | +| DEPPS6 | Auth providers disabled by default | [#7953](https://github.com/parse-community/parse-server/pull/7953) | 5.3.0 (2022) | 7.0.0 (2024) | deprecated | - | +| DEPPS7 | Remove file trigger syntax `Parse.Cloud.beforeSaveFile((request) => {})` | [#7966](https://github.com/parse-community/parse-server/pull/7966) | 5.3.0 (2022) | 7.0.0 (2024) | deprecated | - | [i_deprecation]: ## "The version and date of the deprecation." [i_removal]: ## "The version and date of the planned removal." diff --git a/README.md b/README.md index 7b507e9c80..7663f26708 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,8 @@ [![Coverage](https://img.shields.io/codecov/c/github/parse-community/parse-server/alpha.svg)](https://codecov.io/github/parse-community/parse-server?branch=alpha) [![auto-release](https://img.shields.io/badge/%F0%9F%9A%80-auto--release-9e34eb.svg)](https://github.com/parse-community/parse-dashboard/releases) -[![Node Version](https://img.shields.io/badge/nodejs-12,_14,_16-green.svg?logo=node.js&style=flat)](https://nodejs.org) -[![MongoDB Version](https://img.shields.io/badge/mongodb-4.0,_4.2,_4.4,_5.0-green.svg?logo=mongodb&style=flat)](https://www.mongodb.com) +[![Node Version](https://img.shields.io/badge/nodejs-12,_14,_16,_17,_18-green.svg?logo=node.js&style=flat)](https://nodejs.org) +[![MongoDB Version](https://img.shields.io/badge/mongodb-4.0,_4.2,_4.4,_5.0,_5.1,_5.2-green.svg?logo=mongodb&style=flat)](https://www.mongodb.com) [![Postgres Version](https://img.shields.io/badge/postgresql-11,_12,_13,_14-green.svg?logo=postgresql&style=flat)](https://www.postgresql.org) [![npm latest version](https://img.shields.io/npm/v/parse-server/latest.svg)](https://www.npmjs.com/package/parse-server) @@ -20,6 +20,7 @@ [![License][license-svg]][license-link] [![Forum](https://img.shields.io/discourse/https/community.parseplatform.org/topics.svg)](https://community.parseplatform.org/c/parse-server) [![Twitter](https://img.shields.io/twitter/follow/ParsePlatform.svg?label=Follow&style=social)](https://twitter.com/intent/follow?screen_name=ParsePlatform) +[![Chat](https://img.shields.io/badge/Chat-Join!-%23fff?style=social&logo=slack)](https://chat.parseplatform.org) --- @@ -110,36 +111,43 @@ Before you start make sure you have installed: ### Compatibility #### Node.js + Parse Server is continuously tested with the most recent releases of Node.js to ensure compatibility. We follow the [Node.js Long Term Support plan](https://github.com/nodejs/Release) and only test against versions that are officially supported and have not reached their end-of-life date. -| Version | Latest Version | End-of-Life | Compatible | -|------------|----------------|-------------|---------------| -| Node.js 12 | 12.22.7 | April 2022 | ✅ Yes | -| Node.js 14 | 14.18.1 | April 2023 | ✅ Yes | -| Node.js 16 | 16.13.0 | April 2024 | ✅ Yes | -| Node.js 17 | 17.x | June 2022 | ❌ Not tested | +| Version | Latest Version | End-of-Life | Compatible | +|------------|----------------|-------------|------------| +| Node.js 12 | 12.22.11 | April 2022 | ✅ Yes | +| Node.js 14 | 14.19.1 | April 2023 | ✅ Yes | +| Node.js 16 | 16.14.2 | April 2024 | ✅ Yes | +| Node.js 17 | 17.9.0 | June 2022 | ✅ Yes | +| Node.js 18 | 18.1.0 | April 2025 | ✅ Yes | #### MongoDB + Parse Server is continuously tested with the most recent releases of MongoDB to ensure compatibility. We follow the [MongoDB support schedule](https://www.mongodb.com/support-policy) and only test against versions that are officially supported and have not reached their end-of-life date. -| Version | Latest Version | End-of-Life | Compatible | -|-------------|----------------|--------------|------------| -| MongoDB 4.0 | 4.0.27 | April 2022 | ✅ Yes | -| MongoDB 4.2 | 4.2.17 | TBD | ✅ Yes | -| MongoDB 4.4 | 4.4.10 | TBD | ✅ Yes | -| MongoDB 5.0 | 5.0.3 | January 2024 | ✅ Yes | - +| Version | Latest Version | End-of-Life | Compatible | +|-------------|----------------|-------------|------------| +| MongoDB 4.0 | 4.0.28 | April 2022 | ✅ Yes | +| MongoDB 4.2 | 4.2.19 | TBD | ✅ Yes | +| MongoDB 4.4 | 4.4.13 | TBD | ✅ Yes | +| MongoDB 5.0 | 5.0.6 | TBD | ✅ Yes | +| MongoDB 5.1 | 5.1.1 | TBD | ✅ Yes | +| MongoDB 5.2 | 5.2.1 | TBD | ✅ Yes | + #### PostgreSQL + Parse Server is continuously tested with the most recent releases of PostgreSQL and PostGIS to ensure compatibility, using [PostGIS docker images](https://registry.hub.docker.com/r/postgis/postgis/tags?page=1&ordering=last_updated). We follow the [PostgreSQL support schedule](https://www.postgresql.org/support/versioning) and [PostGIS support schedule](https://www.postgis.net/eol_policy/) and only test against versions that are officially supported and have not reached their end-of-life date. Due to the extensive PostgreSQL support duration of 5 years, Parse Server drops support if a version is older than 3.5 years and a newer version has been available for at least 2.5 years. | Version | PostGIS Version | End-of-Life | Parse Server Support End | Compatible | |-------------|-----------------|---------------|--------------------------|------------| -| Postgres 11 | 3.0, 3.1, 3.2 | November 2023 | April 2022 | ✅ Yes | -| Postgres 12 | 3.2 | November 2024 | April 2023 | ✅ Yes | -| Postgres 13 | 3.2 | November 2025 | April 2024 | ✅ Yes | -| Postgres 14 | 3.2 | November 2026 | April 2025 | ✅ Yes | +| Postgres 11 | 3.0, 3.1, 3.2 | November 2023 | April 2022 | ✅ Yes | +| Postgres 12 | 3.2 | November 2024 | April 2023 | ✅ Yes | +| Postgres 13 | 3.2 | November 2025 | April 2024 | ✅ Yes | +| Postgres 14 | 3.2 | November 2026 | April 2025 | ✅ Yes | ### Locally + ```bash $ npm install -g parse-server mongodb-runner $ mongodb-runner start @@ -232,7 +240,6 @@ $ curl -X GET \ } ] } - ``` To learn more about using saving and querying objects on Parse Server, check out the [Parse documentation](http://docs.parseplatform.org). @@ -382,6 +389,7 @@ const server = ParseServer({ ``` ## Custom Routes + **Caution, this is an experimental feature that may not be appropriate for production.** Custom routes allow to build user flows with webpages, similar to the existing password reset and email verification features. Custom routes are defined with the `pages` option in the Parse Server configuration: @@ -414,6 +422,7 @@ The above route can be invoked by sending a `GET` request to: The `handler` receives the `request` and returns a `custom_page.html` webpage from the `pages.pagesPath` directory as response. The advantage of building a custom route this way is that it automatically makes use of Parse Server's built-in capabilities, such as [page localization](#pages) and [dynamic placeholders](#dynamic-placeholders). ### Reserved Paths + The following paths are already used by Parse Server's built-in features and are therefore not available for custom routes. Custom routes with an identical combination of `path` and `method` are ignored. | Path | HTTP Method | Feature | @@ -509,6 +518,7 @@ Identical requests are identified by their request header `X-Parse-Request-Id`. Deduplication is only done for object creation and update (`POST` and `PUT` requests). Deduplication is not done for object finding and deletion (`GET` and `DELETE` requests), as these operations are already idempotent by definition. ### Configuration example + ``` let api = new ParseServer({ idempotencyOptions: { @@ -517,6 +527,7 @@ let api = new ParseServer({ } } ``` + ### Parameters | Parameter | Optional | Type | Default value | Example values | Environment variable | Description | @@ -549,6 +560,7 @@ Assuming the script above is named, `parse_idempotency_delete_expired_records.sh ## Localization ### Pages + **Caution, this is an experimental feature that may not be appropriate for production.** Custom pages as well as feature pages (e.g. password reset, email verification) can be localized with the `pages` option in the Parse Server configuration: diff --git a/changelogs/CHANGELOG_alpha.md b/changelogs/CHANGELOG_alpha.md index 6938ec3c74..128be529bb 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,144 @@ +# [5.3.0-alpha.18](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.17...5.3.0-alpha.18) (2022-06-17) + + +### Bug Fixes + +* auto-release process may fail if optional back-merging task fails ([#8051](https://github.com/parse-community/parse-server/issues/8051)) ([cf925e7](https://github.com/parse-community/parse-server/commit/cf925e75e87a6989f41e2e2abb2aba4332b1e79f)) + +# [5.3.0-alpha.17](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.16...5.3.0-alpha.17) (2022-06-17) + + +### Bug Fixes + +* errors in GraphQL do not show the original error but a general `Unexpected Error` ([#8045](https://github.com/parse-community/parse-server/issues/8045)) ([0d81887](https://github.com/parse-community/parse-server/commit/0d818879c217f9c56100a5f59868fa37e6d24b71)) +* websocket connection of LiveQuery interrupts frequently ([#8048](https://github.com/parse-community/parse-server/issues/8048)) ([03caae1](https://github.com/parse-community/parse-server/commit/03caae1e611f28079cdddbbe433daaf69e3f595c)) + +# [5.3.0-alpha.16](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.15...5.3.0-alpha.16) (2022-06-11) + + +### Bug Fixes + +* live query role cache does not clear when a user is added to a role ([#8026](https://github.com/parse-community/parse-server/issues/8026)) ([199dfc1](https://github.com/parse-community/parse-server/commit/199dfc17226d85a78ab85f24362cce740f4ada39)) + +# [5.3.0-alpha.15](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.14...5.3.0-alpha.15) (2022-06-05) + + +### Bug Fixes + +* interrupted WebSocket connection not closed by LiveQuery server ([#8012](https://github.com/parse-community/parse-server/issues/8012)) ([2d5221e](https://github.com/parse-community/parse-server/commit/2d5221e48012fb7781c0406d543a922d313075ea)) + +# [5.3.0-alpha.14](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.13...5.3.0-alpha.14) (2022-05-29) + + +### Features + +* align file trigger syntax with class trigger; use the new syntax `Parse.Cloud.beforeSave(Parse.File, (request) => {})`, the old syntax `Parse.Cloud.beforeSaveFile((request) => {})` has been deprecated ([#7966](https://github.com/parse-community/parse-server/issues/7966)) ([c6dcad8](https://github.com/parse-community/parse-server/commit/c6dcad8d167d44912dbd416d328519314c0809bd)) + +# [5.3.0-alpha.13](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.12...5.3.0-alpha.13) (2022-05-28) + + +### Features + +* selectively enable / disable default authentication adapters ([#7953](https://github.com/parse-community/parse-server/issues/7953)) ([c1e808f](https://github.com/parse-community/parse-server/commit/c1e808f9e807fc49508acbde0d8b3f2b901a1638)) + +# [5.3.0-alpha.12](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.11...5.3.0-alpha.12) (2022-05-20) + + +### Bug Fixes + +* afterSave trigger removes pointer in Parse object ([#7913](https://github.com/parse-community/parse-server/issues/7913)) ([47d796e](https://github.com/parse-community/parse-server/commit/47d796ea58f65e71612ce37149be692abc9ea97f)) + +# [5.3.0-alpha.11](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.10...5.3.0-alpha.11) (2022-05-18) + + +### Features + +* replace GraphQL Apollo with GraphQL Yoga ([#7967](https://github.com/parse-community/parse-server/issues/7967)) ([1aa2204](https://github.com/parse-community/parse-server/commit/1aa2204aebfdbe273d54d6d56c6029f7c34aab14)) + +# [5.3.0-alpha.10](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.9...5.3.0-alpha.10) (2022-05-09) + + +### Features + +* upgrade mongodb from 4.4.1 to 4.5.0 ([#7991](https://github.com/parse-community/parse-server/issues/7991)) ([e692b5d](https://github.com/parse-community/parse-server/commit/e692b5dd8214cdb0ce79bedd30d9aa3cf4de76a5)) + +# [5.3.0-alpha.9](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.8...5.3.0-alpha.9) (2022-05-07) + + +### Bug Fixes + +* depreciate allowClientClassCreation defaulting to true ([#7925](https://github.com/parse-community/parse-server/issues/7925)) ([38ed96a](https://github.com/parse-community/parse-server/commit/38ed96ace534d639db007aa7dd5387b2da8f03ae)) + +# [5.3.0-alpha.8](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.7...5.3.0-alpha.8) (2022-05-06) + + +### Features + +* add support for Node 17 and 18 ([#7896](https://github.com/parse-community/parse-server/issues/7896)) ([3e9f292](https://github.com/parse-community/parse-server/commit/3e9f292d840334244934cee9a34545ac86313549)) + +# [5.3.0-alpha.7](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.6...5.3.0-alpha.7) (2022-04-25) + + +### Bug Fixes + +* security upgrade @parse/fs-files-adapter from 1.2.1 to 1.2.2 ([#7948](https://github.com/parse-community/parse-server/issues/7948)) ([20fc4e2](https://github.com/parse-community/parse-server/commit/20fc4e23b53c91aac657f894bd70d049b7525c37)) + +# [5.3.0-alpha.6](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.5...5.3.0-alpha.6) (2022-04-11) + + +### Bug Fixes + +* peer dependency mismatch for GraphQL dependencies ([#7934](https://github.com/parse-community/parse-server/issues/7934)) ([b7a1d76](https://github.com/parse-community/parse-server/commit/b7a1d7617b4bcac677cecedfeb6ac4a27447083b)) + +# [5.3.0-alpha.5](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.4...5.3.0-alpha.5) (2022-04-09) + + +### Bug Fixes + +* security upgrade moment from 2.29.1 to 2.29.2 ([#7931](https://github.com/parse-community/parse-server/issues/7931)) ([6b68593](https://github.com/parse-community/parse-server/commit/6b68593eaec17e8b183899d2b92699c9ede7625b)) + +# [5.3.0-alpha.4](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.3...5.3.0-alpha.4) (2022-04-04) + + +### Bug Fixes + +* custom database options are not passed to MongoDB GridFS ([#7911](https://github.com/parse-community/parse-server/issues/7911)) ([a72b384](https://github.com/parse-community/parse-server/commit/a72b384f76137a3d83ffb69f65cb25aff1bbab4f)) + +# [5.3.0-alpha.3](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.2...5.3.0-alpha.3) (2022-03-27) + + +### Features + +* add MongoDB 5.2 support ([#7894](https://github.com/parse-community/parse-server/issues/7894)) ([6b4b358](https://github.com/parse-community/parse-server/commit/6b4b358f0842ae920e45652f5e8b2afebc6caf3a)) + +# [5.3.0-alpha.2](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.1...5.3.0-alpha.2) (2022-03-27) + + +### Bug Fixes + +* security upgrade parse push adapter from 4.1.0 to 4.1.2 ([#7893](https://github.com/parse-community/parse-server/issues/7893)) ([ef56e98](https://github.com/parse-community/parse-server/commit/ef56e98ef65041b4d3b7b82cce3473269c27f6fd)) + +# [5.3.0-alpha.1](https://github.com/parse-community/parse-server/compare/5.2.1-alpha.2...5.3.0-alpha.1) (2022-03-27) + + +### Features + +* add MongoDB 5.1 compatibility ([#7682](https://github.com/parse-community/parse-server/issues/7682)) ([90155cf](https://github.com/parse-community/parse-server/commit/90155cf1680e5e0499b0000e071c6cb0ce3aef96)) + +## [5.2.1-alpha.2](https://github.com/parse-community/parse-server/compare/5.2.1-alpha.1...5.2.1-alpha.2) (2022-03-26) + + +### Performance Improvements + +* reduce database operations when using the constant parameter in Cloud Function validation ([#7892](https://github.com/parse-community/parse-server/issues/7892)) ([48bd512](https://github.com/parse-community/parse-server/commit/48bd512eeb47666967dff8c5e723ddc5b7801daa)) + +## [5.2.1-alpha.1](https://github.com/parse-community/parse-server/compare/5.2.0...5.2.1-alpha.1) (2022-03-26) + + +### Bug Fixes + +* return correct response when revert is used in beforeSave ([#7839](https://github.com/parse-community/parse-server/issues/7839)) ([f63fb2b](https://github.com/parse-community/parse-server/commit/f63fb2b338c908f0e7a648d338c26b9daa50c8f2)) + # [5.2.0-alpha.3](https://github.com/parse-community/parse-server/compare/5.2.0-alpha.2...5.2.0-alpha.3) (2022-03-24) diff --git a/changelogs/CHANGELOG_beta.md b/changelogs/CHANGELOG_beta.md index 20540c07e7..a6df87465d 100644 --- a/changelogs/CHANGELOG_beta.md +++ b/changelogs/CHANGELOG_beta.md @@ -1,3 +1,36 @@ +# [5.3.0-beta.1](https://github.com/parse-community/parse-server/compare/5.2.1...5.3.0-beta.1) (2022-06-17) + + +### Bug Fixes + +* afterSave trigger removes pointer in Parse object ([#7913](https://github.com/parse-community/parse-server/issues/7913)) ([47d796e](https://github.com/parse-community/parse-server/commit/47d796ea58f65e71612ce37149be692abc9ea97f)) +* auto-release process may fail if optional back-merging task fails ([#8051](https://github.com/parse-community/parse-server/issues/8051)) ([cf925e7](https://github.com/parse-community/parse-server/commit/cf925e75e87a6989f41e2e2abb2aba4332b1e79f)) +* custom database options are not passed to MongoDB GridFS ([#7911](https://github.com/parse-community/parse-server/issues/7911)) ([b1e5565](https://github.com/parse-community/parse-server/commit/b1e5565b22f2eff229571fe9a9500314bd30965b)) +* depreciate allowClientClassCreation defaulting to true ([#7925](https://github.com/parse-community/parse-server/issues/7925)) ([38ed96a](https://github.com/parse-community/parse-server/commit/38ed96ace534d639db007aa7dd5387b2da8f03ae)) +* errors in GraphQL do not show the original error but a general `Unexpected Error` ([#8045](https://github.com/parse-community/parse-server/issues/8045)) ([0d81887](https://github.com/parse-community/parse-server/commit/0d818879c217f9c56100a5f59868fa37e6d24b71)) +* interrupted WebSocket connection not closed by LiveQuery server ([#8012](https://github.com/parse-community/parse-server/issues/8012)) ([2d5221e](https://github.com/parse-community/parse-server/commit/2d5221e48012fb7781c0406d543a922d313075ea)) +* live query role cache does not clear when a user is added to a role ([#8026](https://github.com/parse-community/parse-server/issues/8026)) ([199dfc1](https://github.com/parse-community/parse-server/commit/199dfc17226d85a78ab85f24362cce740f4ada39)) +* peer dependency mismatch for GraphQL dependencies ([#7934](https://github.com/parse-community/parse-server/issues/7934)) ([0a6faa8](https://github.com/parse-community/parse-server/commit/0a6faa81fa97f8620e7fd05e8c7bbdb4b7da9578)) +* return correct response when revert is used in beforeSave ([#7839](https://github.com/parse-community/parse-server/issues/7839)) ([19900fc](https://github.com/parse-community/parse-server/commit/19900fcdf8c9f29a674fb62cf6e4b3341d796891)) +* security upgrade @parse/fs-files-adapter from 1.2.1 to 1.2.2 ([#7948](https://github.com/parse-community/parse-server/issues/7948)) ([3a70fda](https://github.com/parse-community/parse-server/commit/3a70fda6798d4143f21046439b5eaf232a31bdb6)) +* security upgrade moment from 2.29.1 to 2.29.2 ([#7931](https://github.com/parse-community/parse-server/issues/7931)) ([731c550](https://github.com/parse-community/parse-server/commit/731c5507144bbacff236097e7a2a03bfe54f6e10)) +* security upgrade parse push adapter from 4.1.0 to 4.1.2 ([#7893](https://github.com/parse-community/parse-server/issues/7893)) ([93667b4](https://github.com/parse-community/parse-server/commit/93667b4e8402bf13b46c4d3ef12cec6532fd9da7)) +* websocket connection of LiveQuery interrupts frequently ([#8048](https://github.com/parse-community/parse-server/issues/8048)) ([03caae1](https://github.com/parse-community/parse-server/commit/03caae1e611f28079cdddbbe433daaf69e3f595c)) + +### Features + +* add MongoDB 5.1 compatibility ([#7682](https://github.com/parse-community/parse-server/issues/7682)) ([022a856](https://github.com/parse-community/parse-server/commit/022a85619d8a2c57a2f2938e245e4d8a47c15276)) +* add MongoDB 5.2 support ([#7894](https://github.com/parse-community/parse-server/issues/7894)) ([5bfa716](https://github.com/parse-community/parse-server/commit/5bfa7160d9e35b237cbae1016ed86724aa99f8d7)) +* add support for Node 17 and 18 ([#7896](https://github.com/parse-community/parse-server/issues/7896)) ([3e9f292](https://github.com/parse-community/parse-server/commit/3e9f292d840334244934cee9a34545ac86313549)) +* align file trigger syntax with class trigger; use the new syntax `Parse.Cloud.beforeSave(Parse.File, (request) => {})`, the old syntax `Parse.Cloud.beforeSaveFile((request) => {})` has been deprecated ([#7966](https://github.com/parse-community/parse-server/issues/7966)) ([c6dcad8](https://github.com/parse-community/parse-server/commit/c6dcad8d167d44912dbd416d328519314c0809bd)) +* replace GraphQL Apollo with GraphQL Yoga ([#7967](https://github.com/parse-community/parse-server/issues/7967)) ([1aa2204](https://github.com/parse-community/parse-server/commit/1aa2204aebfdbe273d54d6d56c6029f7c34aab14)) +* selectively enable / disable default authentication adapters ([#7953](https://github.com/parse-community/parse-server/issues/7953)) ([c1e808f](https://github.com/parse-community/parse-server/commit/c1e808f9e807fc49508acbde0d8b3f2b901a1638)) +* upgrade mongodb from 4.4.1 to 4.5.0 ([#7991](https://github.com/parse-community/parse-server/issues/7991)) ([e692b5d](https://github.com/parse-community/parse-server/commit/e692b5dd8214cdb0ce79bedd30d9aa3cf4de76a5)) + +### Performance Improvements + +* reduce database operations when using the constant parameter in Cloud Function validation ([#7892](https://github.com/parse-community/parse-server/issues/7892)) ([041197f](https://github.com/parse-community/parse-server/commit/041197fb4ca1cd7cf18dc426ce38647267823668)) + # [5.2.0-beta.2](https://github.com/parse-community/parse-server/compare/5.2.0-beta.1...5.2.0-beta.2) (2022-03-24) diff --git a/ci/ciCheck.js b/ci/ciCheck.js index 2ad5c3e8f3..52518c42cc 100644 --- a/ci/ciCheck.js +++ b/ci/ciCheck.js @@ -61,7 +61,7 @@ async function checkNodeVersions() { '<12.0.0', // These versions have reached their end-of-life support date '>=13.0.0 <14.0.0', // These versions have reached their end-of-life support date '>=15.0.0 <16.0.0', // These versions have reached their end-of-life support date - '>=17.0.0', // These versions are not officially supported yet + '>=19.0.0', // These versions are not officially supported yet ], }).check(); } diff --git a/ci/nodeEngineCheck.js b/ci/nodeEngineCheck.js index da68f314b1..a68f2c593c 100644 --- a/ci/nodeEngineCheck.js +++ b/ci/nodeEngineCheck.js @@ -75,17 +75,21 @@ class NodeEngineCheck { // For each file for (const file of files) { - // Get node version const contentString = await fs.readFile(file, 'utf-8'); - const contentJson = JSON.parse(contentString); - const version = ((contentJson || {}).engines || {}).node; - - // Add response - response.push({ - file: file, - nodeVersion: version - }); + try { + const contentJson = JSON.parse(contentString); + const version = ((contentJson || {}).engines || {}).node; + + // Add response + response.push({ + file: file, + nodeVersion: version + }); + } catch(e) { + console.log(`Ignoring file because it is not valid JSON: ${file}`); + core.warning(`Ignoring file because it is not valid JSON: ${file}`); + } } // If results should be cleaned by removing undefined node versions diff --git a/package-lock.json b/package-lock.json index ad5a608794..465c68a751 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,21 +11,23 @@ "dev": true }, "@apollo/client": { - "version": "3.5.8", - "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.5.8.tgz", - "integrity": "sha512-MAm05+I1ullr64VLpZwon/ISnkMuNLf6vDqgo9wiMhHYBGT4yOAbAIseRdjCHZwfSx/7AUuBgaTNOssZPIr6FQ==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.6.1.tgz", + "integrity": "sha512-WGC7n2IS7GIbCCfVvu58Qncmj6qUBYbI/DxPVHGffDuY5y5l+OI2YIr5UXyR8+G9Ly1d6iYbX6l6l+Rw6F6gHA==", + "dev": true, "requires": { - "@graphql-typed-document-node/core": "^3.0.0", + "@graphql-typed-document-node/core": "^3.1.1", "@wry/context": "^0.6.0", "@wry/equality": "^0.5.0", "@wry/trie": "^0.3.0", - "graphql-tag": "^2.12.3", + "graphql-tag": "^2.12.6", "hoist-non-react-statics": "^3.3.2", "optimism": "^0.16.1", "prop-types": "^15.7.2", "symbol-observable": "^4.0.0", - "ts-invariant": "^0.9.4", + "ts-invariant": "^0.10.0", "tslib": "^2.3.0", + "use-sync-external-store": "^1.0.0", "zen-observable-ts": "^1.2.0" }, "dependencies": { @@ -33,95 +35,28 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/@wry/equality/-/equality-0.5.2.tgz", "integrity": "sha512-oVMxbUXL48EV/C0/M7gLVsoK6qRHPS85x8zECofEZOVvxGmIPLA9o5Z27cc2PoAyZz1S2VoM2A7FLAnpfGlneA==", + "dev": true, "requires": { "tslib": "^2.3.0" } }, "ts-invariant": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.9.4.tgz", - "integrity": "sha512-63jtX/ZSwnUNi/WhXjnK8kz4cHHpYS60AnmA6ixz17l7E12a5puCWFlNpkne5Rl0J8TBPVHpGjsj4fxs8ObVLQ==", + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.10.1.tgz", + "integrity": "sha512-dOmY3naALBtNyK+nrVGzD8DVxSJ9OIHragItZ3XvxGORNAZL6uszgQYaD3PW+TPh2NWNsOpuQUxznuvTkmcdqw==", + "dev": true, "requires": { "tslib": "^2.1.0" } }, "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "zen-observable-ts": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-1.2.3.tgz", - "integrity": "sha512-hc/TGiPkAWpByykMwDcem3SdUgA4We+0Qb36bItSuJC9xD0XVBZoFHYoadAomDSNf64CG8Ydj0Qb8Od8BUWz5g==", - "requires": { - "zen-observable": "0.8.15" - } - } - } - }, - "@apollo/protobufjs": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@apollo/protobufjs/-/protobufjs-1.2.2.tgz", - "integrity": "sha512-vF+zxhPiLtkwxONs6YanSt1EpwpGilThpneExUN5K3tCymuxNnVq2yojTvnpRjv2QfsEIt/n7ozPIIzBLwGIDQ==", - "requires": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/long": "^4.0.0", - "@types/node": "^10.1.0", - "long": "^4.0.0" - }, - "dependencies": { - "@types/node": { - "version": "10.17.60", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", - "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "dev": true } } }, - "@apollographql/apollo-tools": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@apollographql/apollo-tools/-/apollo-tools-0.5.1.tgz", - "integrity": "sha512-ZII+/xUFfb9ezDU2gad114+zScxVFMVlZ91f8fGApMzlS1kkqoyLnC4AJaQ1Ya/X+b63I20B4Gd+eCL8QuB4sA==" - }, - "@apollographql/graphql-playground-html": { - "version": "1.6.29", - "resolved": "https://registry.npmjs.org/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.29.tgz", - "integrity": "sha512-xCcXpoz52rI4ksJSdOCxeOCn2DLocxwHf9dVT/Q90Pte1LX+LY+91SFtJF3KXVHH8kEin+g1KKCQPKBjZJfWNA==", - "requires": { - "xss": "^1.0.8" - } - }, - "@apollographql/graphql-upload-8-fork": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/@apollographql/graphql-upload-8-fork/-/graphql-upload-8-fork-8.1.3.tgz", - "integrity": "sha512-ssOPUT7euLqDXcdVv3Qs4LoL4BPtfermW1IOouaqEmj36TpHYDmYDIbKoSQxikd9vtMumFnP87OybH7sC9fJ6g==", - "requires": { - "@types/express": "*", - "@types/fs-capacitor": "*", - "@types/koa": "*", - "busboy": "^0.3.1", - "fs-capacitor": "^2.0.4", - "http-errors": "^1.7.3", - "object-path": "^0.11.4" - } - }, - "@ardatan/aggregate-error": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/@ardatan/aggregate-error/-/aggregate-error-0.0.6.tgz", - "integrity": "sha512-vyrkEHG1jrukmzTPtyWB4NLPauUw5bQeg4uhn8f+1SSynmrOcyvlb1GKQjjgoBzElLdfXCRYX8UnBlhklOHYRQ==", - "requires": { - "tslib": "~2.0.1" - } - }, "@babel/cli": { "version": "7.10.0", "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.10.0.tgz", @@ -1109,11 +1044,11 @@ } }, "@babel/runtime-corejs3": { - "version": "7.14.6", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.14.6.tgz", - "integrity": "sha512-Xl8SPYtdjcMoCsIM4teyVRg7jIcgl8F2kRtoCcXuHzXswt9UxZCS6BzRo8fcnCuP6u2XtPgvyonmEPF57Kxo9Q==", + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.14.7.tgz", + "integrity": "sha512-Wvzcw4mBYbTagyBVZpAJWI06auSIj033T/yNE0Zn1xcup83MieCddZA7ls3kme17L4NOGBrQ09Q+nKB41RLWBA==", "requires": { - "core-js-pure": "^3.14.0", + "core-js-pure": "^3.15.0", "regenerator-runtime": "^0.13.4" } }, @@ -1187,145 +1122,146 @@ "kuler": "^2.0.0" } }, - "@graphql-tools/batch-delegate": { - "version": "6.2.6", - "resolved": "https://registry.npmjs.org/@graphql-tools/batch-delegate/-/batch-delegate-6.2.6.tgz", - "integrity": "sha512-QUoE9pQtkdNPFdJHSnBhZtUfr3M7pIRoXoMR+TG7DK2Y62ISKbT/bKtZEUU1/2v5uqd5WVIvw9dF8gHDSJAsSA==", + "@envelop/core": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@envelop/core/-/core-2.3.2.tgz", + "integrity": "sha512-NTVY7bajznZyE0S/yzwIu5aimcM8JLqdeWkWUmwmrAHZdE6zjrvOuVCwq1kMIHzgV3bmLdPg2F7534Nxad/HLg==", "requires": { - "@graphql-tools/delegate": "^6.2.4", - "dataloader": "2.0.0", - "tslib": "~2.0.1" + "@envelop/types": "2.2.0" } }, - "@graphql-tools/batch-execute": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/batch-execute/-/batch-execute-8.3.2.tgz", - "integrity": "sha512-ICWqM+MvEkIPHm18Q0cmkvm134zeQMomBKmTRxyxMNhL/ouz6Nqld52/brSlaHnzA3fczupeRJzZ0YatruGBcQ==", + "@envelop/parser-cache": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@envelop/parser-cache/-/parser-cache-4.3.2.tgz", + "integrity": "sha512-gdi814GdJ8PazYBGtWcpKdqtbBbxhbdXBKhSpTjt1kNmgzBsKV1VV2J674/9UqwFjhpuk2POXouIwF0t3z6mXg==", "requires": { - "@graphql-tools/utils": "^8.6.2", - "dataloader": "2.0.0", - "tslib": "~2.3.0", - "value-or-promise": "1.0.11" + "tiny-lru": "7.0.6" + } + }, + "@envelop/types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@envelop/types/-/types-2.2.0.tgz", + "integrity": "sha512-Lghvfs0kh53G5mUKpCMlB/FhHh3O8SSR4hewB7JyE9hOEu/9h/6u+GHH/OEgdaRHky1Sae5Jf4grO+h21ka4ig==" + }, + "@envelop/validation-cache": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@envelop/validation-cache/-/validation-cache-4.3.2.tgz", + "integrity": "sha512-dihBgqbwm52u69QQeyOZQyDeIz/GIlLuSmgVJcsrKbbevX6pqiuZAs7Vbaj8EraIkuhAqPInzKrtWqYRgePIOA==", + "requires": { + "tiny-lru": "7.0.6" + } + }, + "@graphql-tools/merge": { + "version": "8.2.13", + "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.2.13.tgz", + "integrity": "sha512-lhzjCa6wCthOYl7B6UzER3SGjU2WjSGnW0WGr8giMYsrtf6G3vIRotMcSVMlhDzyyMIOn7uPULOUt3/kaJ/rIA==", + "requires": { + "@graphql-tools/utils": "8.6.12", + "tslib": "~2.4.0" }, "dependencies": { "@graphql-tools/utils": { - "version": "8.6.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.6.2.tgz", - "integrity": "sha512-x1DG0cJgpJtImUlNE780B/dfp8pxvVxOD6UeykFH5rHes26S4kGokbgU8F1IgrJ1vAPm/OVBHtd2kicTsPfwdA==", + "version": "8.6.12", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.6.12.tgz", + "integrity": "sha512-WQ91O40RC+UJgZ9K+IzevSf8oolR1QE+WQ21Oyc2fgDYYiqT0eSf+HVyhZr/8x9rVjn3N9HeqCsywbdmbljg0w==", "requires": { - "tslib": "~2.3.0" + "tslib": "~2.4.0" + } + } + } + }, + "@graphql-tools/schema": { + "version": "8.3.13", + "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-8.3.13.tgz", + "integrity": "sha512-e+bx1VHj1i5v4HmhCYCar0lqdoLmkRi/CfV07rTqHR6CRDbIb/S/qDCajHLt7FCovQ5ozlI5sRVbBhzfq5H0PQ==", + "requires": { + "@graphql-tools/merge": "8.2.13", + "@graphql-tools/utils": "8.6.12", + "tslib": "~2.4.0", + "value-or-promise": "1.0.11" + }, + "dependencies": { + "@graphql-tools/merge": { + "version": "8.2.13", + "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.2.13.tgz", + "integrity": "sha512-lhzjCa6wCthOYl7B6UzER3SGjU2WjSGnW0WGr8giMYsrtf6G3vIRotMcSVMlhDzyyMIOn7uPULOUt3/kaJ/rIA==", + "requires": { + "@graphql-tools/utils": "8.6.12", + "tslib": "~2.4.0" } }, - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "value-or-promise": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/value-or-promise/-/value-or-promise-1.0.11.tgz", - "integrity": "sha512-41BrgH+dIbCFXClcSapVs5M6GkENd3gQOJpEfPDNa71LsUGMXDL0jMWpI/Rh7WhX+Aalfz2TTS3Zt5pUsbnhLg==" + "@graphql-tools/utils": { + "version": "8.6.12", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.6.12.tgz", + "integrity": "sha512-WQ91O40RC+UJgZ9K+IzevSf8oolR1QE+WQ21Oyc2fgDYYiqT0eSf+HVyhZr/8x9rVjn3N9HeqCsywbdmbljg0w==", + "requires": { + "tslib": "~2.4.0" + } } } }, - "@graphql-tools/delegate": { - "version": "6.2.4", - "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-6.2.4.tgz", - "integrity": "sha512-mXe6DfoWmq49kPcDrpKHgC2DSWcD5q0YCaHHoXYPAOlnLH8VMTY8BxcE8y/Do2eyg+GLcwAcrpffVszWMwqw0w==", + "@graphql-tools/utils": { + "version": "8.6.12", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.6.12.tgz", + "integrity": "sha512-WQ91O40RC+UJgZ9K+IzevSf8oolR1QE+WQ21Oyc2fgDYYiqT0eSf+HVyhZr/8x9rVjn3N9HeqCsywbdmbljg0w==", "requires": { - "@ardatan/aggregate-error": "0.0.6", - "@graphql-tools/schema": "^6.2.4", - "@graphql-tools/utils": "^6.2.4", - "dataloader": "2.0.0", - "is-promise": "4.0.0", - "tslib": "~2.0.1" + "tslib": "~2.4.0" } }, - "@graphql-tools/links": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/links/-/links-8.2.2.tgz", - "integrity": "sha512-lWyRvG4KqVj/3dpuQzZN34TXs9+5ETaT1MxhPHe6LIF/DdNQk4Q4Y7VeET/fZ8ZhbzgweMy0AA+ZkrS2HxBcgw==", + "@graphql-typed-document-node/core": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.1.1.tgz", + "integrity": "sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg==" + }, + "@graphql-yoga/common": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@graphql-yoga/common/-/common-2.6.0.tgz", + "integrity": "sha512-iG33wMQlBujB1+Q2D/CLEVDW3xTeBVhHKsbaUmVSHV4zpmGRRQMg/YROJ2mU1lONOyZDPIC+9j3AR7+x0dSzoA==", "requires": { - "@graphql-tools/delegate": "^8.5.1", - "@graphql-tools/utils": "^8.6.2", - "apollo-upload-client": "17.0.0", - "form-data": "^4.0.0", - "node-fetch": "^2.6.5", - "tslib": "~2.3.0" + "@envelop/core": "^2.0.0", + "@envelop/parser-cache": "^4.0.0", + "@envelop/validation-cache": "^4.0.0", + "@graphql-tools/schema": "^8.3.1", + "@graphql-tools/utils": "^8.6.0", + "@graphql-typed-document-node/core": "^3.1.1", + "@graphql-yoga/subscription": "2.0.0", + "cross-undici-fetch": "^0.4.2", + "dset": "^3.1.1", + "tslib": "^2.3.1" }, "dependencies": { - "@graphql-tools/delegate": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-8.5.1.tgz", - "integrity": "sha512-/YPmVxitt57F8sH50pnfXASzOOjEfaUDkX48eF5q6f16+JBncej2zeu+Zm2c68q8MbIxhPlEGfpd0QZeqTvAxw==", - "requires": { - "@graphql-tools/batch-execute": "^8.3.2", - "@graphql-tools/schema": "^8.3.2", - "@graphql-tools/utils": "^8.6.2", - "dataloader": "2.0.0", - "graphql-executor": "0.0.18", - "tslib": "~2.3.0", - "value-or-promise": "1.0.11" - } - }, "@graphql-tools/merge": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.2.3.tgz", - "integrity": "sha512-XCSmL6/Xg8259OTWNp69B57CPWiVL69kB7pposFrufG/zaAlI9BS68dgzrxmmSqZV5ZHU4r/6Tbf6fwnEJGiSw==", + "version": "8.2.11", + "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.2.11.tgz", + "integrity": "sha512-fsjJVdsk9GV1jj1Ed2AKLlHYlsf0ZadTK8X5KxFRE1ZSnKqh56BLVX93JrtOIAnsiHkwOK2TC43HGhApF1swpQ==", "requires": { - "@graphql-tools/utils": "^8.6.2", - "tslib": "~2.3.0" + "@graphql-tools/utils": "8.6.10", + "tslib": "~2.4.0" } }, "@graphql-tools/schema": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-8.3.2.tgz", - "integrity": "sha512-77feSmIuHdoxMXRbRyxE8rEziKesd/AcqKV6fmxe7Zt+PgIQITxNDew2XJJg7qFTMNM43W77Ia6njUSBxNOkwg==", + "version": "8.3.11", + "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-8.3.11.tgz", + "integrity": "sha512-esMEnbyXbp8B5VEI4o395+x0G7Qmz3JSX5onFBF8HeLYcqWJasY5vBuWkO18VxrZpEnvnryodP6Y00bVag9O3Q==", "requires": { - "@graphql-tools/merge": "^8.2.3", - "@graphql-tools/utils": "^8.6.2", - "tslib": "~2.3.0", + "@graphql-tools/merge": "8.2.11", + "@graphql-tools/utils": "8.6.10", + "tslib": "~2.4.0", "value-or-promise": "1.0.11" } }, "@graphql-tools/utils": { - "version": "8.6.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.6.2.tgz", - "integrity": "sha512-x1DG0cJgpJtImUlNE780B/dfp8pxvVxOD6UeykFH5rHes26S4kGokbgU8F1IgrJ1vAPm/OVBHtd2kicTsPfwdA==", - "requires": { - "tslib": "~2.3.0" - } - }, - "apollo-upload-client": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/apollo-upload-client/-/apollo-upload-client-17.0.0.tgz", - "integrity": "sha512-pue33bWVbdlXAGFPkgz53TTmxVMrKeQr0mdRcftNY+PoHIdbGZD0hoaXHvO6OePJAkFz7OiCFUf98p1G/9+Ykw==", + "version": "8.6.10", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.6.10.tgz", + "integrity": "sha512-bJH9qwuyM3BP0PTU6/lvBDkk6jdEIOn+dbyk4pHMVNnvbJ1gZQwo62To8SHxxaUTus8OMhhVPSh9ApWXREURcg==", "requires": { - "extract-files": "^11.0.0" - } - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "requires": { - "whatwg-url": "^5.0.0" + "tslib": "~2.4.0" } }, "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, "value-or-promise": { "version": "1.0.11", @@ -1334,149 +1270,50 @@ } } }, - "@graphql-tools/merge": { - "version": "6.2.17", - "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-6.2.17.tgz", - "integrity": "sha512-G5YrOew39fZf16VIrc49q3c8dBqQDD0ax5LYPiNja00xsXDi0T9zsEWVt06ApjtSdSF6HDddlu5S12QjeN8Tow==", + "@graphql-yoga/node": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@graphql-yoga/node/-/node-2.6.0.tgz", + "integrity": "sha512-VkHaiIwDYx+WJI/NnT2x+mGknk1YoNTP/auweDvKzPXdsWR5Za8rEYUloKZX4TxHTpyqbBLMtCt+4TDITriVbA==", "requires": { - "@graphql-tools/schema": "^8.0.2", - "@graphql-tools/utils": "8.0.2", - "tslib": "~2.3.0" + "@envelop/core": "^2.0.0", + "@graphql-tools/utils": "^8.6.0", + "@graphql-yoga/common": "2.6.0", + "@graphql-yoga/subscription": "2.0.0", + "cross-undici-fetch": "^0.4.2", + "tslib": "^2.3.1" }, "dependencies": { - "@graphql-tools/merge": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.0.1.tgz", - "integrity": "sha512-YAozogbjC2Oun+UcwG0LZFumhlCiHBmqe68OIf7bqtBdp4pbPAiVuK/J9oJqRVJmzvUqugo6RD9zz1qDTKZaiQ==", - "requires": { - "@graphql-tools/utils": "8.1.1", - "tslib": "~2.3.0" - }, - "dependencies": { - "@graphql-tools/utils": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.1.1.tgz", - "integrity": "sha512-QbFNoBmBiZ+ej4y6mOv8Ba4lNhcrTEKXAhZ0f74AhdEXi7b9xbGUH/slO5JaSyp85sGQYIPmxjRPpXBjLklbmw==", - "requires": { - "tslib": "~2.3.0" - } - } - } - }, - "@graphql-tools/schema": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-8.1.1.tgz", - "integrity": "sha512-u+0kxPtuP+GcKnGNt459Ob7iIpzesIJeJTmPPailaG7ZhB5hkXIizl4uHrzEIAh2Ja1P/VA8sEBYpu1N0n6Mmg==", - "requires": { - "@graphql-tools/merge": "8.0.1", - "@graphql-tools/utils": "8.1.1", - "tslib": "~2.3.0", - "value-or-promise": "1.0.10" - }, - "dependencies": { - "@graphql-tools/merge": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.0.1.tgz", - "integrity": "sha512-YAozogbjC2Oun+UcwG0LZFumhlCiHBmqe68OIf7bqtBdp4pbPAiVuK/J9oJqRVJmzvUqugo6RD9zz1qDTKZaiQ==", - "requires": { - "@graphql-tools/utils": "8.1.1", - "tslib": "~2.3.0" - } - }, - "@graphql-tools/utils": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.1.1.tgz", - "integrity": "sha512-QbFNoBmBiZ+ej4y6mOv8Ba4lNhcrTEKXAhZ0f74AhdEXi7b9xbGUH/slO5JaSyp85sGQYIPmxjRPpXBjLklbmw==", - "requires": { - "tslib": "~2.3.0" - } - } - } - }, "@graphql-tools/utils": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.0.2.tgz", - "integrity": "sha512-gzkavMOgbhnwkHJYg32Adv6f+LxjbQmmbdD5Hty0+CWxvaiuJq+nU6tzb/7VSU4cwhbNLx/lGu2jbCPEW1McZQ==", + "version": "8.6.10", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.6.10.tgz", + "integrity": "sha512-bJH9qwuyM3BP0PTU6/lvBDkk6jdEIOn+dbyk4pHMVNnvbJ1gZQwo62To8SHxxaUTus8OMhhVPSh9ApWXREURcg==", "requires": { - "tslib": "~2.3.0" + "tslib": "~2.4.0" } }, "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" } } }, - "@graphql-tools/schema": { - "version": "6.2.4", - "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-6.2.4.tgz", - "integrity": "sha512-rh+14lSY1q8IPbEv2J9x8UBFJ5NrDX9W5asXEUlPp+7vraLp/Tiox4GXdgyA92JhwpYco3nTf5Bo2JDMt1KnAQ==", - "requires": { - "@graphql-tools/utils": "^6.2.4", - "tslib": "~2.0.1" - } - }, - "@graphql-tools/stitch": { - "version": "6.2.4", - "resolved": "https://registry.npmjs.org/@graphql-tools/stitch/-/stitch-6.2.4.tgz", - "integrity": "sha512-0C7PNkS7v7iAc001m7c1LPm5FUB0/DYw+s3OyCii6YYYHY8NwdI0roeOyeDGFJkFubWBQfjc3hoSyueKtU73mw==", - "requires": { - "@graphql-tools/batch-delegate": "^6.2.4", - "@graphql-tools/delegate": "^6.2.4", - "@graphql-tools/merge": "^6.2.4", - "@graphql-tools/schema": "^6.2.4", - "@graphql-tools/utils": "^6.2.4", - "@graphql-tools/wrap": "^6.2.4", - "is-promise": "4.0.0", - "tslib": "~2.0.1" - } - }, - "@graphql-tools/utils": { - "version": "6.2.4", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-6.2.4.tgz", - "integrity": "sha512-ybgZ9EIJE3JMOtTrTd2VcIpTXtDrn2q6eiYkeYMKRVh3K41+LZa6YnR2zKERTXqTWqhobROwLt4BZbw2O3Aeeg==", + "@graphql-yoga/subscription": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@graphql-yoga/subscription/-/subscription-2.0.0.tgz", + "integrity": "sha512-HlG+gIddjIP3/BDrMZymdzmzDjNdYuSGMxx6+1JA83gAEVRDR4yOoT4QeNKYqRhLK9xca/Hxp1PfBpquSa244Q==", "requires": { - "@ardatan/aggregate-error": "0.0.6", - "camel-case": "4.1.1", - "tslib": "~2.0.1" + "@repeaterjs/repeater": "^3.0.4", + "tslib": "^2.3.1" }, "dependencies": { - "camel-case": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.1.tgz", - "integrity": "sha512-7fa2WcG4fYFkclIvEmxBbTvmibwF2/agfEBc6q3lOpVu0A13ltLsA+Hr/8Hp6kp5f+G7hKi6t8lys6XxP+1K6Q==", - "requires": { - "pascal-case": "^3.1.1", - "tslib": "^1.10.0" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - } - } + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" } } }, - "@graphql-tools/wrap": { - "version": "6.2.4", - "resolved": "https://registry.npmjs.org/@graphql-tools/wrap/-/wrap-6.2.4.tgz", - "integrity": "sha512-cyQgpybolF9DjL2QNOvTS1WDCT/epgYoiA8/8b3nwv5xmMBQ6/6nYnZwityCZ7njb7MMyk7HBEDNNlP9qNJDcA==", - "requires": { - "@graphql-tools/delegate": "^6.2.4", - "@graphql-tools/schema": "^6.2.4", - "@graphql-tools/utils": "^6.2.4", - "is-promise": "4.0.0", - "tslib": "~2.0.1" - } - }, - "@graphql-typed-document-node/core": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.1.1.tgz", - "integrity": "sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg==" - }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1567,11 +1404,6 @@ } } }, - "@josephg/resolvable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@josephg/resolvable/-/resolvable-1.0.1.tgz", - "integrity": "sha512-CtzORUwWTTOTqfVtHaKRJ0I1kNQd1bpn3sUh8I3nJDVY+5/M/Oe1DnEWzPQvqq/xPIIkzzzIP7mfCoAjFRvDhg==" - }, "@napi-rs/triples": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@napi-rs/triples/-/triples-1.0.3.tgz", @@ -1839,9 +1671,9 @@ "integrity": "sha512-UdkG3mLEqXgnlKsWanWcgb6dOjUzJ+XC5f+aWw30qrtjxeNUSfKX1cd5FBzOaXQumoe9nIqeZUvrRJS03HCCtw==" }, "@parse/fs-files-adapter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@parse/fs-files-adapter/-/fs-files-adapter-1.2.1.tgz", - "integrity": "sha512-jUbmlvql9+5Mz8Q6KSk1jH823MVerhOYK1svayYpF03v75OtDn3p+mAoFvPS5UpRln1kT6BlBnLfw4Hv08SD5Q==" + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@parse/fs-files-adapter/-/fs-files-adapter-1.2.2.tgz", + "integrity": "sha512-VUsVZXgt53FULqUd9xqGDW6RXes62qHXTNOeRSlS1MOemiCdtQOUGgLHgjdYQXnZ1hPLkxZKph96AluZUb953g==" }, "@parse/minami": { "version": "1.0.0", @@ -1850,20 +1682,20 @@ "dev": true }, "@parse/node-apn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@parse/node-apn/-/node-apn-5.1.0.tgz", - "integrity": "sha512-WT3iVwr1Y/Jf4nq4RGNwBdLwm3gTodsb+g3IY98MPSJ7LCNf+R81Nj/nQO5r/twJfN1v5B8cAgfvPGs2rPelvg==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/@parse/node-apn/-/node-apn-5.1.3.tgz", + "integrity": "sha512-Bwhmbm895lEIF2772PJ8dSvBjrtOG9/q/TDMxmX40IgZxQFoXS73+JUIKTq3CA7SUB/Szu5roJINQ0L2U/1MJw==", "requires": { - "debug": "4.3.2", + "debug": "4.3.3", "jsonwebtoken": "8.5.1", - "node-forge": "0.10.0", - "verror": "1.10.0" + "node-forge": "1.3.0", + "verror": "1.10.1" }, "dependencies": { "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", "requires": { "ms": "2.1.2" } @@ -1872,6 +1704,16 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "verror": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", + "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } } } }, @@ -1886,42 +1728,36 @@ } }, "@parse/push-adapter": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@parse/push-adapter/-/push-adapter-4.1.0.tgz", - "integrity": "sha512-8SOU4zgIr3+wn6Hbge4X/zAYAcJR7puJ3aY2ri+8fqMARgBria4JkIeAyKaTG/mUMHw6Qy5DpYYRe0LjImjZNw==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@parse/push-adapter/-/push-adapter-4.1.2.tgz", + "integrity": "sha512-034vZTlAzgdfefIY4+Q4j8DHS/VwUAIVoh1JeRkHNfyQmUQ++uKbQbUQdJ/nf11HHS69kwLENs13BmhlHMpyHQ==", "requires": { - "@parse/node-apn": "5.1.0", + "@parse/node-apn": "5.1.3", "@parse/node-gcm": "1.0.2", "npmlog": "4.1.2", - "parse": "3.3.0" + "parse": "3.4.0" }, "dependencies": { "@babel/runtime": { - "version": "7.14.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.6.tgz", - "integrity": "sha512-/PCB2uJ7oM44tz8YhC4Z/6PeOKXp4K588f+5M3clr1M4zbqztlo0XEfJ2LEzj/FgwfgGcIdl8n7YYjTCI0BYwg==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.4.tgz", + "integrity": "sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw==", "requires": { "regenerator-runtime": "^0.13.4" } }, - "crypto-js": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.0.0.tgz", - "integrity": "sha512-bzHZN8Pn+gS7DQA6n+iUmBfl0hO5DJq++QP3U6uTucDtk/0iGpXd/Gg7CGR0p8tJhofJyaKoWBuJI4eAO00BBg==", - "optional": true - }, "parse": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/parse/-/parse-3.3.0.tgz", - "integrity": "sha512-SQkTDupU7JQBJpYFIpO8TlQjUtjboUdkXaak57pjoC1ZVbhaiNyLsdYbrlM0B+sNYhlvcMh7zwZW48u10+zm0A==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/parse/-/parse-3.4.0.tgz", + "integrity": "sha512-FMZLxPW6PvrBgxkXc9AmnYsFKvPwiS4G2n9OI4mdfiSoNzIVLc+bXzlUdJ+I7hiqHsBTP0BrdQczw2/cnVkJ6w==", "requires": { - "@babel/runtime": "7.14.6", - "@babel/runtime-corejs3": "7.14.6", - "crypto-js": "4.0.0", + "@babel/runtime": "7.15.4", + "@babel/runtime-corejs3": "7.14.7", + "crypto-js": "4.1.1", "idb-keyval": "5.0.6", "react-native-crypto-js": "1.0.0", "uuid": "3.4.0", - "ws": "7.5.0", + "ws": "7.5.1", "xmlhttprequest": "1.8.0" } }, @@ -1931,65 +1767,16 @@ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" }, "ws": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.0.tgz", - "integrity": "sha512-6ezXvzOZupqKj4jUqbQ9tXuJNo+BR2gU8fFRk3XCP3e0G6WT414u5ELe6Y0vtp7kmSJ3F7YWObSNr1ESsgi4vw==" + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.1.tgz", + "integrity": "sha512-2c6faOUH/nhoQN6abwMloF7Iyl0ZS2E9HGtsiLrWn0zOOMWlhtDmdf/uihDt6jnuCxgtwGBNy6Onsoy2s2O2Ow==" } } }, - "@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" - }, - "@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" - }, - "@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" - }, - "@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" - }, - "@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", - "requires": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" - }, - "@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" - }, - "@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" - }, - "@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" - }, - "@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" + "@repeaterjs/repeater": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@repeaterjs/repeater/-/repeater-3.0.4.tgz", + "integrity": "sha512-AW8PKd6iX3vAZ0vA43nOUOnbq/X5ihgU+mSXXqunMkeQADGiqw/PY0JNeYtD5sr0PAy51YPgAPbDoeapv9r8WA==" }, "@saithodev/semantic-release-backmerge": { "version": "2.1.2", @@ -2474,18 +2261,10 @@ "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", "dev": true }, - "@types/accepts": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==", - "requires": { - "@types/node": "*" - } - }, "@types/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==", + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", "requires": { "@types/connect": "*", "@types/node": "*" @@ -2511,27 +2290,6 @@ "@types/node": "*" } }, - "@types/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/@types/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-0mPF08jn9zYI0n0Q/Pnz7C4kThdSt+6LD4amsrYDDpgBfrVWa3TcCOxKX1zkGgYniGagRv8heN2cbh+CAn+uuQ==" - }, - "@types/cookies": { - "version": "0.7.7", - "resolved": "https://registry.npmjs.org/@types/cookies/-/cookies-0.7.7.tgz", - "integrity": "sha512-h7BcvPUogWbKCzBR2lY4oqaZbO3jXZksexYJVFvkrFeLgbZjQkU4x8pRq6eg2MHXQhY0McQdqmmsxRWlVAHooA==", - "requires": { - "@types/connect": "*", - "@types/express": "*", - "@types/keygrip": "*", - "@types/node": "*" - } - }, - "@types/cors": { - "version": "2.8.10", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.10.tgz", - "integrity": "sha512-C7srjHiVG3Ey1nR6d511dtDkCEjxuN9W1HWAEjGq8kpcwmNM6JJkpC0xvabM7BXTG2wDq8Eu33iH9aQKa7IvLQ==" - }, "@types/express": { "version": "4.17.13", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", @@ -2543,57 +2301,22 @@ "@types/serve-static": "*" } }, - "@types/express-jwt": { - "version": "0.0.42", - "resolved": "https://registry.npmjs.org/@types/express-jwt/-/express-jwt-0.0.42.tgz", - "integrity": "sha512-WszgUddvM1t5dPpJ3LhWNH8kfNN8GPIBrAGxgIYXVCEGx6Bx4A036aAuf/r5WH9DIEdlmp7gHOYvSM6U87B0ag==", - "requires": { - "@types/express": "*", - "@types/express-unless": "*" - } - }, "@types/express-serve-static-core": { - "version": "4.17.24", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.24.tgz", - "integrity": "sha512-3UJuW+Qxhzwjq3xhwXm2onQcFHn76frIYVbTu+kn24LFxI+dEhdfISDFovPB8VpEgW8oQCTpRuCe+0zJxB7NEA==", + "version": "4.17.28", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", + "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", "requires": { "@types/node": "*", "@types/qs": "*", "@types/range-parser": "*" } }, - "@types/express-unless": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@types/express-unless/-/express-unless-0.5.2.tgz", - "integrity": "sha512-Q74UyYRX/zIgl1HSp9tUX2PlG8glkVm+59r7aK4KGKzC5jqKIOX6rrVLRQrzpZUQ84VukHtRoeAuon2nIssHPQ==", - "requires": { - "@types/express": "*" - } - }, - "@types/fs-capacitor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@types/fs-capacitor/-/fs-capacitor-2.0.0.tgz", - "integrity": "sha512-FKVPOCFbhCvZxpVAMhdBdTfVfXUpsh15wFHgqOKxh9N9vzWZVuWCSijZ5T4U34XYNnuj2oduh6xcs1i+LPI+BQ==", - "requires": { - "@types/node": "*" - } - }, - "@types/http-assert": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.2.tgz", - "integrity": "sha512-Ddzuzv/bB2prZnJKlS1sEYhaeT50wfJjhcTTTQLjEsEZJlk3XB4Xohieyq+P4VXIzg7lrQ1Spd/PfRnBpQsdqA==" - }, "@types/http-cache-semantics": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", "dev": true }, - "@types/http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-e+2rjEwK6KDaNOm5Aa9wNGgyS9oSZU/4pfSMMPYNOfjvFI0WVXm29+ITRFr6aKDvvKo7uU1jV68MW4ScsfDi7Q==" - }, "@types/istanbul-lib-coverage": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", @@ -2619,11 +2342,6 @@ "@types/istanbul-lib-report": "*" } }, - "@types/keygrip": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.2.tgz", - "integrity": "sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw==" - }, "@types/keyv": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.2.tgz", @@ -2633,34 +2351,6 @@ "@types/node": "*" } }, - "@types/koa": { - "version": "2.13.4", - "resolved": "https://registry.npmjs.org/@types/koa/-/koa-2.13.4.tgz", - "integrity": "sha512-dfHYMfU+z/vKtQB7NUrthdAEiSvnLebvBjwHtfFmpZmB7em2N3WVQdHgnFq+xvyVgxW5jKDmjWfLD3lw4g4uTw==", - "requires": { - "@types/accepts": "*", - "@types/content-disposition": "*", - "@types/cookies": "*", - "@types/http-assert": "*", - "@types/http-errors": "*", - "@types/keygrip": "*", - "@types/koa-compose": "*", - "@types/node": "*" - } - }, - "@types/koa-compose": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/@types/koa-compose/-/koa-compose-3.2.5.tgz", - "integrity": "sha512-B8nG/OoE1ORZqCkBVsup/AKcvjdgoHnfi4pZMn5UwAPCbhk/96xyv284eBYW8JlQbQ7zDmnpFr68I/40mFoIBQ==", - "requires": { - "@types/koa": "*" - } - }, - "@types/long": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", - "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" - }, "@types/mime": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", @@ -2737,14 +2427,6 @@ "@types/webidl-conversions": "*" } }, - "@types/ws": { - "version": "7.4.7", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", - "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", - "requires": { - "@types/node": "*" - } - }, "@types/yargs": { "version": "15.0.14", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz", @@ -2838,14 +2520,16 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/@wry/context/-/context-0.6.1.tgz", "integrity": "sha512-LOmVnY1iTU2D8tv4Xf6MVMZZ+juIJ87Kt/plMijjN20NMAXGmH4u8bS1t0uT74cZ5gwpocYueV58YwyI8y+GKw==", + "dev": true, "requires": { "tslib": "^2.3.0" }, "dependencies": { "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "dev": true } } }, @@ -2853,6 +2537,7 @@ "version": "0.1.11", "resolved": "https://registry.npmjs.org/@wry/equality/-/equality-0.1.11.tgz", "integrity": "sha512-mwEVBDUVODlsQQ5dfuLUS5/Tf7jqUKyhKYHmVi4fPB6bDMOfWvUPJmKgS1Z7Za/sOI3vzWt4+O7yCiL/70MogA==", + "dev": true, "requires": { "tslib": "^1.9.3" }, @@ -2860,7 +2545,8 @@ "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true } } }, @@ -2868,14 +2554,16 @@ "version": "0.3.1", "resolved": "https://registry.npmjs.org/@wry/trie/-/trie-0.3.1.tgz", "integrity": "sha512-WwB53ikYudh9pIorgxrkHKrQZcCqNM/Q/bDzZBffEaGUKGuHrRb3zZUT9Sh2qw9yogC7SsdRmQ1ER0pqvd3bfw==", + "dev": true, "requires": { "tslib": "^2.3.0" }, "dependencies": { "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "dev": true } } }, @@ -2889,18 +2577,41 @@ "through": ">=2.2.7 <3" } }, + "abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "requires": { + "event-target-shim": "^5.0.0" + } + }, "abstract-logging": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.1.tgz", "integrity": "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==" }, "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "dependencies": { + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + } } }, "acorn": { @@ -3089,261 +2800,6 @@ } } }, - "apollo-cache-control": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/apollo-cache-control/-/apollo-cache-control-0.14.0.tgz", - "integrity": "sha512-qN4BCq90egQrgNnTRMUHikLZZAprf3gbm8rC5Vwmc6ZdLolQ7bFsa769Hqi6Tq/lS31KLsXBLTOsRbfPHph12w==", - "requires": { - "apollo-server-env": "^3.1.0", - "apollo-server-plugin-base": "^0.13.0" - } - }, - "apollo-datasource": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/apollo-datasource/-/apollo-datasource-0.9.0.tgz", - "integrity": "sha512-y8H99NExU1Sk4TvcaUxTdzfq2SZo6uSj5dyh75XSQvbpH6gdAXIW9MaBcvlNC7n0cVPsidHmOcHOWxJ/pTXGjA==", - "requires": { - "apollo-server-caching": "^0.7.0", - "apollo-server-env": "^3.1.0" - } - }, - "apollo-graphql": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/apollo-graphql/-/apollo-graphql-0.9.3.tgz", - "integrity": "sha512-rcAl2E841Iko4kSzj4Pt3PRBitmyq1MvoEmpl04TQSpGnoVgl1E/ZXuLBYxMTSnEAm7umn2IsoY+c6Ll9U/10A==", - "requires": { - "core-js-pure": "^3.10.2", - "lodash.sortby": "^4.7.0", - "sha.js": "^2.4.11" - } - }, - "apollo-link": { - "version": "1.2.14", - "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.14.tgz", - "integrity": "sha512-p67CMEFP7kOG1JZ0ZkYZwRDa369w5PIjtMjvrQd/HnIV8FRsHRqLqK+oAZQnFa1DDdZtOtHTi+aMIW6EatC2jg==", - "requires": { - "apollo-utilities": "^1.3.0", - "ts-invariant": "^0.4.0", - "tslib": "^1.9.3", - "zen-observable-ts": "^0.8.21" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - } - } - }, - "apollo-reporting-protobuf": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/apollo-reporting-protobuf/-/apollo-reporting-protobuf-0.8.0.tgz", - "integrity": "sha512-B3XmnkH6Y458iV6OsA7AhfwvTgeZnFq9nPVjbxmLKnvfkEl8hYADtz724uPa0WeBiD7DSFcnLtqg9yGmCkBohg==", - "requires": { - "@apollo/protobufjs": "1.2.2" - } - }, - "apollo-server-caching": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/apollo-server-caching/-/apollo-server-caching-0.7.0.tgz", - "integrity": "sha512-MsVCuf/2FxuTFVhGLK13B+TZH9tBd2qkyoXKKILIiGcZ5CDUEBO14vIV63aNkMkS1xxvK2U4wBcuuNj/VH2Mkw==", - "requires": { - "lru-cache": "^6.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - } - } - }, - "apollo-server-core": { - "version": "2.25.2", - "resolved": "https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-2.25.2.tgz", - "integrity": "sha512-lrohEjde2TmmDTO7FlOs8x5QQbAS0Sd3/t0TaK2TWaodfzi92QAvIsq321Mol6p6oEqmjm8POIDHW1EuJd7XMA==", - "requires": { - "@apollographql/apollo-tools": "^0.5.0", - "@apollographql/graphql-playground-html": "1.6.27", - "@apollographql/graphql-upload-8-fork": "^8.1.3", - "@josephg/resolvable": "^1.0.0", - "@types/ws": "^7.0.0", - "apollo-cache-control": "^0.14.0", - "apollo-datasource": "^0.9.0", - "apollo-graphql": "^0.9.0", - "apollo-reporting-protobuf": "^0.8.0", - "apollo-server-caching": "^0.7.0", - "apollo-server-env": "^3.1.0", - "apollo-server-errors": "^2.5.0", - "apollo-server-plugin-base": "^0.13.0", - "apollo-server-types": "^0.9.0", - "apollo-tracing": "^0.15.0", - "async-retry": "^1.2.1", - "fast-json-stable-stringify": "^2.0.0", - "graphql-extensions": "^0.15.0", - "graphql-tag": "^2.11.0", - "graphql-tools": "^4.0.8", - "loglevel": "^1.6.7", - "lru-cache": "^6.0.0", - "sha.js": "^2.4.11", - "subscriptions-transport-ws": "^0.9.19", - "uuid": "^8.0.0" - }, - "dependencies": { - "@apollographql/graphql-playground-html": { - "version": "1.6.27", - "resolved": "https://registry.npmjs.org/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.27.tgz", - "integrity": "sha512-tea2LweZvn6y6xFV11K0KC8ETjmm52mQrW+ezgB2O/aTQf8JGyFmMcRPFgUaQZeHbWdm8iisDC6EjOKsXu0nfw==", - "requires": { - "xss": "^1.0.8" - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "subscriptions-transport-ws": { - "version": "0.9.19", - "resolved": "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.19.tgz", - "integrity": "sha512-dxdemxFFB0ppCLg10FTtRqH/31FNRL1y1BQv8209MK5I4CwALb7iihQg+7p65lFcIl8MHatINWBLOqpgU4Kyyw==", - "requires": { - "backo2": "^1.0.2", - "eventemitter3": "^3.1.0", - "iterall": "^1.2.1", - "symbol-observable": "^1.0.4", - "ws": "^5.2.0 || ^6.0.0 || ^7.0.0" - }, - "dependencies": { - "ws": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz", - "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==" - } - } - }, - "symbol-observable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", - "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" - } - } - }, - "apollo-server-env": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/apollo-server-env/-/apollo-server-env-3.1.0.tgz", - "integrity": "sha512-iGdZgEOAuVop3vb0F2J3+kaBVi4caMoxefHosxmgzAbbSpvWehB8Y1QiSyyMeouYC38XNVk5wnZl+jdGSsWsIQ==", - "requires": { - "node-fetch": "^2.6.1", - "util.promisify": "^1.0.0" - }, - "dependencies": { - "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "requires": { - "whatwg-url": "^5.0.0" - } - } - } - }, - "apollo-server-errors": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/apollo-server-errors/-/apollo-server-errors-2.5.0.tgz", - "integrity": "sha512-lO5oTjgiC3vlVg2RKr3RiXIIQ5pGXBFxYGGUkKDhTud3jMIhs+gel8L8zsEjKaKxkjHhCQAA/bcEfYiKkGQIvA==" - }, - "apollo-server-express": { - "version": "2.25.2", - "resolved": "https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-2.25.2.tgz", - "integrity": "sha512-A2gF2e85vvDugPlajbhr0A14cDFDIGX0mteNOJ8P3Z3cIM0D4hwrWxJidI+SzobefDIyIHu1dynFedJVhV0euQ==", - "requires": { - "@apollographql/graphql-playground-html": "1.6.27", - "@types/accepts": "^1.3.5", - "@types/body-parser": "1.19.0", - "@types/cors": "2.8.10", - "@types/express": "^4.17.12", - "@types/express-serve-static-core": "^4.17.21", - "accepts": "^1.3.5", - "apollo-server-core": "^2.25.2", - "apollo-server-types": "^0.9.0", - "body-parser": "^1.18.3", - "cors": "^2.8.5", - "express": "^4.17.1", - "graphql-subscriptions": "^1.0.0", - "graphql-tools": "^4.0.8", - "parseurl": "^1.3.2", - "subscriptions-transport-ws": "^0.9.19", - "type-is": "^1.6.16" - }, - "dependencies": { - "@apollographql/graphql-playground-html": { - "version": "1.6.27", - "resolved": "https://registry.npmjs.org/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.27.tgz", - "integrity": "sha512-tea2LweZvn6y6xFV11K0KC8ETjmm52mQrW+ezgB2O/aTQf8JGyFmMcRPFgUaQZeHbWdm8iisDC6EjOKsXu0nfw==", - "requires": { - "xss": "^1.0.8" - } - }, - "subscriptions-transport-ws": { - "version": "0.9.19", - "resolved": "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.19.tgz", - "integrity": "sha512-dxdemxFFB0ppCLg10FTtRqH/31FNRL1y1BQv8209MK5I4CwALb7iihQg+7p65lFcIl8MHatINWBLOqpgU4Kyyw==", - "requires": { - "backo2": "^1.0.2", - "eventemitter3": "^3.1.0", - "iterall": "^1.2.1", - "symbol-observable": "^1.0.4", - "ws": "^5.2.0 || ^6.0.0 || ^7.0.0" - }, - "dependencies": { - "ws": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz", - "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==" - } - } - }, - "symbol-observable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", - "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" - } - } - }, - "apollo-server-plugin-base": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/apollo-server-plugin-base/-/apollo-server-plugin-base-0.13.0.tgz", - "integrity": "sha512-L3TMmq2YE6BU6I4Tmgygmd0W55L+6XfD9137k+cWEBFu50vRY4Re+d+fL5WuPkk5xSPKd/PIaqzidu5V/zz8Kg==", - "requires": { - "apollo-server-types": "^0.9.0" - } - }, - "apollo-server-types": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-0.9.0.tgz", - "integrity": "sha512-qk9tg4Imwpk732JJHBkhW0jzfG0nFsLqK2DY6UhvJf7jLnRePYsPxWfPiNkxni27pLE2tiNlCwoDFSeWqpZyBg==", - "requires": { - "apollo-reporting-protobuf": "^0.8.0", - "apollo-server-caching": "^0.7.0", - "apollo-server-env": "^3.1.0" - } - }, - "apollo-tracing": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/apollo-tracing/-/apollo-tracing-0.15.0.tgz", - "integrity": "sha512-UP0fztFvaZPHDhIB/J+qGuy6hWO4If069MGC98qVs0I8FICIGu4/8ykpX3X3K6RtaQ56EDAWKykCxFv4ScxMeA==", - "requires": { - "apollo-server-env": "^3.1.0", - "apollo-server-plugin-base": "^0.13.0" - } - }, "apollo-upload-client": { "version": "16.0.0", "resolved": "https://registry.npmjs.org/apollo-upload-client/-/apollo-upload-client-16.0.0.tgz", @@ -3357,6 +2813,7 @@ "version": "1.3.4", "resolved": "https://registry.npmjs.org/apollo-utilities/-/apollo-utilities-1.3.4.tgz", "integrity": "sha512-pk2hiWrCXMAy2fRPwEyhvka+mqwzeP60Jr1tRYi5xru+3ko94HI9o6lK0CT33/w4RDlxWchmdhDCrvdr+pHCig==", + "dev": true, "requires": { "@wry/equality": "^0.1.2", "fast-json-stable-stringify": "^2.0.0", @@ -3367,7 +2824,8 @@ "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true } } }, @@ -3445,7 +2903,7 @@ "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, "array-ify": { "version": "1.0.0", @@ -3528,14 +2986,6 @@ "dev": true, "optional": true }, - "async-retry": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", - "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", - "requires": { - "retry": "0.13.1" - } - }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -3595,7 +3045,7 @@ "backoff": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz", - "integrity": "sha1-9hbtqdPktmuMp/ynn2lXIsX44m8=", + "integrity": "sha512-wC5ihrnUXmR2douXmXLCe5O3zg3GKIyvRi/hi58a/XyRxVI+3/yM0PYueQOZXPXQ9pxBislYkw+sF9b7C/RuMA==", "requires": { "precond": "0.2" } @@ -3737,20 +3187,22 @@ "dev": true }, "body-parser": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.1.tgz", - "integrity": "sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", + "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", "requires": { - "bytes": "3.1.1", + "bytes": "3.1.2", "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.8.1", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.9.6", - "raw-body": "2.4.2", - "type-is": "~1.6.18" + "on-finished": "2.4.1", + "qs": "6.10.3", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" }, "dependencies": { "debug": { @@ -3761,22 +3213,48 @@ "ms": "2.0.0" } }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" + }, "http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "requires": { - "depd": "~1.1.2", + "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", + "statuses": "2.0.1", "toidentifier": "1.0.1" } }, + "on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "requires": { + "ee-first": "1.1.1" + } + }, "qs": { - "version": "6.9.6", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", - "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==" + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "requires": { + "side-channel": "^1.0.4" + } + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" }, "toidentifier": { "version": "1.0.1", @@ -3912,17 +3390,17 @@ "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" }, "busboy": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.3.1.tgz", - "integrity": "sha512-y7tTxhGKXcyBxRKAni+awqx8uqaJKrSFSNFSeRG5CsWNdmy2BIK+6VGWEW7TZnIO/533mtMEA4rOevQV815YJw==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", "requires": { - "dicer": "0.3.0" + "streamsearch": "^1.1.0" } }, "bytes": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz", - "integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" }, "cache-base": { "version": "1.0.1", @@ -4592,9 +4070,9 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "color-string": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.0.tgz", - "integrity": "sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", "requires": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" @@ -4832,14 +4310,14 @@ } }, "cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" }, "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, "copy-descriptor": { "version": "0.1.1", @@ -4918,6 +4396,30 @@ "which": "^2.0.1" } }, + "cross-undici-fetch": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/cross-undici-fetch/-/cross-undici-fetch-0.4.3.tgz", + "integrity": "sha512-mv1jusEQsFnBHEBkpFaYROKAzAWyuW8ZyN48NcyqkjLGRrscMKuFRmUigUrkE/pdprQZjNTQQ/aWJKe6F4tzTA==", + "requires": { + "abort-controller": "^3.0.0", + "busboy": "^1.6.0", + "form-data-encoder": "^1.7.1", + "formdata-node": "^4.3.1", + "node-fetch": "^2.6.7", + "undici": "^5.1.0", + "web-streams-polyfill": "^3.2.0" + }, + "dependencies": { + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "requires": { + "whatwg-url": "^5.0.0" + } + } + } + }, "crypto-js": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", @@ -4948,11 +4450,6 @@ "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==", "dev": true }, - "cssfilter": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/cssfilter/-/cssfilter-0.0.10.tgz", - "integrity": "sha1-xtJnJjKi5cg+AT5oZKQs6N79IK4=" - }, "d": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", @@ -4976,11 +4473,6 @@ "integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==", "dev": true }, - "dataloader": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-2.0.0.tgz", - "integrity": "sha512-YzhyDAwA4TaQIhM5go+vCLmU0UikghC/t9DTQYZR2M/UvZ1MdOhPezSDZcjj9uqQJOMqjLcpWtyW2iNINdlatQ==" - }, "dateformat": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", @@ -5246,6 +4738,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, "requires": { "object-keys": "^1.0.12" } @@ -5351,9 +4844,9 @@ "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==" }, "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" }, "dependency-tree": { "version": "8.1.1", @@ -5391,11 +4884,6 @@ } } }, - "deprecated-decorator": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/deprecated-decorator/-/deprecated-decorator-0.1.6.tgz", - "integrity": "sha1-AJZjF7ehL+kvPMgx91g68ym4bDc=" - }, "deprecation": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", @@ -5403,9 +4891,9 @@ "dev": true }, "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" }, "detective-amd": { "version": "3.1.0", @@ -5586,14 +5074,6 @@ "typescript": "^3.9.7" } }, - "dicer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.3.0.tgz", - "integrity": "sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA==", - "requires": { - "streamsearch": "0.1.2" - } - }, "dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -5826,6 +5306,11 @@ } } }, + "dset": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.2.tgz", + "integrity": "sha512-g/M9sqy3oHe477Ar4voQxWtaPIFw1jTdKZuomOjhCcBx9nHUNn0pu6NopuFFrTh/TRZIKEj+76vLWFu9BNKk+Q==" + }, "duplexer2": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", @@ -5889,7 +5374,7 @@ "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" }, "end-of-stream": { "version": "1.4.4", @@ -5984,40 +5469,6 @@ } } }, - "es-abstract": { - "version": "1.18.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.5.tgz", - "integrity": "sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA==", - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.3", - "is-string": "^1.0.6", - "object-inspect": "^1.11.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, "es5-ext": { "version": "0.10.53", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", @@ -6073,7 +5524,7 @@ "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "escape-string-regexp": { "version": "1.0.5", @@ -6368,7 +5819,7 @@ "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" }, "event-emitter": { "version": "0.3.5", @@ -6379,6 +5830,11 @@ "es5-ext": "~0.10.14" } }, + "event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" + }, "eventemitter3": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", @@ -6450,37 +5906,38 @@ } }, "express": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.2.tgz", - "integrity": "sha512-oxlxJxcQlYwqPWKVJJtvQiwHgosH/LrLSPA+H4UxpyvSS6jC5aH+5MoHFM+KABgTOt0APue4w66Ha8jCUo9QGg==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", + "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", "requires": { - "accepts": "~1.3.7", + "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.19.1", + "body-parser": "1.20.0", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.4.1", + "cookie": "0.5.0", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "~1.1.2", + "depd": "2.0.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "~1.1.2", + "finalhandler": "1.2.0", "fresh": "0.5.2", + "http-errors": "2.0.0", "merge-descriptors": "1.0.1", "methods": "~1.1.2", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", "proxy-addr": "~2.0.7", - "qs": "6.9.6", + "qs": "6.10.3", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.17.2", - "serve-static": "1.14.2", + "send": "0.18.0", + "serve-static": "1.15.0", "setprototypeof": "1.2.0", - "statuses": "~1.5.0", + "statuses": "2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" @@ -6503,9 +5960,12 @@ } }, "qs": { - "version": "6.9.6", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", - "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==" + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "requires": { + "side-channel": "^1.0.4" + } } } }, @@ -6656,7 +6116,8 @@ "extract-files": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/extract-files/-/extract-files-11.0.0.tgz", - "integrity": "sha512-FuoE1qtbJ4bBVvv94CC7s0oTnKUGvQs+Rjf1L2SJFfS+HTVVjhPFtehPdQ0JiGPqVNfSSZvL5yzHHQq2Z4WNhQ==" + "integrity": "sha512-FuoE1qtbJ4bBVvv94CC7s0oTnKUGvQs+Rjf1L2SJFfS+HTVVjhPFtehPdQ0JiGPqVNfSSZvL5yzHHQq2Z4WNhQ==", + "dev": true }, "extsprintf": { "version": "1.4.0", @@ -6770,9 +6231,9 @@ "integrity": "sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q==" }, "fetch-blob": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.1.4.tgz", - "integrity": "sha512-Eq5Xv5+VlSrYWEqKrusxY1C3Hm/hjeAsCGVG3ft7pZahlUAChpGZT/Ms1WmSLnEAisEXszjzu/s+ce6HZB2VHA==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.1.5.tgz", + "integrity": "sha512-N64ZpKqoLejlrwkIAnb9iLSA3Vx/kjgzpcDhygcqJ2KKjky8nCgUQ+dzXtbrLaWZGZNmNfQTsiQ0weZ1svglHg==", "dev": true, "requires": { "node-domexception": "^1.0.0", @@ -6976,16 +6437,16 @@ "dev": true }, "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", "requires": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", - "statuses": "~1.5.0", + "statuses": "2.0.1", "unpipe": "~1.0.0" }, "dependencies": { @@ -7087,17 +6548,9 @@ "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" }, "follow-redirects": { - "version": "1.14.8", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", - "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==" - }, - "for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "requires": { - "is-callable": "^1.1.3" - } + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.0.tgz", + "integrity": "sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ==" }, "for-in": { "version": "1.0.2", @@ -7132,6 +6585,27 @@ "mime-types": "^2.1.12" } }, + "form-data-encoder": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz", + "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==" + }, + "formdata-node": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.3.2.tgz", + "integrity": "sha512-k7lYJyzDOSL6h917favP8j1L0/wNyylzU+x+1w4p5haGVHNlP58dbpdJhiCUsDbWsa9HwEtLp89obQgXl2e0qg==", + "requires": { + "node-domexception": "1.0.0", + "web-streams-polyfill": "4.0.0-beta.1" + }, + "dependencies": { + "web-streams-polyfill": { + "version": "4.0.0-beta.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.1.tgz", + "integrity": "sha512-3ux37gEX670UUphBF9AMCq8XM6iQ8Ac6A+DSRRjDoRBm1ufCkaCDdNVbaqq60PsEkdNlLKrGtv/YBP4EJXqNtQ==" + } + } + }, "formdata-polyfill": { "version": "4.0.10", "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", @@ -7159,7 +6633,7 @@ "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" }, "from2": { "version": "2.3.0", @@ -7177,11 +6651,6 @@ "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", "dev": true }, - "fs-capacitor": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/fs-capacitor/-/fs-capacitor-2.0.4.tgz", - "integrity": "sha512-8S4f4WsCryNw2mJJchi46YgB6CR5Ze+4L1h8ewl9tEpL4SJ3ZO+c/bS4BWhB8bK+O3TMqhuZarTitd0S0eh2pA==" - }, "fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -7503,24 +6972,9 @@ "dev": true }, "graphql": { - "version": "15.7.1", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.7.1.tgz", - "integrity": "sha512-x34S6gC0/peBZnlK60zCJox/d45A7p6At9oN9EPA3qhoIAlR4LNZmXRLkICBckwwTMJzVdA8cx3QIQZMOl606A==" - }, - "graphql-executor": { - "version": "0.0.18", - "resolved": "https://registry.npmjs.org/graphql-executor/-/graphql-executor-0.0.18.tgz", - "integrity": "sha512-upUSl7tfZCZ5dWG1XkOvpG70Yk3duZKcCoi/uJso4WxJVT6KIrcK4nZ4+2X/hzx46pL8wAukgYHY6iNmocRN+g==" - }, - "graphql-extensions": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/graphql-extensions/-/graphql-extensions-0.15.0.tgz", - "integrity": "sha512-bVddVO8YFJPwuACn+3pgmrEg6I8iBuYLuwvxiE+lcQQ7POotVZxm2rgGw0PvVYmWWf3DT7nTVDZ5ROh/ALp8mA==", - "requires": { - "@apollographql/apollo-tools": "^0.5.0", - "apollo-server-env": "^3.1.0", - "apollo-server-types": "^0.9.0" - } + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.5.0.tgz", + "integrity": "sha512-qbHgh8Ix+j/qY+a/ZcJnFQ+j8ezakqPiHwPiZhV/3PgGlgf96QMBB5/f2rkiC9sgLoy/xvT6TSiaf2nTHJh5iA==" }, "graphql-list-fields": { "version": "2.0.2", @@ -7528,17 +6982,9 @@ "integrity": "sha512-9TSAwcVA3KWw7JWYep5NCk2aw3wl1ayLtbMpmG7l26vh1FZ+gZexNPP+XJfUFyJa71UU0zcKSgtgpsrsA3Xv9Q==" }, "graphql-relay": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/graphql-relay/-/graphql-relay-0.7.0.tgz", - "integrity": "sha512-P8eS3IbZRhbfbcfud1Q6VPrIru4hchkb15MuOij+WQo9r0chD5NBIxiVjuRE2iG2EMHxIOrZb8LnMe82+YdITA==" - }, - "graphql-subscriptions": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/graphql-subscriptions/-/graphql-subscriptions-1.2.1.tgz", - "integrity": "sha512-95yD/tKi24q8xYa7Q9rhQN16AYj5wPbrb8tmHGM3WRc9EBmWrG/0kkMl+tQG8wcEuE9ibR4zyOM31p5Sdr2v4g==", - "requires": { - "iterall": "^1.3.0" - } + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/graphql-relay/-/graphql-relay-0.10.0.tgz", + "integrity": "sha512-44yBuw2/DLNEiMypbNZBt1yMDbBmyVPVesPywnteGGALiBmdyy1JP8jSg8ClLePg8ZZxk0O4BLhd1a6U/1jDOQ==" }, "graphql-tag": { "version": "2.12.6", @@ -7555,44 +7001,6 @@ } } }, - "graphql-tools": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/graphql-tools/-/graphql-tools-4.0.8.tgz", - "integrity": "sha512-MW+ioleBrwhRjalKjYaLQbr+920pHBgy9vM/n47sswtns8+96sRn5M/G+J1eu7IMeKWiN/9p6tmwCHU7552VJg==", - "requires": { - "apollo-link": "^1.2.14", - "apollo-utilities": "^1.0.1", - "deprecated-decorator": "^0.1.6", - "iterall": "^1.1.3", - "uuid": "^3.1.0" - }, - "dependencies": { - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - } - } - }, - "graphql-upload": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/graphql-upload/-/graphql-upload-11.0.0.tgz", - "integrity": "sha512-zsrDtu5gCbQFDWsNa5bMB4nf1LpKX9KDgh+f8oL1288ijV4RxeckhVozAjqjXAfRpxOHD1xOESsh6zq8SjdgjA==", - "requires": { - "busboy": "^0.3.1", - "fs-capacitor": "^6.1.0", - "http-errors": "^1.7.3", - "isobject": "^4.0.0", - "object-path": "^0.11.4" - }, - "dependencies": { - "fs-capacitor": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/fs-capacitor/-/fs-capacitor-6.2.0.tgz", - "integrity": "sha512-nKcE1UduoSKX27NSZlg879LdQc94OtbOsEmKMN2MBNudXREvijRKx2GEBsTMTfws+BrbkJoEuynbGSVRSpauvw==" - } - } - }, "graphviz": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/graphviz/-/graphviz-0.0.9.tgz", @@ -7651,11 +7059,6 @@ "function-bind": "^1.1.1" } }, - "has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==" - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -7682,14 +7085,6 @@ "has-symbol-support-x": "^1.4.1" } }, - "has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "requires": { - "has-symbols": "^1.0.2" - } - }, "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -7761,6 +7156,7 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dev": true, "requires": { "react-is": "^16.7.0" } @@ -7831,15 +7227,15 @@ "dev": true }, "http-errors": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz", - "integrity": "sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "requires": { - "depd": "~1.1.2", + "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "statuses": "2.0.1", + "toidentifier": "1.0.1" } }, "http-proxy-agent": { @@ -8182,16 +7578,6 @@ } } }, - "internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", - "requires": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - } - }, "intersect": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/intersect/-/intersect-1.0.1.tgz", @@ -8217,9 +7603,9 @@ } }, "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", + "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==" }, "ipaddr.js": { "version": "1.9.1", @@ -8253,14 +7639,6 @@ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" }, - "is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "requires": { - "has-bigints": "^1.0.1" - } - }, "is-binary-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", @@ -8271,15 +7649,6 @@ "binary-extensions": "^1.0.0" } }, - "is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", @@ -8287,11 +7656,6 @@ "dev": true, "optional": true }, - "is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==" - }, "is-core-module": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.6.0.tgz", @@ -8323,14 +7687,6 @@ } } }, - "is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, "is-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", @@ -8421,11 +7777,6 @@ "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=", "dev": true }, - "is-negative-zero": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", - "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==" - }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -8448,14 +7799,6 @@ } } }, - "is-number-object": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", - "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, "is-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", @@ -8505,20 +7848,6 @@ } } }, - "is-promise": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", - "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==" - }, - "is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, "is-regexp": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", @@ -8542,22 +7871,6 @@ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" }, - "is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "requires": { - "has-symbols": "^1.0.2" - } - }, "is-text-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", @@ -8613,11 +7926,6 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, - "isobject": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-4.0.0.tgz", - "integrity": "sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==" - }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -8942,7 +8250,8 @@ "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true }, "js-yaml": { "version": "3.14.1", @@ -9141,21 +8450,21 @@ } }, "jwks-rsa": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-2.0.5.tgz", - "integrity": "sha512-fliHfsiBRzEU0nXzSvwnh0hynzGB0WihF+CinKbSRlaqRxbqqKf2xbBPgwc8mzf18/WgwlG8e5eTpfSTBcU4DQ==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-2.1.3.tgz", + "integrity": "sha512-+zSFnZYHckwxEIgjEu81AAWDyqx8z5/OVtmhuXPbchUA9Y4bipVDqvL/5Z5Qhe088e/uxPvp8QDpIDOmI2cEBg==", "requires": { - "@types/express-jwt": "0.0.42", - "debug": "^4.3.2", + "@types/express": "^4.17.13", + "debug": "^4.3.4", "jose": "^2.0.5", "limiter": "^1.1.5", "lru-memoizer": "^2.1.4" }, "dependencies": { "debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "requires": { "ms": "2.1.2" } @@ -9214,15 +8523,15 @@ "ldap-filter": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/ldap-filter/-/ldap-filter-0.3.3.tgz", - "integrity": "sha1-KxTGiiqdQQTb28kQocqF/Riel5c=", + "integrity": "sha512-/tFkx5WIn4HuO+6w9lsfxq4FN3O+fDZeO9Mek8dCD8rTUpqzRa766BOBO7BcGkn3X86m5+cBm1/2S/Shzz7gMg==", "requires": { "assert-plus": "^1.0.0" } }, "ldapjs": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/ldapjs/-/ldapjs-2.3.1.tgz", - "integrity": "sha512-kf0tHHLrpwKaBAQOhYHXgdeh2PkFuCCxWgLb1MRn67ZQVo787D2pij3mmHVZx193GIdM8xcfi8HF6AIYYnj0fQ==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/ldapjs/-/ldapjs-2.3.2.tgz", + "integrity": "sha512-FU+GR/qbQ96WUZ2DUb7FzaEybYvv3240wTVPcbsdELB3o4cK92zGVjntsh68siVkLeCmlCcsd/cIQzyGXSS7LA==", "requires": { "abstract-logging": "^2.0.0", "asn1": "^0.2.4", @@ -9553,7 +8862,7 @@ "lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" }, "lodash.defaults": { "version": "4.2.0", @@ -9692,11 +9001,6 @@ "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=", "dev": true }, - "lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" - }, "lodash.startswith": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/lodash.startswith/-/lodash.startswith-4.2.1.tgz", @@ -9850,32 +9154,15 @@ } } }, - "loglevel": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz", - "integrity": "sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==" - }, - "long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" - }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, "requires": { "js-tokens": "^3.0.0 || ^4.0.0" } }, - "lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "requires": { - "tslib": "^2.0.3" - } - }, "lowercase-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", @@ -9883,12 +9170,9 @@ "dev": true }, "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.10.1.tgz", + "integrity": "sha512-BQuhQxPuRl79J5zSXRP+uNzPOyZw2oFI9JLRQ80XswSvg21KMKNtQza9eF42rfI/3Z40RvzBdXgziEkudzjo8A==" }, "lru-memoizer": { "version": "2.1.4", @@ -9902,7 +9186,7 @@ "lru-cache": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.2.tgz", - "integrity": "sha1-HRdnnAac2l0ECZGgnbwsDbN35V4=", + "integrity": "sha512-uQw9OqphAGiZhkuPlpFGmdTU2tEuhxTourM/19qGJrxBPHAr/f8BT1a0i/lOclESnGatdJG/UCkP9kZB/Lh1iw==", "requires": { "pseudomap": "^1.0.1", "yallist": "^2.0.0" @@ -10242,7 +9526,7 @@ "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" }, "merge-stream": { "version": "2.0.0", @@ -10259,7 +9543,7 @@ "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" }, "micromatch": { "version": "3.1.10", @@ -10438,26 +9722,26 @@ } }, "moment": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", - "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" + "version": "2.29.3", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz", + "integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==" }, "mongodb": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.3.1.tgz", - "integrity": "sha512-sNa8APSIk+r4x31ZwctKjuPSaeKuvUeNb/fu/3B6dRM02HpEgig7hTHM8A/PJQTlxuC/KFWlDlQjhsk/S43tBg==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.6.0.tgz", + "integrity": "sha512-1gsxVXmjFTPJ+CkMG9olE4bcVsyY8lBJN9m5B5vj+LZ7wkBqq3PO8RVmNX9GwCBOBz1KV0zM00vPviUearSv7A==", "requires": { - "bson": "^4.6.1", + "bson": "^4.6.3", "denque": "^2.0.1", - "mongodb-connection-string-url": "^2.4.1", + "mongodb-connection-string-url": "^2.5.2", "saslprep": "^1.0.3", - "socks": "^2.6.1" + "socks": "^2.6.2" }, "dependencies": { "bson": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/bson/-/bson-4.6.1.tgz", - "integrity": "sha512-I1LQ7Hz5zgwR4QquilLNZwbhPw0Apx7i7X9kGMBTsqPdml/03Q9NBtD9nt/19ahjlphktQImrnderxqpzeVDjw==", + "version": "4.6.4", + "resolved": "https://registry.npmjs.org/bson/-/bson-4.6.4.tgz", + "integrity": "sha512-TdQ3FzguAu5HKPPlr0kYQCyrYUYh8tFM+CMTpxjNzVzxeiJY00Rtuj3LXLHSgiGvmaWlZ8PE+4KyM2thqE38pQ==", "requires": { "buffer": "^5.6.0" } @@ -10470,9 +9754,9 @@ } }, "mongodb-connection-string-url": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.4.1.tgz", - "integrity": "sha512-d5Kd2bVsKcSA7YI/yo57fSTtMwRQdFkvc5IZwod1RRxJtECeWPPSo7zqcUGJELifRA//Igs4spVtYAmvFCatug==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.5.2.tgz", + "integrity": "sha512-tWDyIG8cQlI5k3skB6ywaEA5F9f5OntrKKsT/Lteub2zgwSUlhqEN2inGgBTm8bpYJf8QYBdA/5naz65XDpczA==", "requires": { "@types/whatwg-url": "^8.2.1", "whatwg-url": "^11.0.0" @@ -10836,9 +10120,9 @@ "dev": true }, "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" }, "neo-async": { "version": "2.6.2", @@ -10863,20 +10147,10 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, - "no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "requires": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" - } - }, "node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "dev": true + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==" }, "node-emoji": { "version": "1.11.0", @@ -10888,20 +10162,20 @@ } }, "node-fetch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.1.1.tgz", - "integrity": "sha512-SMk+vKgU77PYotRdWzqZGTZeuFKlsJ0hu4KPviQKkfY+N3vn2MIzr0rvpnYpR8MtB3IEuhlEcuOLbGvLRlA+yg==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.2.4.tgz", + "integrity": "sha512-WvYJRN7mMyOLurFR2YpysQGuwYrJN+qrrpHjJDuKMcSPdfFccRUla/kng2mz6HWSBxJcqPbvatS6Gb4RhOzCJw==", "dev": true, "requires": { "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.3", + "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "node-forge": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", - "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==" + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.0.tgz", + "integrity": "sha512-08ARB91bUi6zNKzVmaj3QO7cr397uiDT2nJ63cHjyNtCTWIgvS47j3eT0WfzUwS9+6Z5YshRaoasFkXCKrIYbA==" }, "node-netstat": { "version": "1.8.0", @@ -13226,19 +12500,15 @@ "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==" }, "object-inspect": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz", - "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==" + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", + "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==" }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" - }, - "object-path": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.8.tgz", - "integrity": "sha512-YJjNZrlXJFM42wTBn6zgOJVar9KFJvzx6sTWDte8sWZF//cnjl0BxHNpfZx+ZffXX63A9q0b1zsFiBX4g4X5KA==" + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true }, "object-visit": { "version": "1.0.1", @@ -13263,6 +12533,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, "requires": { "call-bind": "^1.0.0", "define-properties": "^1.1.3", @@ -13270,16 +12541,6 @@ "object-keys": "^1.1.1" } }, - "object.getownpropertydescriptors": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz", - "integrity": "sha512-WtxeKSzfBjlzL+F9b7M7hewDzMwy+C8NRssHd1YrNlzHzIDrXcXiNOMrezdAEM4UXixgV+vvnyBeN7Rygl2ttQ==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2" - } - }, "object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", @@ -13300,9 +12561,9 @@ } }, "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "requires": { "ee-first": "1.1.1" } @@ -13342,6 +12603,7 @@ "version": "0.16.1", "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.16.1.tgz", "integrity": "sha512-64i+Uw3otrndfq5kaoGNoY7pvOhSsjFEN4bdEFh80MWVk/dbgJfMv7VFDeCT8LxNAlEVhQmdVEbfE7X2nWNIIg==", + "dev": true, "requires": { "@wry/context": "^0.6.0", "@wry/trie": "^0.3.0" @@ -13625,12 +12887,12 @@ } }, "parse": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/parse/-/parse-3.4.1.tgz", - "integrity": "sha512-XTMaHfcOwAOiWLraNtPbCzR8o94ZWjOfaZDMM2jZ1ZDB5twtK1B82lPa+N197efZhcQ+QFbW/eDJsBybD48aSQ==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/parse/-/parse-3.4.2.tgz", + "integrity": "sha512-Ruehcp/S7eB3A0lDG5eAPvZHa5pABCbUR+lMJL2gUNKJLZNcD9/s3RL255PwI5jTqa+TCJ7MdPqobUplouN1pQ==", "requires": { - "@babel/runtime": "7.15.4", - "@babel/runtime-corejs3": "7.14.7", + "@babel/runtime": "7.17.9", + "@babel/runtime-corejs3": "7.17.8", "crypto-js": "4.1.1", "idb-keyval": "6.0.3", "react-native-crypto-js": "1.0.0", @@ -13640,22 +12902,27 @@ }, "dependencies": { "@babel/runtime": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.4.tgz", - "integrity": "sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.9.tgz", + "integrity": "sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==", "requires": { "regenerator-runtime": "^0.13.4" } }, "@babel/runtime-corejs3": { - "version": "7.14.7", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.14.7.tgz", - "integrity": "sha512-Wvzcw4mBYbTagyBVZpAJWI06auSIj033T/yNE0Zn1xcup83MieCddZA7ls3kme17L4NOGBrQ09Q+nKB41RLWBA==", + "version": "7.17.8", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.17.8.tgz", + "integrity": "sha512-ZbYSUvoSF6dXZmMl/CYTMOvzIFnbGfv4W3SEHYgMvNsFTeLaF2gkGAF4K2ddmtSK4Emej+0aYcnSC6N5dPCXUQ==", "requires": { - "core-js-pure": "^3.15.0", + "core-js-pure": "^3.20.2", "regenerator-runtime": "^0.13.4" } }, + "core-js-pure": { + "version": "3.22.8", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.22.8.tgz", + "integrity": "sha512-bOxbZIy9S5n4OVH63XaLVXZ49QKicjowDx/UELyJ68vxfCRpYsbyh/WNZNfEfAk+ekA8vSjt+gCDpvh672bc3w==" + }, "idb-keyval": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.0.3.tgz", @@ -13699,15 +12966,6 @@ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" }, - "pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "requires": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, "pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", @@ -13749,7 +13007,7 @@ "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, "path-type": { "version": "4.0.0", @@ -14068,7 +13326,7 @@ "precond": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/precond/-/precond-0.2.3.tgz", - "integrity": "sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw=" + "integrity": "sha512-QCYG84SgGyGzqJ/vlMsxeXd/pgL/I94ixdNFyh1PusWmTCyVfPJjZ1K1jvHtsbfnXQs2TSkEP2fR7QiMZAnKFQ==" }, "prelude-ls": { "version": "1.1.2", @@ -14165,6 +13423,7 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, "requires": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -14198,7 +13457,7 @@ "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" }, "psl": { "version": "1.8.0", @@ -14255,28 +13514,38 @@ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" }, "raw-body": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.2.tgz", - "integrity": "sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "requires": { - "bytes": "3.1.1", - "http-errors": "1.8.1", + "bytes": "3.1.2", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" }, "dependencies": { + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, "http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "requires": { - "depd": "~1.1.2", + "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", + "statuses": "2.0.1", "toidentifier": "1.0.1" } }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" + }, "toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -14307,7 +13576,8 @@ "react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true }, "react-native-crypto-js": { "version": "1.0.0", @@ -14749,7 +14019,8 @@ "retry": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==" + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true }, "reusify": { "version": "1.0.4", @@ -15142,9 +14413,9 @@ } }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", "requires": { "lru-cache": "^6.0.0" }, @@ -15189,23 +14460,23 @@ "dev": true }, "send": { - "version": "0.17.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", - "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", "requires": { "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", + "depd": "2.0.0", + "destroy": "1.2.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "1.8.1", + "http-errors": "2.0.0", "mime": "1.6.0", "ms": "2.1.3", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "range-parser": "~1.2.1", - "statuses": "~1.5.0" + "statuses": "2.0.1" }, "dependencies": { "debug": { @@ -15219,22 +14490,10 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" } } }, - "http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - } - }, "mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -15244,23 +14503,18 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" } } }, "serve-static": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", - "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", "requires": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.17.2" + "send": "0.18.0" } }, "set-blocking": { @@ -15298,15 +14552,6 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, - "sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -15532,12 +14777,12 @@ } }, "socks": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.1.tgz", - "integrity": "sha512-kLQ9N5ucj8uIcxrDwjm0Jsqk06xdpBjGNQtpXy4Q8/QY2k+fY7nZH8CARy+hkbG+SGAovmzzuauCpBlb8FrnBA==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz", + "integrity": "sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==", "requires": { "ip": "^1.1.5", - "smart-buffer": "^4.1.0" + "smart-buffer": "^4.2.0" } }, "sort-keys": { @@ -15773,9 +15018,9 @@ } }, "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" }, "stream-combiner2": { "version": "1.1.1", @@ -15788,9 +15033,9 @@ } }, "streamsearch": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", - "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==" }, "string-argv": { "version": "0.3.1", @@ -15814,24 +15059,6 @@ "strip-ansi": "^3.0.0" } }, - "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -16007,7 +15234,8 @@ "symbol-observable": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", - "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==" + "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", + "dev": true }, "table": { "version": "5.4.6", @@ -16233,6 +15461,11 @@ "next-tick": "1" } }, + "tiny-lru": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/tiny-lru/-/tiny-lru-7.0.6.tgz", + "integrity": "sha512-zNYO0Kvgn5rXzWpL0y3RS09sMK67eGaQj9805jlK9G6pSadfriTczzLHFXa/xcW4mIRfmlB9HyQ/+SgL0V1uow==" + }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -16307,9 +15540,9 @@ } }, "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" }, "tough-cookie": { "version": "2.4.3", @@ -16362,6 +15595,7 @@ "version": "0.4.4", "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.4.4.tgz", "integrity": "sha512-uEtWkFM/sdZvRNNDL3Ehu4WVpwaulhwQszV8mrtcdeE8nN00BV9mAmQ88RkrBhFgl9gMgvjJLAQcZbnPXI9mlA==", + "dev": true, "requires": { "tslib": "^1.9.3" }, @@ -16369,14 +15603,15 @@ "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true } } }, "tslib": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", - "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, "tsutils": { "version": "3.21.0", @@ -16475,17 +15710,6 @@ "dev": true, "optional": true }, - "unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", - "requires": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", - "which-boxed-primitive": "^1.0.2" - } - }, "unbzip2-stream": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", @@ -16502,6 +15726,11 @@ "integrity": "sha512-D39qtimx0c1fI3ya1Lnhk3E9nONswSKhnffBI0gME9C99fYOkNi04xs8K6pePLhvl1frbDemkaBQ5ikWllR2HQ==", "dev": true }, + "undici": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.2.0.tgz", + "integrity": "sha512-XY6+NS3WH9b3TKOHeNz2CjR+qrVz/k4fO9g3etPpLozRvULoQmZ1+dk9JbIz40ehn27xzFk4jYVU2MU3Nle62A==" + }, "unicode-canonical-property-names-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", @@ -16682,6 +15911,12 @@ "dev": true, "optional": true }, + "use-sync-external-store": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.1.0.tgz", + "integrity": "sha512-SEnieB2FPKEVne66NpXPd1Np4R1lTNKfjuy3XdIoPQKYBAFdzbzSZlSn1KJZUiihQLQC5Znot4SBz1EOTBwQAQ==", + "dev": true + }, "user-home": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", @@ -16693,18 +15928,6 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, - "util.promisify": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.1.1.tgz", - "integrity": "sha512-/s3UsZUrIfa6xDhr7zZhnE9SLQ5RIXyYfiVnMMyMDzOc8WhWN4Nbh36H842OyurKbCDAesZOJaVyvmSl6fhGQw==", - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "for-each": "^0.3.3", - "has-symbols": "^1.0.1", - "object.getownpropertydescriptors": "^2.1.1" - } - }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -16732,9 +15955,9 @@ } }, "value-or-promise": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/value-or-promise/-/value-or-promise-1.0.10.tgz", - "integrity": "sha512-1OwTzvcfXkAfabk60UVr5NdjtjJ0Fg0T5+B1bhxtrOEwSH2fe8y4DnLgoksfCyd8yZCOQQHB0qLMQnwgCjbXLQ==" + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/value-or-promise/-/value-or-promise-1.0.11.tgz", + "integrity": "sha512-41BrgH+dIbCFXClcSapVs5M6GkENd3gQOJpEfPDNa71LsUGMXDL0jMWpI/Rh7WhX+Aalfz2TTS3Zt5pUsbnhLg==" }, "vary": { "version": "1.1.2", @@ -16742,9 +15965,9 @@ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, "vasync": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/vasync/-/vasync-2.2.0.tgz", - "integrity": "sha1-z951GGChWCLbOxMrxZsRakra8Bs=", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vasync/-/vasync-2.2.1.tgz", + "integrity": "sha512-Hq72JaTpcTFdWiNA4Y22Amej2GH3BFmBaKPPlDZ4/oC8HNn2ISHLkFrJU4Ds8R3jcUi7oo5Y9jcMHKjES+N9wQ==", "requires": { "verror": "1.10.0" } @@ -16777,8 +16000,7 @@ "web-streams-polyfill": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz", - "integrity": "sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA==", - "dev": true + "integrity": "sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA==" }, "webidl-conversions": { "version": "3.0.1", @@ -16803,18 +16025,6 @@ "isexe": "^2.0.0" } }, - "which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - } - }, "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", @@ -16836,20 +16046,20 @@ } }, "winston": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.5.1.tgz", - "integrity": "sha512-tbRtVy+vsSSCLcZq/8nXZaOie/S2tPXPFt4be/Q3vI/WtYwm7rrwidxVw2GRa38FIXcJ1kUM6MOZ9Jmnk3F3UA==", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.7.2.tgz", + "integrity": "sha512-QziIqtojHBoyzUOdQvQiar1DH0Xp9nF1A1y7NVy2DGEsz82SBDtOalS0ulTRGVT14xPX3WRWkCsdcJKqNflKng==", "requires": { "@dabh/diagnostics": "^2.0.2", "async": "^3.2.3", "is-stream": "^2.0.0", - "logform": "^2.3.2", + "logform": "^2.4.0", "one-time": "^1.0.0", "readable-stream": "^3.4.0", "safe-stable-stringify": "^2.3.1", "stack-trace": "0.0.x", "triple-beam": "^1.3.0", - "winston-transport": "^4.4.2" + "winston-transport": "^4.5.0" }, "dependencies": { "async": { @@ -16870,9 +16080,9 @@ } }, "winston-daily-rotate-file": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/winston-daily-rotate-file/-/winston-daily-rotate-file-4.6.0.tgz", - "integrity": "sha512-mvpFb1LYmTvh/vz0dIS/aDCwEm0cvDa8D/tE4xWwdUYolD250wf+n0y1PZ2xr7fbvTLF/PQYqXtFIFrmog03Ow==", + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/winston-daily-rotate-file/-/winston-daily-rotate-file-4.6.1.tgz", + "integrity": "sha512-Ycch4LZmTycbhgiI2eQXBKI1pKcEQgAqmBjyq7/dC6Dk77nasdxvhLKraqTdCw7wNDSs8/M0jXaLATHquG7xYg==", "requires": { "file-stream-rotator": "^0.6.1", "object-hash": "^2.0.1", @@ -17010,9 +16220,9 @@ } }, "ws": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", - "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==" + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.6.0.tgz", + "integrity": "sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==" }, "xmlcreate": { "version": "2.0.3", @@ -17025,22 +16235,6 @@ "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=" }, - "xss": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/xss/-/xss-1.0.9.tgz", - "integrity": "sha512-2t7FahYnGJys6DpHLhajusId7R0Pm2yTmuL0GV9+mV0ZlaLSnb2toBmppATfg5sWIhZQGlsTLoecSzya+l4EAQ==", - "requires": { - "commander": "^2.20.3", - "cssfilter": "0.0.10" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - } - } - }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -17139,22 +16333,16 @@ "zen-observable": { "version": "0.8.15", "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz", - "integrity": "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==" + "integrity": "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==", + "dev": true }, "zen-observable-ts": { - "version": "0.8.21", - "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.21.tgz", - "integrity": "sha512-Yj3yXweRc8LdRMrCC8nIc4kkjWecPAUVh0TI0OUrWXx6aX790vLcDlWca6I4vsyCGH3LpWxq0dJRcMOFoVqmeg==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-1.2.3.tgz", + "integrity": "sha512-hc/TGiPkAWpByykMwDcem3SdUgA4We+0Qb36bItSuJC9xD0XVBZoFHYoadAomDSNf64CG8Ydj0Qb8Od8BUWz5g==", + "dev": true, "requires": { - "tslib": "^1.9.3", - "zen-observable": "^0.8.0" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - } + "zen-observable": "0.8.15" } } } diff --git a/package.json b/package.json index ba700337a0..c6aea361a1 100644 --- a/package.json +++ b/package.json @@ -19,50 +19,49 @@ ], "license": "BSD-3-Clause", "dependencies": { - "@apollographql/graphql-playground-html": "1.6.29", - "@graphql-tools/links": "8.2.2", - "@apollo/client": "3.5.8", - "@graphql-tools/stitch": "6.2.4", - "@graphql-tools/utils": "6.2.4", - "@parse/fs-files-adapter": "1.2.1", - "@parse/push-adapter": "4.1.0", - "apollo-server-express": "2.25.2", + "@graphql-yoga/node": "2.6.0", + "@graphql-tools/utils": "8.6.12", + "@graphql-tools/merge": "8.2.13", + "@graphql-tools/schema": "8.3.13", + "@parse/fs-files-adapter": "1.2.2", + "@parse/push-adapter": "4.1.2", "bcryptjs": "2.4.3", - "body-parser": "1.19.1", + "body-parser": "1.20.0", "commander": "5.1.0", "cors": "2.8.5", "deepcopy": "2.1.0", - "express": "4.17.2", - "follow-redirects": "1.14.8", - "graphql": "15.7.1", + "express": "4.18.1", + "follow-redirects": "1.15.0", + "graphql": "16.5.0", "graphql-list-fields": "2.0.2", - "graphql-relay": "0.7.0", "graphql-tag": "2.12.6", - "graphql-upload": "11.0.0", + "graphql-relay": "0.10.0", "intersect": "1.0.1", "jsonwebtoken": "8.5.1", - "jwks-rsa": "2.0.5", - "ldapjs": "2.3.1", + "jwks-rsa": "2.1.3", + "ldapjs": "2.3.2", "lodash": "4.17.21", - "lru-cache": "6.0.0", + "lru-cache": "7.10.1", "mime": "3.0.0", - "mongodb": "4.3.1", + "mongodb": "4.6.0", "mustache": "4.2.0", - "parse": "3.4.1", + "parse": "3.4.2", "pg-monitor": "1.4.1", "pg-promise": "10.11.1", "pluralize": "8.0.0", "redis": "3.1.2", - "semver": "7.3.5", + "semver": "7.3.7", "subscriptions-transport-ws": "0.11.0", "tv4": "1.3.0", "uuid": "8.3.2", - "winston": "3.5.1", - "winston-daily-rotate-file": "4.6.0", - "ws": "8.2.3" + "winston": "3.7.2", + "winston-daily-rotate-file": "4.6.1", + "ws": "8.6.0" }, "devDependencies": { + "graphql-tag": "2.12.6", "@actions/core": "1.2.6", + "@apollo/client": "3.6.1", "@babel/cli": "7.10.0", "@babel/core": "7.10.0", "@babel/plugin-proposal-object-rest-spread": "7.10.0", @@ -98,7 +97,7 @@ "mock-mail-adapter": "file:spec/dependencies/mock-mail-adapter", "mongodb-runner": "4.8.1", "mongodb-version-list": "1.0.0", - "node-fetch": "3.1.1", + "node-fetch": "3.2.4", "nyc": "15.1.0", "prettier": "2.0.5", "semantic-release": "17.4.6", @@ -116,16 +115,18 @@ "test:mongodb:runnerstart": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=$npm_config_dbversion} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} mongodb-runner start", "test:mongodb:testonly": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=$npm_config_dbversion} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} TESTING=1 jasmine", "test:mongodb": "npm run test:mongodb:runnerstart --dbversion=$npm_config_dbversion && npm run test:mongodb:testonly --dbversion=$npm_config_dbversion", - "test:mongodb:4.0.27": "npm run test:mongodb --dbversion=4.0.27", - "test:mongodb:4.2.17": "npm run test:mongodb --dbversion=4.2.17", - "test:mongodb:4.4.10": "npm run test:mongodb --dbversion=4.4.10", - "test:mongodb:5.0.5": "npm run test:mongodb --dbversion=5.0.5", + "test:mongodb:4.0.28": "npm run test:mongodb --dbversion=4.0.28", + "test:mongodb:4.2.19": "npm run test:mongodb --dbversion=4.2.19", + "test:mongodb:4.4.13": "npm run test:mongodb --dbversion=4.4.13", + "test:mongodb:5.0.6": "npm run test:mongodb --dbversion=5.0.6", + "test:mongodb:5.1.1": "npm run test:mongodb --dbversion=5.1.1", + "test:mongodb:5.2.1": "npm run test:mongodb --dbversion=5.2.1", "posttest:mongodb": "mongodb-runner stop", - "pretest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.0.5} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} mongodb-runner start", - "testonly": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.0.5} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} TESTING=1 jasmine", + "pretest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.2.1} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} mongodb-runner start", + "testonly": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.2.1} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} TESTING=1 jasmine", "test": "npm run testonly", - "posttest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.0.5} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} mongodb-runner stop", - "coverage": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.0.5} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} TESTING=1 nyc jasmine", + "posttest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.2.1} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} mongodb-runner stop", + "coverage": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.2.1} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} TESTING=1 nyc jasmine", "start": "node ./bin/parse-server", "prettier": "prettier --write {src,spec}/{**/*,*}.js", "prepare": "npm run build", @@ -133,7 +134,7 @@ "madge:circular": "node_modules/.bin/madge ./src --circular" }, "engines": { - "node": ">=12.22.10 <17" + "node": ">=12.22.10 <19" }, "bin": { "parse-server": "bin/parse-server" diff --git a/release.config.js b/release.config.js index c31eb3ecb8..2307429e77 100644 --- a/release.config.js +++ b/release.config.js @@ -88,6 +88,7 @@ async function config() { labels: ['type:ci'], releasedLabels: ['state:released<%= nextRelease.channel ? `-\${nextRelease.channel}` : "" %>'] }], + // Back-merge module runs last because if it fails it should not impede the release process [ "@saithodev/semantic-release-backmerge", { diff --git a/resources/buildConfigDefinitions.js b/resources/buildConfigDefinitions.js index 670aafad38..b41c53f07c 100644 --- a/resources/buildConfigDefinitions.js +++ b/resources/buildConfigDefinitions.js @@ -23,23 +23,25 @@ const nestedOptionTypes = [ 'PagesRoute', 'PasswordPolicyOptions', 'SecurityOptions', + 'SchemaOptions', ]; /** The prefix of environment variables for nested options. */ const nestedOptionEnvPrefix = { - 'AccountLockoutOptions' : 'PARSE_SERVER_ACCOUNT_LOCKOUT_', - 'CustomPagesOptions' : 'PARSE_SERVER_CUSTOM_PAGES_', + 'AccountLockoutOptions': 'PARSE_SERVER_ACCOUNT_LOCKOUT_', + 'CustomPagesOptions': 'PARSE_SERVER_CUSTOM_PAGES_', 'DatabaseOptions': 'PARSE_SERVER_DATABASE_', - 'FileUploadOptions' : 'PARSE_SERVER_FILE_UPLOAD_', - 'IdempotencyOptions' : 'PARSE_SERVER_EXPERIMENTAL_IDEMPOTENCY_', - 'LiveQueryOptions' : 'PARSE_SERVER_LIVEQUERY_', - 'LiveQueryServerOptions' : 'PARSE_LIVE_QUERY_SERVER_', - 'PagesCustomUrlsOptions' : 'PARSE_SERVER_PAGES_CUSTOM_URL_', - 'PagesOptions' : 'PARSE_SERVER_PAGES_', + 'FileUploadOptions': 'PARSE_SERVER_FILE_UPLOAD_', + 'IdempotencyOptions': 'PARSE_SERVER_EXPERIMENTAL_IDEMPOTENCY_', + 'LiveQueryOptions': 'PARSE_SERVER_LIVEQUERY_', + 'LiveQueryServerOptions': 'PARSE_LIVE_QUERY_SERVER_', + 'PagesCustomUrlsOptions': 'PARSE_SERVER_PAGES_CUSTOM_URL_', + 'PagesOptions': 'PARSE_SERVER_PAGES_', 'PagesRoute': 'PARSE_SERVER_PAGES_ROUTE_', - 'ParseServerOptions' : 'PARSE_SERVER_', - 'PasswordPolicyOptions' : 'PARSE_SERVER_PASSWORD_POLICY_', + 'ParseServerOptions': 'PARSE_SERVER_', + 'PasswordPolicyOptions': 'PARSE_SERVER_PASSWORD_POLICY_', 'SecurityOptions': 'PARSE_SERVER_SECURITY_', + 'SchemaOptions': 'PARSE_SERVER_SCHEMA_', }; function last(array) { @@ -50,7 +52,7 @@ const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' function toENV(key) { let str = ''; let previousIsUpper = false; - for(let i = 0; i < key.length; i++) { + for (let i = 0; i < key.length; i++) { const char = key[i]; if (letters.indexOf(char) >= 0) { if (!previousIsUpper) { @@ -273,8 +275,8 @@ function inject(t, list) { return { results, comments }; } -const makeRequire = function(variableName, module, t) { - const decl = t.variableDeclarator(t.identifier(variableName), t.callExpression(t.identifier('require'), [t.stringLiteral(module)])); +const makeRequire = function (variableName, module, t) { + const decl = t.variableDeclarator(t.identifier(variableName), t.callExpression(t.identifier('require'), [t.stringLiteral(module)])); return t.variableDeclaration('var', [decl]) } let docs = ``; @@ -283,14 +285,14 @@ const plugin = function (babel) { const moduleExports = t.memberExpression(t.identifier('module'), t.identifier('exports')); return { visitor: { - ImportDeclaration: function(path) { + ImportDeclaration: function (path) { path.remove(); }, - Program: function(path) { + Program: function (path) { // Inject the parser's loader path.unshiftContainer('body', makeRequire('parsers', './parsers', t)); }, - ExportDeclaration: function(path) { + ExportDeclaration: function (path) { // Export declaration on an interface if (path.node && path.node.declaration && path.node.declaration.type == 'InterfaceDeclaration') { const { results, comments } = inject(t, doInterface(path.node.declaration)); @@ -313,6 +315,6 @@ Do not edit manually, but update Options/index.js ` const babel = require("@babel/core"); -const res = babel.transformFileSync('./src/Options/index.js', { plugins: [ plugin, '@babel/transform-flow-strip-types' ], babelrc: false, auxiliaryCommentBefore, sourceMaps: false }); +const res = babel.transformFileSync('./src/Options/index.js', { plugins: [plugin, '@babel/transform-flow-strip-types'], babelrc: false, auxiliaryCommentBefore, sourceMaps: false }); require('fs').writeFileSync('./src/Options/Definitions.js', res.code + '\n'); require('fs').writeFileSync('./src/Options/docs.js', docs); diff --git a/spec/.eslintrc.json b/spec/.eslintrc.json index 519da96484..aa4a8fcdcb 100644 --- a/spec/.eslintrc.json +++ b/spec/.eslintrc.json @@ -18,10 +18,13 @@ "it_only_db": true, "it_only_mongodb_version": true, "it_only_postgres_version": true, + "it_only_node_version": true, "fit_only_mongodb_version": true, + "fit_only_node_version": true, "it_exclude_mongodb_version": true, "it_exclude_postgres_version": true, "fit_exclude_mongodb_version": true, + "fit_exclude_node_version": true, "it_exclude_dbs": true, "describe_only_db": true, "describe_only": true, @@ -31,7 +34,6 @@ "jequal": true, "create": true, "arrayContains": true, - "expectAsync": true, "databaseAdapter": true }, "rules": { diff --git a/spec/AuthenticationAdapters.spec.js b/spec/AuthenticationAdapters.spec.js index e96cb02158..a85feb2013 100644 --- a/spec/AuthenticationAdapters.spec.js +++ b/spec/AuthenticationAdapters.spec.js @@ -500,6 +500,34 @@ describe('AuthenticationProviders', function () { expect(appIds).toEqual(['a', 'b']); expect(providerOptions).toEqual(options.custom); }); + + it('can disable provider', async () => { + await reconfigureServer({ + auth: { + myoauth: { + enabled: false, + module: path.resolve(__dirname, 'support/myoauth'), // relative path as it's run from src + }, + }, + }); + const provider = getMockMyOauthProvider(); + Parse.User._registerAuthenticationProvider(provider); + await expectAsync(Parse.User._logInWith('myoauth')).toBeRejectedWith( + new Parse.Error(Parse.Error.UNSUPPORTED_SERVICE, 'This authentication method is unsupported.') + ); + }); + + it('can depreciate', async () => { + const Deprecator = require('../lib/Deprecator/Deprecator'); + const spy = spyOn(Deprecator, 'logRuntimeDeprecation').and.callFake(() => {}); + const provider = getMockMyOauthProvider(); + Parse.User._registerAuthenticationProvider(provider); + await Parse.User._logInWith('myoauth'); + expect(spy).toHaveBeenCalledWith({ + usage: 'auth.myoauth', + solution: 'auth.myoauth.enabled: true', + }); + }); }); describe('instagram auth adapter', () => { @@ -1677,6 +1705,7 @@ describe('Apple Game Center Auth adapter', () => { const gcenter = require('../lib/Adapters/Auth/gcenter'); const fs = require('fs'); const testCert = fs.readFileSync(__dirname + '/support/cert/game_center.pem'); + it('can load adapter', async () => { const options = { gcenter: { @@ -1694,6 +1723,7 @@ describe('Apple Game Center Auth adapter', () => { providerOptions ); }); + it('validateAuthData should validate', async () => { const options = { gcenter: { diff --git a/spec/CloudCode.Validator.spec.js b/spec/CloudCode.Validator.spec.js index b5d5134533..196568f763 100644 --- a/spec/CloudCode.Validator.spec.js +++ b/spec/CloudCode.Validator.spec.js @@ -737,7 +737,8 @@ describe('cloud validator', () => { }); it('basic beforeSaveFile skipWithMasterKey', async done => { - Parse.Cloud.beforeSaveFile( + Parse.Cloud.beforeSave( + Parse.File, () => { throw 'beforeSaveFile should have resolved using master key.'; }, @@ -1431,7 +1432,7 @@ describe('cloud validator', () => { }); it('validate beforeSaveFile', async done => { - Parse.Cloud.beforeSaveFile(() => {}, validatorSuccess); + Parse.Cloud.beforeSave(Parse.File, () => {}, validatorSuccess); const file = new Parse.File('popeye.txt', [1, 2, 3], 'text/plain'); const result = await file.save({ useMasterKey: true }); @@ -1440,7 +1441,7 @@ describe('cloud validator', () => { }); it('validate beforeSaveFile fail', async done => { - Parse.Cloud.beforeSaveFile(() => {}, validatorFail); + Parse.Cloud.beforeSave(Parse.File, () => {}, validatorFail); try { const file = new Parse.File('popeye.txt', [1, 2, 3], 'text/plain'); await file.save({ useMasterKey: true }); @@ -1452,7 +1453,7 @@ describe('cloud validator', () => { }); it('validate afterSaveFile', async done => { - Parse.Cloud.afterSaveFile(() => {}, validatorSuccess); + Parse.Cloud.afterSave(Parse.File, () => {}, validatorSuccess); const file = new Parse.File('popeye.txt', [1, 2, 3], 'text/plain'); const result = await file.save({ useMasterKey: true }); @@ -1461,7 +1462,7 @@ describe('cloud validator', () => { }); it('validate afterSaveFile fail', async done => { - Parse.Cloud.beforeSaveFile(() => {}, validatorFail); + Parse.Cloud.beforeSave(Parse.File, () => {}, validatorFail); try { const file = new Parse.File('popeye.txt', [1, 2, 3], 'text/plain'); await file.save({ useMasterKey: true }); @@ -1473,7 +1474,7 @@ describe('cloud validator', () => { }); it('validate beforeDeleteFile', async done => { - Parse.Cloud.beforeDeleteFile(() => {}, validatorSuccess); + Parse.Cloud.beforeDelete(Parse.File, () => {}, validatorSuccess); const file = new Parse.File('popeye.txt', [1, 2, 3], 'text/plain'); await file.save(); @@ -1482,7 +1483,7 @@ describe('cloud validator', () => { }); it('validate beforeDeleteFile fail', async done => { - Parse.Cloud.beforeDeleteFile(() => {}, validatorFail); + Parse.Cloud.beforeDelete(Parse.File, () => {}, validatorFail); try { const file = new Parse.File('popeye.txt', [1, 2, 3], 'text/plain'); await file.save(); @@ -1495,7 +1496,7 @@ describe('cloud validator', () => { }); it('validate afterDeleteFile', async done => { - Parse.Cloud.afterDeleteFile(() => {}, validatorSuccess); + Parse.Cloud.afterDelete(Parse.File, () => {}, validatorSuccess); const file = new Parse.File('popeye.txt', [1, 2, 3], 'text/plain'); await file.save(); @@ -1504,7 +1505,7 @@ describe('cloud validator', () => { }); it('validate afterDeleteFile fail', async done => { - Parse.Cloud.afterDeleteFile(() => {}, validatorFail); + Parse.Cloud.afterDelete(Parse.File, () => {}, validatorFail); try { const file = new Parse.File('popeye.txt', [1, 2, 3], 'text/plain'); await file.save(); diff --git a/spec/CloudCode.spec.js b/spec/CloudCode.spec.js index 4b8df9f9c9..bf1a2c8c42 100644 --- a/spec/CloudCode.spec.js +++ b/spec/CloudCode.spec.js @@ -1494,6 +1494,136 @@ describe('Cloud Code', () => { }); }); + it('before save can revert fields', async () => { + Parse.Cloud.beforeSave('TestObject', ({ object }) => { + object.revert('foo'); + return object; + }); + + Parse.Cloud.afterSave('TestObject', ({ object }) => { + expect(object.get('foo')).toBeUndefined(); + return object; + }); + + const obj = new TestObject(); + obj.set('foo', 'bar'); + await obj.save(); + + expect(obj.get('foo')).toBeUndefined(); + await obj.fetch(); + + expect(obj.get('foo')).toBeUndefined(); + }); + + it('before save can revert fields with existing object', async () => { + Parse.Cloud.beforeSave( + 'TestObject', + ({ object }) => { + object.revert('foo'); + return object; + }, + { + skipWithMasterKey: true, + } + ); + + Parse.Cloud.afterSave( + 'TestObject', + ({ object }) => { + expect(object.get('foo')).toBe('bar'); + return object; + }, + { + skipWithMasterKey: true, + } + ); + + const obj = new TestObject(); + obj.set('foo', 'bar'); + await obj.save(null, { useMasterKey: true }); + + expect(obj.get('foo')).toBe('bar'); + obj.set('foo', 'yolo'); + await obj.save(); + expect(obj.get('foo')).toBe('bar'); + }); + + it('can unset in afterSave', async () => { + Parse.Cloud.beforeSave('TestObject', ({ object }) => { + if (!object.existed()) { + object.set('secret', true); + return object; + } + object.revert('secret'); + }); + + Parse.Cloud.afterSave('TestObject', ({ object }) => { + object.unset('secret'); + }); + + Parse.Cloud.beforeFind( + 'TestObject', + ({ query }) => { + query.exclude('secret'); + }, + { + skipWithMasterKey: true, + } + ); + + const obj = new TestObject(); + await obj.save(); + expect(obj.get('secret')).toBeUndefined(); + await obj.fetch(); + expect(obj.get('secret')).toBeUndefined(); + await obj.fetch({ useMasterKey: true }); + expect(obj.get('secret')).toBe(true); + }); + + it('should revert in beforeSave', async () => { + Parse.Cloud.beforeSave('MyObject', ({ object }) => { + if (!object.existed()) { + object.set('count', 0); + return object; + } + object.revert('count'); + return object; + }); + const obj = await new Parse.Object('MyObject').save(); + expect(obj.get('count')).toBe(0); + obj.set('count', 10); + await obj.save(); + expect(obj.get('count')).toBe(0); + await obj.fetch(); + expect(obj.get('count')).toBe(0); + }); + + it('pointer should not be cleared by triggers', async () => { + Parse.Cloud.afterSave('MyObject', () => {}); + const foo = await new Parse.Object('Test', { foo: 'bar' }).save(); + const obj = await new Parse.Object('MyObject', { foo }).save(); + const foo2 = obj.get('foo'); + expect(foo2.get('foo')).toBe('bar'); + }); + + it('can set a pointer in triggers', async () => { + Parse.Cloud.beforeSave('MyObject', () => {}); + Parse.Cloud.afterSave( + 'MyObject', + async ({ object }) => { + const foo = await new Parse.Object('Test', { foo: 'bar' }).save(); + object.set({ foo }); + await object.save(null, { useMasterKey: true }); + }, + { + skipWithMasterKey: true, + } + ); + const obj = await new Parse.Object('MyObject').save(); + const foo2 = obj.get('foo'); + expect(foo2.get('foo')).toBe('bar'); + }); + it('beforeSave should not sanitize database', async done => { const { adapter } = Config.get(Parse.applicationId).database; const spy = spyOn(adapter, 'findOneAndUpdate').and.callThrough(); @@ -1860,6 +1990,36 @@ describe('afterSave hooks', () => { const myObject = new MyObject(); myObject.save().then(() => done()); }); + + it('should unset in afterSave', async () => { + Parse.Cloud.afterSave( + 'MyObject', + ({ object }) => { + object.unset('secret'); + }, + { + skipWithMasterKey: true, + } + ); + const obj = new Parse.Object('MyObject'); + obj.set('secret', 'bar'); + await obj.save(); + expect(obj.get('secret')).toBeUndefined(); + await obj.fetch(); + expect(obj.get('secret')).toBe('bar'); + }); + + it('should unset', async () => { + Parse.Cloud.beforeSave('MyObject', ({ object }) => { + object.set('secret', 'hidden'); + }); + + Parse.Cloud.afterSave('MyObject', ({ object }) => { + object.unset('secret'); + }); + const obj = await new Parse.Object('MyObject').save(); + expect(obj.get('secret')).toBeUndefined(); + }); }); describe('beforeDelete hooks', () => { @@ -3245,7 +3405,7 @@ describe('saveFile hooks', () => { it('beforeSaveFile should return file that is already saved and not save anything to files adapter', async () => { await reconfigureServer({ filesAdapter: mockAdapter }); const createFileSpy = spyOn(mockAdapter, 'createFile').and.callThrough(); - Parse.Cloud.beforeSaveFile(() => { + Parse.Cloud.beforeSave(Parse.File, () => { const newFile = new Parse.File('some-file.txt'); newFile._url = 'http://www.somewhere.com/parse/files/some-app-id/some-file.txt'; return newFile; @@ -3260,7 +3420,7 @@ describe('saveFile hooks', () => { it('beforeSaveFile should throw error', async () => { await reconfigureServer({ filesAdapter: mockAdapter }); - Parse.Cloud.beforeSaveFile(() => { + Parse.Cloud.beforeSave(Parse.File, () => { throw new Parse.Error(400, 'some-error-message'); }); const file = new Parse.File('popeye.txt', [1, 2, 3], 'text/plain'); @@ -3274,8 +3434,8 @@ describe('saveFile hooks', () => { it('beforeSaveFile should change values of uploaded file by editing fileObject directly', async () => { await reconfigureServer({ filesAdapter: mockAdapter }); const createFileSpy = spyOn(mockAdapter, 'createFile').and.callThrough(); - Parse.Cloud.beforeSaveFile(async req => { - expect(req.triggerName).toEqual('beforeSaveFile'); + Parse.Cloud.beforeSave(Parse.File, async req => { + expect(req.triggerName).toEqual('beforeSave'); expect(req.master).toBe(true); req.file.addMetadata('foo', 'bar'); req.file.addTag('tagA', 'some-tag'); @@ -3303,8 +3463,8 @@ describe('saveFile hooks', () => { it('beforeSaveFile should change values by returning new fileObject', async () => { await reconfigureServer({ filesAdapter: mockAdapter }); const createFileSpy = spyOn(mockAdapter, 'createFile').and.callThrough(); - Parse.Cloud.beforeSaveFile(async req => { - expect(req.triggerName).toEqual('beforeSaveFile'); + Parse.Cloud.beforeSave(Parse.File, async req => { + expect(req.triggerName).toEqual('beforeSave'); expect(req.fileSize).toBe(3); const newFile = new Parse.File('donald_duck.pdf', [4, 5, 6], 'application/pdf'); newFile.setMetadata({ foo: 'bar' }); @@ -3337,8 +3497,8 @@ describe('saveFile hooks', () => { it('beforeSaveFile should contain metadata and tags saved from client', async () => { await reconfigureServer({ filesAdapter: mockAdapter }); const createFileSpy = spyOn(mockAdapter, 'createFile').and.callThrough(); - Parse.Cloud.beforeSaveFile(async req => { - expect(req.triggerName).toEqual('beforeSaveFile'); + Parse.Cloud.beforeSave(Parse.File, async req => { + expect(req.triggerName).toEqual('beforeSave'); expect(req.fileSize).toBe(3); expect(req.file).toBeInstanceOf(Parse.File); expect(req.file.name()).toBe('popeye.txt'); @@ -3366,7 +3526,7 @@ describe('saveFile hooks', () => { await reconfigureServer({ filesAdapter: mockAdapter }); const config = Config.get('test'); config.filesController.options.preserveFileName = true; - Parse.Cloud.beforeSaveFile(async ({ file }) => { + Parse.Cloud.beforeSave(Parse.File, async ({ file }) => { expect(file.name()).toBe('popeye.txt'); const fileData = await file.getData(); const newFile = new Parse.File('2020-04-01.txt', { base64: fileData }); @@ -3380,13 +3540,13 @@ describe('saveFile hooks', () => { it('afterSaveFile should set fileSize to null if beforeSave returns an already saved file', async () => { await reconfigureServer({ filesAdapter: mockAdapter }); const createFileSpy = spyOn(mockAdapter, 'createFile').and.callThrough(); - Parse.Cloud.beforeSaveFile(req => { + Parse.Cloud.beforeSave(Parse.File, req => { expect(req.fileSize).toBe(3); const newFile = new Parse.File('some-file.txt'); newFile._url = 'http://www.somewhere.com/parse/files/some-app-id/some-file.txt'; return newFile; }); - Parse.Cloud.afterSaveFile(req => { + Parse.Cloud.afterSave(Parse.File, req => { expect(req.fileSize).toBe(null); }); const file = new Parse.File('popeye.txt', [1, 2, 3], 'text/plain'); @@ -3399,7 +3559,7 @@ describe('saveFile hooks', () => { it('afterSaveFile should throw error', async () => { await reconfigureServer({ filesAdapter: mockAdapter }); - Parse.Cloud.afterSaveFile(async () => { + Parse.Cloud.afterSave(Parse.File, async () => { throw new Parse.Error(400, 'some-error-message'); }); const filename = 'donald_duck.pdf'; @@ -3413,11 +3573,11 @@ describe('saveFile hooks', () => { it('afterSaveFile should call with fileObject', async done => { await reconfigureServer({ filesAdapter: mockAdapter }); - Parse.Cloud.beforeSaveFile(async req => { + Parse.Cloud.beforeSave(Parse.File, async req => { req.file.setTags({ tagA: 'some-tag' }); req.file.setMetadata({ foo: 'bar' }); }); - Parse.Cloud.afterSaveFile(async req => { + Parse.Cloud.afterSave(Parse.File, async req => { expect(req.master).toBe(true); expect(req.file._tags).toEqual({ tagA: 'some-tag' }); expect(req.file._metadata).toEqual({ foo: 'bar' }); @@ -3429,13 +3589,13 @@ describe('saveFile hooks', () => { it('afterSaveFile should change fileSize when file data changes', async done => { await reconfigureServer({ filesAdapter: mockAdapter }); - Parse.Cloud.beforeSaveFile(async req => { + Parse.Cloud.beforeSave(Parse.File, async req => { expect(req.fileSize).toBe(3); expect(req.master).toBe(true); const newFile = new Parse.File('donald_duck.pdf', [4, 5, 6, 7, 8, 9], 'application/pdf'); return newFile; }); - Parse.Cloud.afterSaveFile(async req => { + Parse.Cloud.afterSave(Parse.File, async req => { expect(req.fileSize).toBe(6); expect(req.master).toBe(true); done(); @@ -3446,7 +3606,7 @@ describe('saveFile hooks', () => { it('beforeDeleteFile should call with fileObject', async () => { await reconfigureServer({ filesAdapter: mockAdapter }); - Parse.Cloud.beforeDeleteFile(req => { + Parse.Cloud.beforeDelete(Parse.File, req => { expect(req.file).toBeInstanceOf(Parse.File); expect(req.file._name).toEqual('popeye.txt'); expect(req.file._url).toEqual('http://www.somewhere.com/popeye.txt'); @@ -3458,7 +3618,7 @@ describe('saveFile hooks', () => { it('beforeDeleteFile should throw error', async done => { await reconfigureServer({ filesAdapter: mockAdapter }); - Parse.Cloud.beforeDeleteFile(() => { + Parse.Cloud.beforeDelete(Parse.File, () => { throw new Error('some error message'); }); const file = new Parse.File('popeye.txt'); @@ -3472,12 +3632,12 @@ describe('saveFile hooks', () => { it('afterDeleteFile should call with fileObject', async done => { await reconfigureServer({ filesAdapter: mockAdapter }); - Parse.Cloud.beforeDeleteFile(req => { + Parse.Cloud.beforeDelete(Parse.File, req => { expect(req.file).toBeInstanceOf(Parse.File); expect(req.file._name).toEqual('popeye.txt'); expect(req.file._url).toEqual('http://www.somewhere.com/popeye.txt'); }); - Parse.Cloud.afterDeleteFile(req => { + Parse.Cloud.afterDelete(Parse.File, req => { expect(req.file).toBeInstanceOf(Parse.File); expect(req.file._name).toEqual('popeye.txt'); expect(req.file._url).toEqual('http://www.somewhere.com/popeye.txt'); @@ -3489,7 +3649,7 @@ describe('saveFile hooks', () => { it('beforeSaveFile should not change file if nothing is returned', async () => { await reconfigureServer({ filesAdapter: mockAdapter }); - Parse.Cloud.beforeSaveFile(() => { + Parse.Cloud.beforeSave(Parse.File, () => { return; }); const file = new Parse.File('popeye.txt', [1, 2, 3], 'text/plain'); @@ -3498,7 +3658,7 @@ describe('saveFile hooks', () => { }); it('throw custom error from beforeSaveFile', async done => { - Parse.Cloud.beforeSaveFile(() => { + Parse.Cloud.beforeSave(Parse.File, () => { throw new Parse.Error(Parse.Error.SCRIPT_FAILED, 'It should fail'); }); try { @@ -3512,7 +3672,7 @@ describe('saveFile hooks', () => { }); it('throw empty error from beforeSaveFile', async done => { - Parse.Cloud.beforeSaveFile(() => { + Parse.Cloud.beforeSave(Parse.File, () => { throw null; }); try { @@ -3524,6 +3684,55 @@ describe('saveFile hooks', () => { done(); } }); + + it('legacy hooks', async () => { + await reconfigureServer({ filesAdapter: mockAdapter }); + const logger = require('../lib/logger').logger; + const logSpy = spyOn(logger, 'warn').and.callFake(() => {}); + const triggers = { + beforeSaveFile(req) { + req.file.setTags({ tagA: 'some-tag' }); + req.file.setMetadata({ foo: 'bar' }); + expect(req.triggerName).toEqual('beforeSave'); + expect(req.master).toBe(true); + }, + afterSaveFile(req) { + expect(req.master).toBe(true); + expect(req.file._tags).toEqual({ tagA: 'some-tag' }); + expect(req.file._metadata).toEqual({ foo: 'bar' }); + }, + beforeDeleteFile(req) { + expect(req.file).toBeInstanceOf(Parse.File); + expect(req.file._name).toEqual('popeye.txt'); + expect(req.file._url).toEqual('http://www.somewhere.com/popeye.txt'); + expect(req.fileSize).toBe(null); + }, + afterDeleteFile(req) { + expect(req.file).toBeInstanceOf(Parse.File); + expect(req.file._name).toEqual('popeye.txt'); + expect(req.file._url).toEqual('http://www.somewhere.com/popeye.txt'); + }, + }; + + for (const key in triggers) { + spyOn(triggers, key).and.callThrough(); + Parse.Cloud[key](triggers[key]); + } + + const file = new Parse.File('popeye.txt', [1, 2, 3], 'text/plain'); + await file.save({ useMasterKey: true }); + await new Parse.File('popeye.txt', [1, 2, 3], 'text/plain').destroy({ useMasterKey: true }); + await new Promise(resolve => setTimeout(resolve, 100)); + for (const key in triggers) { + expect(triggers[key]).toHaveBeenCalled(); + expect(logSpy).toHaveBeenCalledWith( + `DeprecationWarning: Parse.Cloud.${key} is deprecated and will be removed in a future version. Use Parse.Cloud.${key.replace( + 'File', + '' + )}(Parse.File, (request) => {})` + ); + } + }); }); describe('sendEmail', () => { diff --git a/spec/FilesController.spec.js b/spec/FilesController.spec.js index 9ea66da6ea..8fee5aca2f 100644 --- a/spec/FilesController.spec.js +++ b/spec/FilesController.spec.js @@ -43,6 +43,20 @@ describe('FilesController', () => { done(); }); + it_only_db('mongo')('should pass databaseOptions to GridFSBucketAdapter', async () => { + await reconfigureServer({ + databaseURI: 'mongodb://localhost:27017/parse', + filesAdapter: null, + databaseAdapter: null, + databaseOptions: { + retryWrites: true, + }, + }); + const config = Config.get(Parse.applicationId); + expect(config.database.adapter._mongoOptions.retryWrites).toBeTrue(); + expect(config.filesController.adapter._mongoOptions.retryWrites).toBeTrue(); + }); + it('should create a server log on failure', done => { const logController = new LoggerController(new WinstonLoggerAdapter()); diff --git a/spec/MongoStorageAdapter.spec.js b/spec/MongoStorageAdapter.spec.js index a31a6134f7..130971a535 100644 --- a/spec/MongoStorageAdapter.spec.js +++ b/spec/MongoStorageAdapter.spec.js @@ -308,7 +308,7 @@ describe_only_db('mongo')('MongoStorageAdapter', () => { await expectAsync(adapter.getClass('UnknownClass')).toBeRejectedWith(undefined); }); - it('should use index for caseInsensitive query', async () => { + it_only_mongodb_version('<5.1')('should use index for caseInsensitive query', async () => { const user = new Parse.User(); user.set('username', 'Bugs'); user.set('password', 'Bunny'); @@ -342,6 +342,40 @@ describe_only_db('mongo')('MongoStorageAdapter', () => { expect(postIndexPlan.executionStats.executionStages.stage).toBe('FETCH'); }); + it_only_mongodb_version('>=5.1')('should use index for caseInsensitive query', async () => { + const user = new Parse.User(); + user.set('username', 'Bugs'); + user.set('password', 'Bunny'); + await user.signUp(); + + const database = Config.get(Parse.applicationId).database; + await database.adapter.dropAllIndexes('_User'); + + const preIndexPlan = await database.find( + '_User', + { username: 'bugs' }, + { caseInsensitive: true, explain: true } + ); + + const schema = await new Parse.Schema('_User').get(); + + await database.adapter.ensureIndex( + '_User', + schema, + ['username'], + 'case_insensitive_username', + true + ); + + const postIndexPlan = await database.find( + '_User', + { username: 'bugs' }, + { caseInsensitive: true, explain: true } + ); + expect(preIndexPlan.queryPlanner.winningPlan.queryPlan.stage).toBe('COLLSCAN'); + expect(postIndexPlan.queryPlanner.winningPlan.queryPlan.stage).toBe('FETCH'); + }); + it('should delete field without index', async () => { const database = Config.get(Parse.applicationId).database; const obj = new Parse.Object('MyObject'); diff --git a/spec/ParseGraphQLSchema.spec.js b/spec/ParseGraphQLSchema.spec.js index a06a230f6a..0d4cd7d721 100644 --- a/spec/ParseGraphQLSchema.spec.js +++ b/spec/ParseGraphQLSchema.spec.js @@ -57,7 +57,6 @@ describe('ParseGraphQLSchema', () => { it('should load a brand new GraphQL Schema if Parse Schema changes', async () => { await parseGraphQLSchema.load(); const parseClasses = parseGraphQLSchema.parseClasses; - const parseCachedClasses = parseGraphQLSchema.parseCachedClasses; const parseClassTypes = parseGraphQLSchema.parseClassTypes; const graphQLSchema = parseGraphQLSchema.graphQLSchema; const graphQLTypes = parseGraphQLSchema.graphQLTypes; @@ -70,7 +69,6 @@ describe('ParseGraphQLSchema', () => { await new Promise(resolve => setTimeout(resolve, 200)); await parseGraphQLSchema.load(); expect(parseClasses).not.toBe(parseGraphQLSchema.parseClasses); - expect(parseCachedClasses).not.toBe(parseGraphQLSchema.parseCachedClasses); expect(parseClassTypes).not.toBe(parseGraphQLSchema.parseClassTypes); expect(graphQLSchema).not.toBe(parseGraphQLSchema.graphQLSchema); expect(graphQLTypes).not.toBe(parseGraphQLSchema.graphQLTypes); @@ -94,7 +92,6 @@ describe('ParseGraphQLSchema', () => { }); await parseGraphQLSchema.load(); const parseClasses = parseGraphQLSchema.parseClasses; - const parseCachedClasses = parseGraphQLSchema.parseCachedClasses; const parseClassTypes = parseGraphQLSchema.parseClassTypes; const graphQLSchema = parseGraphQLSchema.graphQLSchema; const graphQLTypes = parseGraphQLSchema.graphQLTypes; @@ -109,7 +106,6 @@ describe('ParseGraphQLSchema', () => { await new Promise(resolve => setTimeout(resolve, 200)); await parseGraphQLSchema.load(); expect(parseClasses).not.toBe(parseGraphQLSchema.parseClasses); - expect(parseCachedClasses).not.toBe(parseGraphQLSchema.parseCachedClasses); expect(parseClassTypes).not.toBe(parseGraphQLSchema.parseClassTypes); expect(graphQLSchema).not.toBe(parseGraphQLSchema.graphQLSchema); expect(graphQLTypes).not.toBe(parseGraphQLSchema.graphQLTypes); diff --git a/spec/ParseGraphQLServer.spec.js b/spec/ParseGraphQLServer.spec.js index 32a526132a..adf004932b 100644 --- a/spec/ParseGraphQLServer.spec.js +++ b/spec/ParseGraphQLServer.spec.js @@ -12,6 +12,7 @@ const { getMainDefinition } = require('apollo-utilities'); const { createUploadLink } = require('apollo-upload-client'); const { SubscriptionClient } = require('subscriptions-transport-ws'); const { WebSocketLink } = require('@apollo/client/link/ws'); +const { mergeSchemas } = require('@graphql-tools/schema'); const { ApolloClient, InMemoryCache, @@ -98,6 +99,24 @@ describe('ParseGraphQLServer', () => { }); }); + describe('_getServer', () => { + it('should only return new server on schema changes', async () => { + parseGraphQLServer.server = undefined; + const server1 = await parseGraphQLServer._getServer(); + const server2 = await parseGraphQLServer._getServer(); + expect(server1).toBe(server2); + + // Trigger a schema change + const obj = new Parse.Object('SomeClass'); + await obj.save(); + + const server3 = await parseGraphQLServer._getServer(); + const server4 = await parseGraphQLServer._getServer(); + expect(server3).not.toBe(server2); + expect(server3).toBe(server4); + }); + }); + describe('_getGraphQLOptions', () => { const req = { info: new Object(), @@ -106,11 +125,15 @@ describe('ParseGraphQLServer', () => { }; it("should return schema and context with req's info, config and auth", async () => { - const options = await parseGraphQLServer._getGraphQLOptions(req); + const options = await parseGraphQLServer._getGraphQLOptions(); + expect(options.multipart).toEqual({ + fileSize: 20971520, + }); expect(options.schema).toEqual(parseGraphQLServer.parseGraphQLSchema.graphQLSchema); - expect(options.context.info).toEqual(req.info); - expect(options.context.config).toEqual(req.config); - expect(options.context.auth).toEqual(req.auth); + const contextResponse = options.context({ req }); + expect(contextResponse.info).toEqual(req.info); + expect(contextResponse.config).toEqual(req.config); + expect(contextResponse.auth).toEqual(req.auth); }); it('should load GraphQL schema in every call', async () => { @@ -467,7 +490,7 @@ describe('ParseGraphQLServer', () => { } }); - it('should be cors enabled', async () => { + it('should be cors enabled and scope the response within the source origin', async () => { let checked = false; const apolloClient = new ApolloClient({ link: new ApolloLink((operation, forward) => { @@ -476,7 +499,7 @@ describe('ParseGraphQLServer', () => { const { response: { headers }, } = context; - expect(headers.get('access-control-allow-origin')).toEqual('*'); + expect(headers.get('access-control-allow-origin')).toEqual('http://example.com'); checked = true; return response; }); @@ -486,7 +509,7 @@ describe('ParseGraphQLServer', () => { fetch, headers: { ...headers, - Origin: 'http://someorigin.com', + Origin: 'http://example.com', }, }) ), @@ -504,14 +527,25 @@ describe('ParseGraphQLServer', () => { }); it('should handle Parse headers', async () => { - let checked = false; + const test = { + context: ({ req: { info, config, auth } }) => { + expect(req.info).toBeDefined(); + expect(req.config).toBeDefined(); + expect(req.auth).toBeDefined(); + return { + info, + config, + auth, + }; + }, + }; + const contextSpy = spyOn(test, 'context'); const originalGetGraphQLOptions = parseGraphQLServer._getGraphQLOptions; - parseGraphQLServer._getGraphQLOptions = async req => { - expect(req.info).toBeDefined(); - expect(req.config).toBeDefined(); - expect(req.auth).toBeDefined(); - checked = true; - return await originalGetGraphQLOptions.bind(parseGraphQLServer)(req); + parseGraphQLServer._getGraphQLOptions = async () => { + return { + schema: await parseGraphQLServer.parseGraphQLSchema.load(), + context: test.context, + }; }; const health = ( await apolloClient.query({ @@ -523,7 +557,7 @@ describe('ParseGraphQLServer', () => { }) ).data.health; expect(health).toBeTruthy(); - expect(checked).toBeTruthy(); + expect(contextSpy).toHaveBeenCalledTimes(1); parseGraphQLServer._getGraphQLOptions = originalGetGraphQLOptions; }); }); @@ -6786,14 +6820,14 @@ describe('ParseGraphQLServer', () => { expect(queryResult.data.customers.edges.length).toEqual(1); } catch (e) { - console.log(JSON.stringify(e)); + console.error(JSON.stringify(e)); } }); }); describe('Files Mutations', () => { describe('Create', () => { - it('should return File object', async () => { + it_only_node_version('<17')('should return File object', async () => { const clientMutationId = uuidv4(); parseServer = await global.reconfigureServer({ @@ -9096,7 +9130,7 @@ describe('ParseGraphQLServer', () => { expect(result6[0].node.name).toEqual('imACountry3'); }); - it('should support files', async () => { + it_only_node_version('<17')('should support files', async () => { try { parseServer = await global.reconfigureServer({ publicServerURL: 'http://localhost:13377/parse', @@ -9107,15 +9141,15 @@ describe('ParseGraphQLServer', () => { 'operations', JSON.stringify({ query: ` - mutation CreateFile($input: CreateFileInput!) { - createFile(input: $input) { - fileInfo { - name - url + mutation CreateFile($input: CreateFileInput!) { + createFile(input: $input) { + fileInfo { + name + url + } } } - } - `, + `, variables: { input: { upload: null, @@ -9176,46 +9210,46 @@ describe('ParseGraphQLServer', () => { 'operations', JSON.stringify({ query: ` - mutation CreateSomeObject( - $fields1: CreateSomeClassFieldsInput - $fields2: CreateSomeClassFieldsInput - $fields3: CreateSomeClassFieldsInput - ) { - createSomeClass1: createSomeClass( - input: { fields: $fields1 } + mutation CreateSomeObject( + $fields1: CreateSomeClassFieldsInput + $fields2: CreateSomeClassFieldsInput + $fields3: CreateSomeClassFieldsInput ) { - someClass { - id - someField { - name - url + createSomeClass1: createSomeClass( + input: { fields: $fields1 } + ) { + someClass { + id + someField { + name + url + } } } - } - createSomeClass2: createSomeClass( - input: { fields: $fields2 } - ) { - someClass { - id - someField { - name - url + createSomeClass2: createSomeClass( + input: { fields: $fields2 } + ) { + someClass { + id + someField { + name + url + } } } - } - createSomeClass3: createSomeClass( - input: { fields: $fields3 } - ) { - someClass { - id - someField { - name - url + createSomeClass3: createSomeClass( + input: { fields: $fields3 } + ) { + someClass { + id + someField { + name + url + } } } } - } - `, + `, variables: { fields1: { someField: { file: someFieldValue }, @@ -9344,6 +9378,51 @@ describe('ParseGraphQLServer', () => { } }); + it_only_node_version('<17')('should not upload if file is too large', async () => { + parseGraphQLServer.parseServer.config.maxUploadSize = '1kb'; + + const body = new FormData(); + body.append( + 'operations', + JSON.stringify({ + query: ` + mutation CreateFile($input: CreateFileInput!) { + createFile(input: $input) { + fileInfo { + name + url + } + } + } + `, + variables: { + input: { + upload: null, + }, + }, + }) + ); + body.append('map', JSON.stringify({ 1: ['variables.input.upload'] })); + body.append( + '1', + Buffer.alloc(parseGraphQLServer._transformMaxUploadSizeToBytes('2kb'), 1), + { + filename: 'myFileName.txt', + contentType: 'text/plain', + } + ); + + const res = await fetch('http://localhost:13377/graphql', { + method: 'POST', + headers, + body, + }); + + const result = JSON.parse(await res.text()); + expect(res.status).toEqual(500); + expect(result.errors[0].message).toEqual('File size limit exceeded: 1024 bytes'); + }); + it('should support object values', async () => { try { const someObjectFieldValue = { @@ -10381,7 +10460,7 @@ describe('ParseGraphQLServer', () => { }); describe('Custom API', () => { - describe('GraphQL Schema Based', () => { + describe('SDL based', () => { let httpServer; const headers = { 'X-Parse-Application-Id': 'test', @@ -10504,7 +10583,7 @@ describe('ParseGraphQLServer', () => { }); }); - describe('SDL Based', () => { + describe('GraphQL Schema Based', () => { let httpServer; const headers = { 'X-Parse-Application-Id': 'test', @@ -10567,6 +10646,12 @@ describe('ParseGraphQLServer', () => { }, resolve: (p, { message }) => message, }, + errorQuery: { + type: new GraphQLNonNull(GraphQLString), + resolve: () => { + throw new Error('A test error'); + }, + }, customQueryWithAutoTypeReturn: { type: SomeClassType, args: { @@ -10655,6 +10740,18 @@ describe('ParseGraphQLServer', () => { expect(result.data.customQuery).toEqual('hello'); }); + it('can forward original error of a custom query', async () => { + await expectAsync( + apolloClient.query({ + query: gql` + query ErrorQuery { + errorQuery + } + `, + }) + ).toBeRejectedWithError('A test error'); + }); + it('can resolve a custom query with auto type return', async () => { const obj = new Parse.Object('SomeClass'); await obj.save({ name: 'aname', type: 'robot' }); @@ -10801,8 +10898,7 @@ describe('ParseGraphQLServer', () => { httpServer = http.createServer(expressApp); parseGraphQLServer = new ParseGraphQLServer(parseServer, { graphQLPath: '/graphql', - graphQLCustomTypeDefs: ({ autoSchema, stitchSchemas }) => - stitchSchemas({ subschemas: [autoSchema] }), + graphQLCustomTypeDefs: ({ autoSchema }) => mergeSchemas({ schemas: [autoSchema] }), }); parseGraphQLServer.applyGraphQL(expressApp); diff --git a/spec/ParseLiveQuery.spec.js b/spec/ParseLiveQuery.spec.js index b439b81ef2..7f3794fa62 100644 --- a/spec/ParseLiveQuery.spec.js +++ b/spec/ParseLiveQuery.spec.js @@ -836,6 +836,50 @@ describe('ParseLiveQuery', function () { } }); + it('LiveQuery should work with changing role', async () => { + await reconfigureServer({ + liveQuery: { + classNames: ['Chat'], + }, + startLiveQueryServer: true, + }); + const user = new Parse.User(); + user.setUsername('username'); + user.setPassword('password'); + await user.signUp(); + + const role = new Parse.Role('Test', new Parse.ACL(user)); + await role.save(); + + const chatQuery = new Parse.Query('Chat'); + const subscription = await chatQuery.subscribe(); + subscription.on('create', () => { + fail('should not call create as user is not part of role.'); + }); + + const object = new Parse.Object('Chat'); + const acl = new Parse.ACL(); + acl.setRoleReadAccess(role, true); + object.setACL(acl); + object.set({ foo: 'bar' }); + await object.save(null, { useMasterKey: true }); + role.getUsers().add(user); + await new Promise(resolve => setTimeout(resolve, 1000)); + await role.save(); + await new Promise(resolve => setTimeout(resolve, 1000)); + object.set('foo', 'yolo'); + await Promise.all([ + new Promise(resolve => { + subscription.on('update', obj => { + expect(obj.get('foo')).toBe('yolo'); + expect(obj.getACL().toJSON()).toEqual({ 'role:Test': { read: true } }); + resolve(); + }); + }), + object.save(null, { useMasterKey: true }), + ]); + }); + it('liveQuery on Session class', async done => { await reconfigureServer({ liveQuery: { classNames: [Parse.Session] }, diff --git a/spec/ParseQuery.hint.spec.js b/spec/ParseQuery.hint.spec.js index 2685137801..db45106359 100644 --- a/spec/ParseQuery.hint.spec.js +++ b/spec/ParseQuery.hint.spec.js @@ -27,7 +27,7 @@ describe_only_db('mongo')('Parse.Query hint', () => { await TestUtils.destroyAllDataPermanently(false); }); - it('query find with hint string', async () => { + it_only_mongodb_version('<5.1')('query find with hint string', async () => { const object = new TestObject(); await object.save(); @@ -39,7 +39,18 @@ describe_only_db('mongo')('Parse.Query hint', () => { expect(explain.queryPlanner.winningPlan.inputStage.indexName).toBe('_id_'); }); - it('query find with hint object', async () => { + it_only_mongodb_version('>=5.1')('query find with hint string', async () => { + const object = new TestObject(); + await object.save(); + + const collection = await config.database.adapter._adaptiveCollection('TestObject'); + const explain = await collection._rawFind({ _id: object.id }, { hint: '_id_', explain: true }); + expect(explain.queryPlanner.winningPlan.queryPlan.stage).toBe('FETCH'); + expect(explain.queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('IXSCAN'); + expect(explain.queryPlanner.winningPlan.queryPlan.inputStage.indexName).toBe('_id_'); + }); + + it_only_mongodb_version('<5.1')('query find with hint object', async () => { const object = new TestObject(); await object.save(); @@ -53,6 +64,20 @@ describe_only_db('mongo')('Parse.Query hint', () => { }); }); + it_only_mongodb_version('>=5.1')('query find with hint object', async () => { + const object = new TestObject(); + await object.save(); + + const collection = await config.database.adapter._adaptiveCollection('TestObject'); + const explain = await collection._rawFind( + { _id: object.id }, + { hint: { _id: 1 }, explain: true } + ); + expect(explain.queryPlanner.winningPlan.queryPlan.stage).toBe('FETCH'); + expect(explain.queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('IXSCAN'); + expect(explain.queryPlanner.winningPlan.queryPlan.inputStage.keyPattern).toEqual({ _id: 1 }); + }); + it_only_mongodb_version('<4.4')('query aggregate with hint string', async () => { const object = new TestObject({ foo: 'bar' }); await object.save(); @@ -73,7 +98,7 @@ describe_only_db('mongo')('Parse.Query hint', () => { expect(queryPlanner.winningPlan.inputStage.indexName).toBe('_id_'); }); - it_only_mongodb_version('>=4.4')('query aggregate with hint string', async () => { + it_only_mongodb_version('>=4.4<5.1')('query aggregate with hint string', async () => { const object = new TestObject({ foo: 'bar' }); await object.save(); @@ -97,6 +122,54 @@ describe_only_db('mongo')('Parse.Query hint', () => { expect(queryPlanner.winningPlan.inputStage.inputStage.indexName).toBe('_id_'); }); + it_only_mongodb_version('>=5.1<5.2')('query aggregate with hint string', async () => { + const object = new TestObject({ foo: 'bar' }); + await object.save(); + + const collection = await config.database.adapter._adaptiveCollection('TestObject'); + let result = await collection.aggregate([{ $group: { _id: '$foo' } }], { + explain: true, + }); + let { queryPlanner } = result[0].stages[0].$cursor; + expect(queryPlanner.winningPlan.queryPlan.stage).toBe('PROJECTION_SIMPLE'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('COLLSCAN'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage).toBeUndefined(); + + result = await collection.aggregate([{ $group: { _id: '$foo' } }], { + hint: '_id_', + explain: true, + }); + queryPlanner = result[0].stages[0].$cursor.queryPlanner; + expect(queryPlanner.winningPlan.queryPlan.stage).toBe('PROJECTION_SIMPLE'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('FETCH'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.stage).toBe('IXSCAN'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_'); + }); + + it_only_mongodb_version('>=5.2')('query aggregate with hint string', async () => { + const object = new TestObject({ foo: 'bar' }); + await object.save(); + + const collection = await config.database.adapter._adaptiveCollection('TestObject'); + let result = await collection.aggregate([{ $group: { _id: '$foo' } }], { + explain: true, + }); + let queryPlanner = result[0].queryPlanner; + expect(queryPlanner.winningPlan.queryPlan.stage).toBe('GROUP'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('COLLSCAN'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage).toBeUndefined(); + + result = await collection.aggregate([{ $group: { _id: '$foo' } }], { + hint: '_id_', + explain: true, + }); + queryPlanner = result[0].queryPlanner; + expect(queryPlanner.winningPlan.queryPlan.stage).toBe('GROUP'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('FETCH'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.stage).toBe('IXSCAN'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_'); + }); + it_only_mongodb_version('<4.4')('query aggregate with hint object', async () => { const object = new TestObject({ foo: 'bar' }); await object.save(); @@ -117,7 +190,7 @@ describe_only_db('mongo')('Parse.Query hint', () => { expect(queryPlanner.winningPlan.inputStage.keyPattern).toEqual({ _id: 1 }); }); - it_only_mongodb_version('>=4.4')('query aggregate with hint object', async () => { + it_only_mongodb_version('>=4.4<5.1')('query aggregate with hint object', async () => { const object = new TestObject({ foo: 'bar' }); await object.save(); @@ -142,7 +215,57 @@ describe_only_db('mongo')('Parse.Query hint', () => { expect(queryPlanner.winningPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 }); }); - it('query find with hint (rest)', async () => { + it_only_mongodb_version('>=5.1<5.2')('query aggregate with hint object', async () => { + const object = new TestObject({ foo: 'bar' }); + await object.save(); + + const collection = await config.database.adapter._adaptiveCollection('TestObject'); + let result = await collection.aggregate([{ $group: { _id: '$foo' } }], { + explain: true, + }); + let { queryPlanner } = result[0].stages[0].$cursor; + expect(queryPlanner.winningPlan.queryPlan.stage).toBe('PROJECTION_SIMPLE'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('COLLSCAN'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage).toBeUndefined(); + + result = await collection.aggregate([{ $group: { _id: '$foo' } }], { + hint: { _id: 1 }, + explain: true, + }); + queryPlanner = result[0].stages[0].$cursor.queryPlanner; + expect(queryPlanner.winningPlan.queryPlan.stage).toBe('PROJECTION_SIMPLE'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('FETCH'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.stage).toBe('IXSCAN'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 }); + }); + + it_only_mongodb_version('>=5.2')('query aggregate with hint object', async () => { + const object = new TestObject({ foo: 'bar' }); + await object.save(); + + const collection = await config.database.adapter._adaptiveCollection('TestObject'); + let result = await collection.aggregate([{ $group: { _id: '$foo' } }], { + explain: true, + }); + let queryPlanner = result[0].queryPlanner; + expect(queryPlanner.winningPlan.queryPlan.stage).toBe('GROUP'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('COLLSCAN'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage).toBeUndefined(); + + result = await collection.aggregate([{ $group: { _id: '$foo' } }], { + hint: { _id: 1 }, + explain: true, + }); + queryPlanner = result[0].queryPlanner; + expect(queryPlanner.winningPlan.queryPlan.stage).toBe('GROUP'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('FETCH'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.stage).toBe('IXSCAN'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 }); + }); + + it_only_mongodb_version('<5.1')('query find with hint (rest)', async () => { const object = new TestObject(); await object.save(); let options = Object.assign({}, masterKeyOptions, { @@ -167,6 +290,31 @@ describe_only_db('mongo')('Parse.Query hint', () => { expect(explain.queryPlanner.winningPlan.inputStage.inputStage.indexName).toBe('_id_'); }); + it_only_mongodb_version('>=5.1')('query find with hint (rest)', async () => { + const object = new TestObject(); + await object.save(); + let options = Object.assign({}, masterKeyOptions, { + url: Parse.serverURL + '/classes/TestObject', + qs: { + explain: true, + }, + }); + let response = await request(options); + let explain = response.data.results; + expect(explain.queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('COLLSCAN'); + + options = Object.assign({}, masterKeyOptions, { + url: Parse.serverURL + '/classes/TestObject', + qs: { + explain: true, + hint: '_id_', + }, + }); + response = await request(options); + explain = response.data.results; + expect(explain.queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_'); + }); + it_only_mongodb_version('<4.4')('query aggregate with hint (rest)', async () => { const object = new TestObject({ foo: 'bar' }); await object.save(); @@ -194,7 +342,7 @@ describe_only_db('mongo')('Parse.Query hint', () => { expect(queryPlanner.winningPlan.inputStage.keyPattern).toEqual({ _id: 1 }); }); - it_only_mongodb_version('>=4.4')('query aggregate with hint (rest)', async () => { + it_only_mongodb_version('>=4.4<5.1')('query aggregate with hint (rest)', async () => { const object = new TestObject({ foo: 'bar' }); await object.save(); let options = Object.assign({}, masterKeyOptions, { @@ -226,4 +374,70 @@ describe_only_db('mongo')('Parse.Query hint', () => { expect(queryPlanner.winningPlan.inputStage.inputStage.indexName).toBe('_id_'); expect(queryPlanner.winningPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 }); }); + + it_only_mongodb_version('>=5.1<5.2')('query aggregate with hint (rest)', async () => { + const object = new TestObject({ foo: 'bar' }); + await object.save(); + let options = Object.assign({}, masterKeyOptions, { + url: Parse.serverURL + '/aggregate/TestObject', + qs: { + explain: true, + group: JSON.stringify({ objectId: '$foo' }), + }, + }); + let response = await request(options); + let { queryPlanner } = response.data.results[0].stages[0].$cursor; + expect(queryPlanner.winningPlan.queryPlan.stage).toBe('PROJECTION_SIMPLE'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('COLLSCAN'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage).toBeUndefined(); + + options = Object.assign({}, masterKeyOptions, { + url: Parse.serverURL + '/aggregate/TestObject', + qs: { + explain: true, + hint: '_id_', + group: JSON.stringify({ objectId: '$foo' }), + }, + }); + response = await request(options); + queryPlanner = response.data.results[0].stages[0].$cursor.queryPlanner; + expect(queryPlanner.winningPlan.queryPlan.stage).toBe('PROJECTION_SIMPLE'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('FETCH'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.stage).toBe('IXSCAN'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 }); + }); + + it_only_mongodb_version('>=5.2')('query aggregate with hint (rest)', async () => { + const object = new TestObject({ foo: 'bar' }); + await object.save(); + let options = Object.assign({}, masterKeyOptions, { + url: Parse.serverURL + '/aggregate/TestObject', + qs: { + explain: true, + group: JSON.stringify({ objectId: '$foo' }), + }, + }); + let response = await request(options); + let queryPlanner = response.data.results[0].queryPlanner; + expect(queryPlanner.winningPlan.queryPlan.stage).toBe('GROUP'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('COLLSCAN'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage).toBeUndefined(); + + options = Object.assign({}, masterKeyOptions, { + url: Parse.serverURL + '/aggregate/TestObject', + qs: { + explain: true, + hint: '_id_', + group: JSON.stringify({ objectId: '$foo' }), + }, + }); + response = await request(options); + queryPlanner = response.data.results[0].queryPlanner; + expect(queryPlanner.winningPlan.queryPlan.stage).toBe('GROUP'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('FETCH'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.stage).toBe('IXSCAN'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 }); + }); }); diff --git a/spec/ParseUser.spec.js b/spec/ParseUser.spec.js index 80f6254be8..92301316e4 100644 --- a/spec/ParseUser.spec.js +++ b/spec/ParseUser.spec.js @@ -2926,7 +2926,7 @@ describe('Parse.User testing', () => { sendPasswordResetEmail: () => Promise.resolve(), sendMail: () => Promise.resolve(), }; - reconfigureServer({ + await reconfigureServer({ appName: 'unused', verifyUserEmails: true, emailAdapter: emailAdapter, diff --git a/spec/ParseWebSocketServer.spec.js b/spec/ParseWebSocketServer.spec.js index 6050ea0f2f..5955ee3241 100644 --- a/spec/ParseWebSocketServer.spec.js +++ b/spec/ParseWebSocketServer.spec.js @@ -23,6 +23,7 @@ describe('ParseWebSocketServer', function () { ws.readyState = 0; ws.OPEN = 0; ws.ping = jasmine.createSpy('ping'); + ws.terminate = () => {}; parseWebSocketServer.onConnection(ws); @@ -75,6 +76,61 @@ describe('ParseWebSocketServer', function () { expect(wssError).toBe('Invalid Packet'); }); + it('can handle ping/pong', async () => { + const onConnectCallback = jasmine.createSpy('onConnectCallback'); + const http = require('http'); + const server = http.createServer(); + const parseWebSocketServer = new ParseWebSocketServer(server, onConnectCallback, { + websocketTimeout: 10, + }).server; + + const ws = new EventEmitter(); + ws.readyState = 0; + ws.OPEN = 0; + ws.ping = jasmine.createSpy('ping'); + ws.terminate = jasmine.createSpy('terminate'); + + parseWebSocketServer.onConnection(ws); + + expect(onConnectCallback).toHaveBeenCalled(); + expect(ws.waitingForPong).toBe(false); + await new Promise(resolve => setTimeout(resolve, 10)); + expect(ws.ping).toHaveBeenCalled(); + expect(ws.waitingForPong).toBe(true); + ws.emit('pong'); + expect(ws.waitingForPong).toBe(false); + await new Promise(resolve => setTimeout(resolve, 10)); + expect(ws.waitingForPong).toBe(true); + expect(ws.terminate).not.toHaveBeenCalled(); + server.close(); + }); + + it('closes interrupted connection', async () => { + const onConnectCallback = jasmine.createSpy('onConnectCallback'); + const http = require('http'); + const server = http.createServer(); + const parseWebSocketServer = new ParseWebSocketServer(server, onConnectCallback, { + websocketTimeout: 5, + }).server; + const ws = new EventEmitter(); + ws.readyState = 0; + ws.OPEN = 0; + ws.ping = jasmine.createSpy('ping'); + ws.terminate = jasmine.createSpy('terminate'); + + parseWebSocketServer.onConnection(ws); + + // Make sure callback is called + expect(onConnectCallback).toHaveBeenCalled(); + expect(ws.waitingForPong).toBe(false); + await new Promise(resolve => setTimeout(resolve, 10)); + expect(ws.ping).toHaveBeenCalled(); + expect(ws.waitingForPong).toBe(true); + await new Promise(resolve => setTimeout(resolve, 10)); + expect(ws.terminate).toHaveBeenCalled(); + server.close(); + }); + afterEach(function () { jasmine.restoreLibrary('ws', 'Server'); }); diff --git a/spec/RestQuery.spec.js b/spec/RestQuery.spec.js index 85d9f87fec..2e37c96b7c 100644 --- a/spec/RestQuery.spec.js +++ b/spec/RestQuery.spec.js @@ -502,4 +502,26 @@ describe('RestQuery.each', () => { done(); }); }); + + it('test afterSave should not affect save response', async () => { + Parse.Cloud.beforeSave('TestObject2', ({ object }) => { + object.set('addedBeforeSave', true); + }); + Parse.Cloud.afterSave('TestObject2', ({ object }) => { + object.set('addedAfterSave', true); + object.unset('initialToRemove'); + }); + const { response } = await rest.create(config, nobody, 'TestObject2', { + initialSave: true, + initialToRemove: true, + }); + expect(Object.keys(response).sort()).toEqual([ + 'addedAfterSave', + 'addedBeforeSave', + 'createdAt', + 'initialToRemove', + 'objectId', + 'updatedAt', + ]); + }); }); diff --git a/spec/helper.js b/spec/helper.js index 612c716202..f769c0f521 100644 --- a/spec/helper.js +++ b/spec/helper.js @@ -1,9 +1,15 @@ 'use strict'; +const dns = require('dns'); const semver = require('semver'); const CurrentSpecReporter = require('./support/CurrentSpecReporter.js'); const { SpecReporter } = require('jasmine-spec-reporter'); const SchemaCache = require('../lib/Adapters/Cache/SchemaCache').default; +// Ensure localhost resolves to ipv4 address first on node v17+ +if (dns.setDefaultResultOrder) { + dns.setDefaultResultOrder('ipv4first'); +} + // Sets up a Parse API server for testing. jasmine.DEFAULT_TIMEOUT_INTERVAL = process.env.PARSE_SERVER_TEST_TIMEOUT || 10000; jasmine.getEnv().addReporter(new CurrentSpecReporter()); @@ -455,6 +461,15 @@ global.it_only_postgres_version = version => { } }; +global.it_only_node_version = version => { + const envVersion = process.version; + if (!envVersion || semver.satisfies(envVersion, version)) { + return it; + } else { + return xit; + } +}; + global.fit_only_mongodb_version = version => { const envVersion = process.env.MONGODB_VERSION; if (!envVersion || semver.satisfies(envVersion, version)) { @@ -464,6 +479,15 @@ global.fit_only_mongodb_version = version => { } }; +global.fit_only_node_version = version => { + const envVersion = process.version; + if (!envVersion || semver.satisfies(envVersion, version)) { + return fit; + } else { + return xit; + } +}; + global.it_exclude_mongodb_version = version => { const envVersion = process.env.MONGODB_VERSION; if (!envVersion || !semver.satisfies(envVersion, version)) { @@ -482,6 +506,15 @@ global.it_exclude_postgres_version = version => { } }; +global.it_exclude_node_version = version => { + const envVersion = process.env.NODE_VERSION; + if (!envVersion || !semver.satisfies(envVersion, version)) { + return it; + } else { + return xit; + } +}; + global.fit_exclude_mongodb_version = version => { const envVersion = process.env.MONGODB_VERSION; if (!envVersion || !semver.satisfies(envVersion, version)) { @@ -491,6 +524,15 @@ global.fit_exclude_mongodb_version = version => { } }; +global.fit_exclude_node_version = version => { + const envVersion = process.env.NODE_VERSION; + if (!envVersion || !semver.satisfies(envVersion, version)) { + return fit; + } else { + return xit; + } +}; + global.fit_exclude_dbs = excluded => { if (excluded.indexOf(process.env.PARSE_SERVER_TEST_DB) >= 0) { return xit; diff --git a/src/Adapters/Cache/LRUCache.js b/src/Adapters/Cache/LRUCache.js index 889ca3d015..a07d0347eb 100644 --- a/src/Adapters/Cache/LRUCache.js +++ b/src/Adapters/Cache/LRUCache.js @@ -5,7 +5,7 @@ export class LRUCache { constructor({ ttl = defaults.cacheTTL, maxSize = defaults.cacheMaxSize }) { this.cache = new LRU({ max: maxSize, - maxAge: ttl, + ttl, }); } diff --git a/src/Auth.js b/src/Auth.js index e3196105c7..ce5c71c860 100644 --- a/src/Auth.js +++ b/src/Auth.js @@ -230,6 +230,15 @@ Auth.prototype.cacheRoles = function () { return true; }; +Auth.prototype.clearRoleCache = function (sessionToken) { + if (!this.cacheController) { + return false; + } + this.cacheController.role.del(this.user.id); + this.cacheController.user.del(sessionToken); + return true; +}; + Auth.prototype.getRolesByIds = async function (ins) { const results = []; // Build an OR query across all parentRoles diff --git a/src/Controllers/LiveQueryController.js b/src/Controllers/LiveQueryController.js index 064084caa4..9a5b6d0ef1 100644 --- a/src/Controllers/LiveQueryController.js +++ b/src/Controllers/LiveQueryController.js @@ -56,6 +56,13 @@ export class LiveQueryController { return false; } + clearCachedRoles(user: any) { + if (!user) { + return; + } + return this.liveQueryPublisher.onClearCachedRoles(user); + } + _makePublisherRequest(currentObject: any, originalObject: any, classLevelPermissions: ?any): any { const req = { object: currentObject, diff --git a/src/Controllers/SchemaController.js b/src/Controllers/SchemaController.js index 9ae6628088..179de37b6e 100644 --- a/src/Controllers/SchemaController.js +++ b/src/Controllers/SchemaController.js @@ -150,9 +150,15 @@ const defaultColumns: { [string]: SchemaFields } = Object.freeze({ }, }); +// fields required for read or write operations on their respective classes. const requiredColumns = Object.freeze({ - _Product: ['productIdentifier', 'icon', 'order', 'title', 'subtitle'], - _Role: ['name', 'ACL'], + read: { + _User: ['username'], + }, + write: { + _Product: ['productIdentifier', 'icon', 'order', 'title', 'subtitle'], + _Role: ['name', 'ACL'], + }, }); const invalidColumns = ['length']; @@ -1269,7 +1275,7 @@ export default class SchemaController { // Validates that all the properties are set for the object validateRequiredColumns(className: string, object: any, query: any) { - const columns = requiredColumns[className]; + const columns = requiredColumns.write[className]; if (!columns || columns.length == 0) { return Promise.resolve(this); } @@ -1600,4 +1606,5 @@ export { convertSchemaToAdapterSchema, VolatileClassesSchemas, SchemaController, + requiredColumns, }; diff --git a/src/Controllers/index.js b/src/Controllers/index.js index b2feff0fc2..0a9b3db57d 100644 --- a/src/Controllers/index.js +++ b/src/Controllers/index.js @@ -91,12 +91,20 @@ export function getLoggerController(options: ParseServerOptions): LoggerControll } export function getFilesController(options: ParseServerOptions): FilesController { - const { appId, databaseURI, filesAdapter, databaseAdapter, preserveFileName, fileKey } = options; + const { + appId, + databaseURI, + databaseOptions = {}, + filesAdapter, + databaseAdapter, + preserveFileName, + fileKey, + } = options; if (!filesAdapter && databaseAdapter) { throw 'When using an explicit database adapter, you must also use an explicit filesAdapter.'; } const filesControllerAdapter = loadAdapter(filesAdapter, () => { - return new GridFSBucketAdapter(databaseURI, {}, fileKey); + return new GridFSBucketAdapter(databaseURI, databaseOptions, fileKey); }); return new FilesController(filesControllerAdapter, appId, { preserveFileName, diff --git a/src/Deprecator/Deprecations.js b/src/Deprecator/Deprecations.js index eb2212bf92..1c3d336be9 100644 --- a/src/Deprecator/Deprecations.js +++ b/src/Deprecator/Deprecations.js @@ -23,4 +23,5 @@ module.exports = [ "Additionally, the environment variable 'PARSE_SERVER_ENABLE_EXPERIMENTAL_DIRECT_ACCESS' will be deprecated and renamed to 'PARSE_SERVER_DIRECT_ACCESS' in a future version; it is currently possible to use either one.", }, { optionKey: 'enforcePrivateUsers', changeNewDefault: 'true' }, + { optionKey: 'allowClientClassCreation', changeNewDefault: 'false' }, ]; diff --git a/src/GraphQL/ParseGraphQLSchema.js b/src/GraphQL/ParseGraphQLSchema.js index 011905ca2d..154e774897 100644 --- a/src/GraphQL/ParseGraphQLSchema.js +++ b/src/GraphQL/ParseGraphQLSchema.js @@ -1,8 +1,8 @@ import Parse from 'parse/node'; import { GraphQLSchema, GraphQLObjectType, DocumentNode, GraphQLNamedType } from 'graphql'; -import { stitchSchemas } from '@graphql-tools/stitch'; +import { mergeSchemas } from '@graphql-tools/schema'; +import { mergeTypeDefs } from '@graphql-tools/merge'; import { isDeepStrictEqual } from 'util'; -import { SchemaDirectiveVisitor } from '@graphql-tools/utils'; import requiredParameter from '../requiredParameter'; import * as defaultGraphQLTypes from './loaders/defaultGraphQLTypes'; import * as parseClassTypes from './loaders/parseClassTypes'; @@ -89,14 +89,19 @@ class ParseGraphQLSchema { this.graphQLCustomTypeDefs = params.graphQLCustomTypeDefs; this.appId = params.appId || requiredParameter('You must provide the appId!'); this.schemaCache = SchemaCache; + this.logCache = {}; } async load() { const { parseGraphQLConfig } = await this._initializeSchemaAndConfig(); - const parseClasses = await this._getClassesForSchema(parseGraphQLConfig); + const parseClassesArray = await this._getClassesForSchema(parseGraphQLConfig); const functionNames = await this._getFunctionNames(); - const functionNamesString = JSON.stringify(functionNames); + const functionNamesString = functionNames.join(); + const parseClasses = parseClassesArray.reduce((acc, clazz) => { + acc[clazz.className] = clazz; + return acc; + }, {}); if ( !this._hasSchemaInputChanged({ parseClasses, @@ -127,7 +132,7 @@ class ParseGraphQLSchema { defaultRelaySchema.load(this); schemaTypes.load(this); - this._getParseClassesWithConfig(parseClasses, parseGraphQLConfig).forEach( + this._getParseClassesWithConfig(parseClassesArray, parseGraphQLConfig).forEach( ([parseClass, parseClassConfig]) => { // Some times schema return the _auth_data_ field // it will lead to unstable graphql generation order @@ -155,7 +160,7 @@ class ParseGraphQLSchema { } ); - defaultGraphQLTypes.loadArrayResult(this, parseClasses); + defaultGraphQLTypes.loadArrayResult(this, parseClassesArray); defaultGraphQLQueries.load(this); defaultGraphQLMutations.load(this); @@ -198,9 +203,8 @@ class ParseGraphQLSchema { if (this.graphQLCustomTypeDefs) { schemaDirectives.load(this); - if (typeof this.graphQLCustomTypeDefs.getTypeMap === 'function') { - // In following code we use underscore attr to avoid js var un ref + // In following code we use underscore attr to keep the direct variable reference const customGraphQLSchemaTypeMap = this.graphQLCustomTypeDefs._typeMap; const findAndReplaceLastType = (parent, key) => { if (parent[key].name) { @@ -275,51 +279,18 @@ class ParseGraphQLSchema { this.graphQLSchema = await this.graphQLCustomTypeDefs({ directivesDefinitionsSchema: this.graphQLSchemaDirectivesDefinitions, autoSchema: this.graphQLAutoSchema, - stitchSchemas, + graphQLSchemaDirectives: this.graphQLSchemaDirectives, }); } else { - this.graphQLSchema = stitchSchemas({ - schemas: [ - this.graphQLSchemaDirectivesDefinitions, - this.graphQLAutoSchema, + this.graphQLSchema = mergeSchemas({ + schemas: [this.graphQLAutoSchema], + typeDefs: mergeTypeDefs([ this.graphQLCustomTypeDefs, - ], - mergeDirectives: true, + this.graphQLSchemaDirectivesDefinitions, + ]), }); + this.graphQLSchema = this.graphQLSchemaDirectives(this.graphQLSchema); } - - // Only merge directive when string schema provided - const graphQLSchemaTypeMap = this.graphQLSchema.getTypeMap(); - Object.keys(graphQLSchemaTypeMap).forEach(graphQLSchemaTypeName => { - const graphQLSchemaType = graphQLSchemaTypeMap[graphQLSchemaTypeName]; - if ( - typeof graphQLSchemaType.getFields === 'function' && - this.graphQLCustomTypeDefs.definitions - ) { - const graphQLCustomTypeDef = this.graphQLCustomTypeDefs.definitions.find( - definition => definition.name.value === graphQLSchemaTypeName - ); - if (graphQLCustomTypeDef) { - const graphQLSchemaTypeFieldMap = graphQLSchemaType.getFields(); - Object.keys(graphQLSchemaTypeFieldMap).forEach(graphQLSchemaTypeFieldName => { - const graphQLSchemaTypeField = graphQLSchemaTypeFieldMap[graphQLSchemaTypeFieldName]; - if (!graphQLSchemaTypeField.astNode) { - const astNode = graphQLCustomTypeDef.fields.find( - field => field.name.value === graphQLSchemaTypeFieldName - ); - if (astNode) { - graphQLSchemaTypeField.astNode = astNode; - } - } - }); - } - } - }); - - SchemaDirectiveVisitor.visitSchemaDirectives( - this.graphQLSchema, - this.graphQLSchemaDirectives - ); } else { this.graphQLSchema = this.graphQLAutoSchema; } @@ -327,6 +298,14 @@ class ParseGraphQLSchema { return this.graphQLSchema; } + _logOnce(severity, message) { + if (this.logCache[message]) { + return; + } + this.log[severity](message); + this.logCache[message] = true; + } + addGraphQLType(type, throwError = false, ignoreReserved = false, ignoreConnection = false) { if ( (!ignoreReserved && RESERVED_GRAPHQL_TYPE_NAMES.includes(type.name)) || @@ -337,7 +316,7 @@ class ParseGraphQLSchema { if (throwError) { throw new Error(message); } - this.log.warn(message); + this._logOnce('warn', message); return undefined; } this.graphQLTypes.push(type); @@ -353,7 +332,7 @@ class ParseGraphQLSchema { if (throwError) { throw new Error(message); } - this.log.warn(message); + this._logOnce('warn', message); return undefined; } this.graphQLQueries[fieldName] = field; @@ -369,7 +348,7 @@ class ParseGraphQLSchema { if (throwError) { throw new Error(message); } - this.log.warn(message); + this._logOnce('warn', message); return undefined; } this.graphQLMutations[fieldName] = field; @@ -478,7 +457,8 @@ class ParseGraphQLSchema { if (/^[_a-zA-Z][_a-zA-Z0-9]*$/.test(functionName)) { return true; } else { - this.log.warn( + this._logOnce( + 'warn', `Function ${functionName} could not be added to the auto schema because GraphQL names must match /^[_a-zA-Z][_a-zA-Z0-9]*$/.` ); return false; @@ -500,29 +480,17 @@ class ParseGraphQLSchema { const { parseClasses, parseGraphQLConfig, functionNamesString } = params; // First init - if (!this.parseCachedClasses || !this.graphQLSchema) { - const thisParseClassesObj = parseClasses.reduce((acc, clzz) => { - acc[clzz.className] = clzz; - return acc; - }, {}); - this.parseCachedClasses = thisParseClassesObj; + if (!this.graphQLSchema) { return true; } - const newParseCachedClasses = parseClasses.reduce((acc, clzz) => { - acc[clzz.className] = clzz; - return acc; - }, {}); - if ( isDeepStrictEqual(this.parseGraphQLConfig, parseGraphQLConfig) && this.functionNamesString === functionNamesString && - isDeepStrictEqual(this.parseCachedClasses, newParseCachedClasses) + isDeepStrictEqual(this.parseClasses, parseClasses) ) { return false; } - - this.parseCachedClasses = newParseCachedClasses; return true; } } diff --git a/src/GraphQL/ParseGraphQLServer.js b/src/GraphQL/ParseGraphQLServer.js index bb47ca2938..7ab03fc1be 100644 --- a/src/GraphQL/ParseGraphQLServer.js +++ b/src/GraphQL/ParseGraphQLServer.js @@ -1,8 +1,5 @@ import corsMiddleware from 'cors'; -import bodyParser from 'body-parser'; -import { graphqlUploadExpress } from 'graphql-upload'; -import { graphqlExpress } from 'apollo-server-express/dist/expressApollo'; -import { renderPlaygroundPage } from '@apollographql/graphql-playground-html'; +import { createServer, renderGraphiQL } from '@graphql-yoga/node'; import { execute, subscribe } from 'graphql'; import { SubscriptionServer } from 'subscriptions-transport-ws'; import { handleParseErrors, handleParseHeaders } from '../middlewares'; @@ -32,18 +29,20 @@ class ParseGraphQLServer { }); } - async _getGraphQLOptions(req) { + async _getGraphQLOptions() { try { return { schema: await this.parseGraphQLSchema.load(), - context: { - info: req.info, - config: req.config, - auth: req.auth, - }, - formatError: error => { - // Allow to console.log here to debug - return error; + context: ({ req: { info, config, auth } }) => ({ + info, + config, + auth, + }), + maskedErrors: false, + multipart: { + fileSize: this._transformMaxUploadSizeToBytes( + this.parseServer.config.maxUploadSize || '20mb' + ), }, }; } catch (e) { @@ -52,6 +51,17 @@ class ParseGraphQLServer { } } + async _getServer() { + const schemaRef = this.parseGraphQLSchema.graphQLSchema; + const newSchemaRef = await this.parseGraphQLSchema.load(); + if (schemaRef === newSchemaRef && this._server) { + return this._server; + } + const options = await this._getGraphQLOptions(); + this._server = createServer(options); + return this._server; + } + _transformMaxUploadSizeToBytes(maxUploadSize) { const unitMap = { kb: 1, @@ -70,22 +80,13 @@ class ParseGraphQLServer { requiredParameter('You must provide an Express.js app instance!'); } - app.use( - this.config.graphQLPath, - graphqlUploadExpress({ - maxFileSize: this._transformMaxUploadSizeToBytes( - this.parseServer.config.maxUploadSize || '20mb' - ), - }) - ); app.use(this.config.graphQLPath, corsMiddleware()); - app.use(this.config.graphQLPath, bodyParser.json()); app.use(this.config.graphQLPath, handleParseHeaders); app.use(this.config.graphQLPath, handleParseErrors); - app.use( - this.config.graphQLPath, - graphqlExpress(async req => await this._getGraphQLOptions(req)) - ); + app.use(this.config.graphQLPath, async (req, res) => { + const server = await this._getServer(); + return server(req, res); + }); } applyPlayground(app) { @@ -98,14 +99,13 @@ class ParseGraphQLServer { (_req, res) => { res.setHeader('Content-Type', 'text/html'); res.write( - renderPlaygroundPage({ + renderGraphiQL({ endpoint: this.config.graphQLPath, - version: '1.7.25', subscriptionEndpoint: this.config.subscriptionsPath, - headers: { + headers: JSON.stringify({ 'X-Parse-Application-Id': this.parseServer.config.appId, 'X-Parse-Master-Key': this.parseServer.config.masterKey, - }, + }), }) ); res.end(); diff --git a/src/GraphQL/helpers/objectsQueries.js b/src/GraphQL/helpers/objectsQueries.js index 7b973312ce..4d21f24143 100644 --- a/src/GraphQL/helpers/objectsQueries.js +++ b/src/GraphQL/helpers/objectsQueries.js @@ -12,9 +12,7 @@ const needToGetAllKeys = (fields, keys, parseClasses) => if (fields[key[0]]) { if (fields[key[0]].type === 'Relation') return false; if (fields[key[0]].type === 'Pointer') { - const subClass = parseClasses.find( - ({ className: parseClassName }) => fields[key[0]].targetClass === parseClassName - ); + const subClass = parseClasses[fields[key[0]].targetClass]; if (subClass && subClass.fields[key[1]]) { // Current sub key is not custom return false; @@ -48,17 +46,11 @@ const getObject = async ( ) => { const options = {}; try { - if ( - !needToGetAllKeys( - parseClasses.find(({ className: parseClassName }) => className === parseClassName).fields, - keys, - parseClasses - ) - ) { + if (!needToGetAllKeys(parseClasses[className].fields, keys, parseClasses)) { options.keys = keys; } } catch (e) { - console.log(e); + console.error(e); } if (include) { options.include = include; @@ -165,13 +157,7 @@ const findObjects = async ( // Silently replace the limit on the query with the max configured options.limit = config.maxLimit; } - if ( - !needToGetAllKeys( - parseClasses.find(({ className: parseClassName }) => className === parseClassName).fields, - keys, - parseClasses - ) - ) { + if (!needToGetAllKeys(parseClasses[className].fields, keys, parseClasses)) { options.keys = keys; } if (includeAll === true) { diff --git a/src/GraphQL/loaders/defaultGraphQLTypes.js b/src/GraphQL/loaders/defaultGraphQLTypes.js index f340cfb35f..6824f75ba6 100644 --- a/src/GraphQL/loaders/defaultGraphQLTypes.js +++ b/src/GraphQL/loaders/defaultGraphQLTypes.js @@ -15,7 +15,6 @@ import { GraphQLUnionType, } from 'graphql'; import { toGlobalId } from 'graphql-relay'; -import { GraphQLUpload } from '@graphql-tools/links'; class TypeValidationError extends Error { constructor(value, type) { @@ -223,6 +222,11 @@ const DATE = new GraphQLScalarType({ }, }); +const GraphQLUpload = new GraphQLScalarType({ + name: 'Upload', + description: 'The Upload scalar type represents a file upload.', +}); + const BYTES = new GraphQLScalarType({ name: 'Bytes', description: @@ -1190,8 +1194,8 @@ const ELEMENT = new GraphQLObjectType({ // Default static union type, we update types and resolveType function later let ARRAY_RESULT; -const loadArrayResult = (parseGraphQLSchema, parseClasses) => { - const classTypes = parseClasses +const loadArrayResult = (parseGraphQLSchema, parseClassesArray) => { + const classTypes = parseClassesArray .filter(parseClass => parseGraphQLSchema.parseClassTypes[parseClass.className].classGraphQLOutputType ? true : false ) @@ -1206,12 +1210,12 @@ const loadArrayResult = (parseGraphQLSchema, parseClasses) => { resolveType: value => { if (value.__type === 'Object' && value.className && value.objectId) { if (parseGraphQLSchema.parseClassTypes[value.className]) { - return parseGraphQLSchema.parseClassTypes[value.className].classGraphQLOutputType; + return parseGraphQLSchema.parseClassTypes[value.className].classGraphQLOutputType.name; } else { - return ELEMENT; + return ELEMENT.name; } } else { - return ELEMENT; + return ELEMENT.name; } }, }); @@ -1265,6 +1269,7 @@ const load = parseGraphQLSchema => { }; export { + GraphQLUpload, TypeValidationError, parseStringValue, parseIntValue, diff --git a/src/GraphQL/loaders/defaultRelaySchema.js b/src/GraphQL/loaders/defaultRelaySchema.js index 87f19955ba..0a8f0f7620 100644 --- a/src/GraphQL/loaders/defaultRelaySchema.js +++ b/src/GraphQL/loaders/defaultRelaySchema.js @@ -39,7 +39,7 @@ const load = parseGraphQLSchema => { } }, obj => { - return parseGraphQLSchema.parseClassTypes[obj.className].classGraphQLOutputType; + return parseGraphQLSchema.parseClassTypes[obj.className].classGraphQLOutputType.name; } ); diff --git a/src/GraphQL/loaders/filesMutations.js b/src/GraphQL/loaders/filesMutations.js index a732c277ef..1b6c26ab40 100644 --- a/src/GraphQL/loaders/filesMutations.js +++ b/src/GraphQL/loaders/filesMutations.js @@ -1,43 +1,33 @@ import { GraphQLNonNull } from 'graphql'; import { mutationWithClientMutationId } from 'graphql-relay'; -import { GraphQLUpload } from '@graphql-tools/links'; import Parse from 'parse/node'; import * as defaultGraphQLTypes from './defaultGraphQLTypes'; import logger from '../../logger'; const handleUpload = async (upload, config) => { - const { createReadStream, filename, mimetype } = await upload; - let data = null; - if (createReadStream) { - const stream = createReadStream(); - data = await new Promise((resolve, reject) => { - const chunks = []; - stream - .on('error', reject) - .on('data', chunk => chunks.push(chunk)) - .on('end', () => resolve(Buffer.concat(chunks))); - }); - } + const data = Buffer.from(await upload.arrayBuffer()); + const fileName = upload.name; + const type = upload.type; if (!data || !data.length) { throw new Parse.Error(Parse.Error.FILE_SAVE_ERROR, 'Invalid file upload.'); } - if (filename.length > 128) { + if (fileName.length > 128) { throw new Parse.Error(Parse.Error.INVALID_FILE_NAME, 'Filename too long.'); } - if (!filename.match(/^[_a-zA-Z0-9][a-zA-Z0-9@\.\ ~_-]*$/)) { + if (!fileName.match(/^[_a-zA-Z0-9][a-zA-Z0-9@\.\ ~_-]*$/)) { throw new Parse.Error(Parse.Error.INVALID_FILE_NAME, 'Filename contains invalid characters.'); } try { return { - fileInfo: await config.filesController.createFile(config, filename, data, mimetype), + fileInfo: await config.filesController.createFile(config, fileName, data, type), }; } catch (e) { logger.error('Error creating a file: ', e); - throw new Parse.Error(Parse.Error.FILE_SAVE_ERROR, `Could not store file: ${filename}.`); + throw new Parse.Error(Parse.Error.FILE_SAVE_ERROR, `Could not store file: ${fileName}.`); } }; @@ -48,7 +38,7 @@ const load = parseGraphQLSchema => { inputFields: { upload: { description: 'This is the new file to be created and uploaded.', - type: new GraphQLNonNull(GraphQLUpload), + type: new GraphQLNonNull(defaultGraphQLTypes.GraphQLUpload), }, }, outputFields: { diff --git a/src/GraphQL/loaders/schemaDirectives.js b/src/GraphQL/loaders/schemaDirectives.js index 43a8fe273b..f354167317 100644 --- a/src/GraphQL/loaders/schemaDirectives.js +++ b/src/GraphQL/loaders/schemaDirectives.js @@ -1,8 +1,7 @@ -import gql from 'graphql-tag'; -import { SchemaDirectiveVisitor } from '@graphql-tools/utils'; +import { mapSchema, getDirective, MapperKind } from '@graphql-tools/utils'; import { FunctionsRouter } from '../../Routers/FunctionsRouter'; -export const definitions = gql` +export const definitions = ` directive @resolve(to: String) on FIELD_DEFINITION directive @mock(with: Any!) on FIELD_DEFINITION `; @@ -10,46 +9,48 @@ export const definitions = gql` const load = parseGraphQLSchema => { parseGraphQLSchema.graphQLSchemaDirectivesDefinitions = definitions; - class ResolveDirectiveVisitor extends SchemaDirectiveVisitor { - visitFieldDefinition(field) { - field.resolve = async (_source, args, context) => { - try { - const { config, auth, info } = context; - - let functionName = field.name; - if (this.args.to) { - functionName = this.args.to; - } - - return ( - await FunctionsRouter.handleCloudFunction({ - params: { - functionName, - }, - config, - auth, - info, - body: args, - }) - ).response.result; - } catch (e) { - parseGraphQLSchema.handleError(e); + const resolveDirective = schema => + mapSchema(schema, { + [MapperKind.OBJECT_FIELD]: fieldConfig => { + const directive = getDirective(schema, fieldConfig, 'resolve')?.[0]; + if (directive) { + const { to: targetCloudFunction } = directive; + fieldConfig.resolve = async (_source, args, context, gqlInfo) => { + try { + const { config, auth, info } = context; + const functionName = targetCloudFunction || gqlInfo.fieldName; + return ( + await FunctionsRouter.handleCloudFunction({ + params: { + functionName, + }, + config, + auth, + info, + body: args, + }) + ).response.result; + } catch (e) { + parseGraphQLSchema.handleError(e); + } + }; } - }; - } - } - - parseGraphQLSchema.graphQLSchemaDirectives.resolve = ResolveDirectiveVisitor; - - class MockDirectiveVisitor extends SchemaDirectiveVisitor { - visitFieldDefinition(field) { - field.resolve = () => { - return this.args.with; - }; - } - } + return fieldConfig; + }, + }); + + const mockDirective = schema => + mapSchema(schema, { + [MapperKind.OBJECT_FIELD]: fieldConfig => { + const directive = getDirective(schema, fieldConfig, 'mock')?.[0]; + if (directive) { + const { with: mockValue } = directive; + fieldConfig.resolve = async () => mockValue; + } + return fieldConfig; + }, + }); - parseGraphQLSchema.graphQLSchemaDirectives.mock = MockDirectiveVisitor; + parseGraphQLSchema.graphQLSchemaDirectives = schema => mockDirective(resolveDirective(schema)); }; - export { load }; diff --git a/src/GraphQL/loaders/schemaTypes.js b/src/GraphQL/loaders/schemaTypes.js index bd057f0217..ea8a24aca5 100644 --- a/src/GraphQL/loaders/schemaTypes.js +++ b/src/GraphQL/loaders/schemaTypes.js @@ -29,19 +29,19 @@ const SCHEMA_FIELD = new GraphQLInterfaceType({ }, resolveType: value => ({ - String: SCHEMA_STRING_FIELD, - Number: SCHEMA_NUMBER_FIELD, - Boolean: SCHEMA_BOOLEAN_FIELD, - Array: SCHEMA_ARRAY_FIELD, - Object: SCHEMA_OBJECT_FIELD, - Date: SCHEMA_DATE_FIELD, - File: SCHEMA_FILE_FIELD, - GeoPoint: SCHEMA_GEO_POINT_FIELD, - Polygon: SCHEMA_POLYGON_FIELD, - Bytes: SCHEMA_BYTES_FIELD, - Pointer: SCHEMA_POINTER_FIELD, - Relation: SCHEMA_RELATION_FIELD, - ACL: SCHEMA_ACL_FIELD, + String: SCHEMA_STRING_FIELD.name, + Number: SCHEMA_NUMBER_FIELD.name, + Boolean: SCHEMA_BOOLEAN_FIELD.name, + Array: SCHEMA_ARRAY_FIELD.name, + Object: SCHEMA_OBJECT_FIELD.name, + Date: SCHEMA_DATE_FIELD.name, + File: SCHEMA_FILE_FIELD.name, + GeoPoint: SCHEMA_GEO_POINT_FIELD.name, + Polygon: SCHEMA_POLYGON_FIELD.name, + Bytes: SCHEMA_BYTES_FIELD.name, + Pointer: SCHEMA_POINTER_FIELD.name, + Relation: SCHEMA_RELATION_FIELD.name, + ACL: SCHEMA_ACL_FIELD.name, }[value.type]), }); diff --git a/src/GraphQL/parseGraphQLUtils.js b/src/GraphQL/parseGraphQLUtils.js index 0bd6ad2b55..19b91f681b 100644 --- a/src/GraphQL/parseGraphQLUtils.js +++ b/src/GraphQL/parseGraphQLUtils.js @@ -1,5 +1,5 @@ import Parse from 'parse/node'; -import { ApolloError } from 'apollo-server-core'; +import { GraphQLYogaError } from '@graphql-yoga/node'; export function enforceMasterKeyAccess(auth) { if (!auth.isMaster) { @@ -16,7 +16,7 @@ export function toGraphQLError(error) { code = Parse.Error.INTERNAL_SERVER_ERROR; message = 'Internal server error'; } - return new ApolloError(message, code); + return new GraphQLYogaError(message, { code }); } export const extractKeysAndInclude = selectedFields => { diff --git a/src/GraphQL/transformers/mutation.js b/src/GraphQL/transformers/mutation.js index 2a21816fe9..5b72d6f05d 100644 --- a/src/GraphQL/transformers/mutation.js +++ b/src/GraphQL/transformers/mutation.js @@ -14,7 +14,7 @@ const transformTypes = async ( classGraphQLUpdateType, config: { isCreateEnabled, isUpdateEnabled }, } = parseGraphQLSchema.parseClassTypes[className]; - const parseClass = parseGraphQLSchema.parseClasses.find(clazz => clazz.className === className); + const parseClass = parseGraphQLSchema.parseClasses[className]; if (fields) { const classGraphQLCreateTypeFields = isCreateEnabled && classGraphQLCreateType ? classGraphQLCreateType.getFields() : null; diff --git a/src/GraphQL/transformers/query.js b/src/GraphQL/transformers/query.js index 92ea7be5fe..a91ee208ad 100644 --- a/src/GraphQL/transformers/query.js +++ b/src/GraphQL/transformers/query.js @@ -51,7 +51,7 @@ const transformQueryConstraintInputToParse = ( parentConstraints, parseClasses ) => { - const fields = parseClasses.find(parseClass => parseClass.className === className).fields; + const fields = parseClasses[className].fields; if (parentFieldName === 'id' && className) { Object.keys(constraints).forEach(constraintName => { const constraintValue = constraints[constraintName]; diff --git a/src/LiveQuery/ParseCloudCodePublisher.js b/src/LiveQuery/ParseCloudCodePublisher.js index 7d306d1b57..3ecd740e12 100644 --- a/src/LiveQuery/ParseCloudCodePublisher.js +++ b/src/LiveQuery/ParseCloudCodePublisher.js @@ -19,6 +19,13 @@ class ParseCloudCodePublisher { this._onCloudCodeMessage(Parse.applicationId + 'afterDelete', request); } + onClearCachedRoles(user: Parse.Object) { + this.parsePublisher.publish( + Parse.applicationId + 'clearCache', + JSON.stringify({ userId: user.id }) + ); + } + // Request is the request object from cloud code functions. request.object is a ParseObject. _onCloudCodeMessage(type: string, request: any): void { logger.verbose( diff --git a/src/LiveQuery/ParseLiveQueryServer.js b/src/LiveQuery/ParseLiveQueryServer.js index f2a27a8080..02c6ad30a1 100644 --- a/src/LiveQuery/ParseLiveQueryServer.js +++ b/src/LiveQuery/ParseLiveQueryServer.js @@ -65,7 +65,7 @@ class ParseLiveQueryServer { // The main benefit is to be able to reuse the same user / session token resolution. this.authCache = new LRU({ max: 500, // 500 concurrent - maxAge: config.cacheTimeout, + ttl: config.cacheTimeout, }); // Initialize websocket server this.parseWebSocketServer = new ParseWebSocketServer( @@ -78,6 +78,7 @@ class ParseLiveQueryServer { this.subscriber = ParsePubSub.createSubscriber(config); this.subscriber.subscribe(Parse.applicationId + 'afterSave'); this.subscriber.subscribe(Parse.applicationId + 'afterDelete'); + this.subscriber.subscribe(Parse.applicationId + 'clearCache'); // Register message handler for subscriber. When publisher get messages, it will publish message // to the subscribers and the handler will be called. this.subscriber.on('message', (channel, messageStr) => { @@ -89,6 +90,10 @@ class ParseLiveQueryServer { logger.error('unable to parse message', messageStr, e); return; } + if (channel === Parse.applicationId + 'clearCache') { + this._clearCachedRoles(message.userId); + return; + } this._inflateParseObject(message); if (channel === Parse.applicationId + 'afterSave') { this._onAfterSave(message); @@ -473,6 +478,32 @@ class ParseLiveQueryServer { return matchesQuery(parseObject, subscription.query); } + async _clearCachedRoles(userId: string) { + try { + const validTokens = await new Parse.Query(Parse.Session) + .equalTo('user', Parse.User.createWithoutData(userId)) + .find({ useMasterKey: true }); + await Promise.all( + validTokens.map(async token => { + const sessionToken = token.get('sessionToken'); + const authPromise = this.authCache.get(sessionToken); + if (!authPromise) { + return; + } + const [auth1, auth2] = await Promise.all([ + authPromise, + getAuthForSessionToken({ cacheController: this.cacheController, sessionToken }), + ]); + auth1.auth?.clearRoleCache(sessionToken); + auth2.auth?.clearRoleCache(sessionToken); + this.authCache.del(sessionToken); + }) + ); + } catch (e) { + logger.verbose(`Could not clear role cache. ${e}`); + } + } + getAuthForSessionToken(sessionToken: ?string): Promise<{ auth: ?Auth, userId: ?string }> { if (!sessionToken) { return Promise.resolve({}); @@ -627,7 +658,6 @@ class ParseLiveQueryServer { if (!acl_has_roles) { return false; } - const roleNames = await auth.getUserRoles(); // Finally, see if any of the user's roles allow them read access for (const role of roleNames) { diff --git a/src/LiveQuery/ParseWebSocketServer.js b/src/LiveQuery/ParseWebSocketServer.js index a0d1e9891f..927ee4b275 100644 --- a/src/LiveQuery/ParseWebSocketServer.js +++ b/src/LiveQuery/ParseWebSocketServer.js @@ -14,6 +14,10 @@ export class ParseWebSocketServer { logger.info('Parse LiveQuery Server started running'); }; wss.onConnection = ws => { + ws.waitingForPong = false; + ws.on('pong', () => { + ws.waitingForPong = false; + }); ws.on('error', error => { logger.error(error.message); logger.error(inspect(ws, false)); @@ -21,10 +25,12 @@ export class ParseWebSocketServer { onConnect(new ParseWebSocket(ws)); // Send ping to client periodically const pingIntervalId = setInterval(() => { - if (ws.readyState == ws.OPEN) { + if (!ws.waitingForPong) { ws.ping(); + ws.waitingForPong = true; } else { clearInterval(pingIntervalId); + ws.terminate(); } }, config.websocketTimeout || 10 * 1000); }; diff --git a/src/LiveQuery/SessionTokenCache.js b/src/LiveQuery/SessionTokenCache.js index 0eb4c2ead5..13b84c7367 100644 --- a/src/LiveQuery/SessionTokenCache.js +++ b/src/LiveQuery/SessionTokenCache.js @@ -19,7 +19,7 @@ class SessionTokenCache { constructor(timeout: number = 30 * 24 * 60 * 60 * 1000, maxSize: number = 10000) { this.cache = new LRU({ max: maxSize, - maxAge: timeout, + ttl: timeout, }); } diff --git a/src/Options/Definitions.js b/src/Options/Definitions.js index 1edd704bd6..c9a316db36 100644 --- a/src/Options/Definitions.js +++ b/src/Options/Definitions.js @@ -5,6 +5,51 @@ Do not edit manually, but update Options/index.js */ var parsers = require('./parsers'); +module.exports.SchemaOptions = { + afterMigration: { + env: 'PARSE_SERVER_SCHEMA_AFTER_MIGRATION', + help: 'Execute a callback after running schema migrations.', + }, + beforeMigration: { + env: 'PARSE_SERVER_SCHEMA_BEFORE_MIGRATION', + help: 'Execute a callback before running schema migrations.', + }, + definitions: { + env: 'PARSE_SERVER_SCHEMA_DEFINITIONS', + help: + 'Rest representation on Parse.Schema https://docs.parseplatform.org/rest/guide/#adding-a-schema', + required: true, + action: parsers.objectParser, + default: [], + }, + deleteExtraFields: { + env: 'PARSE_SERVER_SCHEMA_DELETE_EXTRA_FIELDS', + help: + 'Is true if Parse Server should delete any fields not defined in a schema definition. This should only be used during development.', + action: parsers.booleanParser, + default: false, + }, + lockSchemas: { + env: 'PARSE_SERVER_SCHEMA_LOCK_SCHEMAS', + help: + 'Is true if Parse Server will reject any attempts to modify the schema while the server is running.', + action: parsers.booleanParser, + default: false, + }, + recreateModifiedFields: { + env: 'PARSE_SERVER_SCHEMA_RECREATE_MODIFIED_FIELDS', + help: + 'Is true if Parse Server should recreate any fields that are different between the current database schema and theschema definition. This should only be used during development.', + action: parsers.booleanParser, + default: false, + }, + strict: { + env: 'PARSE_SERVER_SCHEMA_STRICT', + help: 'Is true if Parse Server should exit if schema update fail.', + action: parsers.booleanParser, + default: false, + }, +}; module.exports.ParseServerOptions = { accountLockout: { env: 'PARSE_SERVER_ACCOUNT_LOCKOUT', @@ -50,7 +95,7 @@ module.exports.ParseServerOptions = { env: 'PARSE_SERVER_AUTH_PROVIDERS', help: 'Configuration for your authentication providers, as stringified JSON. See http://docs.parseplatform.org/parse-server/guide/#oauth-and-3rd-party-authentication', - action: parsers.objectParser, + action: parsers.arrayParser, }, cacheAdapter: { env: 'PARSE_SERVER_CACHE_ADAPTER', @@ -385,6 +430,11 @@ module.exports.ParseServerOptions = { action: parsers.booleanParser, default: false, }, + schema: { + env: 'PARSE_SERVER_SCHEMA', + help: 'Defined schema', + action: parsers.objectParser, + }, security: { env: 'PARSE_SERVER_SECURITY', help: 'The security options to identify and report weak security settings.', @@ -464,45 +514,6 @@ module.exports.SecurityOptions = { default: false, }, }; -module.exports.SchemaOptions = { - definitions: { - help: 'The schema definitions.', - default: [], - }, - strict: { - env: 'PARSE_SERVER_SCHEMA_STRICT', - help: 'Is true if Parse Server should exit if schema update fail.', - action: parsers.booleanParser, - default: true, - }, - deleteExtraFields: { - env: 'PARSE_SERVER_SCHEMA_DELETE_EXTRA_FIELDS', - help: - 'Is true if Parse Server should delete any fields not defined in a schema definition. This should only be used during development.', - action: parsers.booleanParser, - default: false, - }, - recreateModifiedFields: { - env: 'PARSE_SERVER_SCHEMA_RECREATE_MODIFIED_FIELDS', - help: - 'Is true if Parse Server should recreate any fields that are different between the current database schema and theschema definition. This should only be used during development.', - action: parsers.booleanParser, - default: false, - }, - lockSchemas: { - env: 'PARSE_SERVER_SCHEMA_LOCK', - help: - 'Is true if Parse Server will reject any attempts to modify the schema while the server is running.', - action: parsers.booleanParser, - default: false, - }, - beforeMigration: { - help: 'Execute a callback before running schema migrations.', - }, - afterMigration: { - help: 'Execute a callback after running schema migrations.', - }, -}; module.exports.PagesOptions = { customRoutes: { env: 'PARSE_SERVER_PAGES_CUSTOM_ROUTES', @@ -865,3 +876,10 @@ module.exports.DatabaseOptions = { default: false, }, }; +module.exports.AuthAdapter = { + enabled: { + help: 'Is `true` if the auth adapter is enabled, `false` otherwise.', + action: parsers.booleanParser, + default: true, + }, +}; diff --git a/src/Options/docs.js b/src/Options/docs.js index fc0ff3b799..e8601bd4e5 100644 --- a/src/Options/docs.js +++ b/src/Options/docs.js @@ -1,3 +1,14 @@ +/** + * @interface SchemaOptions + * @property {Function} afterMigration Execute a callback after running schema migrations. + * @property {Function} beforeMigration Execute a callback before running schema migrations. + * @property {Any} definitions Rest representation on Parse.Schema https://docs.parseplatform.org/rest/guide/#adding-a-schema + * @property {Boolean} deleteExtraFields Is true if Parse Server should delete any fields not defined in a schema definition. This should only be used during development. + * @property {Boolean} lockSchemas Is true if Parse Server will reject any attempts to modify the schema while the server is running. + * @property {Boolean} recreateModifiedFields Is true if Parse Server should recreate any fields that are different between the current database schema and theschema definition. This should only be used during development. + * @property {Boolean} strict Is true if Parse Server should exit if schema update fail. + */ + /** * @interface ParseServerOptions * @property {AccountLockoutOptions} accountLockout The account lockout policy for failed login attempts. @@ -8,7 +19,7 @@ * @property {Adapter} analyticsAdapter Adapter module for the analytics * @property {String} appId Your Parse Application ID * @property {String} appName Sets the app name - * @property {Any} auth Configuration for your authentication providers, as stringified JSON. See http://docs.parseplatform.org/parse-server/guide/#oauth-and-3rd-party-authentication + * @property {AuthAdapter[]} auth Configuration for your authentication providers, as stringified JSON. See http://docs.parseplatform.org/parse-server/guide/#oauth-and-3rd-party-authentication * @property {Adapter} cacheAdapter Adapter module for the cache * @property {Number} cacheMaxSize Sets the maximum size for the in memory cache, defaults to 10000 * @property {Number} cacheTTL Sets the TTL for the in memory cache (in ms), defaults to 5000 (5 seconds) @@ -68,6 +79,7 @@ * @property {String} restAPIKey Key for REST calls * @property {Boolean} revokeSessionOnPasswordReset When a user changes their password, either through the reset password email or while logged in, all sessions are revoked if this is true. Set to false if you don't want to revoke sessions. * @property {Boolean} scheduledPush Configuration for push scheduling, defaults to false. + * @property {SchemaOptions} schema Defined schema * @property {SecurityOptions} security The security options to identify and report weak security settings. * @property {Function} serverCloseComplete Callback when server has closed * @property {Function} serverStartComplete Callback when server has started @@ -196,3 +208,8 @@ * @interface DatabaseOptions * @property {Boolean} enableSchemaHooks Enables database real-time hooks to update single schema cache. Set to `true` if using multiple Parse Servers instances connected to the same database. Failing to do so will cause a schema change to not propagate to all instances and re-syncing will only happen when the instances restart. To use this feature with MongoDB, a replica set cluster with [change stream](https://docs.mongodb.com/manual/changeStreams/#availability) support is required. */ + +/** + * @interface AuthAdapter + * @property {Boolean} enabled Is `true` if the auth adapter is enabled, `false` otherwise. + */ diff --git a/src/Options/index.js b/src/Options/index.js index 3482d88c50..c298bc78e2 100644 --- a/src/Options/index.js +++ b/src/Options/index.js @@ -8,7 +8,28 @@ import { MailAdapter } from '../Adapters/Email/MailAdapter'; import { PubSubAdapter } from '../Adapters/PubSub/PubSubAdapter'; import { WSSAdapter } from '../Adapters/WebSocketServer/WSSAdapter'; import { CheckGroup } from '../Security/CheckGroup'; -import type { SchemaOptions } from '../SchemaMigrations/Migrations'; + +export interface SchemaOptions { + /* Rest representation on Parse.Schema https://docs.parseplatform.org/rest/guide/#adding-a-schema + :DEFAULT: [] */ + definitions: any; + /* Is true if Parse Server should exit if schema update fail. + :DEFAULT: false */ + strict: ?boolean; + /* Is true if Parse Server should delete any fields not defined in a schema definition. This should only be used during development. + :DEFAULT: false */ + deleteExtraFields: ?boolean; + /* Is true if Parse Server should recreate any fields that are different between the current database schema and theschema definition. This should only be used during development. + :DEFAULT: false */ + recreateModifiedFields: ?boolean; + /* Is true if Parse Server will reject any attempts to modify the schema while the server is running. + :DEFAULT: false */ + lockSchemas: ?boolean; + /* Execute a callback before running schema migrations. */ + beforeMigration: ?() => void | Promise; + /* Execute a callback after running schema migrations. */ + afterMigration: ?() => void | Promise; +} type Adapter = string | any | T; type NumberOrBoolean = number | boolean; @@ -119,7 +140,7 @@ export interface ParseServerOptions { allowCustomObjectId: ?boolean; /* Configuration for your authentication providers, as stringified JSON. See http://docs.parseplatform.org/parse-server/guide/#oauth-and-3rd-party-authentication :ENV: PARSE_SERVER_AUTH_PROVIDERS */ - auth: ?any; + auth: ?(AuthAdapter[]); /* Max file size for uploads, defaults to 20mb :DEFAULT: 20mb */ maxUploadSize: ?string; @@ -246,7 +267,9 @@ export interface ParseServerOptions { playgroundPath: ?string; /* Callback when server has started */ serverStartComplete: ?(error: ?Error) => void; - /* Rest representation on Parse.Schema https://docs.parseplatform.org/rest/guide/#adding-a-schema */ + /* Defined schema + :ENV: PARSE_SERVER_SCHEMA + */ schema: ?SchemaOptions; /* Callback when server has closed */ serverCloseComplete: ?() => void; @@ -483,3 +506,11 @@ export interface DatabaseOptions { :DEFAULT: false */ enableSchemaHooks: ?boolean; } + +export interface AuthAdapter { + /* Is `true` if the auth adapter is enabled, `false` otherwise. + :DEFAULT: true + :ENV: + */ + enabled: ?boolean; +} diff --git a/src/RestWrite.js b/src/RestWrite.js index be3eea908c..0fc07dc112 100644 --- a/src/RestWrite.js +++ b/src/RestWrite.js @@ -15,6 +15,8 @@ var ClientSDK = require('./ClientSDK'); import RestQuery from './RestQuery'; import _ from 'lodash'; import logger from './logger'; +import Deprecator from './Deprecator/Deprecator'; +import { requiredColumns } from './Controllers/SchemaController'; // query and data are both provided in REST API format. So data // types are encoded by plain old objects. @@ -95,6 +97,7 @@ function RestWrite(config, auth, className, query, data, originalData, clientSDK // Shared SchemaController to be reused to reduce the number of loadSchema() calls per request // Once set the schemaData should be immutable this.validSchemaController = null; + this.pendingOps = {}; } // A convenient method to perform all the steps of processing the @@ -225,18 +228,11 @@ RestWrite.prototype.runBeforeSaveTrigger = function () { return Promise.resolve(); } - // Cloud code gets a bit of extra data for its objects - var extraData = { className: this.className }; - if (this.query && this.query.objectId) { - extraData.objectId = this.query.objectId; - } + const { originalObject, updatedObject } = this.buildParseObjects(); - let originalObject = null; - const updatedObject = this.buildUpdatedObject(extraData); - if (this.query && this.query.objectId) { - // This is an update for existing object. - originalObject = triggers.inflate(extraData, this.originalData); - } + const stateController = Parse.CoreManager.getObjectStateController(); + const [pending] = stateController.getPendingOps(updatedObject._getStateIdentifier()); + this.pendingOps = { ...pending }; return Promise.resolve() .then(() => { @@ -435,7 +431,14 @@ RestWrite.prototype.handleAuthDataValidation = function (authData) { return Promise.resolve(); } const validateAuthData = this.config.authDataManager.getValidatorForProvider(provider); - if (!validateAuthData) { + const authProvider = (this.config.auth || {})[provider] || {}; + if (authProvider.enabled == null) { + Deprecator.logRuntimeDeprecation({ + usage: `auth.${provider}`, + solution: `auth.${provider}.enabled: true`, + }); + } + if (!validateAuthData || authProvider.enabled === false) { throw new Parse.Error( Parse.Error.UNSUPPORTED_SERVICE, 'This authentication method is unsupported.' @@ -1337,6 +1340,9 @@ RestWrite.prototype.runDatabaseOperation = function () { if (this.className === '_Role') { this.config.cacheController.role.clear(); + if (this.config.liveQueryController) { + this.config.liveQueryController.clearCachedRoles(this.auth.user); + } } if (this.className === '_User' && this.query && this.auth.isUnauthenticated()) { @@ -1545,20 +1551,7 @@ RestWrite.prototype.runAfterSaveTrigger = function () { return Promise.resolve(); } - var extraData = { className: this.className }; - if (this.query && this.query.objectId) { - extraData.objectId = this.query.objectId; - } - - // Build the original object, we only do this for a update write. - let originalObject; - if (this.query && this.query.objectId) { - originalObject = triggers.inflate(extraData, this.originalData); - } - - // Build the inflated object, different from beforeSave, originalData is not empty - // since developers can change data in the beforeSave. - const updatedObject = this.buildUpdatedObject(extraData); + const { originalObject, updatedObject } = this.buildParseObjects(); updatedObject._handleSaveResponse(this.response.response, this.response.status || 200); this.config.database.loadSchema().then(schemaController => { @@ -1583,8 +1576,15 @@ RestWrite.prototype.runAfterSaveTrigger = function () { this.context ) .then(result => { - if (result && typeof result === 'object') { + const jsonReturned = result && !result._toFullJSON; + if (jsonReturned) { + this.pendingOps = {}; this.response.response = result; + } else { + this.response.response = this._updateResponseWithData( + (result || updatedObject).toJSON(), + this.data + ); } }) .catch(function (err) { @@ -1618,7 +1618,13 @@ RestWrite.prototype.sanitizedData = function () { }; // Returns an updated copy of the object -RestWrite.prototype.buildUpdatedObject = function (extraData) { +RestWrite.prototype.buildParseObjects = function () { + const extraData = { className: this.className, objectId: this.query?.objectId }; + let originalObject; + if (this.query && this.query.objectId) { + originalObject = triggers.inflate(extraData, this.originalData); + } + const className = Parse.Object.fromJSON(extraData); const readOnlyAttributes = className.constructor.readOnlyAttributes ? className.constructor.readOnlyAttributes() @@ -1656,7 +1662,7 @@ RestWrite.prototype.buildUpdatedObject = function (extraData) { delete sanitized[attribute]; } updatedObject.set(sanitized); - return updatedObject; + return { updatedObject, originalObject }; }; RestWrite.prototype.cleanUserAuthData = function () { @@ -1676,6 +1682,30 @@ RestWrite.prototype.cleanUserAuthData = function () { }; RestWrite.prototype._updateResponseWithData = function (response, data) { + const { updatedObject } = this.buildParseObjects(); + const stateController = Parse.CoreManager.getObjectStateController(); + const [pending] = stateController.getPendingOps(updatedObject._getStateIdentifier()); + for (const key in this.pendingOps) { + if (!pending[key]) { + data[key] = this.originalData ? this.originalData[key] : { __op: 'Delete' }; + this.storage.fieldsChangedByTrigger.push(key); + } + } + const skipKeys = [ + 'objectId', + 'createdAt', + 'updatedAt', + ...(requiredColumns.read[this.className] || []), + ]; + for (const key in response) { + if (skipKeys.includes(key)) { + continue; + } + const value = response[key]; + if (value == null || (value.__type && value.__type === 'Pointer') || data[key] === value) { + delete response[key]; + } + } if (_.isEmpty(this.storage.fieldsChangedByTrigger)) { return response; } diff --git a/src/Routers/FilesRouter.js b/src/Routers/FilesRouter.js index a828f7adf4..f8f25475a7 100644 --- a/src/Routers/FilesRouter.js +++ b/src/Routers/FilesRouter.js @@ -147,7 +147,7 @@ export class FilesRouter { try { // run beforeSaveFile trigger const triggerResult = await triggers.maybeRunFileTrigger( - triggers.Types.beforeSaveFile, + triggers.Types.beforeSave, fileObject, config, req.auth @@ -200,12 +200,7 @@ export class FilesRouter { }; } // run afterSaveFile trigger - await triggers.maybeRunFileTrigger( - triggers.Types.afterSaveFile, - fileObject, - config, - req.auth - ); + await triggers.maybeRunFileTrigger(triggers.Types.afterSave, fileObject, config, req.auth); res.status(201); res.set('Location', saveResult.url); res.json(saveResult); @@ -228,7 +223,7 @@ export class FilesRouter { file._url = filesController.adapter.getFileLocation(req.config, filename); const fileObject = { file, fileSize: null }; await triggers.maybeRunFileTrigger( - triggers.Types.beforeDeleteFile, + triggers.Types.beforeDelete, fileObject, req.config, req.auth @@ -237,7 +232,7 @@ export class FilesRouter { await filesController.deleteFile(req.config, filename); // run afterDeleteFile trigger await triggers.maybeRunFileTrigger( - triggers.Types.afterDeleteFile, + triggers.Types.afterDelete, fileObject, req.config, req.auth diff --git a/src/SchemaMigrations/Migrations.js b/src/SchemaMigrations/Migrations.js index 9142cdbcde..8768911189 100644 --- a/src/SchemaMigrations/Migrations.js +++ b/src/SchemaMigrations/Migrations.js @@ -1,5 +1,15 @@ // @flow +export interface SchemaOptions { + definitions: JSONSchema[]; + strict: ?boolean; + deleteExtraFields: ?boolean; + recreateModifiedFields: ?boolean; + lockSchemas: ?boolean; + beforeMigration: ?() => void | Promise; + afterMigration: ?() => void | Promise; +} + export type FieldValueType = | 'String' | 'Boolean' @@ -35,17 +45,6 @@ export interface IndexesInterface { [key: string]: IndexInterface; } -export interface SchemaOptions { - definitions: JSONSchema[]; - strict: ?boolean; - deleteExtraFields: ?boolean; - recreateModifiedFields: ?boolean; - lockSchemas: ?boolean; - /* Callback when server has started and before running schemas migration operations if schemas key provided */ - beforeMigration: ?() => void | Promise; - afterMigration: ?() => void | Promise; -} - export type CLPOperation = 'find' | 'count' | 'get' | 'update' | 'create' | 'delete'; // @Typescript 4.1+ // type CLPPermission = 'requiresAuthentication' | '*' | `user:${string}` | `role:${string}` diff --git a/src/cloud-code/Parse.Cloud.js b/src/cloud-code/Parse.Cloud.js index 9fb437cada..1ee02fdb60 100644 --- a/src/cloud-code/Parse.Cloud.js +++ b/src/cloud-code/Parse.Cloud.js @@ -134,7 +134,7 @@ ParseCloud.job = function (functionName, handler) { * * **Available in Cloud Code only.** * - * If you want to use beforeSave for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User}), you should pass the class itself and not the String for arg1. + * If you want to use beforeSave for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User} or {@link Parse.File}), you should pass the class itself and not the String for arg1. * * ``` * Parse.Cloud.beforeSave('MyCustomClass', (request) => { @@ -171,7 +171,7 @@ ParseCloud.beforeSave = function (parseClass, handler, validationHandler) { * * **Available in Cloud Code only.** * - * If you want to use beforeDelete for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User}), you should pass the class itself and not the String for arg1. + * If you want to use beforeDelete for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User} or {@link Parse.File}), you should pass the class itself and not the String for arg1. * ``` * Parse.Cloud.beforeDelete('MyCustomClass', (request) => { * // code here @@ -300,7 +300,7 @@ ParseCloud.afterLogout = function (handler) { * * **Available in Cloud Code only.** * - * If you want to use afterSave for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User}), you should pass the class itself and not the String for arg1. + * If you want to use afterSave for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User} or {@link Parse.File}), you should pass the class itself and not the String for arg1. * * ``` * Parse.Cloud.afterSave('MyCustomClass', async function(request) { @@ -337,7 +337,7 @@ ParseCloud.afterSave = function (parseClass, handler, validationHandler) { * * **Available in Cloud Code only.** * - * If you want to use afterDelete for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User}), you should pass the class itself and not the String for arg1. + * If you want to use afterDelete for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User} or {@link Parse.File}), you should pass the class itself and not the String for arg1. * ``` * Parse.Cloud.afterDelete('MyCustomClass', async (request) => { * // code here @@ -373,7 +373,7 @@ ParseCloud.afterDelete = function (parseClass, handler, validationHandler) { * * **Available in Cloud Code only.** * - * If you want to use beforeFind for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User}), you should pass the class itself and not the String for arg1. + * If you want to use beforeFind for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User} or {@link Parse.File}), you should pass the class itself and not the String for arg1. * ``` * Parse.Cloud.beforeFind('MyCustomClass', async (request) => { * // code here @@ -409,7 +409,7 @@ ParseCloud.beforeFind = function (parseClass, handler, validationHandler) { * * **Available in Cloud Code only.** * - * If you want to use afterFind for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User}), you should pass the class itself and not the String for arg1. + * If you want to use afterFind for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User} or {@link Parse.File}), you should pass the class itself and not the String for arg1. * ``` * Parse.Cloud.afterFind('MyCustomClass', async (request) => { * // code here @@ -458,18 +458,17 @@ ParseCloud.afterFind = function (parseClass, handler, validationHandler) { *``` * * @method beforeSaveFile + * @deprecated * @name Parse.Cloud.beforeSaveFile * @param {Function} func The function to run before saving a file. This function can be async and should take just one parameter, {@link Parse.Cloud.FileTriggerRequest}. * @param {(Object|Function)} validator An optional function to help validating cloud code. This function can be an async function and should take one parameter a {@link Parse.Cloud.FileTriggerRequest}, or a {@link Parse.Cloud.ValidatorObject}. */ ParseCloud.beforeSaveFile = function (handler, validationHandler) { - validateValidator(validationHandler); - triggers.addFileTrigger( - triggers.Types.beforeSaveFile, - handler, - Parse.applicationId, - validationHandler - ); + Deprecator.logRuntimeDeprecation({ + usage: 'Parse.Cloud.beforeSaveFile', + solution: 'Use Parse.Cloud.beforeSave(Parse.File, (request) => {})', + }); + ParseCloud.beforeSave(Parse.File, handler, validationHandler); }; /** @@ -490,18 +489,17 @@ ParseCloud.beforeSaveFile = function (handler, validationHandler) { *``` * * @method afterSaveFile + * @deprecated * @name Parse.Cloud.afterSaveFile * @param {Function} func The function to run after saving a file. This function can be async and should take just one parameter, {@link Parse.Cloud.FileTriggerRequest}. * @param {(Object|Function)} validator An optional function to help validating cloud code. This function can be an async function and should take one parameter a {@link Parse.Cloud.FileTriggerRequest}, or a {@link Parse.Cloud.ValidatorObject}. */ ParseCloud.afterSaveFile = function (handler, validationHandler) { - validateValidator(validationHandler); - triggers.addFileTrigger( - triggers.Types.afterSaveFile, - handler, - Parse.applicationId, - validationHandler - ); + Deprecator.logRuntimeDeprecation({ + usage: 'Parse.Cloud.afterSaveFile', + solution: 'Use Parse.Cloud.afterSave(Parse.File, (request) => {})', + }); + ParseCloud.afterSave(Parse.File, handler, validationHandler); }; /** @@ -522,18 +520,17 @@ ParseCloud.afterSaveFile = function (handler, validationHandler) { *``` * * @method beforeDeleteFile + * @deprecated * @name Parse.Cloud.beforeDeleteFile * @param {Function} func The function to run before deleting a file. This function can be async and should take just one parameter, {@link Parse.Cloud.FileTriggerRequest}. * @param {(Object|Function)} validator An optional function to help validating cloud code. This function can be an async function and should take one parameter a {@link Parse.Cloud.FileTriggerRequest}, or a {@link Parse.Cloud.ValidatorObject}. */ ParseCloud.beforeDeleteFile = function (handler, validationHandler) { - validateValidator(validationHandler); - triggers.addFileTrigger( - triggers.Types.beforeDeleteFile, - handler, - Parse.applicationId, - validationHandler - ); + Deprecator.logRuntimeDeprecation({ + usage: 'Parse.Cloud.beforeDeleteFile', + solution: 'Use Parse.Cloud.beforeDelete(Parse.File, (request) => {})', + }); + ParseCloud.beforeDelete(Parse.File, handler, validationHandler); }; /** @@ -554,18 +551,17 @@ ParseCloud.beforeDeleteFile = function (handler, validationHandler) { *``` * * @method afterDeleteFile + * @deprecated * @name Parse.Cloud.afterDeleteFile * @param {Function} func The function to after before deleting a file. This function can be async and should take just one parameter, {@link Parse.Cloud.FileTriggerRequest}. * @param {(Object|Function)} validator An optional function to help validating cloud code. This function can be an async function and should take one parameter a {@link Parse.Cloud.FileTriggerRequest}, or a {@link Parse.Cloud.ValidatorObject}. */ ParseCloud.afterDeleteFile = function (handler, validationHandler) { - validateValidator(validationHandler); - triggers.addFileTrigger( - triggers.Types.afterDeleteFile, - handler, - Parse.applicationId, - validationHandler - ); + Deprecator.logRuntimeDeprecation({ + usage: 'Parse.Cloud.afterDeleteFile', + solution: 'Use Parse.Cloud.afterDelete(Parse.File, (request) => {})', + }); + ParseCloud.afterDelete(Parse.File, handler, validationHandler); }; /** @@ -636,7 +632,7 @@ ParseCloud.sendEmail = function (data) { * * **Available in Cloud Code only.** * - * If you want to use beforeSubscribe for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User}), you should pass the class itself and not the String for arg1. + * If you want to use beforeSubscribe for a predefined class in the Parse JavaScript SDK (e.g. {@link Parse.User} or {@link Parse.File}), you should pass the class itself and not the String for arg1. * ``` * Parse.Cloud.beforeSubscribe('MyCustomClass', (request) => { * // code here diff --git a/src/triggers.js b/src/triggers.js index 8320b5fb74..4ba21b32ea 100644 --- a/src/triggers.js +++ b/src/triggers.js @@ -12,16 +12,11 @@ export const Types = { afterDelete: 'afterDelete', beforeFind: 'beforeFind', afterFind: 'afterFind', - beforeSaveFile: 'beforeSaveFile', - afterSaveFile: 'afterSaveFile', - beforeDeleteFile: 'beforeDeleteFile', - afterDeleteFile: 'afterDeleteFile', beforeConnect: 'beforeConnect', beforeSubscribe: 'beforeSubscribe', afterEvent: 'afterEvent', }; -const FileClassName = '@File'; const ConnectClassName = '@Connect'; const baseStore = function () { @@ -50,6 +45,9 @@ export function getClassName(parseClass) { if (parseClass && parseClass.className) { return parseClass.className; } + if (parseClass && parseClass.name) { + return parseClass.name.replace('Parse', '@'); + } return parseClass; } @@ -140,11 +138,6 @@ export function addTrigger(type, className, handler, applicationId, validationHa add(Category.Validators, `${type}.${className}`, validationHandler, applicationId); } -export function addFileTrigger(type, handler, applicationId, validationHandler) { - add(Category.Triggers, `${type}.${FileClassName}`, handler, applicationId); - add(Category.Validators, `${type}.${FileClassName}`, validationHandler, applicationId); -} - export function addConnectTrigger(type, handler, applicationId, validationHandler) { add(Category.Triggers, `${type}.${ConnectClassName}`, handler, applicationId); add(Category.Validators, `${type}.${ConnectClassName}`, validationHandler, applicationId); @@ -207,10 +200,6 @@ export async function runTrigger(trigger, name, request, auth) { return await trigger(request); } -export function getFileTrigger(type, applicationId) { - return getTrigger(FileClassName, type, applicationId); -} - export function triggerExists(className: string, type: string, applicationId: string): boolean { return getTrigger(className, type, applicationId) != undefined; } @@ -738,7 +727,7 @@ async function builtInTriggerValidator(options, request, auth) { } if (opt.constant && request.object) { if (request.original) { - request.object.set(key, request.original.get(key)); + request.object.revert(key); } else if (opt.default != null) { request.object.set(key, opt.default); } @@ -961,7 +950,8 @@ export function getRequestFileObject(triggerType, auth, fileObject, config) { } export async function maybeRunFileTrigger(triggerType, fileObject, config, auth) { - const fileTrigger = getFileTrigger(triggerType, config.applicationId); + const FileClassName = getClassName(Parse.File); + const fileTrigger = getTrigger(FileClassName, triggerType, config.applicationId); if (typeof fileTrigger === 'function') { try { const request = getRequestFileObject(triggerType, auth, fileObject, config);