diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a2be99ec13..b4d741ae69 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -153,10 +153,6 @@ jobs: strategy: matrix: include: - - name: MongoDB 6, ReplicaSet - MONGODB_VERSION: 6.0.19 - MONGODB_TOPOLOGY: replset - NODE_VERSION: 24.11.0 - name: MongoDB 7, ReplicaSet MONGODB_VERSION: 7.0.16 MONGODB_TOPOLOGY: replset @@ -173,11 +169,7 @@ jobs: - name: Node 20 MONGODB_VERSION: 8.0.4 MONGODB_TOPOLOGY: standalone - NODE_VERSION: 20.18.0 - - name: Node 18 - MONGODB_VERSION: 8.0.4 - MONGODB_TOPOLOGY: standalone - NODE_VERSION: 18.20.4 + NODE_VERSION: 20.19.0 - name: Node 22 MONGODB_VERSION: 8.0.4 MONGODB_TOPOLOGY: standalone @@ -227,15 +219,6 @@ jobs: strategy: matrix: include: - - name: PostgreSQL 15, PostGIS 3.3 - POSTGRES_IMAGE: postgis/postgis:15-3.3 - NODE_VERSION: 24.11.0 - - name: PostgreSQL 15, PostGIS 3.4 - POSTGRES_IMAGE: postgis/postgis:15-3.4 - NODE_VERSION: 24.11.0 - - name: PostgreSQL 15, PostGIS 3.5 - POSTGRES_IMAGE: postgis/postgis:15-3.5 - NODE_VERSION: 24.11.0 - name: PostgreSQL 16, PostGIS 3.5 POSTGRES_IMAGE: postgis/postgis:16-3.5 NODE_VERSION: 24.11.0 diff --git a/.releaserc.js b/.releaserc.js index aa60e1dde7..49ace56f8d 100644 --- a/.releaserc.js +++ b/.releaserc.js @@ -34,7 +34,8 @@ async function config() { console.log(`Running on branch: ${branch}`); // Set changelog file - const changelogFile = `./changelogs/CHANGELOG_${branch}.md`; + const changelogFileSuffix = branch.match(/release-\d+\.x\.x/) ? 'release' : branch; + const changelogFile = `./changelogs/CHANGELOG_${changelogFileSuffix}.md`; // eslint-disable-next-line no-console console.log(`Changelog file output to: ${changelogFile}`); @@ -46,9 +47,8 @@ async function config() { 'release', { name: 'alpha', prerelease: true }, // { name: 'beta', prerelease: true }, - 'next-major', // Long-Term-Support branch - 'release-8.x.x', + { name: 'release-9.x.x', range: '9.x.x', channel: '9.x.x' }, ], dryRun: false, debug: true, diff --git a/9.0.0.md b/9.0.0.md new file mode 100644 index 0000000000..80ba6cf0a8 --- /dev/null +++ b/9.0.0.md @@ -0,0 +1,56 @@ +# Parse Server 9 Migration Guide + +This document only highlights specific changes that require a longer explanation. For a full list of changes in Parse Server 9 please refer to the [changelog](https://github.com/parse-community/parse-server/blob/alpha/CHANGELOG.md). + +--- +- [Route Path Syntax and Rate Limiting](#route-path-syntax-and-rate-limiting) +--- + +## Route Path Syntax and Rate Limiting +Parse Server 9 standardizes the route pattern syntax across cloud routes and rate-limiting to use the new **path-to-regexp v8** style. This update introduces validation and a clear deprecation error for the old wildcard route syntax. + +### Key Changes +- **Standardization**: All route paths now use the path-to-regexp v8 syntax, which provides better consistency and security. +- **Validation**: Added validation to ensure route paths conform to the new syntax. +- **Deprecation**: Old wildcard route syntax is deprecated and will trigger a clear error message. + +### Migration Steps + +#### Path Syntax Examples + +Update your rate limit configurations to use the new path-to-regexp v8 syntax: + +| Old Syntax (deprecated) | New Syntax (v8) | +|------------------------|-----------------| +| `/functions/*` | `/functions/*path` | +| `/classes/*` | `/classes/*path` | +| `/*` | `/*path` | +| `*` | `*path` | + +**Before:** +```javascript +rateLimit: { + requestPath: '/functions/*', + requestTimeWindow: 10000, + requestCount: 100 +} +``` + +**After:** +```javascript +rateLimit: { + requestPath: '/functions/*path', + requestTimeWindow: 10000, + requestCount: 100 +} +``` + +- Review your custom cloud routes and ensure they use the new path-to-regexp v8 syntax. +- Update any rate-limiting configurations to use the new route path format. +- Test your application to ensure all routes work as expected with the new syntax. + +> [!Note] +> Consult the [path-to-regexp v8 docs](https://github.com/pillarjs/path-to-regexp) and the [Express 5 migration guide](https://expressjs.com/en/guide/migrating-5.html#path-syntax) for more details on the new path syntax. + +### Related Pull Request +- [#9942](https://github.com/parse-community/parse-server/pull/9942) diff --git a/DEPRECATIONS.md b/DEPRECATIONS.md index 6ac20b4616..f731644914 100644 --- a/DEPRECATIONS.md +++ b/DEPRECATIONS.md @@ -13,9 +13,10 @@ The following is a list of deprecations, according to the [Deprecation Policy](h | 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) | removed | - | | DEPPS8 | Login with expired 3rd party authentication token defaults to `false` | [#7079](https://github.com/parse-community/parse-server/pull/7079) | 5.3.0 (2022) | 7.0.0 (2024) | removed | - | | DEPPS9 | Rename LiveQuery `fields` option to `keys` | [#8389](https://github.com/parse-community/parse-server/issues/8389) | 6.0.0 (2023) | 7.0.0 (2024) | removed | - | -| DEPPS10 | Encode `Parse.Object` in Cloud Function and remove option `encodeParseObjectInCloudFunction` | [#8634](https://github.com/parse-community/parse-server/issues/8634) | 6.2.0 (2023) | 9.0.0 (2026) | deprecated | - | -| DEPPS11 | Replace `PublicAPIRouter` with `PagesRouter` | [#7625](https://github.com/parse-community/parse-server/issues/7625) | 8.0.0 (2025) | 9.0.0 (2026) | deprecated | - | -| DEPPS12 | Database option `allowPublicExplain` will default to `true` | [#7519](https://github.com/parse-community/parse-server/issues/7519) | 8.5.0 (2025) | 9.0.0 (2026) | deprecated | - | +| DEPPS10 | Encode `Parse.Object` in Cloud Function and remove option `encodeParseObjectInCloudFunction` | [#8634](https://github.com/parse-community/parse-server/issues/8634) | 6.2.0 (2023) | 9.0.0 (2026) | removed | - | +| DEPPS11 | Replace `PublicAPIRouter` with `PagesRouter` | [#7625](https://github.com/parse-community/parse-server/issues/7625) | 8.0.0 (2025) | 9.0.0 (2026) | removed | - | +| DEPPS12 | Database option `allowPublicExplain` defaults to `false` | [#7519](https://github.com/parse-community/parse-server/issues/7519) | 8.5.0 (2025) | 9.0.0 (2026) | removed | - | +| DEPPS13 | Config option `enableInsecureAuthAdapters` defaults to `false` | [#9667](https://github.com/parse-community/parse-server/pull/9667) | 8.0.0 (2025) | 9.0.0 (2026) | removed | - | [i_deprecation]: ## "The version and date of the deprecation." [i_removal]: ## "The version and date of the planned removal." diff --git a/Dockerfile b/Dockerfile index f51759e941..bda315c7d1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -40,7 +40,7 @@ COPY --from=build /tmp/lib lib COPY package*.json ./ COPY bin bin -COPY public_html public_html +COPY public public COPY views views RUN mkdir -p logs && chown -R node: logs diff --git a/README.md b/README.md index ad51487019..de0b21d442 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ [![Coverage](https://codecov.io/github/parse-community/parse-server/branch/alpha/graph/badge.svg)](https://app.codecov.io/github/parse-community/parse-server/tree/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-18,_20,_22,_24-green.svg?logo=node.js&style=flat)](https://nodejs.org) -[![MongoDB Version](https://img.shields.io/badge/mongodb-6,_7,_8-green.svg?logo=mongodb&style=flat)](https://www.mongodb.com) -[![Postgres Version](https://img.shields.io/badge/postgresql-13,_14,_15,_16,_17,_18-green.svg?logo=postgresql&style=flat)](https://www.postgresql.org) +[![Node Version](https://img.shields.io/badge/nodejs-20,_22,_24-green.svg?logo=node.js&style=flat)](https://nodejs.org) +[![MongoDB Version](https://img.shields.io/badge/mongodb-7,_8-green.svg?logo=mongodb&style=flat)](https://www.mongodb.com) +[![Postgres Version](https://img.shields.io/badge/postgresql-16,_17,_18-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) [![npm alpha version](https://img.shields.io/npm/v/parse-server/alpha.svg)](https://www.npmjs.com/package/parse-server) @@ -29,7 +29,7 @@ The full documentation for Parse Server is available in the [wiki](https://githu --- -A big *thank you* 🙏 to our [sponsors](#sponsors) and [backers](#backers) who support the development of Parse Platform! +A big _thank you_ 🙏 to our [sponsors](#sponsors) and [backers](#backers) who support the development of Parse Platform! #### Bronze Sponsors @@ -126,9 +126,9 @@ Before you start make sure you have installed: 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 | Minimum Version | End-of-Life | Parse Server Support | -|------------|-----------------|-------------|----------------------| +| ---------- | --------------- | ----------- | -------------------- | | Node.js 18 | 18.20.4 | April 2025 | <= 8.x (2025) | -| Node.js 20 | 20.18.0 | April 2026 | <= 9.x (2026) | +| Node.js 20 | 20.19.0 | April 2026 | <= 9.x (2026) | | Node.js 22 | 22.12.0 | April 2027 | <= 10.x (2027) | | Node.js 24 | 24.11.0 | April 2028 | <= 11.x (2028) | @@ -137,7 +137,7 @@ Parse Server is continuously tested with the most recent releases of Node.js to 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 [MongoDB lifecycle schedule](https://www.mongodb.com/support-policy/lifecycles) and only test against versions that are officially supported and have not reached their end-of-life date. MongoDB "rapid releases" are ignored as these are considered pre-releases of the next major version. | Version | Minimum Version | End-of-Life | Parse Server Support | -|-----------|-----------------|-------------|----------------------| +| --------- | --------------- | ----------- | -------------------- | | MongoDB 6 | 6.0.19 | July 2025 | <= 8.x (2025) | | MongoDB 7 | 7.0.16 | August 2026 | <= 9.x (2026) | | MongoDB 8 | 8.0.4 | TDB | <= 10.x (2027) | @@ -147,7 +147,7 @@ Parse Server is continuously tested with the most recent releases of MongoDB to 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 about 2 years before the official end-of-life date. | Version | PostGIS Version | End-of-Life | Parse Server Support | -|-------------|-------------------------|---------------|----------------------| +| ----------- | ----------------------- | ------------- | -------------------- | | Postgres 13 | 3.1, 3.2, 3.3, 3.4, 3.5 | November 2025 | <= 6.x (2023) | | Postgres 14 | 3.5 | November 2026 | <= 7.x (2024) | | Postgres 15 | 3.3, 3.4, 3.5 | November 2027 | <= 8.x (2025) | @@ -162,8 +162,8 @@ $ npm install -g parse-server mongodb-runner $ mongodb-runner start $ parse-server --appId APPLICATION_ID --masterKey MASTER_KEY --databaseURI mongodb://localhost/test ``` -***Note:*** *If installation with* `-g` *fails due to permission problems* (`npm ERR! code 'EACCES'`), *please refer to [this link](https://docs.npmjs.com/getting-started/fixing-npm-permissions).* +**_Note:_** _If installation with_ `-g` _fails due to permission problems_ (`npm ERR! code 'EACCES'`), _please refer to [this link](https://docs.npmjs.com/getting-started/fixing-npm-permissions)._ ### Docker Container @@ -180,13 +180,13 @@ $ docker run --name my-mongo -d mongo $ docker run --name my-parse-server -v config-vol:/parse-server/config -p 1337:1337 --link my-mongo:mongo -d parse-server --appId APPLICATION_ID --masterKey MASTER_KEY --databaseURI mongodb://mongo/test ``` -***Note:*** *If you want to use [Cloud Code](https://docs.parseplatform.org/cloudcode/guide/), add `-v cloud-code-vol:/parse-server/cloud --cloud /parse-server/cloud/main.js` to the command above. Make sure `main.js` is in the `cloud-code-vol` directory before starting Parse Server.* +**_Note:_** _If you want to use [Cloud Code](https://docs.parseplatform.org/cloudcode/guide/), add `-v cloud-code-vol:/parse-server/cloud --cloud /parse-server/cloud/main.js` to the command above. Make sure `main.js` is in the `cloud-code-vol` directory before starting Parse Server._ You can use any arbitrary string as your application id and master key. These will be used by your clients to authenticate with the Parse Server. That's it! You are now running a standalone version of Parse Server on your machine. -**Using a remote MongoDB?** Pass the `--databaseURI DATABASE_URI` parameter when starting `parse-server`. Learn more about configuring Parse Server [here](#configuration). For a full list of available options, run `parse-server --help`. +**Using a remote MongoDB?** Pass the `--databaseURI DATABASE_URI` parameter when starting `parse-server`. Learn more about configuring Parse Server [here](#configuration). For a full list of available options, run `parse-server --help`. ### Saving and Querying Objects @@ -204,17 +204,17 @@ Once you have a better understanding of how the project works, please refer to t We have provided a basic [Node.js application](https://github.com/parse-community/parse-server-example) that uses the Parse Server module on Express and can be easily deployed to various infrastructure providers: -* [Heroku and mLab](https://devcenter.heroku.com/articles/deploying-a-parse-server-to-heroku) -* [AWS and Elastic Beanstalk](http://mobile.awsblog.com/post/TxCD57GZLM2JR/How-to-set-up-Parse-Server-on-AWS-using-AWS-Elastic-Beanstalk) -* [Google App Engine](https://medium.com/@justinbeckwith/deploying-parse-server-to-google-app-engine-6bc0b7451d50) -* [Microsoft Azure](https://azure.microsoft.com/en-us/blog/azure-welcomes-parse-developers/) -* [SashiDo](https://blog.sashido.io/tag/migration/) -* [Digital Ocean](https://www.digitalocean.com/community/tutorials/how-to-run-parse-server-on-ubuntu-14-04) -* [Pivotal Web Services](https://github.com/cf-platform-eng/pws-parse-server) -* [Back4app](https://www.back4app.com/docs/get-started/welcome) -* [Glitch](https://glitch.com/edit/#!/parse-server) -* [Flynn](https://flynn.io/blog/parse-apps-on-flynn) -* [Elestio](https://elest.io/open-source/parse) +- [Heroku and mLab](https://devcenter.heroku.com/articles/deploying-a-parse-server-to-heroku) +- [AWS and Elastic Beanstalk](http://mobile.awsblog.com/post/TxCD57GZLM2JR/How-to-set-up-Parse-Server-on-AWS-using-AWS-Elastic-Beanstalk) +- [Google App Engine](https://medium.com/@justinbeckwith/deploying-parse-server-to-google-app-engine-6bc0b7451d50) +- [Microsoft Azure](https://azure.microsoft.com/en-us/blog/azure-welcomes-parse-developers/) +- [SashiDo](https://blog.sashido.io/tag/migration/) +- [Digital Ocean](https://www.digitalocean.com/community/tutorials/how-to-run-parse-server-on-ubuntu-14-04) +- [Pivotal Web Services](https://github.com/cf-platform-eng/pws-parse-server) +- [Back4app](https://www.back4app.com/docs/get-started/welcome) +- [Glitch](https://glitch.com/edit/#!/parse-server) +- [Flynn](https://flynn.io/blog/parse-apps-on-flynn) +- [Elestio](https://elest.io/open-source/parse) ### Parse Server + Express @@ -231,7 +231,7 @@ const server = new ParseServer({ appId: 'myAppId', masterKey: 'myMasterKey', // Keep this key secret! fileKey: 'optionalFileKey', - serverURL: 'http://localhost:1337/parse' // Don't forget to change to https if needed + serverURL: 'http://localhost:1337/parse', // Don't forget to change to https if needed }); // Start server @@ -240,7 +240,7 @@ await server.start(); // Serve the Parse API on the /parse URL prefix app.use('/parse', server.app); -app.listen(1337, function() { +app.listen(1337, function () { console.log('parse-server-example running on port 1337.'); }); ``` @@ -262,7 +262,7 @@ The response looks like this: ### Status Values | Value | Description | -|---------------|-----------------------------------------------------------------------------| +| ------------- | --------------------------------------------------------------------------- | | `initialized` | The server has been created but the `start` method has not been called yet. | | `starting` | The server is starting up. | | `ok` | The server started and is running. | @@ -276,27 +276,27 @@ For the full list of available options, run `parse-server --help` or take a look ## Basic Options -* `appId` **(required)** - The application id to host with this server instance. You can use any arbitrary string. For migrated apps, this should match your hosted Parse app. -* `masterKey` **(required)** - The master key to use for overriding ACL security. You can use any arbitrary string. Keep it secret! For migrated apps, this should match your hosted Parse app. -* `databaseURI` **(required)** - The connection string for your database, i.e. `mongodb://user:pass@host.com/dbname`. Be sure to [URL encode your password](https://app.zencoder.com/docs/guides/getting-started/special-characters-in-usernames-and-passwords) if your password has special characters. -* `port` - The default port is 1337, specify this parameter to use a different port. -* `serverURL` - URL to your Parse Server (don't forget to specify http:// or https://). This URL will be used when making requests to Parse Server from Cloud Code. -* `cloud` - The absolute path to your cloud code `main.js` file. -* `push` - Configuration options for APNS and GCM push. See the [Push Notifications quick start](https://docs.parseplatform.org/parse-server/guide/#push-notifications-quick-start). +- `appId` **(required)** - The application id to host with this server instance. You can use any arbitrary string. For migrated apps, this should match your hosted Parse app. +- `masterKey` **(required)** - The master key to use for overriding ACL security. You can use any arbitrary string. Keep it secret! For migrated apps, this should match your hosted Parse app. +- `databaseURI` **(required)** - The connection string for your database, i.e. `mongodb://user:pass@host.com/dbname`. Be sure to [URL encode your password](https://app.zencoder.com/docs/guides/getting-started/special-characters-in-usernames-and-passwords) if your password has special characters. +- `port` - The default port is 1337, specify this parameter to use a different port. +- `serverURL` - URL to your Parse Server (don't forget to specify http:// or https://). This URL will be used when making requests to Parse Server from Cloud Code. +- `cloud` - The absolute path to your cloud code `main.js` file. +- `push` - Configuration options for APNS and FCM push. See the [Push Notifications quick start](https://docs.parseplatform.org/parse-server/guide/#push-notifications-quick-start). ## Client Key Options The client keys used with Parse are no longer necessary with Parse Server. If you wish to still require them, perhaps to be able to refuse access to older clients, you can set the keys at initialization time. Setting any of these keys will require all requests to provide one of the configured keys. -* `clientKey` -* `javascriptKey` -* `restAPIKey` -* `dotNetKey` +- `clientKey` +- `javascriptKey` +- `restAPIKey` +- `dotNetKey` ## Access Scopes | Scope | Internal data | Read-only data (1) | Custom data | Restricted by CLP, ACL | Key | -|----------------|---------------|-------------------------------|-------------|------------------------|---------------------| +| -------------- | ------------- | ----------------------------- | ----------- | ---------------------- | ------------------- | | Internal | r/w | r/w | r/w | no | `maintenanceKey` | | Master | -/- | r/- | r/w | no | `masterKey` | | ReadOnlyMaster | -/- | r/- | r/- | no | `readOnlyMasterKey` | @@ -323,16 +323,18 @@ const server = ParseServer({ module: 'example-mail-adapter', options: { // Additional adapter options - ...mailAdapterOptions - } + ...mailAdapterOptions, + }, }, }); ``` Offical email adapters maintained by Parse Platform: + - [parse-server-api-mail-adapter](https://github.com/parse-community/parse-server-api-mail-adapter) (localization, templates, universally supports any email provider) Email adapters contributed by the community: + - [parse-smtp-template](https://www.npmjs.com/package/parse-smtp-template) (localization, templates) - [parse-server-postmark-adapter](https://www.npmjs.com/package/parse-server-postmark-adapter) - [parse-server-sendgrid-adapter](https://www.npmjs.com/package/parse-server-sendgrid-adapter) @@ -410,7 +412,7 @@ The `handler` receives the `request` and returns a `custom_page.html` webpage fr 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 | -|-----------------------------|-------------|--------------------| +| --------------------------- | ----------- | ------------------ | | `verify_email` | `GET` | email verification | | `resend_verification_email` | `POST` | email verification | | `choose_password` | `GET` | password reset | @@ -420,7 +422,7 @@ The following paths are already used by Parse Server's built-in features and are ### Parameters | Parameter | Optional | Type | Default value | Example values | Environment variable | Description | -|------------------------------|----------|-----------------|---------------|-----------------------|------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| ---------------------------- | -------- | --------------- | ------------- | --------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `pages` | yes | `Object` | `undefined` | - | `PARSE_SERVER_PAGES` | The options for pages such as password reset and email verification. | | `pages.enableRouter` | yes | `Boolean` | `false` | - | `PARSE_SERVER_PAGES_ENABLE_ROUTER` | Is `true` if the pages router should be enabled; this is required for any of the pages options to take effect. | | `pages.customRoutes` | yes | `Array` | `[]` | - | `PARSE_SERVER_PAGES_CUSTOM_ROUTES` | The custom routes. The routes are added in the order they are defined here, which has to be considered since requests traverse routes in an ordered manner. Custom routes are traversed after build-in routes such as password reset and email verification. | @@ -437,16 +439,16 @@ const server = ParseServer({ ...otherOptions, customPages: { - passwordResetSuccess: "http://yourapp.com/passwordResetSuccess", - verifyEmailSuccess: "http://yourapp.com/verifyEmailSuccess", - parseFrameURL: "http://yourapp.com/parseFrameURL", - linkSendSuccess: "http://yourapp.com/linkSendSuccess", - linkSendFail: "http://yourapp.com/linkSendFail", - invalidLink: "http://yourapp.com/invalidLink", - invalidVerificationLink: "http://yourapp.com/invalidVerificationLink", - choosePassword: "http://yourapp.com/choosePassword" - } -}) + passwordResetSuccess: 'http://yourapp.com/passwordResetSuccess', + verifyEmailSuccess: 'http://yourapp.com/verifyEmailSuccess', + parseFrameURL: 'http://yourapp.com/parseFrameURL', + linkSendSuccess: 'http://yourapp.com/linkSendSuccess', + linkSendFail: 'http://yourapp.com/linkSendFail', + invalidLink: 'http://yourapp.com/invalidLink', + invalidVerificationLink: 'http://yourapp.com/invalidVerificationLink', + choosePassword: 'http://yourapp.com/choosePassword', + }, +}); ``` ## Using Environment Variables @@ -482,10 +484,10 @@ You can also find more adapters maintained by the community by searching on [npm Parse Server allows developers to choose from several options when hosting files: -* `GridFSBucketAdapter` - which is backed by MongoDB -* `S3Adapter` - which is backed by [Amazon S3](https://aws.amazon.com/s3/) -* `GCSAdapter` - which is backed by [Google Cloud Storage](https://cloud.google.com/storage/) -* `FSAdapter` - local file storage +- `GridFSBucketAdapter` - which is backed by MongoDB +- `S3Adapter` - which is backed by [Amazon S3](https://aws.amazon.com/s3/) +- `GCSAdapter` - which is backed by [Google Cloud Storage](https://cloud.google.com/storage/) +- `FSAdapter` - local file storage `GridFSBucketAdapter` is used by default and requires no setup, but if you're interested in using Amazon S3, Google Cloud Storage, or local file storage, additional configuration information is available in the [Parse Server guide](http://docs.parseplatform.org/parse-server/guide/#configuring-file-adapters). @@ -515,7 +517,7 @@ let api = new ParseServer({ ### Parameters | Parameter | Optional | Type | Default value | Example values | Environment variable | Description | -|----------------------------|----------|-----------------|---------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| -------------------------- | -------- | --------------- | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `idempotencyOptions` | yes | `Object` | `undefined` | | PARSE_SERVER_EXPERIMENTAL_IDEMPOTENCY_OPTIONS | Setting this enables idempotency enforcement for the specified paths. | | `idempotencyOptions.paths` | yes | `Array` | `[]` | `.*` (all paths, includes the examples below),
`functions/.*` (all functions),
`jobs/.*` (all jobs),
`classes/.*` (all classes),
`functions/.*` (all functions),
`users` (user creation / update),
`installations` (installation creation / update) | PARSE_SERVER_EXPERIMENTAL_IDEMPOTENCY_PATHS | An array of path patterns that have to match the request path for request deduplication to be enabled. The mount path must not be included, for example to match the request path `/parse/functions/myFunction` specify the path pattern `functions/myFunction`. A trailing slash of the request path is ignored, for example the path pattern `functions/myFunction` matches both `/parse/functions/myFunction` and `/parse/functions/myFunction/`. | | `idempotencyOptions.ttl` | yes | `Integer` | `300` | `60` (60 seconds) | PARSE_SERVER_EXPERIMENTAL_IDEMPOTENCY_TTL | The duration in seconds after which a request record is discarded from the database. Duplicate requests due to network issues can be expected to arrive within milliseconds up to several seconds. This value must be greater than `0`. | @@ -559,11 +561,13 @@ const api = new ParseServer({ ``` Localization is achieved by matching a request-supplied `locale` parameter with localized page content. The locale can be supplied in either the request query, body or header with the following keys: + - query: `locale` - body: `locale` - header: `x-parse-page-param-locale` For example, a password reset link with the locale parameter in the query could look like this: + ``` http://example.com/parse/apps/[appId]/request_password_reset?token=[token]&username=[username]&locale=de-AT ``` @@ -579,6 +583,7 @@ Pages can be localized in two ways: Pages are localized by using the corresponding file in the directory structure where the files are placed in subdirectories named after the locale or language. The file in the base directory is the default file. **Example Directory Structure:** + ```js root/ ├── public/ // pages base path @@ -590,11 +595,13 @@ root/ ``` Files are matched with the locale in the following order: + 1. Locale match, e.g. locale `de-AT` matches file in folder `de-AT`. 1. Language match, e.g. locale `de-CH` matches file in folder `de`. 1. Default; file in base folder is returned. **Configuration Example:** + ```js const api = new ParseServer({ ...otherOptions, @@ -610,9 +617,11 @@ const api = new ParseServer({ ``` Pros: + - All files are complete in their content and can be easily opened and previewed by viewing the file in a browser. Cons: + - In most cases, a localized page differs only slightly from the default page, which could cause a lot of duplicate code that is difficult to maintain. #### Localization with JSON Resource @@ -620,6 +629,7 @@ Cons: Pages are localized by adding placeholders in the HTML files and providing a JSON resource that contains the translations to fill into the placeholders. **Example Directory Structure:** + ```js root/ ├── public/ // pages base path @@ -631,6 +641,7 @@ root/ The JSON resource file loosely follows the [i18next](https://github.com/i18next/i18next) syntax, which is a syntax that is often supported by translation platforms, making it easy to manage translations, exporting them for use in Parse Server, and even to automate this workflow. **Example JSON Content:** + ```json { "en": { // resource for language `en` (English) @@ -652,6 +663,7 @@ The JSON resource file loosely follows the [i18next](https://github.com/i18next/ ``` **Configuration Example:** + ```js const api = new ParseServer({ ...otherOptions, @@ -666,9 +678,11 @@ const api = new ParseServer({ ``` Pros: + - There is only one HTML file to maintain that contains the placeholders that are filled with the translations according to the locale. Cons: + - Files cannot be easily previewed by viewing the file in a browser because the content contains only placeholders and even HTML or CSS changes may be dynamically applied, e.g. when a localization requires a Right-To-Left layout direction. - Style and other fundamental layout changes may be more difficult to apply. @@ -677,6 +691,7 @@ Cons: In addition to feature related default parameters such as `appId` and the translations provided via JSON resource, it is possible to define custom dynamic placeholders as part of the router configuration. This works independently of localization and, also if `enableLocalization` is disabled. **Configuration Example:** + ```js const api = new ParseServer({ ...otherOptions, @@ -689,6 +704,7 @@ const api = new ParseServer({ } } ``` + The placeholders can also be provided as function or as async function, with the `locale` and other feature related parameters passed through, to allow for dynamic placeholder values: ```js @@ -714,7 +730,7 @@ The following parameter and placeholder keys are reserved because they are used #### Parameters | Parameter | Optional | Type | Default value | Example values | Environment variable | Description | -|-------------------------------------------------|----------|---------------------------------------|----------------------------------------|------------------------------------------------------|-----------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| ----------------------------------------------- | -------- | ------------------------------------- | -------------------------------------- | ---------------------------------------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `pages` | yes | `Object` | `undefined` | - | `PARSE_SERVER_PAGES` | The options for pages such as password reset and email verification. | | `pages.enableRouter` | yes | `Boolean` | `false` | - | `PARSE_SERVER_PAGES_ENABLE_ROUTER` | Is `true` if the pages router should be enabled; this is required for any of the pages options to take effect. | | `pages.enableLocalization` | yes | `Boolean` | `false` | - | `PARSE_SERVER_PAGES_ENABLE_LOCALIZATION` | Is true if pages should be localized; this has no effect on custom page redirects. | @@ -741,18 +757,19 @@ The following parameter and placeholder keys are reserved because they are used ## Logging Parse Server will, by default, log: -* to the console -* daily rotating files as new line delimited JSON + +- to the console +- daily rotating files as new line delimited JSON Logs are also viewable in Parse Dashboard. -**Want to log each request and response?** Set the `VERBOSE` environment variable when starting `parse-server`. Usage :- `VERBOSE='1' parse-server --appId APPLICATION_ID --masterKey MASTER_KEY` +**Want to log each request and response?** Set the `VERBOSE` environment variable when starting `parse-server`. Usage :- `VERBOSE='1' parse-server --appId APPLICATION_ID --masterKey MASTER_KEY` -**Want logs to be placed in a different folder?** Pass the `PARSE_SERVER_LOGS_FOLDER` environment variable when starting `parse-server`. Usage :- `PARSE_SERVER_LOGS_FOLDER='' parse-server --appId APPLICATION_ID --masterKey MASTER_KEY` +**Want logs to be placed in a different folder?** Pass the `PARSE_SERVER_LOGS_FOLDER` environment variable when starting `parse-server`. Usage :- `PARSE_SERVER_LOGS_FOLDER='' parse-server --appId APPLICATION_ID --masterKey MASTER_KEY` -**Want to log specific levels?** Pass the `logLevel` parameter when starting `parse-server`. Usage :- `parse-server --appId APPLICATION_ID --masterKey MASTER_KEY --logLevel LOG_LEVEL` +**Want to log specific levels?** Pass the `logLevel` parameter when starting `parse-server`. Usage :- `parse-server --appId APPLICATION_ID --masterKey MASTER_KEY --logLevel LOG_LEVEL` -**Want new line delimited JSON error logs (for consumption by CloudWatch, Google Cloud Logging, etc)?** Pass the `JSON_LOGS` environment variable when starting `parse-server`. Usage :- `JSON_LOGS='1' parse-server --appId APPLICATION_ID --masterKey MASTER_KEY` +**Want new line delimited JSON error logs (for consumption by CloudWatch, Google Cloud Logging, etc)?** Pass the `JSON_LOGS` environment variable when starting `parse-server`. Usage :- `JSON_LOGS='1' parse-server --appId APPLICATION_ID --masterKey MASTER_KEY` # Deprecations @@ -782,7 +799,7 @@ $ parse-server --appId APPLICATION_ID --masterKey MASTER_KEY --databaseURI mongo After starting the server, you can visit http://localhost:1337/playground in your browser to start playing with your GraphQL API. -***Note:*** Do ***NOT*** use --mountPlayground option in production. [Parse Dashboard](https://github.com/parse-community/parse-dashboard) has a built-in GraphQL Playground and it is the recommended option for production apps. +**_Note:_** Do **_NOT_** use --mountPlayground option in production. [Parse Dashboard](https://github.com/parse-community/parse-dashboard) has a built-in GraphQL Playground and it is the recommended option for production apps. ### Using Docker @@ -801,11 +818,11 @@ $ docker run --name my-mongo -d mongo $ docker run --name my-parse-server --link my-mongo:mongo -v config-vol:/parse-server/config -p 1337:1337 -d parse-server --appId APPLICATION_ID --masterKey MASTER_KEY --databaseURI mongodb://mongo/test --publicServerURL http://localhost:1337/parse --mountGraphQL --mountPlayground ``` -***Note:*** *If you want to use [Cloud Code](https://docs.parseplatform.org/cloudcode/guide/), add `-v cloud-code-vol:/parse-server/cloud --cloud /parse-server/cloud/main.js` to the command above. Make sure `main.js` is in the `cloud-code-vol` directory before starting Parse Server.* +**_Note:_** _If you want to use [Cloud Code](https://docs.parseplatform.org/cloudcode/guide/), add `-v cloud-code-vol:/parse-server/cloud --cloud /parse-server/cloud/main.js` to the command above. Make sure `main.js` is in the `cloud-code-vol` directory before starting Parse Server._ After starting the server, you can visit http://localhost:1337/playground in your browser to start playing with your GraphQL API. -***Note:*** Do ***NOT*** use --mountPlayground option in production. [Parse Dashboard](https://github.com/parse-community/parse-dashboard) has a built-in GraphQL Playground and it is the recommended option for production apps. +**_Note:_** Do **_NOT_** use --mountPlayground option in production. [Parse Dashboard](https://github.com/parse-community/parse-dashboard) has a built-in GraphQL Playground and it is the recommended option for production apps. ### Using Express.js @@ -830,23 +847,20 @@ const parseServer = new ParseServer({ appId: 'APPLICATION_ID', masterKey: 'MASTER_KEY', serverURL: 'http://localhost:1337/parse', - publicServerURL: 'http://localhost:1337/parse' + publicServerURL: 'http://localhost:1337/parse', }); -const parseGraphQLServer = new ParseGraphQLServer( - parseServer, - { - graphQLPath: '/graphql', - playgroundPath: '/playground' - } -); +const parseGraphQLServer = new ParseGraphQLServer(parseServer, { + graphQLPath: '/graphql', + playgroundPath: '/playground', +}); app.use('/parse', parseServer.app); // (Optional) Mounts the REST API parseGraphQLServer.applyGraphQL(app); // Mounts the GraphQL API parseGraphQLServer.applyPlayground(app); // (Optional) Mounts the GraphQL Playground - do NOT use in Production await parseServer.start(); -app.listen(1337, function() { +app.listen(1337, function () { console.log('REST API running on http://localhost:1337/parse'); console.log('GraphQL API running on http://localhost:1337/graphql'); console.log('GraphQL Playground running on http://localhost:1337/playground'); @@ -862,7 +876,7 @@ $ node index.js After starting the app, you can visit http://localhost:1337/playground in your browser to start playing with your GraphQL API. -***Note:*** Do ***NOT*** mount the GraphQL Playground in production. [Parse Dashboard](https://github.com/parse-community/parse-dashboard) has a built-in GraphQL Playground and it is the recommended option for production apps. +**_Note:_** Do **_NOT_** mount the GraphQL Playground in production. [Parse Dashboard](https://github.com/parse-community/parse-dashboard) has a built-in GraphQL Playground and it is the recommended option for production apps. ## Checking the API health @@ -957,13 +971,7 @@ Run the following to create your first object: ```graphql mutation CreateGameScore { - createGameScore( - fields: { - playerName: "Sean Plott" - score: 1337 - cheatMode: false - } - ) { + createGameScore(fields: { playerName: "Sean Plott", score: 1337, cheatMode: false }) { id updatedAt createdAt @@ -1142,4 +1150,5 @@ Support us with a monthly donation and help us continue our activities. [Become [log_release]: https://github.com/parse-community/parse-server/blob/release/changelogs/CHANGELOG_release.md [log_beta]: https://github.com/parse-community/parse-server/blob/beta/changelogs/CHANGELOG_beta.md [log_alpha]: https://github.com/parse-community/parse-server/blob/alpha/changelogs/CHANGELOG_alpha.md + [server-options] http://parseplatform.org/parse-server/api/release/ParseServerOptions.html diff --git a/changelogs/CHANGELOG_alpha.md b/changelogs/CHANGELOG_alpha.md index b3cb71775a..e689b543c2 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,125 @@ +# [9.0.0-alpha.11](https://github.com/parse-community/parse-server/compare/9.0.0-alpha.10...9.0.0-alpha.11) (2025-12-14) + + +### Features + +* Deprecation DEPPS113: Config option `enableInsecureAuthAdapters` defaults to `false` ([#9982](https://github.com/parse-community/parse-server/issues/9982)) ([22d4622](https://github.com/parse-community/parse-server/commit/22d4622230b74839ed408a02bfcabb7b37b85aba)) + + +### BREAKING CHANGES + +* This release changes the config option `enableInsecureAuthAdapters` default to `false` (Deprecation DEPPS13). ([22d4622](22d4622)) + +# [9.0.0-alpha.10](https://github.com/parse-community/parse-server/compare/9.0.0-alpha.9...9.0.0-alpha.10) (2025-12-12) + + +### Features + +* Upgrade to @parse/push-adapter 8.1.0 ([#9938](https://github.com/parse-community/parse-server/issues/9938)) ([d5e76b0](https://github.com/parse-community/parse-server/commit/d5e76b01db2b4eeb22a0bb5a04347a89209aa822)) + +# [9.0.0-alpha.9](https://github.com/parse-community/parse-server/compare/9.0.0-alpha.8...9.0.0-alpha.9) (2025-12-12) + + +### Features + +* Deprecation DEPPS12: Database option `allowPublicExplain` defaults to `false` ([#9975](https://github.com/parse-community/parse-server/issues/9975)) ([c1c7e69](https://github.com/parse-community/parse-server/commit/c1c7e6976d868ccbc7dff325edce78ddfa999bb9)) + + +### BREAKING CHANGES + +* This release changes the MongoDB database option `allowPublicExplain` default to `false` (Deprecation DEPPS12). ([c1c7e69](c1c7e69)) + +# [9.0.0-alpha.8](https://github.com/parse-community/parse-server/compare/9.0.0-alpha.7...9.0.0-alpha.8) (2025-12-12) + + +### Features + +* Deprecation DEPPS11: Replace `PublicAPIRouter` with `PagesRouter` ([#9974](https://github.com/parse-community/parse-server/issues/9974)) ([8f877d4](https://github.com/parse-community/parse-server/commit/8f877d42c02a6492b97c61e75ab77a896878f866)) + + +### BREAKING CHANGES + +* This release replaces `PublicAPIRouter` with `PagesRouter` (Deprecation DEPPS11). ([8f877d4](8f877d4)) + +# [9.0.0-alpha.7](https://github.com/parse-community/parse-server/compare/9.0.0-alpha.6...9.0.0-alpha.7) (2025-12-12) + + +### Features + +* Deprecation DEPPS10: Encode `Parse.Object` in Cloud Function and remove option `encodeParseObjectInCloudFunction` ([#9973](https://github.com/parse-community/parse-server/issues/9973)) ([a2d3dbe](https://github.com/parse-community/parse-server/commit/a2d3dbe972e2e02ac599bfffe1ae6cd9768b02ca)) + + +### BREAKING CHANGES + +* This release encodes `Parse.Object` in Cloud Function and removes option `encodeParseObjectInCloudFunction` (Deprecation DEPPS10). ([a2d3dbe](a2d3dbe)) + +# [9.0.0-alpha.6](https://github.com/parse-community/parse-server/compare/9.0.0-alpha.5...9.0.0-alpha.6) (2025-12-12) + + +### Features + +* Increase required minimum version to Postgres `16`, PostGIS `3.5` ([#9972](https://github.com/parse-community/parse-server/issues/9972)) ([7483add](https://github.com/parse-community/parse-server/commit/7483add73934e7d16098ccfb672cc45b3f7c7fbe)) + + +### BREAKING CHANGES + +* This releases increases the required minimum version to Postgres `16`, PostGIS `3.5`. ([7483add](7483add)) + +# [9.0.0-alpha.5](https://github.com/parse-community/parse-server/compare/9.0.0-alpha.4...9.0.0-alpha.5) (2025-12-12) + + +### Features + +* Update route patterns to use path-to-regexp v8 syntax ([#9942](https://github.com/parse-community/parse-server/issues/9942)) ([fa8723b](https://github.com/parse-community/parse-server/commit/fa8723b3d1e895602d1187540818bbdb446259ba)) + + +### BREAKING CHANGES + +* Route pattern syntax across cloud routes and rate-limiting now use the new path-to-regexp v8 syntax; see the [migration guide](https://github.com/parse-community/parse-server/blob/alpha/9.0.0.md) for more details. ([fa8723b](fa8723b)) + +# [9.0.0-alpha.4](https://github.com/parse-community/parse-server/compare/9.0.0-alpha.3...9.0.0-alpha.4) (2025-12-12) + + +### Features + +* Increase required minimum MongoDB version to `7.0.16` ([#9971](https://github.com/parse-community/parse-server/issues/9971)) ([7bb548b](https://github.com/parse-community/parse-server/commit/7bb548bf81b3cebc9ec92ef9e5e6faf8f9edbd3b)) + + +### BREAKING CHANGES + +* This releases increases the required minimum MongoDB version to `7.0.16`. ([7bb548b](7bb548b)) + +# [9.0.0-alpha.3](https://github.com/parse-community/parse-server/compare/9.0.0-alpha.2...9.0.0-alpha.3) (2025-12-12) + + +### Bug Fixes + +* Upgrade to GraphQL Apollo Server 5 and restrict GraphQL introspection ([#9888](https://github.com/parse-community/parse-server/issues/9888)) ([87c7f07](https://github.com/parse-community/parse-server/commit/87c7f076eb84c9540f79f06c27fe13e102dc6295)) + + +### BREAKING CHANGES + +* Upgrade to Apollo Server 5 and GraphQL express 5 integration; GraphQL introspection now requires using `masterKey` or setting `graphQLPublicIntrospection: true`. ([87c7f07](87c7f07)) + +# [9.0.0-alpha.2](https://github.com/parse-community/parse-server/compare/9.0.0-alpha.1...9.0.0-alpha.2) (2025-12-12) + + +### Features + +* Upgrade to parse 8.0.0 ([#9976](https://github.com/parse-community/parse-server/issues/9976)) ([f9970d4](https://github.com/parse-community/parse-server/commit/f9970d4bb253494392fb4cc366f222119927f082)) + +# [9.0.0-alpha.1](https://github.com/parse-community/parse-server/compare/8.6.0...9.0.0-alpha.1) (2025-12-12) + + +### Features + +* Increase required minimum Node version to `20.19.0` ([#9970](https://github.com/parse-community/parse-server/issues/9970)) ([633964d](https://github.com/parse-community/parse-server/commit/633964d32e249d8cc16c58de7ddd9b7637c69fb1)) + + +### BREAKING CHANGES + +* This releases increases the required minimum Node version to `20.19.0`. ([633964d](633964d)) + # [8.6.0-alpha.2](https://github.com/parse-community/parse-server/compare/8.6.0-alpha.1...8.6.0-alpha.2) (2025-12-10) diff --git a/package-lock.json b/package-lock.json index 1d8eb8f06c..6fee783984 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,21 +1,22 @@ { "name": "parse-server", - "version": "8.6.0", + "version": "9.0.0-alpha.11", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "parse-server", - "version": "8.6.0", + "version": "9.0.0-alpha.11", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "@apollo/server": "4.12.1", + "@apollo/server": "5.0.0", + "@as-integrations/express5": "1.1.2", "@graphql-tools/merge": "9.0.24", "@graphql-tools/schema": "10.0.23", "@graphql-tools/utils": "10.8.6", "@parse/fs-files-adapter": "3.0.0", - "@parse/push-adapter": "6.11.0", + "@parse/push-adapter": "8.1.0", "bcryptjs": "3.0.2", "commander": "13.1.0", "cors": "2.8.5", @@ -37,8 +38,8 @@ "mongodb": "6.20.0", "mustache": "4.2.0", "otpauth": "9.4.0", - "parse": "7.1.2", - "path-to-regexp": "6.3.0", + "parse": "8.0.0", + "path-to-regexp": "8.3.0", "pg-monitor": "3.0.0", "pg-promise": "12.2.0", "pluralize": "8.0.0", @@ -81,7 +82,7 @@ "eslint": "9.27.0", "eslint-plugin-expect-type": "0.6.2", "eslint-plugin-unused-imports": "4.3.0", - "form-data": "4.0.4", + "form-data": "4.0.5", "globals": "16.2.0", "graphql-tag": "2.12.6", "jasmine": "5.7.1", @@ -104,7 +105,7 @@ "yaml": "2.8.0" }, "engines": { - "node": ">=18.20.4 <19.0.0 || >=20.18.0 <21.0.0 || >=22.12.0 <23.0.0 || >=24.11.0 <25.0.0" + "node": ">=20.19.0 <21.0.0 || >=22.12.0 <23.0.0 || >=24.11.0 <25.0.0" }, "funding": { "type": "opencollective", @@ -237,418 +238,61 @@ } }, "node_modules/@apollo/server": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@apollo/server/-/server-4.12.1.tgz", - "integrity": "sha512-jceK1LK6l074in4mWu8XkwzDjvxdSzkmk8M7YpVLOGjQ6PmlaChcGRJ9BUwB46r22MxdPCXdC/6U5Vi8gzYbvQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@apollo/server/-/server-5.0.0.tgz", + "integrity": "sha512-PHopOm7pr69k7eDJvCBU4cZy9Z19qyCFKB9/luLnf2YCatu2WOYhoQPNr3dAoe//xv0RZFhxXbRcnK6IXIP7Nw==", "license": "MIT", "dependencies": { "@apollo/cache-control-types": "^1.0.3", - "@apollo/server-gateway-interface": "^1.1.1", + "@apollo/server-gateway-interface": "^2.0.0", "@apollo/usage-reporting-protobuf": "^4.1.1", - "@apollo/utils.createhash": "^2.0.2", - "@apollo/utils.fetcher": "^2.0.0", - "@apollo/utils.isnodelike": "^2.0.0", - "@apollo/utils.keyvaluecache": "^2.1.0", - "@apollo/utils.logger": "^2.0.0", + "@apollo/utils.createhash": "^3.0.0", + "@apollo/utils.fetcher": "^3.0.0", + "@apollo/utils.isnodelike": "^3.0.0", + "@apollo/utils.keyvaluecache": "^4.0.0", + "@apollo/utils.logger": "^3.0.0", "@apollo/utils.usagereporting": "^2.1.0", - "@apollo/utils.withrequired": "^2.0.0", - "@graphql-tools/schema": "^9.0.0", - "@types/express": "^4.17.13", - "@types/express-serve-static-core": "^4.17.30", - "@types/node-fetch": "^2.6.1", + "@apollo/utils.withrequired": "^3.0.0", + "@graphql-tools/schema": "^10.0.0", "async-retry": "^1.2.1", + "body-parser": "^2.2.0", "cors": "^2.8.5", - "express": "^4.21.1", + "finalhandler": "^2.1.0", "loglevel": "^1.6.8", - "lru-cache": "^7.10.1", - "negotiator": "^0.6.3", - "node-abort-controller": "^3.1.1", - "node-fetch": "^2.6.7", - "uuid": "^9.0.0", - "whatwg-mimetype": "^3.0.0" + "lru-cache": "^11.1.0", + "negotiator": "^1.0.0", + "uuid": "^11.1.0", + "whatwg-mimetype": "^4.0.0" }, "engines": { - "node": ">=14.16.0" + "node": ">=20" }, "peerDependencies": { - "graphql": "^16.6.0" + "graphql": "^16.11.0" } }, "node_modules/@apollo/server-gateway-interface": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@apollo/server-gateway-interface/-/server-gateway-interface-1.1.1.tgz", - "integrity": "sha512-pGwCl/po6+rxRmDMFgozKQo2pbsSwE91TpsDBAOgf74CRDPXHHtM88wbwjab0wMMZh95QfR45GGyDIdhY24bkQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@apollo/server-gateway-interface/-/server-gateway-interface-2.0.0.tgz", + "integrity": "sha512-3HEMD6fSantG2My3jWkb9dvfkF9vJ4BDLRjMgsnD790VINtuPaEp+h3Hg9HOHiWkML6QsOhnaRqZ+gvhp3y8Nw==", + "license": "MIT", "dependencies": { "@apollo/usage-reporting-protobuf": "^4.1.1", - "@apollo/utils.fetcher": "^2.0.0", - "@apollo/utils.keyvaluecache": "^2.1.0", - "@apollo/utils.logger": "^2.0.0" + "@apollo/utils.fetcher": "^3.0.0", + "@apollo/utils.keyvaluecache": "^4.0.0", + "@apollo/utils.logger": "^3.0.0" }, "peerDependencies": { "graphql": "14.x || 15.x || 16.x" } }, - "node_modules/@apollo/server/node_modules/@graphql-tools/merge": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.4.2.tgz", - "integrity": "sha512-XbrHAaj8yDuINph+sAfuq3QCZ/tKblrTLOpirK0+CAgNlZUCHs0Fa+xtMUURgwCVThLle1AF7svJCxFizygLsw==", - "dependencies": { - "@graphql-tools/utils": "^9.2.1", - "tslib": "^2.4.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@apollo/server/node_modules/@graphql-tools/schema": { - "version": "9.0.19", - "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-9.0.19.tgz", - "integrity": "sha512-oBRPoNBtCkk0zbUsyP4GaIzCt8C0aCI4ycIRUL67KK5pOHljKLBBtGT+Jr6hkzA74C8Gco8bpZPe7aWFjiaK2w==", - "dependencies": { - "@graphql-tools/merge": "^8.4.1", - "@graphql-tools/utils": "^9.2.1", - "tslib": "^2.4.0", - "value-or-promise": "^1.0.12" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@apollo/server/node_modules/@graphql-tools/utils": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-9.2.1.tgz", - "integrity": "sha512-WUw506Ql6xzmOORlriNrD6Ugx+HjVgYxt9KCXD9mHAak+eaXSwuGGPyE60hy9xaDEoXKBsG7SkG69ybitaVl6A==", - "dependencies": { - "@graphql-typed-document-node/core": "^3.1.1", - "tslib": "^2.4.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@apollo/server/node_modules/accepts": { - "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==", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@apollo/server/node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/@apollo/server/node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@apollo/server/node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" - }, - "node_modules/@apollo/server/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/@apollo/server/node_modules/express": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", - "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "~1.20.3", - "content-disposition": "~0.5.4", - "content-type": "~1.0.4", - "cookie": "~0.7.1", - "cookie-signature": "~1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.3.1", - "fresh": "~0.5.2", - "http-errors": "~2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "~0.1.12", - "proxy-addr": "~2.0.7", - "qs": "~6.14.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "~0.19.0", - "serve-static": "~1.16.2", - "setprototypeof": "1.2.0", - "statuses": "~2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@apollo/server/node_modules/express/node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/@apollo/server/node_modules/finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@apollo/server/node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@apollo/server/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/@apollo/server/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "engines": { - "node": ">=12" - } - }, - "node_modules/@apollo/server/node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@apollo/server/node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@apollo/server/node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@apollo/server/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/@apollo/server/node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/@apollo/server/node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" - }, - "node_modules/@apollo/server/node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@apollo/server/node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", - "dependencies": { - "debug": "2.6.9", - "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": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/@apollo/server/node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@apollo/server/node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "node_modules/@apollo/server/node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", - "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/@apollo/server/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "node_modules/@apollo/server/node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.2.tgz", + "integrity": "sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==", + "license": "ISC", "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@apollo/server/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@apollo/server/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "node_modules/@apollo/server/node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" + "node": "20 || >=22" } }, "node_modules/@apollo/usage-reporting-protobuf": { @@ -660,15 +304,16 @@ } }, "node_modules/@apollo/utils.createhash": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@apollo/utils.createhash/-/utils.createhash-2.0.2.tgz", - "integrity": "sha512-UkS3xqnVFLZ3JFpEmU/2cM2iKJotQXMoSTgxXsfQgXLC5gR1WaepoXagmYnPSA7Q/2cmnyTYK5OgAgoC4RULPg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@apollo/utils.createhash/-/utils.createhash-3.0.1.tgz", + "integrity": "sha512-CKrlySj4eQYftBE5MJ8IzKwIibQnftDT7yGfsJy5KSEEnLlPASX0UTpbKqkjlVEwPPd4mEwI7WOM7XNxEuO05A==", + "license": "MIT", "dependencies": { - "@apollo/utils.isnodelike": "^2.0.1", + "@apollo/utils.isnodelike": "^3.0.0", "sha.js": "^2.4.11" }, "engines": { - "node": ">=14" + "node": ">=16" } }, "node_modules/@apollo/utils.dropunuseddefinitions": { @@ -683,47 +328,52 @@ } }, "node_modules/@apollo/utils.fetcher": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@apollo/utils.fetcher/-/utils.fetcher-2.0.1.tgz", - "integrity": "sha512-jvvon885hEyWXd4H6zpWeN3tl88QcWnHp5gWF5OPF34uhvoR+DFqcNxs9vrRaBBSY3qda3Qe0bdud7tz2zGx1A==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@apollo/utils.fetcher/-/utils.fetcher-3.1.0.tgz", + "integrity": "sha512-Z3QAyrsQkvrdTuHAFwWDNd+0l50guwoQUoaDQssLOjkmnmVuvXlJykqlEJolio+4rFwBnWdoY1ByFdKaQEcm7A==", + "license": "MIT", "engines": { - "node": ">=14" + "node": ">=16" } }, "node_modules/@apollo/utils.isnodelike": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@apollo/utils.isnodelike/-/utils.isnodelike-2.0.1.tgz", - "integrity": "sha512-w41XyepR+jBEuVpoRM715N2ZD0xMD413UiJx8w5xnAZD2ZkSJnMJBoIzauK83kJpSgNuR6ywbV29jG9NmxjK0Q==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@apollo/utils.isnodelike/-/utils.isnodelike-3.0.0.tgz", + "integrity": "sha512-xrjyjfkzunZ0DeF6xkHaK5IKR8F1FBq6qV+uZ+h9worIF/2YSzA0uoBxGv6tbTeo9QoIQnRW4PVFzGix5E7n/g==", + "license": "MIT", "engines": { - "node": ">=14" + "node": ">=16" } }, "node_modules/@apollo/utils.keyvaluecache": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@apollo/utils.keyvaluecache/-/utils.keyvaluecache-2.1.1.tgz", - "integrity": "sha512-qVo5PvUUMD8oB9oYvq4ViCjYAMWnZ5zZwEjNF37L2m1u528x5mueMlU+Cr1UinupCgdB78g+egA1G98rbJ03Vw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@apollo/utils.keyvaluecache/-/utils.keyvaluecache-4.0.0.tgz", + "integrity": "sha512-mKw1myRUkQsGPNB+9bglAuhviodJ2L2MRYLTafCMw5BIo7nbvCPNCkLnIHjZ1NOzH7SnMAr5c9LmXiqsgYqLZw==", + "license": "MIT", "dependencies": { - "@apollo/utils.logger": "^2.0.1", - "lru-cache": "^7.14.1" + "@apollo/utils.logger": "^3.0.0", + "lru-cache": "^11.0.0" }, "engines": { - "node": ">=14" + "node": ">=20" } }, "node_modules/@apollo/utils.keyvaluecache/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.2.tgz", + "integrity": "sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==", + "license": "ISC", "engines": { - "node": ">=12" + "node": "20 || >=22" } }, "node_modules/@apollo/utils.logger": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@apollo/utils.logger/-/utils.logger-2.0.1.tgz", - "integrity": "sha512-YuplwLHaHf1oviidB7MxnCXAdHp3IqYV8n0momZ3JfLniae92eYqMIx+j5qJFX6WKJPs6q7bczmV4lXIsTu5Pg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@apollo/utils.logger/-/utils.logger-3.0.0.tgz", + "integrity": "sha512-M8V8JOTH0F2qEi+ktPfw4RL7MvUycDfKp7aEap2eWXfL5SqWHN6jTLbj5f5fj1cceHpyaUSOZlvlaaryaxZAmg==", + "license": "MIT", "engines": { - "node": ">=14" + "node": ">=16" } }, "node_modules/@apollo/utils.printwithreducedwhitespace": { @@ -793,11 +443,25 @@ } }, "node_modules/@apollo/utils.withrequired": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@apollo/utils.withrequired/-/utils.withrequired-2.0.1.tgz", - "integrity": "sha512-YBDiuAX9i1lLc6GeTy1m7DGLFn/gMnvXqlalOIMjM7DeOgIacEjjfwPqb0M1CQ2v11HhR15d1NmxJoRCfrNqcA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@apollo/utils.withrequired/-/utils.withrequired-3.0.0.tgz", + "integrity": "sha512-aaxeavfJ+RHboh7c2ofO5HHtQobGX4AgUujXP4CXpREHp9fQ9jPi6K9T1jrAKe7HIipoP0OJ1gd6JamSkFIpvA==", + "license": "MIT", "engines": { - "node": ">=14" + "node": ">=16" + } + }, + "node_modules/@as-integrations/express5": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@as-integrations/express5/-/express5-1.1.2.tgz", + "integrity": "sha512-BxfwtcWNf2CELDkuPQxi5Zl3WqY/dQVJYafeCBOGoFQjv5M0fjhxmAFZ9vKx/5YKKNeok4UY6PkFbHzmQrdxIA==", + "license": "MIT", + "engines": { + "node": ">=20" + }, + "peerDependencies": { + "@apollo/server": "^4.0.0 || ^5.0.0", + "express": "^5.0.0" } }, "node_modules/@babel/cli": { @@ -2828,9 +2492,9 @@ } }, "node_modules/@fastify/busboy": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-3.1.1.tgz", - "integrity": "sha512-5DGmA8FTdB2XbDeEwc/5ZXBl6UbBAyBOOLlPuBnZ/N1SwdH9Ii+cOX3tBROlDgcTXxjOYnLMVoKk9+FXAw0CJw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-3.2.0.tgz", + "integrity": "sha512-m9FVDXU3GT2ITSe0UaMA5rU3QkfC/UXtCU8y0gSN/GugTqtVldOBWIB5V6V3sbmenVZUIpU6f+mPEO2+m5iTaA==", "license": "MIT" }, "node_modules/@firebase/app-check-interop-types": { @@ -2852,92 +2516,92 @@ "license": "Apache-2.0" }, "node_modules/@firebase/component": { - "version": "0.6.13", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.13.tgz", - "integrity": "sha512-I/Eg1NpAtZ8AAfq8mpdfXnuUpcLxIDdCDtTzWSh+FXnp/9eCKJ3SNbOCKrUCyhLzNa2SiPJYruei0sxVjaOTeg==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.0.tgz", + "integrity": "sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg==", "license": "Apache-2.0", "dependencies": { - "@firebase/util": "1.11.0", + "@firebase/util": "1.13.0", "tslib": "^2.1.0" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, "node_modules/@firebase/database": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.13.tgz", - "integrity": "sha512-cdc+LuseKdJXzlrCx8ePMXyctSWtYS9SsP3y7EeA85GzNh/IL0b7HOq0eShridL935iQ0KScZCj5qJtKkGE53g==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.1.0.tgz", + "integrity": "sha512-gM6MJFae3pTyNLoc9VcJNuaUDej0ctdjn3cVtILo3D5lpp0dmUHHLFN/pUKe7ImyeB1KAvRlEYxvIHNF04Filg==", "license": "Apache-2.0", "dependencies": { "@firebase/app-check-interop-types": "0.3.3", "@firebase/auth-interop-types": "0.2.4", - "@firebase/component": "0.6.13", - "@firebase/logger": "0.4.4", - "@firebase/util": "1.11.0", + "@firebase/component": "0.7.0", + "@firebase/logger": "0.5.0", + "@firebase/util": "1.13.0", "faye-websocket": "0.11.4", "tslib": "^2.1.0" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, "node_modules/@firebase/database-compat": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-2.0.4.tgz", - "integrity": "sha512-4qsptwZ3DTGNBje56ETItZQyA/HMalOelnLmkC3eR0M6+zkzOHjNHyWUWodW2mqxRKAM0sGkn+aIwYHKZFJXug==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-2.1.0.tgz", + "integrity": "sha512-8nYc43RqxScsePVd1qe1xxvWNf0OBnbwHxmXJ7MHSuuTVYFO3eLyLW3PiCKJ9fHnmIz4p4LbieXwz+qtr9PZDg==", "license": "Apache-2.0", "dependencies": { - "@firebase/component": "0.6.13", - "@firebase/database": "1.0.13", - "@firebase/database-types": "1.0.9", - "@firebase/logger": "0.4.4", - "@firebase/util": "1.11.0", + "@firebase/component": "0.7.0", + "@firebase/database": "1.1.0", + "@firebase/database-types": "1.0.16", + "@firebase/logger": "0.5.0", + "@firebase/util": "1.13.0", "tslib": "^2.1.0" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, "node_modules/@firebase/database-types": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.9.tgz", - "integrity": "sha512-uCntrxPbJHhZsNRpMhxNCm7GzhYWX+7J2e57wq1ZZ4NJrQw5DORgkAzJMByYZcVAjgADnCxxhK/GkoypH+XpvQ==", + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.16.tgz", + "integrity": "sha512-xkQLQfU5De7+SPhEGAXFBnDryUWhhlFXelEg2YeZOQMCdoe7dL64DDAd77SQsR+6uoXIZY5MB4y/inCs4GTfcw==", "license": "Apache-2.0", "dependencies": { "@firebase/app-types": "0.9.3", - "@firebase/util": "1.11.0" + "@firebase/util": "1.13.0" } }, "node_modules/@firebase/logger": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.4.tgz", - "integrity": "sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.5.0.tgz", + "integrity": "sha512-cGskaAvkrnh42b3BA3doDWeBmuHFO/Mx5A83rbRDYakPjO9bJtRL3dX7javzc2Rr/JHZf4HlterTW2lUkfeN4g==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.1.0" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, "node_modules/@firebase/util": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.11.0.tgz", - "integrity": "sha512-PzSrhIr++KI6y4P6C/IdgBNMkEx0Ex6554/cYd0Hm+ovyFSJtJXqb/3OSIdnBoa2cpwZT1/GW56EmRc5qEc5fQ==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.13.0.tgz", + "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { "tslib": "^2.1.0" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, "node_modules/@google-cloud/firestore": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-7.11.0.tgz", - "integrity": "sha512-88uZ+jLsp1aVMj7gh3EKYH1aulTAMFAp8sH/v5a9w8q8iqSG27RiWLoxSAFr/XocZ9hGiWH1kEnBw+zl3xAgNA==", + "version": "7.11.6", + "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-7.11.6.tgz", + "integrity": "sha512-EW/O8ktzwLfyWBOsNuhRoMi8lrC3clHM5LVFhGvO1HCsLozCOOXRAlHrYBoE6HL42Sc8yYMuCb2XqcnJ4OOEpw==", "license": "Apache-2.0", "optional": true, "dependencies": { @@ -2976,25 +2640,25 @@ } }, "node_modules/@google-cloud/promisify": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-4.1.0.tgz", - "integrity": "sha512-G/FQx5cE/+DqBbOpA5jKsegGwdPniU6PuIEMt+qxWgFxvxuFOzVmp6zYchtYuwAWV5/8Dgs0yAmjvNZv3uXLQg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-4.0.0.tgz", + "integrity": "sha512-Orxzlfb9c67A15cq2JQEyVc7wEsmFBmHjZWZYQMUyJ1qivXyMwdyNOs9odi79hze+2zqdTtu1E19IM/FtqZ10g==", "license": "Apache-2.0", "optional": true, "engines": { - "node": ">=18" + "node": ">=14" } }, "node_modules/@google-cloud/storage": { - "version": "7.15.2", - "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-7.15.2.tgz", - "integrity": "sha512-+2k+mcQBb9zkaXMllf2wwR/rI07guAx+eZLWsGTDihW2lJRGfiqB7xu1r7/s4uvSP/T+nAumvzT5TTscwHKJ9A==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-7.18.0.tgz", + "integrity": "sha512-r3ZwDMiz4nwW6R922Z1pwpePxyRwE5GdevYX63hRmAQUkUQJcBH/79EnQPDv5cOv1mFBgevdNWQfi3tie3dHrQ==", "license": "Apache-2.0", "optional": true, "dependencies": { "@google-cloud/paginator": "^5.0.0", "@google-cloud/projectify": "^4.0.0", - "@google-cloud/promisify": "^4.0.0", + "@google-cloud/promisify": "<4.1.0", "abort-controller": "^3.0.0", "async-retry": "^1.3.3", "duplexify": "^4.1.3", @@ -3096,23 +2760,147 @@ } }, "node_modules/@grpc/grpc-js": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.13.0.tgz", - "integrity": "sha512-pMuxInZjUnUkgMT2QLZclRqwk2ykJbIU05aZgPgJYXEpN9+2I7z7aNwcjWZSycRPl232FfhPszyBFJyOxTHNog==", + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.14.2.tgz", + "integrity": "sha512-QzVUtEFyu05UNx2xr0fCQmStUO17uVQhGNowtxs00IgTZT6/W2PBLfUkj30s0FKJ29VtTa3ArVNIhNP6akQhqA==", "license": "Apache-2.0", "optional": true, "dependencies": { - "@grpc/proto-loader": "^0.7.13", + "@grpc/proto-loader": "^0.8.0", "@js-sdsl/ordered-map": "^4.4.2" }, "engines": { "node": ">=12.10.0" } }, + "node_modules/@grpc/grpc-js/node_modules/@grpc/proto-loader": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.8.0.tgz", + "integrity": "sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.5.3", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@grpc/grpc-js/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "optional": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@grpc/grpc-js/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@grpc/grpc-js/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@grpc/grpc-js/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT", + "optional": true + }, + "node_modules/@grpc/grpc-js/node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0", + "optional": true + }, + "node_modules/@grpc/grpc-js/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@grpc/grpc-js/node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@grpc/grpc-js/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "optional": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/@grpc/proto-loader": { - "version": "0.7.13", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", - "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", + "version": "0.7.15", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.15.tgz", + "integrity": "sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ==", "license": "Apache-2.0", "optional": true, "dependencies": { @@ -3180,9 +2968,9 @@ "optional": true }, "node_modules/@grpc/proto-loader/node_modules/long": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/long/-/long-5.3.1.tgz", - "integrity": "sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", "license": "Apache-2.0", "optional": true }, @@ -4342,121 +4130,35 @@ "integrity": "sha512-Bb+qLtXQ/1SA2Ck6JLVhfD9JQf6cCwgeDZZJjcIdHzUtdPTFu1hj51xdD7tUCL47Ed2i3aAx6K/M6AjLWYVs3A==" }, "node_modules/@parse/node-apn": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@parse/node-apn/-/node-apn-6.5.0.tgz", - "integrity": "sha512-ktIgD8ElZf23G04+W4ufvSBFJyqHeyPZ9AcMNBh2bGnkj6bMcV3QGKavxOxOn7OTr8heOMuvFkzv09zkrA0G2A==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@parse/node-apn/-/node-apn-7.0.1.tgz", + "integrity": "sha512-2xBiaznvupLOoXFaxWxcWcqCGlRn9rvqeAQnv8ogL8hZPe1Rd0es+F8ppE7g4QIy5DPJv0R4fruB8amGM6K/qA==", "license": "MIT", "dependencies": { - "debug": "4.4.0", + "debug": "4.4.3", "jsonwebtoken": "9.0.2", - "node-forge": "1.3.1", + "node-forge": "1.3.2", "verror": "1.10.1" }, "engines": { - "node": ">= 14" - } - }, - "node_modules/@parse/node-gcm": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@parse/node-gcm/-/node-gcm-1.0.2.tgz", - "integrity": "sha512-5LwLAYaGPWvuAyqaRr+4LD3Lq4V/A8DiznCFC2as9XBqfmhP7bwQMKKcymVcINrJGxPhNi69RrQpuEhIehtIqQ==", - "dependencies": { - "debug": "^3.1.0", - "lodash": "^4.17.10", - "request": "2.88.0" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/@parse/node-gcm/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dependencies": { - "ms": "^2.1.1" + "node": ">=18" } }, "node_modules/@parse/push-adapter": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@parse/push-adapter/-/push-adapter-6.11.0.tgz", - "integrity": "sha512-r6zl5F7o+dLmLrbqCfo/eH6J6MVJfBZocx9Ouwi3tugXNzc/sUbWY/94/Ef3f0X/bUuRoDlUsPB7T8yMBdZQ1w==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@parse/push-adapter/-/push-adapter-8.1.0.tgz", + "integrity": "sha512-AVZsUD9JxHYn9uwCFNnAf2gmbGAumqMDIvBzeGmtDx6BoGp/jbNLU3FhZWRwkJ3mbWcumWm4Ah2O+7DBIms+IQ==", "license": "MIT", "dependencies": { - "@parse/node-apn": "6.5.0", - "@parse/node-gcm": "1.0.2", - "expo-server-sdk": "3.14.0", - "firebase-admin": "13.2.0", + "@parse/node-apn": "7.0.1", + "expo-server-sdk": "4.0.0", + "firebase-admin": "13.6.0", "npmlog": "7.0.1", - "parse": "6.0.0", + "parse": "8.0.0", "web-push": "3.6.7" }, "engines": { - "node": "18 || 20 || 22" - } - }, - "node_modules/@parse/push-adapter/node_modules/@babel/runtime-corejs3": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.26.9.tgz", - "integrity": "sha512-5EVjbTegqN7RSJle6hMWYxO4voo4rI+9krITk+DWR+diJgGrjZjrIBnJhjrHYYQsFgI7j1w1QnrvV7YSKBfYGg==", - "dependencies": { - "core-js-pure": "^3.30.2", - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@parse/push-adapter/node_modules/parse": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/parse/-/parse-6.0.0.tgz", - "integrity": "sha512-uBfgO5refS/KhrKGQWEgTEjz5+m9F+Q9d6N4gbKWElGUWwoOUCBlGVgfErZOouunTwbKmpBy5f1i8KeYk46qkw==", - "dependencies": { - "@babel/runtime-corejs3": "7.26.9", - "idb-keyval": "6.2.1", - "react-native-crypto-js": "1.0.0", - "uuid": "10.0.0", - "ws": "8.18.1", - "xmlhttprequest": "1.8.0" - }, - "engines": { - "node": "18 || 19 || 20 || 22" - }, - "optionalDependencies": { - "crypto-js": "4.2.0" - } - }, - "node_modules/@parse/push-adapter/node_modules/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@parse/push-adapter/node_modules/ws": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", - "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "node": "20 || 22 || 24" } }, "node_modules/@pkgjs/parseargs": { @@ -6472,28 +6174,6 @@ "undici-types": "~6.19.8" } }, - "node_modules/@types/node-fetch": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", - "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", - "dependencies": { - "@types/node": "*", - "form-data": "4.0.0" - } - }, - "node_modules/@types/node-fetch/node_modules/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==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/@types/normalize-package-data": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", @@ -6516,28 +6196,29 @@ "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" }, "node_modules/@types/request": { - "version": "2.48.12", - "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.12.tgz", - "integrity": "sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw==", + "version": "2.48.13", + "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.13.tgz", + "integrity": "sha512-FGJ6udDNUCjd19pp0Q3iTiDkwhYup7J8hpMW9c4k53NrccQFFWKRho6hvtPPEhnXWKvukfwAlB6DbDz4yhH5Gg==", "license": "MIT", "optional": true, "dependencies": { "@types/caseless": "*", "@types/node": "*", "@types/tough-cookie": "*", - "form-data": "^2.5.0" + "form-data": "^2.5.5" } }, "node_modules/@types/request/node_modules/form-data": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.3.tgz", - "integrity": "sha512-XHIrMD0NpDrNM/Ckf7XJiBbLl57KEhT3+i3yY+eWm+cqYZJQTZrKo8Y8AWKnuV5GT4scfuUGt9LzNoIx3dU1nQ==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.5.tgz", + "integrity": "sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A==", "license": "MIT", "optional": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.35", "safe-buffer": "^5.2.1" }, @@ -7477,14 +7158,6 @@ "node": ">= 0.6" } }, - "node_modules/accepts/node_modules/negotiator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/acorn": { "version": "8.14.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", @@ -7537,6 +7210,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -7724,11 +7398,6 @@ "integrity": "sha512-F2+Hkm9xFaRg+GkaNnbwXNDV5O6pnCFEmqyhvfC/Ic5LbgOWjJh3L+mN/s91rxVL3znE7DYVpW0GJFT+4YBgWw==", "dev": true }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" - }, "node_modules/array-ify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", @@ -7754,14 +7423,6 @@ "node": ">=8" } }, - "node_modules/asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, "node_modules/asn1.js": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", @@ -7815,7 +7476,8 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "devOptional": true }, "node_modules/available-typed-arrays": { "version": "1.0.7", @@ -7831,19 +7493,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" - }, "node_modules/babel-plugin-polyfill-corejs2": { "version": "0.4.11", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", @@ -7934,14 +7583,6 @@ } ] }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, "node_modules/bcryptjs": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-3.0.2.tgz", @@ -8034,22 +7675,6 @@ "url": "https://opencollective.com/express" } }, - "node_modules/body-parser/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, "node_modules/body-parser/node_modules/qs": { "version": "6.14.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", @@ -8408,11 +8033,6 @@ "cdl": "bin/cdl.js" } }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" - }, "node_modules/catharsis": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", @@ -8948,6 +8568,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "devOptional": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -9254,17 +8875,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/data-uri-to-buffer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", @@ -9275,9 +8885,10 @@ } }, "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", "dependencies": { "ms": "^2.1.3" }, @@ -9604,6 +9215,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "devOptional": true, "engines": { "node": ">=0.4.0" } @@ -9650,15 +9262,6 @@ "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", "dev": true }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, "node_modules/detective-amd": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/detective-amd/-/detective-amd-6.0.0.tgz", @@ -9888,15 +9491,6 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -10669,14 +10263,17 @@ } }, "node_modules/expo-server-sdk": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/expo-server-sdk/-/expo-server-sdk-3.14.0.tgz", - "integrity": "sha512-vuDDhEhO+MoNX0678rhRzwxaK+dqLwDb6Onv2/ANVM4qdU3pNR5rqUmjnfCGt8VBq4UgmbzpMABuc8qxmd6mPA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/expo-server-sdk/-/expo-server-sdk-4.0.0.tgz", + "integrity": "sha512-zi83XtG2pqyP3gyn1JIRYkydo2i6HU3CYaWo/VvhZG/F29U+QIDv6LBEUsWf4ddZlVE7c9WN1N8Be49rHgO8OQ==", "license": "MIT", "dependencies": { "node-fetch": "^2.6.0", "promise-limit": "^2.7.0", "promise-retry": "^2.0.1" + }, + "engines": { + "node": ">=20" } }, "node_modules/expo-server-sdk/node_modules/node-fetch": { @@ -10890,7 +10487,8 @@ "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true }, "node_modules/fast-levenshtein": { "version": "2.0.6", @@ -11280,9 +10878,9 @@ } }, "node_modules/firebase-admin": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-13.2.0.tgz", - "integrity": "sha512-qQBTKo0QWCDaWwISry989pr8YfZSSk00rNCKaucjOgltEm3cCYzEe4rODqBd1uUwma+Iu5jtAzg89Nfsjr3fGg==", + "version": "13.6.0", + "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-13.6.0.tgz", + "integrity": "sha512-GdPA/t0+Cq8p1JnjFRBmxRxAGvF/kl2yfdhALl38PrRp325YxyQ5aNaHui0XmaKcKiGRFIJ/EgBNWFoDP0onjw==", "license": "Apache-2.0", "dependencies": { "@fastify/busboy": "^3.0.0", @@ -11290,6 +10888,7 @@ "@firebase/database-types": "^1.0.6", "@types/node": "^22.8.7", "farmhash-modern": "^1.1.0", + "fast-deep-equal": "^3.1.1", "google-auth-library": "^9.14.2", "jsonwebtoken": "^9.0.0", "jwks-rsa": "^3.1.0", @@ -11376,18 +10975,10 @@ "node": ">=8.0.0" } }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", - "engines": { - "node": "*" - } - }, "node_modules/form-data": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "dev": true, "dependencies": { "asynckit": "^0.4.0", @@ -11622,9 +11213,9 @@ } }, "node_modules/gaxios/node_modules/agent-base": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", - "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", "license": "MIT", "engines": { "node": ">= 14" @@ -11906,14 +11497,6 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", - "dependencies": { - "assert-plus": "^1.0.0" - } - }, "node_modules/git-log-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/git-log-parser/-/git-log-parser-1.2.0.tgz", @@ -12095,6 +11678,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "license": "MIT", "dependencies": { "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", @@ -12111,9 +11695,9 @@ } }, "node_modules/google-gax": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-4.4.1.tgz", - "integrity": "sha512-Phyp9fMfA00J3sZbJxbbB4jC55b7DBjE3F6poyL3wKMEBVKA79q6BGuHcTiM28yOzVql0NDbRL8MLLh8Iwk9Dg==", + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-4.6.1.tgz", + "integrity": "sha512-V6eky/xz2mcKfAd1Ioxyd6nmA61gao3n01C+YeuIwu3vzM9EDR6wcVzMSIbLMDXWeoi9SHYctXuKYC5uJUT3eQ==", "license": "Apache-2.0", "optional": true, "dependencies": { @@ -12343,6 +11927,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "license": "MIT", "dependencies": { "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", @@ -12379,27 +11964,6 @@ "uglify-js": "^3.1.4" } }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -12531,9 +12095,9 @@ } }, "node_modules/html-entities": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", - "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz", + "integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==", "funding": [ { "type": "github", @@ -12614,9 +12178,9 @@ } }, "node_modules/http-parser-js": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.9.tgz", - "integrity": "sha512-n1XsPy3rXVxlqxVioEWdC+0+M+SQw0DpJynwtOPo1X+ZlvdzTLtDBIJJlDQTnwZIFJrZSzSGmIOUdP8tu+SgLw==", + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz", + "integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==", "license": "MIT" }, "node_modules/http-proxy-agent": { @@ -12644,20 +12208,6 @@ "node": ">= 14" } }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, "node_modules/http2-wrapper": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", @@ -12710,9 +12260,10 @@ } }, "node_modules/idb-keyval": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.1.tgz", - "integrity": "sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==" + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.2.tgz", + "integrity": "sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg==", + "license": "Apache-2.0" }, "node_modules/ieee754": { "version": "1.2.1", @@ -12854,13 +12405,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", - "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==", - "optional": true, - "peer": true - }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -13038,7 +12582,8 @@ "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true }, "node_modules/is-unicode-supported": { "version": "0.1.0", @@ -13091,11 +12636,6 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" - }, "node_modules/issue-parser": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/issue-parser/-/issue-parser-7.0.1.tgz", @@ -13448,11 +12988,6 @@ "xmlcreate": "^2.0.4" } }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" - }, "node_modules/jsdoc": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.4.tgz", @@ -13551,15 +13086,11 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -13570,7 +13101,8 @@ "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true }, "node_modules/json5": { "version": "2.2.3", @@ -13642,38 +13174,6 @@ "npm": ">=6" } }, - "node_modules/jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/jsprim/node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" - }, - "node_modules/jsprim/node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, "node_modules/jwa": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", @@ -13858,24 +13358,6 @@ "node": ">=20" } }, - "node_modules/lint-staged/node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, "node_modules/listr2": { "version": "8.3.3", "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.3.3.tgz", @@ -14850,14 +14332,6 @@ "node": ">= 8" } }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -14890,6 +14364,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "devOptional": true, "engines": { "node": ">= 0.6" } @@ -14898,6 +14373,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "devOptional": true, "dependencies": { "mime-db": "1.52.0" }, @@ -15363,9 +14839,10 @@ "dev": true }, "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -15395,7 +14872,8 @@ "node_modules/node-abort-controller": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", - "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==" + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", + "dev": true }, "node_modules/node-domexception": { "version": "1.0.0", @@ -15463,9 +14941,9 @@ } }, "node_modules/node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.2.tgz", + "integrity": "sha512-6xKiQ+cph9KImrRh0VsjH2d8/GXA4FIMlgU4B757iI1ApvcyA9VlouP0yZJha01V+huImO+kKMU7ih+2+E14fw==", "license": "(BSD-3-Clause OR GPL-2.0)", "engines": { "node": ">= 6.13.0" @@ -18338,14 +17816,6 @@ "semver": "bin/semver.js" } }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "engines": { - "node": "*" - } - }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -18719,9 +18189,9 @@ } }, "node_modules/parse": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse/-/parse-7.1.2.tgz", - "integrity": "sha512-PXcPZDElBni06WPMxg0e6XmvgYBu3v39pRezZDbsomi8y9k1uNEDO/uICIqndw8jdES2ZfVpHp0TQoar2SObHQ==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/parse/-/parse-8.0.0.tgz", + "integrity": "sha512-T1PGLe+HaySulYSrS598tXZASgMwMAq8yQOJHtNEfxi14eYnbM89h51SXckEocIyHpOX/YnUY0C9iHH6ZTJ+Xg==", "license": "Apache-2.0", "dependencies": { "@babel/runtime-corejs3": "7.28.4", @@ -18731,7 +18201,7 @@ "ws": "8.18.3" }, "engines": { - "node": "18 || 19 || 20 || 22 || 24" + "node": ">=20.19.0 <21 || >=22.12.0 <23 || >=24.1.0 <25" } }, "node_modules/parse-json": { @@ -18761,12 +18231,6 @@ "node": ">=6" } }, - "node_modules/parse/node_modules/idb-keyval": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.2.tgz", - "integrity": "sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg==", - "license": "Apache-2.0" - }, "node_modules/parse/node_modules/ws": { "version": "8.18.3", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", @@ -18880,9 +18344,14 @@ } }, "node_modules/path-to-regexp": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", - "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==" + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", + "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } }, "node_modules/path-type": { "version": "4.0.0", @@ -18900,11 +18369,6 @@ "dev": true, "license": "MIT" }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" - }, "node_modules/pg": { "version": "8.16.3", "resolved": "https://registry.npmjs.org/pg/-/pg-8.16.3.tgz", @@ -19469,9 +18933,9 @@ } }, "node_modules/protobufjs": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz", - "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz", + "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==", "hasInstallScript": true, "license": "BSD-3-Clause", "optional": true, @@ -19494,9 +18958,9 @@ } }, "node_modules/protobufjs/node_modules/long": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/long/-/long-5.3.1.tgz", - "integrity": "sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", "license": "Apache-2.0", "optional": true }, @@ -19517,11 +18981,6 @@ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" - }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -19540,20 +18999,6 @@ "node": ">=6" } }, - "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -19835,11 +19280,6 @@ "node": ">=4" } }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" - }, "node_modules/regexpu-core": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz", @@ -19929,67 +19369,6 @@ "node": ">=4" } }, - "node_modules/request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/request/node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/request/node_modules/qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/request/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "bin": { - "uuid": "bin/uuid" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -20196,14 +19575,6 @@ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==" }, - "node_modules/router/node_modules/path-to-regexp": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", - "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", - "engines": { - "node": ">=16" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -20843,6 +20214,7 @@ "version": "2.4.12", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz", "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==", + "license": "(MIT AND BSD-3-Clause)", "dependencies": { "inherits": "^2.0.4", "safe-buffer": "^5.2.1", @@ -21081,32 +20453,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "optional": true, - "peer": true, - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", - "optional": true, - "peer": true, - "dependencies": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.13.0", - "npm": ">= 3.0.0" - } - }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -21245,30 +20591,6 @@ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, - "node_modules/sshpk": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", - "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", @@ -21979,23 +21301,6 @@ "node": ">=0.6" } }, - "node_modules/tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", - "dependencies": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/tough-cookie/node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" - }, "node_modules/tr46": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", @@ -22111,17 +21416,6 @@ "node": ">=0.6.11 <=0.7.0 || >=0.7.3" } }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, "node_modules/tv4": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/tv4/-/tv4-1.3.0.tgz", @@ -22130,11 +21424,6 @@ "node": ">= 0.8.0" } }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -22440,6 +21729,7 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, "dependencies": { "punycode": "^2.1.0" } @@ -22458,14 +21748,6 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/uuid": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", @@ -22489,14 +21771,6 @@ "spdx-expression-parse": "^3.0.0" } }, - "node_modules/value-or-promise": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/value-or-promise/-/value-or-promise-1.0.12.tgz", - "integrity": "sha512-Z6Uz+TYwEqE7ZN50gwn+1LCVo9ZVrpxRPOhOLnncYkY1ZzOYtrX8Fwf/rFktZ8R5mJms6EZf5TqNOMeZmnPq9Q==", - "engines": { - "node": ">=12" - } - }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -22671,11 +21945,12 @@ } }, "node_modules/whatwg-mimetype": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", - "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/whatwg-url": { @@ -22981,14 +22256,6 @@ "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", "dev": true }, - "node_modules/xmlhttprequest": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", - "integrity": "sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA==", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -23268,325 +22535,48 @@ } }, "@apollo/server": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@apollo/server/-/server-4.12.1.tgz", - "integrity": "sha512-jceK1LK6l074in4mWu8XkwzDjvxdSzkmk8M7YpVLOGjQ6PmlaChcGRJ9BUwB46r22MxdPCXdC/6U5Vi8gzYbvQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@apollo/server/-/server-5.0.0.tgz", + "integrity": "sha512-PHopOm7pr69k7eDJvCBU4cZy9Z19qyCFKB9/luLnf2YCatu2WOYhoQPNr3dAoe//xv0RZFhxXbRcnK6IXIP7Nw==", "requires": { "@apollo/cache-control-types": "^1.0.3", - "@apollo/server-gateway-interface": "^1.1.1", + "@apollo/server-gateway-interface": "^2.0.0", "@apollo/usage-reporting-protobuf": "^4.1.1", - "@apollo/utils.createhash": "^2.0.2", - "@apollo/utils.fetcher": "^2.0.0", - "@apollo/utils.isnodelike": "^2.0.0", - "@apollo/utils.keyvaluecache": "^2.1.0", - "@apollo/utils.logger": "^2.0.0", + "@apollo/utils.createhash": "^3.0.0", + "@apollo/utils.fetcher": "^3.0.0", + "@apollo/utils.isnodelike": "^3.0.0", + "@apollo/utils.keyvaluecache": "^4.0.0", + "@apollo/utils.logger": "^3.0.0", "@apollo/utils.usagereporting": "^2.1.0", - "@apollo/utils.withrequired": "^2.0.0", - "@graphql-tools/schema": "^9.0.0", - "@types/express": "^4.17.13", - "@types/express-serve-static-core": "^4.17.30", - "@types/node-fetch": "^2.6.1", + "@apollo/utils.withrequired": "^3.0.0", + "@graphql-tools/schema": "^10.0.0", "async-retry": "^1.2.1", + "body-parser": "^2.2.0", "cors": "^2.8.5", - "express": "^4.21.1", + "finalhandler": "^2.1.0", "loglevel": "^1.6.8", - "lru-cache": "^7.10.1", - "negotiator": "^0.6.3", - "node-abort-controller": "^3.1.1", - "node-fetch": "^2.6.7", - "uuid": "^9.0.0", - "whatwg-mimetype": "^3.0.0" + "lru-cache": "^11.1.0", + "negotiator": "^1.0.0", + "uuid": "^11.1.0", + "whatwg-mimetype": "^4.0.0" }, "dependencies": { - "@graphql-tools/merge": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.4.2.tgz", - "integrity": "sha512-XbrHAaj8yDuINph+sAfuq3QCZ/tKblrTLOpirK0+CAgNlZUCHs0Fa+xtMUURgwCVThLle1AF7svJCxFizygLsw==", - "requires": { - "@graphql-tools/utils": "^9.2.1", - "tslib": "^2.4.0" - } - }, - "@graphql-tools/schema": { - "version": "9.0.19", - "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-9.0.19.tgz", - "integrity": "sha512-oBRPoNBtCkk0zbUsyP4GaIzCt8C0aCI4ycIRUL67KK5pOHljKLBBtGT+Jr6hkzA74C8Gco8bpZPe7aWFjiaK2w==", - "requires": { - "@graphql-tools/merge": "^8.4.1", - "@graphql-tools/utils": "^9.2.1", - "tslib": "^2.4.0", - "value-or-promise": "^1.0.12" - } - }, - "@graphql-tools/utils": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-9.2.1.tgz", - "integrity": "sha512-WUw506Ql6xzmOORlriNrD6Ugx+HjVgYxt9KCXD9mHAak+eaXSwuGGPyE60hy9xaDEoXKBsG7SkG69ybitaVl6A==", - "requires": { - "@graphql-typed-document-node/core": "^3.1.1", - "tslib": "^2.4.0" - } - }, - "accepts": { - "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.34", - "negotiator": "0.6.3" - } - }, - "body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", - "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - } - }, - "content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "requires": { - "safe-buffer": "5.2.1" - } - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "express": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", - "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", - "requires": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "~1.20.3", - "content-disposition": "~0.5.4", - "content-type": "~1.0.4", - "cookie": "~0.7.1", - "cookie-signature": "~1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.3.1", - "fresh": "~0.5.2", - "http-errors": "~2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "~0.1.12", - "proxy-addr": "~2.0.7", - "qs": "~6.14.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "~0.19.0", - "serve-static": "~1.16.2", - "setprototypeof": "1.2.0", - "statuses": "~2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", - "requires": { - "side-channel": "^1.1.0" - } - } - } - }, - "finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", - "requires": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - } - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==" - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" - }, - "merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==" - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" - }, - "raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "requires": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", - "requires": { - "debug": "2.6.9", - "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": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "dependencies": { - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - } - } - }, - "serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", - "requires": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" - } - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.2.tgz", + "integrity": "sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==" } } }, "@apollo/server-gateway-interface": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@apollo/server-gateway-interface/-/server-gateway-interface-1.1.1.tgz", - "integrity": "sha512-pGwCl/po6+rxRmDMFgozKQo2pbsSwE91TpsDBAOgf74CRDPXHHtM88wbwjab0wMMZh95QfR45GGyDIdhY24bkQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@apollo/server-gateway-interface/-/server-gateway-interface-2.0.0.tgz", + "integrity": "sha512-3HEMD6fSantG2My3jWkb9dvfkF9vJ4BDLRjMgsnD790VINtuPaEp+h3Hg9HOHiWkML6QsOhnaRqZ+gvhp3y8Nw==", "requires": { "@apollo/usage-reporting-protobuf": "^4.1.1", - "@apollo/utils.fetcher": "^2.0.0", - "@apollo/utils.keyvaluecache": "^2.1.0", - "@apollo/utils.logger": "^2.0.0" + "@apollo/utils.fetcher": "^3.0.0", + "@apollo/utils.keyvaluecache": "^4.0.0", + "@apollo/utils.logger": "^3.0.0" } }, "@apollo/usage-reporting-protobuf": { @@ -23598,11 +22588,11 @@ } }, "@apollo/utils.createhash": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@apollo/utils.createhash/-/utils.createhash-2.0.2.tgz", - "integrity": "sha512-UkS3xqnVFLZ3JFpEmU/2cM2iKJotQXMoSTgxXsfQgXLC5gR1WaepoXagmYnPSA7Q/2cmnyTYK5OgAgoC4RULPg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@apollo/utils.createhash/-/utils.createhash-3.0.1.tgz", + "integrity": "sha512-CKrlySj4eQYftBE5MJ8IzKwIibQnftDT7yGfsJy5KSEEnLlPASX0UTpbKqkjlVEwPPd4mEwI7WOM7XNxEuO05A==", "requires": { - "@apollo/utils.isnodelike": "^2.0.1", + "@apollo/utils.isnodelike": "^3.0.0", "sha.js": "^2.4.11" } }, @@ -23613,35 +22603,35 @@ "requires": {} }, "@apollo/utils.fetcher": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@apollo/utils.fetcher/-/utils.fetcher-2.0.1.tgz", - "integrity": "sha512-jvvon885hEyWXd4H6zpWeN3tl88QcWnHp5gWF5OPF34uhvoR+DFqcNxs9vrRaBBSY3qda3Qe0bdud7tz2zGx1A==" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@apollo/utils.fetcher/-/utils.fetcher-3.1.0.tgz", + "integrity": "sha512-Z3QAyrsQkvrdTuHAFwWDNd+0l50guwoQUoaDQssLOjkmnmVuvXlJykqlEJolio+4rFwBnWdoY1ByFdKaQEcm7A==" }, "@apollo/utils.isnodelike": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@apollo/utils.isnodelike/-/utils.isnodelike-2.0.1.tgz", - "integrity": "sha512-w41XyepR+jBEuVpoRM715N2ZD0xMD413UiJx8w5xnAZD2ZkSJnMJBoIzauK83kJpSgNuR6ywbV29jG9NmxjK0Q==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@apollo/utils.isnodelike/-/utils.isnodelike-3.0.0.tgz", + "integrity": "sha512-xrjyjfkzunZ0DeF6xkHaK5IKR8F1FBq6qV+uZ+h9worIF/2YSzA0uoBxGv6tbTeo9QoIQnRW4PVFzGix5E7n/g==" }, "@apollo/utils.keyvaluecache": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@apollo/utils.keyvaluecache/-/utils.keyvaluecache-2.1.1.tgz", - "integrity": "sha512-qVo5PvUUMD8oB9oYvq4ViCjYAMWnZ5zZwEjNF37L2m1u528x5mueMlU+Cr1UinupCgdB78g+egA1G98rbJ03Vw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@apollo/utils.keyvaluecache/-/utils.keyvaluecache-4.0.0.tgz", + "integrity": "sha512-mKw1myRUkQsGPNB+9bglAuhviodJ2L2MRYLTafCMw5BIo7nbvCPNCkLnIHjZ1NOzH7SnMAr5c9LmXiqsgYqLZw==", "requires": { - "@apollo/utils.logger": "^2.0.1", - "lru-cache": "^7.14.1" + "@apollo/utils.logger": "^3.0.0", + "lru-cache": "^11.0.0" }, "dependencies": { "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==" + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.2.tgz", + "integrity": "sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==" } } }, "@apollo/utils.logger": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@apollo/utils.logger/-/utils.logger-2.0.1.tgz", - "integrity": "sha512-YuplwLHaHf1oviidB7MxnCXAdHp3IqYV8n0momZ3JfLniae92eYqMIx+j5qJFX6WKJPs6q7bczmV4lXIsTu5Pg==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@apollo/utils.logger/-/utils.logger-3.0.0.tgz", + "integrity": "sha512-M8V8JOTH0F2qEi+ktPfw4RL7MvUycDfKp7aEap2eWXfL5SqWHN6jTLbj5f5fj1cceHpyaUSOZlvlaaryaxZAmg==" }, "@apollo/utils.printwithreducedwhitespace": { "version": "2.0.1", @@ -23683,9 +22673,15 @@ } }, "@apollo/utils.withrequired": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@apollo/utils.withrequired/-/utils.withrequired-2.0.1.tgz", - "integrity": "sha512-YBDiuAX9i1lLc6GeTy1m7DGLFn/gMnvXqlalOIMjM7DeOgIacEjjfwPqb0M1CQ2v11HhR15d1NmxJoRCfrNqcA==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@apollo/utils.withrequired/-/utils.withrequired-3.0.0.tgz", + "integrity": "sha512-aaxeavfJ+RHboh7c2ofO5HHtQobGX4AgUujXP4CXpREHp9fQ9jPi6K9T1jrAKe7HIipoP0OJ1gd6JamSkFIpvA==" + }, + "@as-integrations/express5": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@as-integrations/express5/-/express5-1.1.2.tgz", + "integrity": "sha512-BxfwtcWNf2CELDkuPQxi5Zl3WqY/dQVJYafeCBOGoFQjv5M0fjhxmAFZ9vKx/5YKKNeok4UY6PkFbHzmQrdxIA==", + "requires": {} }, "@babel/cli": { "version": "7.27.0", @@ -25018,9 +24014,9 @@ } }, "@fastify/busboy": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-3.1.1.tgz", - "integrity": "sha512-5DGmA8FTdB2XbDeEwc/5ZXBl6UbBAyBOOLlPuBnZ/N1SwdH9Ii+cOX3tBROlDgcTXxjOYnLMVoKk9+FXAw0CJw==" + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-3.2.0.tgz", + "integrity": "sha512-m9FVDXU3GT2ITSe0UaMA5rU3QkfC/UXtCU8y0gSN/GugTqtVldOBWIB5V6V3sbmenVZUIpU6f+mPEO2+m5iTaA==" }, "@firebase/app-check-interop-types": { "version": "0.3.3", @@ -25038,70 +24034,70 @@ "integrity": "sha512-JPgcXKCuO+CWqGDnigBtvo09HeBs5u/Ktc2GaFj2m01hLarbxthLNm7Fk8iOP1aqAtXV+fnnGj7U28xmk7IwVA==" }, "@firebase/component": { - "version": "0.6.13", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.13.tgz", - "integrity": "sha512-I/Eg1NpAtZ8AAfq8mpdfXnuUpcLxIDdCDtTzWSh+FXnp/9eCKJ3SNbOCKrUCyhLzNa2SiPJYruei0sxVjaOTeg==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.0.tgz", + "integrity": "sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg==", "requires": { - "@firebase/util": "1.11.0", + "@firebase/util": "1.13.0", "tslib": "^2.1.0" } }, "@firebase/database": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.13.tgz", - "integrity": "sha512-cdc+LuseKdJXzlrCx8ePMXyctSWtYS9SsP3y7EeA85GzNh/IL0b7HOq0eShridL935iQ0KScZCj5qJtKkGE53g==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.1.0.tgz", + "integrity": "sha512-gM6MJFae3pTyNLoc9VcJNuaUDej0ctdjn3cVtILo3D5lpp0dmUHHLFN/pUKe7ImyeB1KAvRlEYxvIHNF04Filg==", "requires": { "@firebase/app-check-interop-types": "0.3.3", "@firebase/auth-interop-types": "0.2.4", - "@firebase/component": "0.6.13", - "@firebase/logger": "0.4.4", - "@firebase/util": "1.11.0", + "@firebase/component": "0.7.0", + "@firebase/logger": "0.5.0", + "@firebase/util": "1.13.0", "faye-websocket": "0.11.4", "tslib": "^2.1.0" } }, "@firebase/database-compat": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-2.0.4.tgz", - "integrity": "sha512-4qsptwZ3DTGNBje56ETItZQyA/HMalOelnLmkC3eR0M6+zkzOHjNHyWUWodW2mqxRKAM0sGkn+aIwYHKZFJXug==", - "requires": { - "@firebase/component": "0.6.13", - "@firebase/database": "1.0.13", - "@firebase/database-types": "1.0.9", - "@firebase/logger": "0.4.4", - "@firebase/util": "1.11.0", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-2.1.0.tgz", + "integrity": "sha512-8nYc43RqxScsePVd1qe1xxvWNf0OBnbwHxmXJ7MHSuuTVYFO3eLyLW3PiCKJ9fHnmIz4p4LbieXwz+qtr9PZDg==", + "requires": { + "@firebase/component": "0.7.0", + "@firebase/database": "1.1.0", + "@firebase/database-types": "1.0.16", + "@firebase/logger": "0.5.0", + "@firebase/util": "1.13.0", "tslib": "^2.1.0" } }, "@firebase/database-types": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.9.tgz", - "integrity": "sha512-uCntrxPbJHhZsNRpMhxNCm7GzhYWX+7J2e57wq1ZZ4NJrQw5DORgkAzJMByYZcVAjgADnCxxhK/GkoypH+XpvQ==", + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.16.tgz", + "integrity": "sha512-xkQLQfU5De7+SPhEGAXFBnDryUWhhlFXelEg2YeZOQMCdoe7dL64DDAd77SQsR+6uoXIZY5MB4y/inCs4GTfcw==", "requires": { "@firebase/app-types": "0.9.3", - "@firebase/util": "1.11.0" + "@firebase/util": "1.13.0" } }, "@firebase/logger": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.4.tgz", - "integrity": "sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.5.0.tgz", + "integrity": "sha512-cGskaAvkrnh42b3BA3doDWeBmuHFO/Mx5A83rbRDYakPjO9bJtRL3dX7javzc2Rr/JHZf4HlterTW2lUkfeN4g==", "requires": { "tslib": "^2.1.0" } }, "@firebase/util": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.11.0.tgz", - "integrity": "sha512-PzSrhIr++KI6y4P6C/IdgBNMkEx0Ex6554/cYd0Hm+ovyFSJtJXqb/3OSIdnBoa2cpwZT1/GW56EmRc5qEc5fQ==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.13.0.tgz", + "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", "requires": { "tslib": "^2.1.0" } }, "@google-cloud/firestore": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-7.11.0.tgz", - "integrity": "sha512-88uZ+jLsp1aVMj7gh3EKYH1aulTAMFAp8sH/v5a9w8q8iqSG27RiWLoxSAFr/XocZ9hGiWH1kEnBw+zl3xAgNA==", + "version": "7.11.6", + "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-7.11.6.tgz", + "integrity": "sha512-EW/O8ktzwLfyWBOsNuhRoMi8lrC3clHM5LVFhGvO1HCsLozCOOXRAlHrYBoE6HL42Sc8yYMuCb2XqcnJ4OOEpw==", "optional": true, "requires": { "@opentelemetry/api": "^1.3.0", @@ -25128,20 +24124,20 @@ "optional": true }, "@google-cloud/promisify": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-4.1.0.tgz", - "integrity": "sha512-G/FQx5cE/+DqBbOpA5jKsegGwdPniU6PuIEMt+qxWgFxvxuFOzVmp6zYchtYuwAWV5/8Dgs0yAmjvNZv3uXLQg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-4.0.0.tgz", + "integrity": "sha512-Orxzlfb9c67A15cq2JQEyVc7wEsmFBmHjZWZYQMUyJ1qivXyMwdyNOs9odi79hze+2zqdTtu1E19IM/FtqZ10g==", "optional": true }, "@google-cloud/storage": { - "version": "7.15.2", - "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-7.15.2.tgz", - "integrity": "sha512-+2k+mcQBb9zkaXMllf2wwR/rI07guAx+eZLWsGTDihW2lJRGfiqB7xu1r7/s4uvSP/T+nAumvzT5TTscwHKJ9A==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-7.18.0.tgz", + "integrity": "sha512-r3ZwDMiz4nwW6R922Z1pwpePxyRwE5GdevYX63hRmAQUkUQJcBH/79EnQPDv5cOv1mFBgevdNWQfi3tie3dHrQ==", "optional": true, "requires": { "@google-cloud/paginator": "^5.0.0", "@google-cloud/projectify": "^4.0.0", - "@google-cloud/promisify": "^4.0.0", + "@google-cloud/promisify": "<4.1.0", "abort-controller": "^3.0.0", "async-retry": "^1.3.3", "duplexify": "^4.1.3", @@ -25208,19 +24204,106 @@ "requires": {} }, "@grpc/grpc-js": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.13.0.tgz", - "integrity": "sha512-pMuxInZjUnUkgMT2QLZclRqwk2ykJbIU05aZgPgJYXEpN9+2I7z7aNwcjWZSycRPl232FfhPszyBFJyOxTHNog==", + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.14.2.tgz", + "integrity": "sha512-QzVUtEFyu05UNx2xr0fCQmStUO17uVQhGNowtxs00IgTZT6/W2PBLfUkj30s0FKJ29VtTa3ArVNIhNP6akQhqA==", "optional": true, "requires": { - "@grpc/proto-loader": "^0.7.13", + "@grpc/proto-loader": "^0.8.0", "@js-sdsl/ordered-map": "^4.4.2" + }, + "dependencies": { + "@grpc/proto-loader": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.8.0.tgz", + "integrity": "sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ==", + "optional": true, + "requires": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.5.3", + "yargs": "^17.7.2" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "optional": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "optional": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "optional": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "optional": true + }, + "long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "optional": true + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "optional": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "optional": true + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "optional": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + } } }, "@grpc/proto-loader": { - "version": "0.7.13", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", - "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", + "version": "0.7.15", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.15.tgz", + "integrity": "sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ==", "optional": true, "requires": { "lodash.camelcase": "^4.3.0", @@ -25265,9 +24348,9 @@ "optional": true }, "long": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/long/-/long-5.3.1.tgz", - "integrity": "sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", "optional": true }, "wrap-ansi": { @@ -26104,84 +25187,27 @@ "integrity": "sha512-Bb+qLtXQ/1SA2Ck6JLVhfD9JQf6cCwgeDZZJjcIdHzUtdPTFu1hj51xdD7tUCL47Ed2i3aAx6K/M6AjLWYVs3A==" }, "@parse/node-apn": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@parse/node-apn/-/node-apn-6.5.0.tgz", - "integrity": "sha512-ktIgD8ElZf23G04+W4ufvSBFJyqHeyPZ9AcMNBh2bGnkj6bMcV3QGKavxOxOn7OTr8heOMuvFkzv09zkrA0G2A==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@parse/node-apn/-/node-apn-7.0.1.tgz", + "integrity": "sha512-2xBiaznvupLOoXFaxWxcWcqCGlRn9rvqeAQnv8ogL8hZPe1Rd0es+F8ppE7g4QIy5DPJv0R4fruB8amGM6K/qA==", "requires": { - "debug": "4.4.0", + "debug": "4.4.3", "jsonwebtoken": "9.0.2", - "node-forge": "1.3.1", + "node-forge": "1.3.2", "verror": "1.10.1" } }, - "@parse/node-gcm": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@parse/node-gcm/-/node-gcm-1.0.2.tgz", - "integrity": "sha512-5LwLAYaGPWvuAyqaRr+4LD3Lq4V/A8DiznCFC2as9XBqfmhP7bwQMKKcymVcINrJGxPhNi69RrQpuEhIehtIqQ==", - "requires": { - "debug": "^3.1.0", - "lodash": "^4.17.10", - "request": "2.88.0" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "requires": { - "ms": "^2.1.1" - } - } - } - }, "@parse/push-adapter": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@parse/push-adapter/-/push-adapter-6.11.0.tgz", - "integrity": "sha512-r6zl5F7o+dLmLrbqCfo/eH6J6MVJfBZocx9Ouwi3tugXNzc/sUbWY/94/Ef3f0X/bUuRoDlUsPB7T8yMBdZQ1w==", - "requires": { - "@parse/node-apn": "6.5.0", - "@parse/node-gcm": "1.0.2", - "expo-server-sdk": "3.14.0", - "firebase-admin": "13.2.0", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@parse/push-adapter/-/push-adapter-8.1.0.tgz", + "integrity": "sha512-AVZsUD9JxHYn9uwCFNnAf2gmbGAumqMDIvBzeGmtDx6BoGp/jbNLU3FhZWRwkJ3mbWcumWm4Ah2O+7DBIms+IQ==", + "requires": { + "@parse/node-apn": "7.0.1", + "expo-server-sdk": "4.0.0", + "firebase-admin": "13.6.0", "npmlog": "7.0.1", - "parse": "6.0.0", + "parse": "8.0.0", "web-push": "3.6.7" - }, - "dependencies": { - "@babel/runtime-corejs3": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.26.9.tgz", - "integrity": "sha512-5EVjbTegqN7RSJle6hMWYxO4voo4rI+9krITk+DWR+diJgGrjZjrIBnJhjrHYYQsFgI7j1w1QnrvV7YSKBfYGg==", - "requires": { - "core-js-pure": "^3.30.2", - "regenerator-runtime": "^0.14.0" - } - }, - "parse": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/parse/-/parse-6.0.0.tgz", - "integrity": "sha512-uBfgO5refS/KhrKGQWEgTEjz5+m9F+Q9d6N4gbKWElGUWwoOUCBlGVgfErZOouunTwbKmpBy5f1i8KeYk46qkw==", - "requires": { - "@babel/runtime-corejs3": "7.26.9", - "crypto-js": "4.2.0", - "idb-keyval": "6.2.1", - "react-native-crypto-js": "1.0.0", - "uuid": "10.0.0", - "ws": "8.18.1", - "xmlhttprequest": "1.8.0" - } - }, - "uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==" - }, - "ws": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", - "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", - "requires": {} - } } }, "@pkgjs/parseargs": { @@ -27603,27 +26629,6 @@ "undici-types": "~6.19.8" } }, - "@types/node-fetch": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", - "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", - "requires": { - "@types/node": "*", - "form-data": "4.0.0" - }, - "dependencies": { - "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" - } - } - } - }, "@types/normalize-package-data": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", @@ -27646,26 +26651,27 @@ "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" }, "@types/request": { - "version": "2.48.12", - "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.12.tgz", - "integrity": "sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw==", + "version": "2.48.13", + "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.13.tgz", + "integrity": "sha512-FGJ6udDNUCjd19pp0Q3iTiDkwhYup7J8hpMW9c4k53NrccQFFWKRho6hvtPPEhnXWKvukfwAlB6DbDz4yhH5Gg==", "optional": true, "requires": { "@types/caseless": "*", "@types/node": "*", "@types/tough-cookie": "*", - "form-data": "^2.5.0" + "form-data": "^2.5.5" }, "dependencies": { "form-data": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.3.tgz", - "integrity": "sha512-XHIrMD0NpDrNM/Ckf7XJiBbLl57KEhT3+i3yY+eWm+cqYZJQTZrKo8Y8AWKnuV5GT4scfuUGt9LzNoIx3dU1nQ==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.5.tgz", + "integrity": "sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A==", "optional": true, "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.35", "safe-buffer": "^5.2.1" } @@ -28268,11 +27274,6 @@ "requires": { "mime-db": "^1.53.0" } - }, - "negotiator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==" } } }, @@ -28312,6 +27313,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -28451,11 +27453,6 @@ "integrity": "sha512-F2+Hkm9xFaRg+GkaNnbwXNDV5O6pnCFEmqyhvfC/Ic5LbgOWjJh3L+mN/s91rxVL3znE7DYVpW0GJFT+4YBgWw==", "dev": true }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" - }, "array-ify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", @@ -28474,14 +27471,6 @@ "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", "optional": true }, - "asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "requires": { - "safer-buffer": "~2.1.0" - } - }, "asn1.js": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", @@ -28525,7 +27514,8 @@ "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "devOptional": true }, "available-typed-arrays": { "version": "1.0.7", @@ -28535,16 +27525,6 @@ "possible-typed-array-names": "^1.0.0" } }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==" - }, - "aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" - }, "babel-plugin-polyfill-corejs2": { "version": "0.4.11", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", @@ -28607,14 +27587,6 @@ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "requires": { - "tweetnacl": "^0.14.3" - } - }, "bcryptjs": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-3.0.2.tgz", @@ -28689,14 +27661,6 @@ "type-is": "^2.0.1" }, "dependencies": { - "debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "requires": { - "ms": "^2.1.3" - } - }, "qs": { "version": "6.14.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", @@ -28934,11 +27898,6 @@ "redeyed": "~2.1.0" } }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" - }, "catharsis": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", @@ -29323,6 +28282,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "devOptional": true, "requires": { "delayed-stream": "~1.0.0" } @@ -29532,14 +28492,6 @@ } } }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", - "requires": { - "assert-plus": "^1.0.0" - } - }, "data-uri-to-buffer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", @@ -29547,9 +28499,9 @@ "dev": true }, "debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "requires": { "ms": "^2.1.3" } @@ -29782,7 +28734,8 @@ "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "devOptional": true }, "depd": { "version": "2.0.0", @@ -29815,11 +28768,6 @@ "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", "dev": true }, - "destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" - }, "detective-amd": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/detective-amd/-/detective-amd-6.0.0.tgz", @@ -29995,15 +28943,6 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -30533,9 +29472,9 @@ } }, "expo-server-sdk": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/expo-server-sdk/-/expo-server-sdk-3.14.0.tgz", - "integrity": "sha512-vuDDhEhO+MoNX0678rhRzwxaK+dqLwDb6Onv2/ANVM4qdU3pNR5rqUmjnfCGt8VBq4UgmbzpMABuc8qxmd6mPA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/expo-server-sdk/-/expo-server-sdk-4.0.0.tgz", + "integrity": "sha512-zi83XtG2pqyP3gyn1JIRYkydo2i6HU3CYaWo/VvhZG/F29U+QIDv6LBEUsWf4ddZlVE7c9WN1N8Be49rHgO8OQ==", "requires": { "node-fetch": "^2.6.0", "promise-limit": "^2.7.0", @@ -30686,7 +29625,8 @@ "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true }, "fast-levenshtein": { "version": "2.0.6", @@ -30953,9 +29893,9 @@ } }, "firebase-admin": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-13.2.0.tgz", - "integrity": "sha512-qQBTKo0QWCDaWwISry989pr8YfZSSk00rNCKaucjOgltEm3cCYzEe4rODqBd1uUwma+Iu5jtAzg89Nfsjr3fGg==", + "version": "13.6.0", + "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-13.6.0.tgz", + "integrity": "sha512-GdPA/t0+Cq8p1JnjFRBmxRxAGvF/kl2yfdhALl38PrRp325YxyQ5aNaHui0XmaKcKiGRFIJ/EgBNWFoDP0onjw==", "requires": { "@fastify/busboy": "^3.0.0", "@firebase/database-compat": "^2.0.0", @@ -30964,6 +29904,7 @@ "@google-cloud/storage": "^7.14.0", "@types/node": "^22.8.7", "farmhash-modern": "^1.1.0", + "fast-deep-equal": "^3.1.1", "google-auth-library": "^9.14.2", "jsonwebtoken": "^9.0.0", "jwks-rsa": "^3.1.0", @@ -31015,15 +29956,10 @@ "signal-exit": "^3.0.2" } }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==" - }, "form-data": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "dev": true, "requires": { "asynckit": "^0.4.0", @@ -31187,9 +30123,9 @@ }, "dependencies": { "agent-base": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", - "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==" + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==" }, "https-proxy-agent": { "version": "7.0.6", @@ -31381,14 +30317,6 @@ "resolve-pkg-maps": "^1.0.0" } }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", - "requires": { - "assert-plus": "^1.0.0" - } - }, "git-log-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/git-log-parser/-/git-log-parser-1.2.0.tgz", @@ -31547,9 +30475,9 @@ } }, "google-gax": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-4.4.1.tgz", - "integrity": "sha512-Phyp9fMfA00J3sZbJxbbB4jC55b7DBjE3F6poyL3wKMEBVKA79q6BGuHcTiM28yOzVql0NDbRL8MLLh8Iwk9Dg==", + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-4.6.1.tgz", + "integrity": "sha512-V6eky/xz2mcKfAd1Ioxyd6nmA61gao3n01C+YeuIwu3vzM9EDR6wcVzMSIbLMDXWeoi9SHYctXuKYC5uJUT3eQ==", "optional": true, "requires": { "@grpc/grpc-js": "^1.10.9", @@ -31728,20 +30656,6 @@ "wordwrap": "^1.0.0" } }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==" - }, - "har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - } - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -31831,9 +30745,9 @@ } }, "html-entities": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", - "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz", + "integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==", "optional": true }, "html-escaper": { @@ -31889,9 +30803,9 @@ } }, "http-parser-js": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.9.tgz", - "integrity": "sha512-n1XsPy3rXVxlqxVioEWdC+0+M+SQw0DpJynwtOPo1X+ZlvdzTLtDBIJJlDQTnwZIFJrZSzSGmIOUdP8tu+SgLw==" + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz", + "integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==" }, "http-proxy-agent": { "version": "7.0.2", @@ -31914,16 +30828,6 @@ } } }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, "http2-wrapper": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", @@ -31959,9 +30863,9 @@ } }, "idb-keyval": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.1.tgz", - "integrity": "sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==" + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.2.tgz", + "integrity": "sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg==" }, "ieee754": { "version": "1.2.1", @@ -32055,13 +30959,6 @@ "p-is-promise": "^3.0.0" } }, - "ip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", - "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==", - "optional": true, - "peer": true - }, "ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -32178,7 +31075,8 @@ "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true }, "is-unicode-supported": { "version": "0.1.0", @@ -32216,11 +31114,6 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" - }, "issue-parser": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/issue-parser/-/issue-parser-7.0.1.tgz", @@ -32488,11 +31381,6 @@ "xmlcreate": "^2.0.4" } }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" - }, "jsdoc": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.4.tgz", @@ -32572,15 +31460,11 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, - "json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -32591,7 +31475,8 @@ "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true }, "json5": { "version": "2.2.3", @@ -32642,34 +31527,6 @@ "semver": "^7.5.4" } }, - "jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - }, - "dependencies": { - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - } - } - }, "jwa": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", @@ -32820,15 +31677,6 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.0.tgz", "integrity": "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==", "dev": true - }, - "debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", - "dev": true, - "requires": { - "ms": "^2.1.3" - } } } }, @@ -33518,11 +32366,6 @@ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" - }, "micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -33541,12 +32384,14 @@ "mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "devOptional": true }, "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==", + "devOptional": true, "requires": { "mime-db": "1.52.0" } @@ -33849,9 +32694,9 @@ "dev": true }, "negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==" }, "neo-async": { "version": "2.6.2", @@ -33878,7 +32723,8 @@ "node-abort-controller": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", - "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==" + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", + "dev": true }, "node-domexception": { "version": "1.0.0", @@ -33918,9 +32764,9 @@ } }, "node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==" + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.2.tgz", + "integrity": "sha512-6xKiQ+cph9KImrRh0VsjH2d8/GXA4FIMlgU4B757iI1ApvcyA9VlouP0yZJha01V+huImO+kKMU7ih+2+E14fw==" }, "node-preload": { "version": "0.2.1", @@ -35858,11 +34704,6 @@ } } }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" - }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -36132,9 +34973,9 @@ } }, "parse": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse/-/parse-7.1.2.tgz", - "integrity": "sha512-PXcPZDElBni06WPMxg0e6XmvgYBu3v39pRezZDbsomi8y9k1uNEDO/uICIqndw8jdES2ZfVpHp0TQoar2SObHQ==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/parse/-/parse-8.0.0.tgz", + "integrity": "sha512-T1PGLe+HaySulYSrS598tXZASgMwMAq8yQOJHtNEfxi14eYnbM89h51SXckEocIyHpOX/YnUY0C9iHH6ZTJ+Xg==", "requires": { "@babel/runtime-corejs3": "7.28.4", "crypto-js": "4.2.0", @@ -36143,11 +34984,6 @@ "ws": "8.18.3" }, "dependencies": { - "idb-keyval": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.2.tgz", - "integrity": "sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg==" - }, "ws": { "version": "8.18.3", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", @@ -36247,9 +35083,9 @@ } }, "path-to-regexp": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", - "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==" + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", + "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==" }, "path-type": { "version": "4.0.0", @@ -36263,11 +35099,6 @@ "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", "dev": true }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" - }, "pg": { "version": "8.16.3", "resolved": "https://registry.npmjs.org/pg/-/pg-8.16.3.tgz", @@ -36655,9 +35486,9 @@ } }, "protobufjs": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz", - "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz", + "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==", "optional": true, "requires": { "@protobufjs/aspromise": "^1.1.2", @@ -36675,9 +35506,9 @@ }, "dependencies": { "long": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/long/-/long-5.3.1.tgz", - "integrity": "sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", "optional": true } } @@ -36696,11 +35527,6 @@ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" }, - "psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" - }, "punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -36712,14 +35538,6 @@ "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", "dev": true }, - "qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "requires": { - "side-channel": "^1.0.6" - } - }, "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -36928,11 +35746,6 @@ "regenerate": "^1.4.2" } }, - "regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" - }, "regexpu-core": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz", @@ -36993,55 +35806,6 @@ "es6-error": "^4.0.1" } }, - "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==" - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - } - } - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -37186,11 +35950,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==" - }, - "path-to-regexp": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", - "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==" } } }, @@ -37779,24 +36538,6 @@ } } }, - "smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "optional": true, - "peer": true - }, - "socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", - "optional": true, - "peer": true, - "requires": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" - } - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -37912,22 +36653,6 @@ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, - "sshpk": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", - "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, "stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", @@ -38442,22 +37167,6 @@ "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", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" - } - } - }, "tr46": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", @@ -38535,24 +37244,11 @@ "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", "dev": true }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "requires": { - "safe-buffer": "^5.0.1" - } - }, "tv4": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/tv4/-/tv4-1.3.0.tgz", "integrity": "sha512-afizzfpJgvPr+eDkREK4MxJ/+r8nEEHcmitwgnPUqpaP+FpwQyadnxNoSACbgc/b1LsZYtODGoPiFxQrgJgjvw==" }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" - }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -38748,6 +37444,7 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, "requires": { "punycode": "^2.1.0" } @@ -38763,11 +37460,6 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" - }, "uuid": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", @@ -38783,11 +37475,6 @@ "spdx-expression-parse": "^3.0.0" } }, - "value-or-promise": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/value-or-promise/-/value-or-promise-1.0.12.tgz", - "integrity": "sha512-Z6Uz+TYwEqE7ZN50gwn+1LCVo9ZVrpxRPOhOLnncYkY1ZzOYtrX8Fwf/rFktZ8R5mJms6EZf5TqNOMeZmnPq9Q==" - }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -38927,9 +37614,9 @@ "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==" }, "whatwg-mimetype": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", - "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==" }, "whatwg-url": { "version": "13.0.0", @@ -39160,11 +37847,6 @@ "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", "dev": true }, - "xmlhttprequest": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", - "integrity": "sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA==" - }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/package.json b/package.json index 5d47aca20d..58dfabd5a9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "8.6.0", + "version": "9.0.0-alpha.11", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { @@ -20,12 +20,13 @@ ], "license": "Apache-2.0", "dependencies": { - "@apollo/server": "4.12.1", + "@apollo/server": "5.0.0", + "@as-integrations/express5": "1.1.2", "@graphql-tools/merge": "9.0.24", "@graphql-tools/schema": "10.0.23", "@graphql-tools/utils": "10.8.6", "@parse/fs-files-adapter": "3.0.0", - "@parse/push-adapter": "6.11.0", + "@parse/push-adapter": "8.1.0", "bcryptjs": "3.0.2", "commander": "13.1.0", "cors": "2.8.5", @@ -47,8 +48,8 @@ "mongodb": "6.20.0", "mustache": "4.2.0", "otpauth": "9.4.0", - "parse": "7.1.2", - "path-to-regexp": "6.3.0", + "parse": "8.0.0", + "path-to-regexp": "8.3.0", "pg-monitor": "3.0.0", "pg-promise": "12.2.0", "pluralize": "8.0.0", @@ -88,7 +89,7 @@ "eslint": "9.27.0", "eslint-plugin-expect-type": "0.6.2", "eslint-plugin-unused-imports": "4.3.0", - "form-data": "4.0.4", + "form-data": "4.0.5", "globals": "16.2.0", "graphql-tag": "2.12.6", "jasmine": "5.7.1", @@ -122,7 +123,6 @@ "build:types": "tsc", "watch": "babel --watch src/ -d lib/ --copy-files", "watch:ts": "tsc --watch", - "test:mongodb:6.0.19": "MONGODB_VERSION=6.0.19 npm run test", "test:mongodb:7.0.16": "MONGODB_VERSION=7.0.16 npm run test", "test:mongodb:8.0.4": "MONGODB_VERSION=8.0.4 npm run test", "test:postgres:testonly": "cross-env PARSE_SERVER_TEST_DB=postgres PARSE_SERVER_TEST_DATABASE_URI=postgres://postgres:password@localhost:5432/parse_server_postgres_adapter_test_database npm run testonly", @@ -142,7 +142,7 @@ }, "types": "types/index.d.ts", "engines": { - "node": ">=18.20.4 <19.0.0 || >=20.18.0 <21.0.0 || >=22.12.0 <23.0.0 || >=24.11.0 <25.0.0" + "node": ">=20.19.0 <21.0.0 || >=22.12.0 <23.0.0 || >=24.11.0 <25.0.0" }, "bin": { "parse-server": "bin/parse-server" diff --git a/public_html/invalid_link.html b/public_html/invalid_link.html deleted file mode 100644 index b19044e52f..0000000000 --- a/public_html/invalid_link.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - - Invalid Link - - - - -
-

Invalid Link

-
- - diff --git a/public_html/invalid_verification_link.html b/public_html/invalid_verification_link.html deleted file mode 100644 index 063ac354f4..0000000000 --- a/public_html/invalid_verification_link.html +++ /dev/null @@ -1,68 +0,0 @@ - - - - - Invalid Link - - - - - -
-

Invalid Verification Link

-
- - -
-
- - diff --git a/public_html/link_send_fail.html b/public_html/link_send_fail.html deleted file mode 100644 index 7f817a2cc4..0000000000 --- a/public_html/link_send_fail.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - - Invalid Link - - - - -
-

No link sent. User not found or email already verified

-
- - diff --git a/public_html/link_send_success.html b/public_html/link_send_success.html deleted file mode 100644 index 55d9cad6f6..0000000000 --- a/public_html/link_send_success.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - - Invalid Link - - - - -
-

Link Sent! Check your email.

-
- - diff --git a/public_html/password_reset_success.html b/public_html/password_reset_success.html deleted file mode 100644 index 774cbb350c..0000000000 --- a/public_html/password_reset_success.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - Password Reset - - -

Successfully updated your password!

- - diff --git a/public_html/verify_email_success.html b/public_html/verify_email_success.html deleted file mode 100644 index 774ea38a0d..0000000000 --- a/public_html/verify_email_success.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - Email Verification - - -

Successfully verified your email!

- - diff --git a/spec/AdapterLoader.spec.js b/spec/AdapterLoader.spec.js index dd726bc768..a71e373f5b 100644 --- a/spec/AdapterLoader.spec.js +++ b/spec/AdapterLoader.spec.js @@ -105,8 +105,19 @@ describe('AdapterLoader', () => { it('should load push adapter from options', async () => { const options = { android: { - senderId: 'yolo', - apiKey: 'yolo', + firebaseServiceAccount: { + "type": "service_account", + "project_id": "example-xxxx", + "private_key_id": "xxxx", + "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCxFcVMD9L2xJWW\nEMi4w/XIBPvX5bTStIEdt4GY+yfrmCHspaVdgpTcHlTLA60sAGTFdorPprOwAm6f\njaTG4j86zfW25GF6AlFO/8vE2B0tjreuQQtcP9gkWJmsTp8yzXDirDQ43Kv93Kbc\nUPmsyAN5WB8XiFjjWLnFCeDiOVdd8sHfG0HYldNzyYwXrOTLE5kOjASYSJDzdrfI\nwN9PzZC7+cCy/DDzTRKQCqfz9pEZmxqJk4Id5HLVNkGKgji3C3b6o3MXWPS+1+zD\nGheKC9WLDZnCVycAnNHFiPpsp7R82lLKC3Dth37b6qzJO+HwfTmzCb0/xCVJ0/mZ\nC4Mxih/bAgMBAAECggEACbL1DvDw75Yd0U3TCJenDxEC0DTjHgVH6x5BaWUcLyGy\nffkmoQQFbjb1Evd9FSNiYZRYDv6E6feAIpoJ8+CxcOGV+zHwCtQ0qtyExx/FHVkr\nQ06JtkBC8N6vcAoQWyJ4c9nVtGWVv/5FX1zKCAYedpd2gH31zGHwLtQXLpzQZbNO\nO/0rcggg4unGSUIyw5437XiyckJ3QdneSEPe9HvY2wxLn/f1PjMpRYiNLBSuaFBJ\n+MYXr//Vh7cMInQk5/pMFbGxugNb7dtjgvm3LKRssKnubEOyrKldo8DVJmAvjhP4\nWboOOBVEo2ZhXgnBjeMvI8btXlJ85h9lZ7xwqfWsjQKBgQDkrrLpA3Mm21rsP1Ar\nMLEnYTdMZ7k+FTm5pJffPOsC7wiLWdRLwwrtb0V3kC3jr2K4SZY/OEV8IAWHfut/\n8mP8cPQPJiFp92iOgde4Xq/Ycwx4ZAXUj7mHHgywFi2K0xATzgc9sgX3NCVl9utR\nIU/FbEDCLxyD4T3Jb5gL3xFdhwKBgQDGPS46AiHuYmV7OG4gEOsNdczTppBJCgTt\nKGSJOxZg8sQodNJeWTPP2iQr4yJ4EY57NQmH7WSogLrGj8tmorEaL7I2kYlHJzGm\nniwApWEZlFc00xgXwV5d8ATfmAf8W1ZSZ6THbHesDUGjXSoL95k3KKXhnztjUT6I\n8d5qkCygDQKBgFN7p1rDZKVZzO6UCntJ8lJS/jIJZ6nPa9xmxv67KXxPsQnWSFdE\nI9gcF/sXCnmlTF/ElXIM4+j1c69MWULDRVciESb6n5YkuOnVYuAuyPk2vuWwdiRs\nN6mpAa7C2etlM+hW/XO7aswdIE4B/1QF2i5TX6zEMB/A+aJw98vVqmw/AoGADOm9\nUiADb9DPBXjGi6YueYD756mI6okRixU/f0TvDz+hEXWSonyzCE4QXx97hlC2dEYf\nKdCH5wYDpJ2HRVdBrBABTtaqF41xCYZyHVSof48PIyzA/AMnj3zsBFiV5JVaiSGh\nNTBWl0mBxg9yhrcJLvOh4pGJv81yAl+m+lAL6B0CgYEArtqtQ1YVLIUn4Pb/HDn8\nN8o7WbhloWQnG34iSsAG8yNtzbbxdugFrEm5ejPSgZ+dbzSzi/hizOFS/+/fwEdl\nay9jqY1fngoqSrS8eddUsY1/WAcmd6wPWEamsSjazA4uxQERruuFOi94E4b895KA\nqYe0A3xb0JL2ieAOZsn8XNA=\n-----END PRIVATE KEY-----\n", + "client_email": "test@example.com", + "client_id": "1", + "auth_uri": "https://example.com", + "token_uri": "https://example.com", + "auth_provider_x509_cert_url": "https://example.com", + "client_x509_cert_url": "https://example.com", + "universe_domain": "example.com" + } }, }; const ParsePushAdapter = await loadModule('@parse/push-adapter'); diff --git a/spec/CloudCode.spec.js b/spec/CloudCode.spec.js index b2aac473b2..400efbc380 100644 --- a/spec/CloudCode.spec.js +++ b/spec/CloudCode.spec.js @@ -1702,28 +1702,7 @@ describe('Cloud Code', () => { }); }); - it('should not encode Parse Objects', async () => { - await reconfigureServer({ encodeParseObjectInCloudFunction: false }); - const user = new Parse.User(); - user.setUsername('username'); - user.setPassword('password'); - user.set('deleted', false); - await user.signUp(); - Parse.Cloud.define( - 'deleteAccount', - async req => { - expect(req.params.object instanceof Parse.Object).not.toBeTrue(); - return 'Object deleted'; - }, - { - requireMaster: true, - } - ); - await Parse.Cloud.run('deleteAccount', { object: user.toPointer() }, { useMasterKey: true }); - }); - - it('allow cloud to encode Parse Objects', async () => { - await reconfigureServer({ encodeParseObjectInCloudFunction: true }); + it('should encode Parse Objects in cloud functions', async () => { const user = new Parse.User(); user.setUsername('username'); user.setPassword('password'); diff --git a/spec/Deprecator.spec.js b/spec/Deprecator.spec.js index 80e8632014..f5b6812699 100644 --- a/spec/Deprecator.spec.js +++ b/spec/Deprecator.spec.js @@ -47,7 +47,7 @@ describe('Deprecator', () => { }); it('logs deprecation for nested option key with dot notation', async () => { - deprecations = [{ optionKey: 'databaseOptions.allowPublicExplain', changeNewDefault: 'false' }]; + deprecations = [{ optionKey: 'databaseOptions.testOption', changeNewDefault: 'false' }]; spyOn(Deprecator, '_getDeprecations').and.callFake(() => deprecations); const logger = require('../lib/logger').logger; @@ -60,14 +60,14 @@ describe('Deprecator', () => { }); it('does not log deprecation for nested option key if option is set manually', async () => { - deprecations = [{ optionKey: 'databaseOptions.allowPublicExplain', changeNewDefault: 'false' }]; + deprecations = [{ optionKey: 'databaseOptions.testOption', changeNewDefault: 'false' }]; spyOn(Deprecator, '_getDeprecations').and.callFake(() => deprecations); const logSpy = spyOn(Deprecator, '_logOption').and.callFake(() => {}); const Config = require('../lib/Config'); const config = Config.get('test'); // Directly test scanParseServerOptions with nested option set - Deprecator.scanParseServerOptions({ databaseOptions: { allowPublicExplain: true } }); + Deprecator.scanParseServerOptions({ databaseOptions: { testOption: true } }); expect(logSpy).not.toHaveBeenCalled(); }); }); diff --git a/spec/EmailVerificationToken.spec.js b/spec/EmailVerificationToken.spec.js index 1a235d8d13..a0834196af 100644 --- a/spec/EmailVerificationToken.spec.js +++ b/spec/EmailVerificationToken.spec.js @@ -40,12 +40,8 @@ describe('Email Verification Token Expiration:', () => { url: sendEmailOptions.link, followRedirects: false, }); - expect(response.status).toEqual(302); - const url = new URL(sendEmailOptions.link); - const token = url.searchParams.get('token'); - expect(response.text).toEqual( - `Found. Redirecting to http://localhost:8378/1/apps/invalid_verification_link.html?appId=test&token=${token}` - ); + expect(response.status).toEqual(200); + expect(response.text).toContain('Invalid verification link!'); }); it('emailVerified should set to false, if the user does not verify their email before the email verify token expires', async () => { @@ -81,7 +77,7 @@ describe('Email Verification Token Expiration:', () => { url: sendEmailOptions.link, followRedirects: false, }); - expect(response.status).toEqual(302); + expect(response.status).toEqual(200); await user.fetch(); expect(user.get('emailVerified')).toEqual(false); }); @@ -114,10 +110,8 @@ describe('Email Verification Token Expiration:', () => { url: sendEmailOptions.link, followRedirects: false, }); - expect(response.status).toEqual(302); - expect(response.text).toEqual( - 'Found. Redirecting to http://localhost:8378/1/apps/verify_email_success.html' - ); + expect(response.status).toEqual(200); + expect(response.text).toContain('Email verified!'); }); it_id('94956799-c85e-4297-b879-e2d1f985394c')(it)('if user clicks on the email verify link before email verification token expiration then emailVerified should be true', async () => { @@ -148,7 +142,7 @@ describe('Email Verification Token Expiration:', () => { url: sendEmailOptions.link, followRedirects: false, }); - expect(response.status).toEqual(302); + expect(response.status).toEqual(200); await user.fetch(); expect(user.get('emailVerified')).toEqual(true); }); @@ -181,7 +175,7 @@ describe('Email Verification Token Expiration:', () => { url: sendEmailOptions.link, followRedirects: false, }); - expect(response.status).toEqual(302); + expect(response.status).toEqual(200); const verifiedUser = await Parse.User.logIn('testEmailVerifyTokenValidity', 'expiringToken'); expect(typeof verifiedUser).toBe('object'); expect(verifiedUser.get('emailVerified')).toBe(true); @@ -268,9 +262,7 @@ describe('Email Verification Token Expiration:', () => { url: `http://localhost:8378/1/apps/test/verify_email?token=${token}`, method: 'GET', }); - expect(res.text).toEqual( - `Found. Redirecting to http://localhost:8378/1/apps/invalid_verification_link.html?appId=test&token=${token}` - ); + expect(res.text).toContain('Invalid verification link!'); const formUrl = `http://localhost:8378/1/apps/test/resend_verification_email`; const formResponse = await request({ @@ -282,9 +274,7 @@ describe('Email Verification Token Expiration:', () => { headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, followRedirects: false, }); - expect(formResponse.text).toEqual( - `Found. Redirecting to http://localhost:8378/1/apps/link_send_success.html` - ); + expect(formResponse.text).toContain('email_verification_send_success.html'); }); it_id('9365c53c-b8b4-41f7-a3c1-77882f76a89c')(it)('can conditionally send emails', async () => { @@ -493,7 +483,7 @@ describe('Email Verification Token Expiration:', () => { url: sendEmailOptions.link, followRedirects: false, }); - expect(response.status).toEqual(302); + expect(response.status).toEqual(200); const config = Config.get('test'); const results = await config.database.find('_User', { username: 'unsets_email_verify_token_expires_at', @@ -536,7 +526,7 @@ describe('Email Verification Token Expiration:', () => { url: sendEmailOptions.link, followRedirects: false, }); - expect(response.status).toEqual(302); + expect(response.status).toEqual(200); const config = Config.get('test'); const results = await config.database.find('_User', { username: 'unsets_email_verify_token_expires_at', @@ -580,7 +570,7 @@ describe('Email Verification Token Expiration:', () => { url: sendEmailOptions.link, followRedirects: false, }); - expect(response.status).toEqual(302); + expect(response.status).toEqual(200); await user.fetch(); expect(user.get('emailVerified')).toEqual(true); // RECONFIGURE the server i.e., ENABLE the expire email verify token flag @@ -591,12 +581,8 @@ describe('Email Verification Token Expiration:', () => { url: sendEmailOptions.link, followRedirects: false, }); - expect(response.status).toEqual(302); - const url = new URL(sendEmailOptions.link); - const token = url.searchParams.get('token'); - expect(response.text).toEqual( - `Found. Redirecting to http://localhost:8378/1/apps/invalid_verification_link.html?appId=test&token=${token}` - ); + expect(response.status).toEqual(200); + expect(response.text).toContain('Invalid verification link!'); }); it('clicking on the email verify link by an email UNVERIFIED user that was setup before enabling the expire email verify token should show invalid verficiation link page', async () => { @@ -637,12 +623,8 @@ describe('Email Verification Token Expiration:', () => { url: sendEmailOptions.link, followRedirects: false, }); - expect(response.status).toEqual(302); - const url = new URL(sendEmailOptions.link); - const token = url.searchParams.get('token'); - expect(response.text).toEqual( - `Found. Redirecting to http://localhost:8378/1/apps/invalid_verification_link.html?appId=test&token=${token}` - ); + expect(response.status).toEqual(200); + expect(response.text).toContain('Invalid verification link!'); }); it_id('b6c87f35-d887-477d-bc86-a9217a424f53')(it)('setting the email on the user should set a new email verification token and new expiration date for the token when expire email verify token flag is set', async () => { @@ -958,7 +940,7 @@ describe('Email Verification Token Expiration:', () => { url: sendEmailOptions.link, followRedirects: false, }); - expect(response.status).toEqual(302); + expect(response.status).toEqual(200); expect(sendVerificationEmailCallCount).toBe(1); response = await request({ @@ -1143,7 +1125,7 @@ describe('Email Verification Token Expiration:', () => { url: sendEmailOptions.link, followRedirects: false, }); - expect(response.status).toEqual(302); + expect(response.status).toEqual(200); user = await Parse.User.logIn('testEmailVerifyTokenValidity', 'expiringToken'); expect(typeof user).toBe('object'); expect(user.get('emailVerified')).toBe(true); @@ -1159,6 +1141,6 @@ describe('Email Verification Token Expiration:', () => { url: sendEmailOptions.link, followRedirects: false, }); - expect(response.status).toEqual(302); + expect(response.status).toEqual(200); }); }); diff --git a/spec/ParseAPI.spec.js b/spec/ParseAPI.spec.js index 779a97c9f2..8cfe9ef03f 100644 --- a/spec/ParseAPI.spec.js +++ b/spec/ParseAPI.spec.js @@ -1266,7 +1266,6 @@ describe('miscellaneous', () => { }); it('test cloud function query parameters with array of pointers', async () => { - await reconfigureServer({ encodeParseObjectInCloudFunction: false }); Parse.Cloud.define('echoParams', req => { return req.params; }); @@ -1279,7 +1278,7 @@ describe('miscellaneous', () => { method: 'POST', headers: headers, url: 'http://localhost:8378/1/functions/echoParams', - body: '{"arr": [{ "__type": "Pointer", "className": "PointerTest" }]}', + body: '{"arr": [{ "__type": "Pointer", "className": "PointerTest", "objectId": "test123" }]}', }); const res = response.data.result; expect(res.arr.length).toEqual(1); diff --git a/spec/ParseGraphQLServer.spec.js b/spec/ParseGraphQLServer.spec.js index a767f413b3..3477f9d01c 100644 --- a/spec/ParseGraphQLServer.spec.js +++ b/spec/ParseGraphQLServer.spec.js @@ -748,10 +748,223 @@ describe('ParseGraphQLServer', () => { }) expect(introspection.data).toBeDefined(); }); + + it('should block __type introspection without master key', async () => { + try { + await apolloClient.query({ + query: gql` + query TypeIntrospection { + __type(name: "User") { + name + kind + } + } + `, + }); + + fail('should have thrown an error'); + } catch (e) { + expect(e.message).toEqual('Response not successful: Received status code 403'); + expect(e.networkError.result.errors[0].message).toEqual('Introspection is not allowed'); + } + }); + + it('should block aliased __type introspection without master key', async () => { + try { + await apolloClient.query({ + query: gql` + query AliasedTypeIntrospection { + myAlias: __type(name: "User") { + name + kind + } + } + `, + }); + + fail('should have thrown an error'); + } catch (e) { + expect(e.message).toEqual('Response not successful: Received status code 403'); + expect(e.networkError.result.errors[0].message).toEqual('Introspection is not allowed'); + } + }); + + it('should block __type introspection in fragments without master key', async () => { + try { + await apolloClient.query({ + query: gql` + fragment TypeIntrospectionFields on Query { + typeInfo: __type(name: "User") { + name + kind + } + } + + query FragmentTypeIntrospection { + ...TypeIntrospectionFields + } + `, + }); + + fail('should have thrown an error'); + } catch (e) { + expect(e.message).toEqual('Response not successful: Received status code 403'); + expect(e.networkError.result.errors[0].message).toEqual('Introspection is not allowed'); + } + }); + + it('should block __type introspection through nested fragment spreads without master key', async () => { + try { + await apolloClient.query({ + query: gql` + fragment InnerFragment on Query { + __type(name: "User") { + name + fields { + name + } + } + } + + fragment OuterFragment on Query { + ...InnerFragment + } + + query NestedFragmentIntrospection { + ...OuterFragment + } + `, + }); + + fail('should have thrown an error'); + } catch (e) { + expect(e.message).toEqual('Response not successful: Received status code 403'); + expect(e.networkError.result.errors[0].message).toEqual('Introspection is not allowed'); + } + }); + + it('should block __type introspection hidden in fragment with valid field without master key', async () => { + try { + // First create a test object to query + const object = new Parse.Object('SomeClass'); + await object.save(); + + await apolloClient.query({ + query: gql` + fragment MixedFragment on Query { + someClasses { + edges { + node { + objectId + } + } + } + __type(name: "User") { + name + kind + } + } + + query MixedQuery { + ...MixedFragment + } + `, + }); + + fail('should have thrown an error'); + } catch (e) { + expect(e.message).toEqual('Response not successful: Received status code 403'); + expect(e.networkError.result.errors[0].message).toEqual('Introspection is not allowed'); + } + }); + + it('should allow __type introspection with master key', async () => { + const introspection = await apolloClient.query({ + query: gql` + query TypeIntrospection { + __type(name: "User") { + name + kind + } + } + `, + context: { + headers: { + 'X-Parse-Master-Key': 'test', + }, + }, + }); + expect(introspection.data).toBeDefined(); + expect(introspection.data.__type).toBeDefined(); + expect(introspection.errors).not.toBeDefined(); + }); + + it('should allow aliased __type introspection with master key', async () => { + const introspection = await apolloClient.query({ + query: gql` + query AliasedTypeIntrospection { + myAlias: __type(name: "User") { + name + kind + } + } + `, + context: { + headers: { + 'X-Parse-Master-Key': 'test', + }, + }, + }); + expect(introspection.data).toBeDefined(); + expect(introspection.data.myAlias).toBeDefined(); + expect(introspection.errors).not.toBeDefined(); + }); + + it('should allow __type introspection with maintenance key', async () => { + const introspection = await apolloClient.query({ + query: gql` + query TypeIntrospection { + __type(name: "User") { + name + kind + } + } + `, + context: { + headers: { + 'X-Parse-Maintenance-Key': 'test2', + }, + }, + }); + expect(introspection.data).toBeDefined(); + expect(introspection.data.__type).toBeDefined(); + expect(introspection.errors).not.toBeDefined(); + }); + + it('should allow __type introspection when public introspection is enabled', async () => { + const parseServer = await reconfigureServer(); + await createGQLFromParseServer(parseServer, { graphQLPublicIntrospection: true }); + + const introspection = await apolloClient.query({ + query: gql` + query TypeIntrospection { + __type(name: "User") { + name + kind + } + } + `, + }); + expect(introspection.data).toBeDefined(); + expect(introspection.data.__type).toBeDefined(); + }); }); describe('Default Types', () => { + beforeEach(async () => { + await createGQLFromParseServer(parseServer, { graphQLPublicIntrospection: true }); + }); it('should have Object scalar type', async () => { const objectType = ( await apolloClient.query({ @@ -911,6 +1124,10 @@ describe('ParseGraphQLServer', () => { }); describe('Relay Specific Types', () => { + beforeEach(async () => { + await createGQLFromParseServer(parseServer, { graphQLPublicIntrospection: true }); + }); + let clearCache; beforeEach(async () => { if (!clearCache) { @@ -1454,6 +1671,9 @@ describe('ParseGraphQLServer', () => { }); describe('Parse Class Types', () => { + beforeEach(async () => { + await createGQLFromParseServer(parseServer, { graphQLPublicIntrospection: true }); + }); it('should have all expected types', async () => { await parseServer.config.databaseController.loadSchema(); @@ -1565,6 +1785,7 @@ describe('ParseGraphQLServer', () => { beforeEach(async () => { await parseGraphQLServer.setGraphQLConfig({}); await resetGraphQLCache(); + await createGQLFromParseServer(parseServer, { graphQLPublicIntrospection: true }); }); it_id('d6a23a2f-ca18-4b15-bc73-3e636f99e6bc')(it)('should only include types in the enabledForClasses list', async () => { @@ -8141,6 +8362,9 @@ describe('ParseGraphQLServer', () => { }); describe('Functions Mutations', () => { + beforeEach(async () => { + await createGQLFromParseServer(parseServer, { graphQLPublicIntrospection: true }); + }); it('can be called', async () => { try { const clientMutationId = uuidv4(); diff --git a/spec/ParseLiveQueryServer.spec.js b/spec/ParseLiveQueryServer.spec.js index 9961b2503d..dd306ac1be 100644 --- a/spec/ParseLiveQueryServer.spec.js +++ b/spec/ParseLiveQueryServer.spec.js @@ -154,36 +154,24 @@ describe('ParseLiveQueryServer', function () { }); it('properly passes the CLP to afterSave/afterDelete hook', function (done) { - function setPermissionsOnClass(className, permissions, doPut) { - const request = require('request'); - let op = request.post; - if (doPut) { - op = request.put; - } - return new Promise((resolve, reject) => { - op( - { - url: Parse.serverURL + '/schemas/' + className, - headers: { - 'X-Parse-Application-Id': Parse.applicationId, - 'X-Parse-Master-Key': Parse.masterKey, - }, - json: true, - body: { - classLevelPermissions: permissions, - }, - }, - (error, response, body) => { - if (error) { - return reject(error); - } - if (body.error) { - return reject(body); - } - return resolve(body); - } - ); + async function setPermissionsOnClass(className, permissions, doPut) { + const method = doPut ? 'PUT' : 'POST'; + const response = await fetch(Parse.serverURL + '/schemas/' + className, { + method, + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-Master-Key': Parse.masterKey, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + classLevelPermissions: permissions, + }), }); + const body = await response.json(); + if (body.error) { + throw body; + } + return body; } let saveSpy; @@ -641,7 +629,7 @@ describe('ParseLiveQueryServer', function () { it('can forward event to cloud code', function () { const cloudCodeHandler = { - handler: () => {}, + handler: () => { }, }; const spy = spyOn(cloudCodeHandler, 'handler').and.callThrough(); Parse.Cloud.onLiveQueryEvent(cloudCodeHandler.handler); @@ -1932,36 +1920,24 @@ describe('ParseLiveQueryServer', function () { describe('LiveQueryController', () => { it('properly passes the CLP to afterSave/afterDelete hook', function (done) { - function setPermissionsOnClass(className, permissions, doPut) { - const request = require('request'); - let op = request.post; - if (doPut) { - op = request.put; - } - return new Promise((resolve, reject) => { - op( - { - url: Parse.serverURL + '/schemas/' + className, - headers: { - 'X-Parse-Application-Id': Parse.applicationId, - 'X-Parse-Master-Key': Parse.masterKey, - }, - json: true, - body: { - classLevelPermissions: permissions, - }, - }, - (error, response, body) => { - if (error) { - return reject(error); - } - if (body.error) { - return reject(body); - } - return resolve(body); - } - ); + async function setPermissionsOnClass(className, permissions, doPut) { + const method = doPut ? 'PUT' : 'POST'; + const response = await fetch(Parse.serverURL + '/schemas/' + className, { + method, + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-Master-Key': Parse.masterKey, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + classLevelPermissions: permissions, + }), }); + const body = await response.json(); + if (body.error) { + throw body; + } + return body; } let saveSpy; diff --git a/spec/ParseQuery.hint.spec.js b/spec/ParseQuery.hint.spec.js index 0905eb7d32..5a6ed63b19 100644 --- a/spec/ParseQuery.hint.spec.js +++ b/spec/ParseQuery.hint.spec.js @@ -79,30 +79,6 @@ describe_only_db('mongo')('Parse.Query hint', () => { }); }); - it_only_mongodb_version('<7')('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.queryPlanner; - expect(queryPlanner.winningPlan.stage).toBe('PROJECTION_SIMPLE'); - expect(queryPlanner.winningPlan.inputStage.stage).toBe('COLLSCAN'); - expect(queryPlanner.winningPlan.inputStage.inputStage).toBeUndefined(); - - result = await collection.aggregate([{ $group: { _id: '$foo' } }], { - hint: '_id_', - explain: true, - }); - queryPlanner = result[0].stages[0].$cursor.queryPlanner; - expect(queryPlanner.winningPlan.stage).toBe('PROJECTION_SIMPLE'); - expect(queryPlanner.winningPlan.inputStage.stage).toBe('FETCH'); - expect(queryPlanner.winningPlan.inputStage.inputStage.stage).toBe('IXSCAN'); - expect(queryPlanner.winningPlan.inputStage.inputStage.indexName).toBe('_id_'); - }); - it_only_mongodb_version('>=7')('query aggregate with hint string', async () => { const object = new TestObject({ foo: 'bar' }); await object.save(); @@ -127,31 +103,6 @@ describe_only_db('mongo')('Parse.Query hint', () => { expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_'); }); - it_only_mongodb_version('<7')('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.queryPlanner; - expect(queryPlanner.winningPlan.stage).toBe('PROJECTION_SIMPLE'); - expect(queryPlanner.winningPlan.inputStage.stage).toBe('COLLSCAN'); - expect(queryPlanner.winningPlan.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.stage).toBe('PROJECTION_SIMPLE'); - expect(queryPlanner.winningPlan.inputStage.stage).toBe('FETCH'); - expect(queryPlanner.winningPlan.inputStage.inputStage.stage).toBe('IXSCAN'); - expect(queryPlanner.winningPlan.inputStage.inputStage.indexName).toBe('_id_'); - expect(queryPlanner.winningPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 }); - }); - it_only_mongodb_version('>=7')('query aggregate with hint object', async () => { const object = new TestObject({ foo: 'bar' }); await object.save(); @@ -202,39 +153,6 @@ describe_only_db('mongo')('Parse.Query hint', () => { expect(explain.queryPlanner.winningPlan.inputStage.inputStage.indexName).toBe('_id_'); }); - it_only_mongodb_version('<7')('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({ _id: '$foo' }), - }, - }); - let response = await request(options); - let queryPlanner = response.data.results[0].stages[0].$cursor.queryPlanner; - expect(queryPlanner.winningPlan.stage).toBe('PROJECTION_SIMPLE'); - expect(queryPlanner.winningPlan.inputStage.stage).toBe('COLLSCAN'); - expect(queryPlanner.winningPlan.inputStage.inputStage).toBeUndefined(); - - options = Object.assign({}, masterKeyOptions, { - url: Parse.serverURL + '/aggregate/TestObject', - qs: { - explain: true, - hint: '_id_', - $group: JSON.stringify({ _id: '$foo' }), - }, - }); - response = await request(options); - queryPlanner = response.data.results[0].stages[0].$cursor.queryPlanner; - expect(queryPlanner.winningPlan.stage).toBe('PROJECTION_SIMPLE'); - expect(queryPlanner.winningPlan.inputStage.stage).toBe('FETCH'); - expect(queryPlanner.winningPlan.inputStage.inputStage.stage).toBe('IXSCAN'); - expect(queryPlanner.winningPlan.inputStage.inputStage.indexName).toBe('_id_'); - expect(queryPlanner.winningPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 }); - }); - it_only_mongodb_version('>=7')('query aggregate with hint (rest)', async () => { const object = new TestObject({ foo: 'bar' }); await object.save(); diff --git a/spec/ParseQuery.spec.js b/spec/ParseQuery.spec.js index 0aa173dc65..4dd7eaecea 100644 --- a/spec/ParseQuery.spec.js +++ b/spec/ParseQuery.spec.js @@ -5369,7 +5369,7 @@ describe('Parse.Query testing', () => { const query = new Parse.Query('_User'); query.equalTo('objectId', user.id); query.explain(); - const result = await query.find(); + const result = await query.find({ useMasterKey: true }); // Validate expect(result.executionStats).not.toBeUndefined(); }); @@ -5533,11 +5533,8 @@ describe('Parse.Query testing', () => { ); it_id('c3d4e5f6-a7b8-4c9d-0e1f-2a3b4c5d6e7f')(it_only_db('mongo'))( - 'explain works with and without master key by default', + 'explain requires master key by default', async () => { - const logger = require('../lib/logger').logger; - const logSpy = spyOn(logger, 'warn').and.callFake(() => {}); - await reconfigureServer({ databaseAdapter: undefined, databaseURI: 'mongodb://localhost:27017/parse', @@ -5546,21 +5543,20 @@ describe('Parse.Query testing', () => { }, }); - // Verify deprecation warning is logged when allowPublicExplain is not explicitly set - expect(logSpy).toHaveBeenCalledWith( - jasmine.stringMatching(/DeprecationWarning.*databaseOptions\.allowPublicExplain.*false/) - ); - const obj = new TestObject({ foo: 'bar' }); await obj.save(); - // Without master key + // Without master key - should fail const query = new Parse.Query(TestObject); query.explain(); - const resultWithoutMasterKey = await query.find(); - expect(resultWithoutMasterKey).toBeDefined(); + await expectAsync(query.find()).toBeRejectedWith( + new Parse.Error( + Parse.Error.INVALID_QUERY, + 'Using the explain query parameter requires the master key' + ) + ); - // With master key + // With master key - should succeed const queryWithMasterKey = new Parse.Query(TestObject); queryWithMasterKey.explain(); const resultWithMasterKey = await queryWithMasterKey.find({ useMasterKey: true }); diff --git a/spec/PasswordPolicy.spec.js b/spec/PasswordPolicy.spec.js index 1fd2e6aa50..27145015bc 100644 --- a/spec/PasswordPolicy.spec.js +++ b/spec/PasswordPolicy.spec.js @@ -46,10 +46,8 @@ describe('Password Policy: ', () => { resolveWithFullResponse: true, }) .then(response => { - expect(response.status).toEqual(302); - expect(response.text).toEqual( - 'Found. Redirecting to http://localhost:8378/1/apps/invalid_link.html' - ); + expect(response.status).toEqual(200); + expect(response.text).toContain('Invalid password reset link!'); done(); }) .catch(error => { @@ -106,9 +104,8 @@ describe('Password Policy: ', () => { followRedirects: false, }) .then(response => { - expect(response.status).toEqual(302); - const re = /http:\/\/localhost:8378\/1\/apps\/choose_password\?token=[a-zA-Z0-9]+\&id=test\&/; - expect(response.text.match(re)).not.toBe(null); + expect(response.status).toEqual(200); + expect(response.text).toContain('password'); done(); }) .catch(error => { @@ -621,8 +618,8 @@ describe('Password Policy: ', () => { resolveWithFullResponse: true, }) .then(response => { - expect(response.status).toEqual(302); - const re = /http:\/\/localhost:8378\/1\/apps\/choose_password\?token=([a-zA-Z0-9]+)\&id=test\&/; + expect(response.status).toEqual(200); + const re = /name="token"[^>]*value="([^"]+)"/; const match = response.text.match(re); if (!match) { fail('should have a token'); @@ -643,10 +640,8 @@ describe('Password Policy: ', () => { resolveWithFullResponse: true, }) .then(response => { - expect(response.status).toEqual(302); - expect(response.text).toEqual( - 'Found. Redirecting to http://localhost:8378/1/apps/password_reset_success.html' - ); + expect(response.status).toEqual(200); + expect(response.text).toContain('Success!'); Parse.User.logIn('user1', 'has2init') .then(function () { @@ -713,8 +708,8 @@ describe('Password Policy: ', () => { resolveWithFullResponse: true, }) .then(response => { - expect(response.status).toEqual(302); - const re = /http:\/\/localhost:8378\/1\/apps\/choose_password\?token=([a-zA-Z0-9]+)\&id=test\&/; + expect(response.status).toEqual(200); + const re = /name="token"[^>]*value="([^"]+)"/; const match = response.text.match(re); if (!match) { fail('should have a token'); @@ -735,10 +730,8 @@ describe('Password Policy: ', () => { resolveWithFullResponse: true, }) .then(response => { - expect(response.status).toEqual(302); - expect(response.text).toEqual( - `Found. Redirecting to http://localhost:8378/1/apps/choose_password?token=${token}&id=test&error=Password%20should%20contain%20at%20least%20one%20digit.&app=passwordPolicy` - ); + expect(response.status).toEqual(200); + expect(response.text).toContain('Password should contain at least one digit.'); Parse.User.logIn('user1', 'has 1 digit') .then(function () { @@ -899,8 +892,8 @@ describe('Password Policy: ', () => { resolveWithFullResponse: true, }) .then(response => { - expect(response.status).toEqual(302); - const re = /http:\/\/localhost:8378\/1\/apps\/choose_password\?token=([a-zA-Z0-9]+)\&id=test\&/; + expect(response.status).toEqual(200); + const re = /name="token"[^>]*value="([^"]+)"/; const match = response.text.match(re); if (!match) { fail('should have a token'); @@ -921,10 +914,8 @@ describe('Password Policy: ', () => { resolveWithFullResponse: true, }) .then(response => { - expect(response.status).toEqual(302); - expect(response.text).toEqual( - `Found. Redirecting to http://localhost:8378/1/apps/choose_password?token=${token}&id=test&error=Password%20cannot%20contain%20your%20username.&app=passwordPolicy` - ); + expect(response.status).toEqual(200); + expect(response.text).toContain('Password cannot contain your username.'); Parse.User.logIn('user1', 'r@nd0m') .then(function () { @@ -990,8 +981,8 @@ describe('Password Policy: ', () => { simple: false, resolveWithFullResponse: true, }); - expect(response.status).toEqual(302); - const re = /http:\/\/localhost:8378\/1\/apps\/choose_password\?token=([a-zA-Z0-9]+)\&id=test\&/; + expect(response.status).toEqual(200); + const re = /name="token"[^>]*value="([^"]+)"/; const match = response.text.match(re); if (!match) { fail('should have a token'); @@ -1050,8 +1041,8 @@ describe('Password Policy: ', () => { resolveWithFullResponse: true, }) .then(response => { - expect(response.status).toEqual(302); - const re = /http:\/\/localhost:8378\/1\/apps\/choose_password\?token=([a-zA-Z0-9]+)\&id=test\&/; + expect(response.status).toEqual(200); + const re = /name="token"[^>]*value="([^"]+)"/; const match = response.text.match(re); if (!match) { fail('should have a token'); @@ -1072,10 +1063,8 @@ describe('Password Policy: ', () => { resolveWithFullResponse: true, }) .then(response => { - expect(response.status).toEqual(302); - expect(response.text).toEqual( - 'Found. Redirecting to http://localhost:8378/1/apps/password_reset_success.html' - ); + expect(response.status).toEqual(200); + expect(response.text).toContain('Success!'); Parse.User.logIn('user1', 'uuser11') .then(function () { @@ -1316,8 +1305,8 @@ describe('Password Policy: ', () => { resolveWithFullResponse: true, }) .then(response => { - expect(response.status).toEqual(302); - const re = /http:\/\/localhost:8378\/1\/apps\/choose_password\?token=([a-zA-Z0-9]+)\&id=test\&/; + expect(response.status).toEqual(200); + const re = /name="token"[^>]*value="([^"]+)"/; const match = response.text.match(re); if (!match) { fail('should have a token'); @@ -1338,10 +1327,8 @@ describe('Password Policy: ', () => { resolveWithFullResponse: true, }) .then(response => { - expect(response.status).toEqual(302); - expect(response.text).toEqual( - 'Found. Redirecting to http://localhost:8378/1/apps/password_reset_success.html' - ); + expect(response.status).toEqual(200); + expect(response.text).toContain('Success!'); Parse.User.logIn('user1', 'uuser11') .then(function () { @@ -1471,8 +1458,8 @@ describe('Password Policy: ', () => { followRedirects: false, }) .then(response => { - expect(response.status).toEqual(302); - const re = /http:\/\/localhost:8378\/1\/apps\/choose_password\?token=([a-zA-Z0-9]+)\&id=test\&/; + expect(response.status).toEqual(200); + const re = /name="token"[^>]*value="([^"]+)"/; const match = response.text.match(re); if (!match) { fail('should have a token'); @@ -1498,10 +1485,8 @@ describe('Password Policy: ', () => { .then(data => { const response = data[0]; const token = data[1]; - expect(response.status).toEqual(302); - expect(response.text).toEqual( - `Found. Redirecting to http://localhost:8378/1/apps/choose_password?token=${token}&id=test&error=New%20password%20should%20not%20be%20the%20same%20as%20last%201%20passwords.&app=passwordPolicy` - ); + expect(response.status).toEqual(200); + expect(response.text).toContain('New password should not be the same as last 1 passwords.'); done(); return Promise.resolve(); }) diff --git a/spec/PublicAPI.spec.js b/spec/PublicAPI.spec.js deleted file mode 100644 index 940417ad24..0000000000 --- a/spec/PublicAPI.spec.js +++ /dev/null @@ -1,162 +0,0 @@ -const req = require('../lib/request'); - -const request = function (url, callback) { - return req({ - url, - }).then( - response => callback(null, response), - err => callback(err, err) - ); -}; - -describe('public API', () => { - it('should return missing token error on ajax request without token provided', async () => { - await reconfigureServer({ - publicServerURL: 'http://localhost:8378/1', - }); - - try { - await req({ - method: 'POST', - url: 'http://localhost:8378/1/apps/test/request_password_reset', - body: `new_password=user1&token=`, - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - 'X-Requested-With': 'XMLHttpRequest', - }, - followRedirects: false, - }); - } catch (error) { - expect(error.status).not.toBe(302); - expect(error.text).toEqual('{"code":-1,"error":"Missing token"}'); - } - }); - - it('should return missing password error on ajax request without password provided', async () => { - await reconfigureServer({ - publicServerURL: 'http://localhost:8378/1', - }); - - try { - await req({ - method: 'POST', - url: 'http://localhost:8378/1/apps/test/request_password_reset', - body: `new_password=&token=132414`, - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - 'X-Requested-With': 'XMLHttpRequest', - }, - followRedirects: false, - }); - } catch (error) { - expect(error.status).not.toBe(302); - expect(error.text).toEqual('{"code":201,"error":"Missing password"}'); - } - }); - - it('should get invalid_link.html', done => { - request('http://localhost:8378/1/apps/invalid_link.html', (err, httpResponse) => { - expect(httpResponse.status).toBe(200); - done(); - }); - }); - - it('should get choose_password', done => { - reconfigureServer({ - appName: 'unused', - publicServerURL: 'http://localhost:8378/1', - }).then(() => { - request('http://localhost:8378/1/apps/choose_password?id=test', (err, httpResponse) => { - expect(httpResponse.status).toBe(200); - done(); - }); - }); - }); - - it('should get verify_email_success.html', done => { - request('http://localhost:8378/1/apps/verify_email_success.html', (err, httpResponse) => { - expect(httpResponse.status).toBe(200); - done(); - }); - }); - - it('should get password_reset_success.html', done => { - request('http://localhost:8378/1/apps/password_reset_success.html', (err, httpResponse) => { - expect(httpResponse.status).toBe(200); - done(); - }); - }); -}); - -describe('public API without publicServerURL', () => { - beforeEach(async () => { - await reconfigureServer({ appName: 'unused' }); - }); - it('should get 404 on verify_email', done => { - request('http://localhost:8378/1/apps/test/verify_email', (err, httpResponse) => { - expect(httpResponse.status).toBe(404); - done(); - }); - }); - - it('should get 404 choose_password', done => { - request('http://localhost:8378/1/apps/choose_password?id=test', (err, httpResponse) => { - expect(httpResponse.status).toBe(404); - done(); - }); - }); - - it('should get 404 on request_password_reset', done => { - request('http://localhost:8378/1/apps/test/request_password_reset', (err, httpResponse) => { - expect(httpResponse.status).toBe(404); - done(); - }); - }); -}); - -describe('public API supplied with invalid application id', () => { - beforeEach(async () => { - await reconfigureServer({ appName: 'unused' }); - }); - - it('should get 403 on verify_email', done => { - request('http://localhost:8378/1/apps/invalid/verify_email', (err, httpResponse) => { - expect(httpResponse.status).toBe(403); - done(); - }); - }); - - it('should get 403 choose_password', done => { - request('http://localhost:8378/1/apps/choose_password?id=invalid', (err, httpResponse) => { - expect(httpResponse.status).toBe(403); - done(); - }); - }); - - it('should get 403 on get of request_password_reset', done => { - request('http://localhost:8378/1/apps/invalid/request_password_reset', (err, httpResponse) => { - expect(httpResponse.status).toBe(403); - done(); - }); - }); - - it('should get 403 on post of request_password_reset', done => { - req({ - url: 'http://localhost:8378/1/apps/invalid/request_password_reset', - method: 'POST', - }).then(done.fail, httpResponse => { - expect(httpResponse.status).toBe(403); - done(); - }); - }); - - it('should get 403 on resendVerificationEmail', done => { - request( - 'http://localhost:8378/1/apps/invalid/resend_verification_email', - (err, httpResponse) => { - expect(httpResponse.status).toBe(403); - done(); - } - ); - }); -}); diff --git a/spec/RateLimit.spec.js b/spec/RateLimit.spec.js index 3c57810702..429b7aaed2 100644 --- a/spec/RateLimit.spec.js +++ b/spec/RateLimit.spec.js @@ -5,7 +5,7 @@ describe('rate limit', () => { await reconfigureServer({ rateLimit: [ { - requestPath: '/functions/*', + requestPath: '/functions/*path', requestTimeWindow: 10000, requestCount: 1, errorResponseMessage: 'Too many requests', @@ -26,7 +26,7 @@ describe('rate limit', () => { await reconfigureServer({ rateLimit: [ { - requestPath: '/functions/*', + requestPath: '/functions/*path', requestTimeWindow: 10000, requestCount: 1, errorResponseMessage: 'Too many requests', @@ -45,7 +45,7 @@ describe('rate limit', () => { Parse.Cloud.define('test', () => 'Abc'); await reconfigureServer({ rateLimit: { - requestPath: '*', + requestPath: '/*path', requestTimeWindow: 10000, requestCount: 1, errorResponseMessage: 'Too many requests', @@ -83,7 +83,7 @@ describe('rate limit', () => { await reconfigureServer({ rateLimit: [ { - requestPath: '/functions/*', + requestPath: '/functions/*path', requestTimeWindow: 10000, requestCount: 1, errorResponseMessage: 'Too many requests', @@ -102,7 +102,7 @@ describe('rate limit', () => { await reconfigureServer({ rateLimit: [ { - requestPath: '/functions/*', + requestPath: '/functions/*path', requestTimeWindow: 10000, requestCount: 1, includeMasterKey: true, @@ -122,7 +122,7 @@ describe('rate limit', () => { await reconfigureServer({ rateLimit: [ { - requestPath: '/classes/*', + requestPath: '/classes/*path', requestTimeWindow: 10000, requestCount: 1, errorResponseMessage: 'Too many requests', @@ -141,7 +141,7 @@ describe('rate limit', () => { await reconfigureServer({ rateLimit: [ { - requestPath: '/classes/*', + requestPath: '/classes/*path', requestTimeWindow: 10000, requestCount: 1, requestMethods: 'POST', @@ -240,7 +240,7 @@ describe('rate limit', () => { await reconfigureServer({ rateLimit: [ { - requestPath: '/classes/Test/*', + requestPath: '/classes/Test/*path', requestTimeWindow: 10000, requestCount: 1, requestMethods: 'DELETE', @@ -294,7 +294,7 @@ describe('rate limit', () => { await reconfigureServer({ rateLimit: [ { - requestPath: '/functions/*', + requestPath: '/functions/*path', requestTimeWindow: 10000, requestCount: 100, errorResponseMessage: 'Too many requests', @@ -320,7 +320,7 @@ describe('rate limit', () => { await reconfigureServer({ rateLimit: [ { - requestPath: '/functions/*', + requestPath: '/functions/*path', requestTimeWindow: 10000, requestCount: 1, errorResponseMessage: 'Too many requests', @@ -340,7 +340,7 @@ describe('rate limit', () => { it('can use global zone', async () => { await reconfigureServer({ rateLimit: { - requestPath: '*', + requestPath: '*path', requestTimeWindow: 10000, requestCount: 1, errorResponseMessage: 'Too many requests', @@ -373,7 +373,7 @@ describe('rate limit', () => { }); fakeRes.json = jasmine.createSpy('json').and.callFake(resolvingPromise); middlewares.handleParseHeaders(fakeReq, fakeRes, () => { - throw 'Should not call next'; + throw new Error('Should not call next'); }); await promise; expect(fakeRes.status).toHaveBeenCalledWith(429); @@ -386,7 +386,7 @@ describe('rate limit', () => { it('can use session zone', async () => { await reconfigureServer({ rateLimit: { - requestPath: '/functions/*', + requestPath: '/functions/*path', requestTimeWindow: 10000, requestCount: 1, errorResponseMessage: 'Too many requests', @@ -407,7 +407,7 @@ describe('rate limit', () => { it('can use user zone', async () => { await reconfigureServer({ rateLimit: { - requestPath: '/functions/*', + requestPath: '/functions/*path', requestTimeWindow: 10000, requestCount: 1, errorResponseMessage: 'Too many requests', @@ -494,7 +494,7 @@ describe('rate limit', () => { await reconfigureServer({ rateLimit: [ { - requestPath: '/classes/*', + requestPath: '/classes/*path', requestTimeWindow: 10000, requestCount: 1, errorResponseMessage: 'Too many requests', diff --git a/spec/RegexVulnerabilities.spec.js b/spec/RegexVulnerabilities.spec.js index 8418494bac..aab0241ad8 100644 --- a/spec/RegexVulnerabilities.spec.js +++ b/spec/RegexVulnerabilities.spec.js @@ -147,8 +147,8 @@ describe('Regex Vulnerabilities', () => { url: `${serverURL}/apps/test/request_password_reset?token[$regex]=`, method: 'GET', }); - expect(passwordResetResponse.status).toEqual(302); - expect(passwordResetResponse.headers.location).toMatch(`\\/invalid\\_link\\.html`); + expect(passwordResetResponse.status).toEqual(200); + expect(passwordResetResponse.text).toContain('Invalid password reset link!'); await request({ url: `${serverURL}/apps/test/request_password_reset`, method: 'POST', @@ -195,10 +195,8 @@ describe('Regex Vulnerabilities', () => { url: `${serverURL}/apps/test/request_password_reset?token=${token}`, method: 'GET', }); - expect(passwordResetResponse.status).toEqual(302); - expect(passwordResetResponse.headers.location).toMatch( - `\\/choose\\_password\\?token\\=${token}\\&` - ); + expect(passwordResetResponse.status).toEqual(200); + expect(passwordResetResponse.text).toContain('Reset Your Password'); await request({ url: `${serverURL}/apps/test/request_password_reset`, method: 'POST', diff --git a/spec/SecurityCheckGroups.spec.js b/spec/SecurityCheckGroups.spec.js index aea4468da8..8031733322 100644 --- a/spec/SecurityCheckGroups.spec.js +++ b/spec/SecurityCheckGroups.spec.js @@ -49,6 +49,7 @@ describe('Security Check Groups', () => { config.masterKey = 'insecure'; config.security.enableCheckLog = true; config.allowClientClassCreation = true; + config.enableInsecureAuthAdapters = true; config.graphQLPublicIntrospection = true; await reconfigureServer(config); diff --git a/spec/ValidationAndPasswordsReset.spec.js b/spec/ValidationAndPasswordsReset.spec.js index 3f6d4048c5..e2113c2804 100644 --- a/spec/ValidationAndPasswordsReset.spec.js +++ b/spec/ValidationAndPasswordsReset.spec.js @@ -333,10 +333,8 @@ describe('Custom Pages, Email Verification, Password Reset', () => { url: sendEmailOptions.link, followRedirects: false, }); - expect(response.status).toEqual(302); - expect(response.text).toEqual( - 'Found. Redirecting to http://localhost:8378/1/apps/verify_email_success.html' - ); + expect(response.status).toEqual(200); + expect(response.text).toContain('Email verified!'); user = await new Parse.Query(Parse.User).first({ useMasterKey: true }); expect(user.get('emailVerified')).toEqual(true); user = await Parse.User.logIn('user', 'other-password'); @@ -674,10 +672,8 @@ describe('Custom Pages, Email Verification, Password Reset', () => { url: sendEmailOptions.link, followRedirects: false, }).then(response => { - expect(response.status).toEqual(302); - expect(response.text).toEqual( - 'Found. Redirecting to http://localhost:8378/1/apps/verify_email_success.html' - ); + expect(response.status).toEqual(200); + expect(response.text).toContain('Email verified!'); user .fetch() .then( @@ -714,10 +710,8 @@ describe('Custom Pages, Email Verification, Password Reset', () => { url: 'http://localhost:8378/1/apps/test/verify_email', followRedirects: false, }).then(response => { - expect(response.status).toEqual(302); - expect(response.text).toEqual( - 'Found. Redirecting to http://localhost:8378/1/apps/invalid_link.html' - ); + expect(response.status).toEqual(200); + expect(response.text).toContain('Invalid verification link!'); done(); }); }); @@ -738,10 +732,8 @@ describe('Custom Pages, Email Verification, Password Reset', () => { url: 'http://localhost:8378/1/apps/test/verify_email?token=asdfasdf', followRedirects: false, }).then(response => { - expect(response.status).toEqual(302); - expect(response.text).toEqual( - 'Found. Redirecting to http://localhost:8378/1/apps/invalid_verification_link.html?appId=test&token=asdfasdf' - ); + expect(response.status).toEqual(200); + expect(response.text).toContain('Invalid verification link!'); done(); }); }); @@ -766,10 +758,8 @@ describe('Custom Pages, Email Verification, Password Reset', () => { username: 'sadfasga', }, }).then(response => { - expect(response.status).toEqual(302); - expect(response.text).toEqual( - 'Found. Redirecting to http://localhost:8378/1/apps/link_send_fail.html' - ); + expect(response.status).toEqual(303); + expect(response.text).toContain('email_verification_send_fail.html'); done(); }); }); @@ -783,10 +773,8 @@ describe('Custom Pages, Email Verification, Password Reset', () => { url: 'http://localhost:8378/1/apps/test/verify_email?token=invalid', followRedirects: false, }).then(response => { - expect(response.status).toEqual(302); - expect(response.text).toEqual( - 'Found. Redirecting to http://localhost:8378/1/apps/invalid_verification_link.html?appId=test&token=invalid' - ); + expect(response.status).toEqual(200); + expect(response.text).toContain('Invalid verification link!'); user.fetch().then(() => { expect(user.get('emailVerified')).toEqual(false); done(); @@ -824,8 +812,8 @@ describe('Custom Pages, Email Verification, Password Reset', () => { url: options.link, followRedirects: false, }).then(response => { - expect(response.status).toEqual(302); - const re = /http:\/\/localhost:8378\/1\/apps\/choose_password\?token=[a-zA-Z0-9]+\&id=test\&/; + expect(response.status).toEqual(200); + const re = /name="token"[^>]*value="([^"]+)"/; expect(response.text.match(re)).not.toBe(null); done(); }); @@ -868,10 +856,8 @@ describe('Custom Pages, Email Verification, Password Reset', () => { url: 'http://localhost:8378/1/apps/test/request_password_reset?token=asdfasdf', followRedirects: false, }).then(response => { - expect(response.status).toEqual(302); - expect(response.text).toEqual( - 'Found. Redirecting to http://localhost:8378/1/apps/invalid_link.html' - ); + expect(response.status).toEqual(200); + expect(response.text).toContain('Invalid password reset link!'); done(); }); }); @@ -886,8 +872,8 @@ describe('Custom Pages, Email Verification, Password Reset', () => { url: options.link, followRedirects: false, }).then(response => { - expect(response.status).toEqual(302); - const re = /http:\/\/localhost:8378\/1\/apps\/choose_password\?token=([a-zA-Z0-9]+)\&id=test\&/; + expect(response.status).toEqual(200); + const re = /name="token"[^>]*value="([^"]+)"/; const match = response.text.match(re); if (!match) { fail('should have a token'); @@ -905,10 +891,8 @@ describe('Custom Pages, Email Verification, Password Reset', () => { }, followRedirects: false, }).then(response => { - expect(response.status).toEqual(302); - expect(response.text).toEqual( - 'Found. Redirecting to http://localhost:8378/1/apps/password_reset_success.html' - ); + expect(response.status).toEqual(200); + expect(response.text).toContain('Success!'); Parse.User.logIn('zxcv', 'hello').then( function () { @@ -963,8 +947,8 @@ describe('Custom Pages, Email Verification, Password Reset', () => { url: options.link, followRedirects: false, }).then(response => { - expect(response.status).toEqual(302); - const re = /http:\/\/localhost:8378\/1\/apps\/choose_password\?token=([a-zA-Z0-9]+)\&id=test\&/; + expect(response.status).toEqual(200); + const re = /name="token"[^>]*value="([^"]+)"/; const match = response.text.match(re); if (!match) { fail('should have a token'); @@ -982,10 +966,8 @@ describe('Custom Pages, Email Verification, Password Reset', () => { }, followRedirects: false, }).then(response => { - expect(response.status).toEqual(302); - expect(response.text).toEqual( - 'Found. Redirecting to http://localhost:8378/1/apps/password_reset_success.html' - ); + expect(response.status).toEqual(200); + expect(response.text).toContain('Success!'); done(); }); }); @@ -1022,8 +1004,8 @@ describe('Custom Pages, Email Verification, Password Reset', () => { url: options.link, followRedirects: false, }); - expect(response.status).toEqual(302); - const re = /http:\/\/localhost:8378\/1\/apps\/choose_password\?token=([a-zA-Z0-9]+)\&id=test\&/; + expect(response.status).toEqual(200); + const re = /name="token"[^>]*value="([^"]+)"/; const match = response.text.match(re); if (!match) { fail('should have a token'); @@ -1197,9 +1179,7 @@ describe('Custom Pages, Email Verification, Password Reset', () => { new_password: 'newpassword', }, }); - expect(res.text).toEqual( - `Found. Redirecting to http://localhost:8378/1/apps/choose_password?id=test&error=The%20password%20reset%20link%20has%20expired&app=emailVerifyToken&token=${token}` - ); + expect(res.text).toContain('The password reset link has expired'); await request({ url: `http://localhost:8378/1/requestPasswordReset`, diff --git a/spec/helper.js b/spec/helper.js index 43b5ceeb81..28fb4afa80 100644 --- a/spec/helper.js +++ b/spec/helper.js @@ -136,8 +136,20 @@ const defaultConfiguration = { }, push: { android: { - senderId: 'yolo', - apiKey: 'yolo', + firebaseServiceAccount: { + "type": "service_account", + "project_id": "example-xxxx", + "private_key_id": "xxxx", + "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCxFcVMD9L2xJWW\nEMi4w/XIBPvX5bTStIEdt4GY+yfrmCHspaVdgpTcHlTLA60sAGTFdorPprOwAm6f\njaTG4j86zfW25GF6AlFO/8vE2B0tjreuQQtcP9gkWJmsTp8yzXDirDQ43Kv93Kbc\nUPmsyAN5WB8XiFjjWLnFCeDiOVdd8sHfG0HYldNzyYwXrOTLE5kOjASYSJDzdrfI\nwN9PzZC7+cCy/DDzTRKQCqfz9pEZmxqJk4Id5HLVNkGKgji3C3b6o3MXWPS+1+zD\nGheKC9WLDZnCVycAnNHFiPpsp7R82lLKC3Dth37b6qzJO+HwfTmzCb0/xCVJ0/mZ\nC4Mxih/bAgMBAAECggEACbL1DvDw75Yd0U3TCJenDxEC0DTjHgVH6x5BaWUcLyGy\nffkmoQQFbjb1Evd9FSNiYZRYDv6E6feAIpoJ8+CxcOGV+zHwCtQ0qtyExx/FHVkr\nQ06JtkBC8N6vcAoQWyJ4c9nVtGWVv/5FX1zKCAYedpd2gH31zGHwLtQXLpzQZbNO\nO/0rcggg4unGSUIyw5437XiyckJ3QdneSEPe9HvY2wxLn/f1PjMpRYiNLBSuaFBJ\n+MYXr//Vh7cMInQk5/pMFbGxugNb7dtjgvm3LKRssKnubEOyrKldo8DVJmAvjhP4\nWboOOBVEo2ZhXgnBjeMvI8btXlJ85h9lZ7xwqfWsjQKBgQDkrrLpA3Mm21rsP1Ar\nMLEnYTdMZ7k+FTm5pJffPOsC7wiLWdRLwwrtb0V3kC3jr2K4SZY/OEV8IAWHfut/\n8mP8cPQPJiFp92iOgde4Xq/Ycwx4ZAXUj7mHHgywFi2K0xATzgc9sgX3NCVl9utR\nIU/FbEDCLxyD4T3Jb5gL3xFdhwKBgQDGPS46AiHuYmV7OG4gEOsNdczTppBJCgTt\nKGSJOxZg8sQodNJeWTPP2iQr4yJ4EY57NQmH7WSogLrGj8tmorEaL7I2kYlHJzGm\nniwApWEZlFc00xgXwV5d8ATfmAf8W1ZSZ6THbHesDUGjXSoL95k3KKXhnztjUT6I\n8d5qkCygDQKBgFN7p1rDZKVZzO6UCntJ8lJS/jIJZ6nPa9xmxv67KXxPsQnWSFdE\nI9gcF/sXCnmlTF/ElXIM4+j1c69MWULDRVciESb6n5YkuOnVYuAuyPk2vuWwdiRs\nN6mpAa7C2etlM+hW/XO7aswdIE4B/1QF2i5TX6zEMB/A+aJw98vVqmw/AoGADOm9\nUiADb9DPBXjGi6YueYD756mI6okRixU/f0TvDz+hEXWSonyzCE4QXx97hlC2dEYf\nKdCH5wYDpJ2HRVdBrBABTtaqF41xCYZyHVSof48PIyzA/AMnj3zsBFiV5JVaiSGh\nNTBWl0mBxg9yhrcJLvOh4pGJv81yAl+m+lAL6B0CgYEArtqtQ1YVLIUn4Pb/HDn8\nN8o7WbhloWQnG34iSsAG8yNtzbbxdugFrEm5ejPSgZ+dbzSzi/hizOFS/+/fwEdl\nay9jqY1fngoqSrS8eddUsY1/WAcmd6wPWEamsSjazA4uxQERruuFOi94E4b895KA\nqYe0A3xb0JL2ieAOZsn8XNA=\n-----END PRIVATE KEY-----\n", + "client_email": "test@example.com", + "client_id": "1", + "auth_uri": "https://example.com", + "token_uri": "https://example.com", + "auth_provider_x509_cert_url": "https://example.com", + "client_x509_cert_url": "https://example.com", + "universe_domain": "example.com" + } + }, }, auth: { @@ -150,7 +162,6 @@ const defaultConfiguration = { shortLivedAuth: mockShortLivedAuth(), }, allowClientClassCreation: true, - encodeParseObjectInCloudFunction: true, }; if (silent) { diff --git a/src/Adapters/Push/PushAdapter.js b/src/Adapters/Push/PushAdapter.js index d6862b00c3..6f89886b1b 100644 --- a/src/Adapters/Push/PushAdapter.js +++ b/src/Adapters/Push/PushAdapter.js @@ -8,7 +8,7 @@ // * getValidPushTypes() // * send(devices, installations, pushStatus) // -// Default is ParsePushAdapter, which uses GCM for +// Default is ParsePushAdapter, which uses FCM for // android push and APNS for ios push. /** diff --git a/src/Config.js b/src/Config.js index 241edf9771..54e3cc5ca4 100644 --- a/src/Config.js +++ b/src/Config.js @@ -3,6 +3,7 @@ // mount is the URL for the root of the API; includes http, domain, etc. import { isBoolean, isString } from 'lodash'; +import { pathToRegexp } from 'path-to-regexp'; import net from 'net'; import AppCache from './cache'; import DatabaseController from './Controllers/DatabaseController'; @@ -687,6 +688,14 @@ export class Config { if (typeof option.requestPath !== 'string') { throw `rateLimit.requestPath must be a string`; } + + // Validate that the path is valid path-to-regexp syntax + try { + pathToRegexp(option.requestPath); + } catch (error) { + throw `rateLimit.requestPath "${option.requestPath}" is not valid: ${error.message}`; + } + if (option.requestTimeWindow == null) { throw `rateLimit.requestTimeWindow must be defined`; } @@ -819,10 +828,8 @@ export class Config { return this.masterKey; } - // TODO: Remove this function once PagesRouter replaces the PublicAPIRouter; - // the (default) endpoint has to be defined in PagesRouter only. get pagesEndpoint() { - return this.pages && this.pages.enableRouter && this.pages.pagesEndpoint + return this.pages && this.pages.pagesEndpoint ? this.pages.pagesEndpoint : 'apps'; } diff --git a/src/Deprecator/Deprecations.js b/src/Deprecator/Deprecations.js index c63225f5b5..cd47d80c4e 100644 --- a/src/Deprecator/Deprecations.js +++ b/src/Deprecator/Deprecations.js @@ -15,8 +15,4 @@ * * If there are no deprecations, this must return an empty array. */ -module.exports = [ - { optionKey: 'encodeParseObjectInCloudFunction', changeNewDefault: 'true' }, - { optionKey: 'enableInsecureAuthAdapters', changeNewDefault: 'false' }, - { optionKey: 'databaseOptions.allowPublicExplain', changeNewDefault: 'false' }, -]; +module.exports = []; diff --git a/src/GraphQL/ParseGraphQLServer.js b/src/GraphQL/ParseGraphQLServer.js index 231e44f5ef..5c6ee7bf85 100644 --- a/src/GraphQL/ParseGraphQLServer.js +++ b/src/GraphQL/ParseGraphQLServer.js @@ -1,10 +1,10 @@ import corsMiddleware from 'cors'; import graphqlUploadExpress from 'graphql-upload/graphqlUploadExpress.js'; import { ApolloServer } from '@apollo/server'; -import { expressMiddleware } from '@apollo/server/express4'; +import { expressMiddleware } from '@as-integrations/express5'; import { ApolloServerPluginCacheControlDisabled } from '@apollo/server/plugin/disabled'; import express from 'express'; -import { execute, subscribe, GraphQLError } from 'graphql'; +import { execute, subscribe, GraphQLError, parse } from 'graphql'; import { SubscriptionServer } from 'subscriptions-transport-ws'; import { handleParseErrors, handleParseHeaders, handleParseSession } from '../middlewares'; import requiredParameter from '../requiredParameter'; @@ -13,6 +13,42 @@ import { ParseGraphQLSchema } from './ParseGraphQLSchema'; import ParseGraphQLController, { ParseGraphQLConfig } from '../Controllers/ParseGraphQLController'; +const hasTypeIntrospection = (query) => { + try { + const ast = parse(query); + // Check only root-level fields in the query + // Note: selection.name.value is the actual field name, so this correctly handles + // aliases like "myAlias: __type(...)" where name.value === "__type" + for (const definition of ast.definitions) { + if ((definition.kind === 'OperationDefinition' || definition.kind === 'FragmentDefinition') && definition.selectionSet) { + for (const selection of definition.selectionSet.selections) { + if (selection.kind === 'Field' && selection.name.value === '__type') { + // GraphQL's introspection __type field requires a 'name' argument + // This distinguishes it from potential user-defined __type fields + if (selection.arguments && selection.arguments.length > 0) { + return true; + } + } + } + } + } + return false; + } catch { + // If parsing fails, we assume it's not a valid query and let Apollo handle it + return false; + } +}; + +const throwIntrospectionError = () => { + throw new GraphQLError('Introspection is not allowed', { + extensions: { + http: { + status: 403, + }, + } + }); +}; + const IntrospectionControlPlugin = (publicIntrospection) => ({ @@ -29,21 +65,20 @@ const IntrospectionControlPlugin = (publicIntrospection) => ({ return; } - // Now we check if the query is an introspection query - // this check strategy should work in 99.99% cases - // we can have an issue if a user name a field or class __schemaSomething - // we want to avoid a full AST check - const isIntrospectionQuery = - requestContext.request.query?.includes('__schema') - - if (isIntrospectionQuery) { - throw new GraphQLError('Introspection is not allowed', { - extensions: { - http: { - status: 403, - }, - } - }); + const query = requestContext.request.query; + + + // Fast path: simple string check for __schema + // This avoids parsing the query in most cases + if (query?.includes('__schema')) { + return throwIntrospectionError(); + } + + // Smart check for __type: only parse if the string is present + // This avoids false positives (e.g., "__type" in strings or comments) + // while still being efficient for the common case + if (query?.includes('__type') && hasTypeIntrospection(query)) { + return throwIntrospectionError(); } }, diff --git a/src/Options/Definitions.js b/src/Options/Definitions.js index 66c1d8bcea..0cf047a84c 100644 --- a/src/Options/Definitions.js +++ b/src/Options/Definitions.js @@ -244,9 +244,9 @@ module.exports.ParseServerOptions = { enableInsecureAuthAdapters: { env: 'PARSE_SERVER_ENABLE_INSECURE_AUTH_ADAPTERS', help: - 'Enable (or disable) insecure auth adapters, defaults to true. Insecure auth adapters are deprecated and it is recommended to disable them.', + 'Optional. Enables insecure authentication adapters. Insecure auth adapters are deprecated and will be removed in a future version. Defaults to `false`.', action: parsers.booleanParser, - default: true, + default: false, }, enableSanitizedErrorResponse: { env: 'PARSE_SERVER_ENABLE_SANITIZED_ERROR_RESPONSE', @@ -255,13 +255,6 @@ module.exports.ParseServerOptions = { action: parsers.booleanParser, default: true, }, - encodeParseObjectInCloudFunction: { - env: 'PARSE_SERVER_ENCODE_PARSE_OBJECT_IN_CLOUD_FUNCTION', - help: - 'If set to `true`, a `Parse.Object` that is in the payload when calling a Cloud Function will be converted to an instance of `Parse.Object`. If `false`, the object will not be converted and instead be a plain JavaScript object, which contains the raw data of a `Parse.Object` but is not an actual instance of `Parse.Object`. Default is `false`.

\u2139\uFE0F The expected behavior would be that the object is converted to an instance of `Parse.Object`, so you would normally set this option to `true`. The default is `false` because this is a temporary option that has been introduced to avoid a breaking change when fixing a bug where JavaScript objects are not converted to actual instances of `Parse.Object`.', - action: parsers.booleanParser, - default: true, - }, encryptionKey: { env: 'PARSE_SERVER_ENCRYPTION_KEY', help: 'Key for encrypting your files', @@ -686,7 +679,7 @@ module.exports.RateLimitOptions = { requestPath: { env: 'PARSE_SERVER_RATE_LIMIT_REQUEST_PATH', help: - 'The path of the API route to be rate limited. Route paths, in combination with a request method, define the endpoints at which requests can be made. Route paths can be strings, string patterns, or regular expression. See: https://expressjs.com/en/guide/routing.html', + 'The path of the API route to be rate limited. Route paths, in combination with a request method, define the endpoints at which requests can be made. Route paths can be strings or string patterns following path-to-regexp v8 syntax.', required: true, }, requestTimeWindow: { @@ -1151,7 +1144,7 @@ module.exports.DatabaseOptions = { help: 'Set to `true` to allow `Parse.Query.explain` without master key.

\u26A0\uFE0F Enabling this option may expose sensitive query performance data to unauthorized users and could potentially be exploited for malicious purposes.', action: parsers.booleanParser, - default: true, + default: false, }, appName: { env: 'PARSE_SERVER_DATABASE_APP_NAME', diff --git a/src/Options/docs.js b/src/Options/docs.js index 9569239ef7..4e0ce8577d 100644 --- a/src/Options/docs.js +++ b/src/Options/docs.js @@ -44,9 +44,8 @@ * @property {Boolean} enableAnonymousUsers Enable (or disable) anonymous users, defaults to true * @property {Boolean} enableCollationCaseComparison Optional. If set to `true`, the collation rule of case comparison for queries and indexes is enabled. Enable this option to run Parse Server with MongoDB Atlas Serverless or AWS Amazon DocumentDB. If `false`, the collation rule of case comparison is disabled. Default is `false`. * @property {Boolean} enableExpressErrorHandler Enables the default express error handler for all errors - * @property {Boolean} enableInsecureAuthAdapters Enable (or disable) insecure auth adapters, defaults to true. Insecure auth adapters are deprecated and it is recommended to disable them. + * @property {Boolean} enableInsecureAuthAdapters Optional. Enables insecure authentication adapters. Insecure auth adapters are deprecated and will be removed in a future version. Defaults to `false`. * @property {Boolean} enableSanitizedErrorResponse If set to `true`, error details are removed from error messages in responses to client requests, and instead a generic error message is sent. Default is `true`. - * @property {Boolean} encodeParseObjectInCloudFunction If set to `true`, a `Parse.Object` that is in the payload when calling a Cloud Function will be converted to an instance of `Parse.Object`. If `false`, the object will not be converted and instead be a plain JavaScript object, which contains the raw data of a `Parse.Object` but is not an actual instance of `Parse.Object`. Default is `false`.

â„šī¸ The expected behavior would be that the object is converted to an instance of `Parse.Object`, so you would normally set this option to `true`. The default is `false` because this is a temporary option that has been introduced to avoid a breaking change when fixing a bug where JavaScript objects are not converted to actual instances of `Parse.Object`. * @property {String} encryptionKey Key for encrypting your files * @property {Boolean} enforcePrivateUsers Set to true if new users should be created without public read and write access. * @property {Boolean} expireInactiveSessions Sets whether we should expire the inactive sessions, defaults to true. If false, all new sessions are created with no expiration date. @@ -121,7 +120,7 @@ * @property {String} redisUrl Optional, the URL of the Redis server to store rate limit data. This allows to rate limit requests for multiple servers by calculating the sum of all requests across all servers. This is useful if multiple servers are processing requests behind a load balancer. For example, the limit of 10 requests is reached if each of 2 servers processed 5 requests. * @property {Number} requestCount The number of requests that can be made per IP address within the time window set in `requestTimeWindow` before the rate limit is applied. * @property {String[]} requestMethods Optional, the HTTP request methods to which the rate limit should be applied, default is all methods. - * @property {String} requestPath The path of the API route to be rate limited. Route paths, in combination with a request method, define the endpoints at which requests can be made. Route paths can be strings, string patterns, or regular expression. See: https://expressjs.com/en/guide/routing.html + * @property {String} requestPath The path of the API route to be rate limited. Route paths, in combination with a request method, define the endpoints at which requests can be made. Route paths can be strings or string patterns following path-to-regexp v8 syntax. * @property {Number} requestTimeWindow The window of time in milliseconds within which the number of requests set in `requestCount` can be made before the rate limit is applied. * @property {String} zone The type of rate limit to apply. The following types are supported:
  • `global`: rate limit based on the number of requests made by all users
  • `ip`: rate limit based on the IP address of the request
  • `user`: rate limit based on the user ID of the request
  • `session`: rate limit based on the session token of the request
Default is `ip`. */ diff --git a/src/Options/index.js b/src/Options/index.js index cdeb7cd846..619a417378 100644 --- a/src/Options/index.js +++ b/src/Options/index.js @@ -167,9 +167,9 @@ export interface ParseServerOptions { /* 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: ?{ [string]: AuthAdapter }; - /* Enable (or disable) insecure auth adapters, defaults to true. Insecure auth adapters are deprecated and it is recommended to disable them. + /* Optional. Enables insecure authentication adapters. Insecure auth adapters are deprecated and will be removed in a future version. Defaults to `false`. :ENV: PARSE_SERVER_ENABLE_INSECURE_AUTH_ADAPTERS - :DEFAULT: true */ + :DEFAULT: false */ enableInsecureAuthAdapters: ?boolean; /* Max file size for uploads, defaults to 20mb :DEFAULT: 20mb */ @@ -223,9 +223,6 @@ export interface ParseServerOptions { cacheAdapter: ?Adapter; /* Adapter module for email sending */ emailAdapter: ?Adapter; - /* If set to `true`, a `Parse.Object` that is in the payload when calling a Cloud Function will be converted to an instance of `Parse.Object`. If `false`, the object will not be converted and instead be a plain JavaScript object, which contains the raw data of a `Parse.Object` but is not an actual instance of `Parse.Object`. Default is `false`.

â„šī¸ The expected behavior would be that the object is converted to an instance of `Parse.Object`, so you would normally set this option to `true`. The default is `false` because this is a temporary option that has been introduced to avoid a breaking change when fixing a bug where JavaScript objects are not converted to actual instances of `Parse.Object`. - :DEFAULT: true */ - encodeParseObjectInCloudFunction: ?boolean; /* Optional. The public URL to Parse Server. This URL will be used to reach Parse Server publicly for features like password reset and email verification links. The option can be set to a string or a function that can be asynchronously resolved. The returned URL string must start with `http://` or `https://`. :ENV: PARSE_PUBLIC_SERVER_URL */ publicServerURL: ?(string | (() => string) | (() => Promise)); @@ -353,7 +350,7 @@ export interface ParseServerOptions { } export interface RateLimitOptions { - /* The path of the API route to be rate limited. Route paths, in combination with a request method, define the endpoints at which requests can be made. Route paths can be strings, string patterns, or regular expression. See: https://expressjs.com/en/guide/routing.html */ + /* The path of the API route to be rate limited. Route paths, in combination with a request method, define the endpoints at which requests can be made. Route paths can be strings or string patterns following path-to-regexp v8 syntax. */ requestPath: string; /* The window of time in milliseconds within which the number of requests set in `requestCount` can be made before the rate limit is applied. */ requestTimeWindow: ?number; @@ -754,7 +751,7 @@ export interface DatabaseOptions { /* Set to `true` to disable validation of index fields. When disabled, indexes can be created even if the fields do not exist in the schema. This can be useful when creating indexes on fields that will be added later. */ disableIndexFieldValidation: ?boolean; /* Set to `true` to allow `Parse.Query.explain` without master key.

âš ī¸ Enabling this option may expose sensitive query performance data to unauthorized users and could potentially be exploited for malicious purposes. - :DEFAULT: true */ + :DEFAULT: false */ allowPublicExplain: ?boolean; /* An array of MongoDB client event configurations to enable logging of specific events. */ logClientEvents: ?(LogClientEvent[]); diff --git a/src/ParseServer.ts b/src/ParseServer.ts index 04543ac1c3..fea0764cf5 100644 --- a/src/ParseServer.ts +++ b/src/ParseServer.ts @@ -27,7 +27,6 @@ import { InstallationsRouter } from './Routers/InstallationsRouter'; import { LogsRouter } from './Routers/LogsRouter'; import { ParseLiveQueryServer } from './LiveQuery/ParseLiveQueryServer'; import { PagesRouter } from './Routers/PagesRouter'; -import { PublicAPIRouter } from './Routers/PublicAPIRouter'; import { PushRouter } from './Routers/PushRouter'; import { CloudCodeRouter } from './Routers/CloudCodeRouter'; import { RolesRouter } from './Routers/RolesRouter'; @@ -330,9 +329,7 @@ class ParseServer { api.use( '/', express.urlencoded({ extended: false }), - pages.enableRouter - ? new PagesRouter(pages).expressRouter() - : new PublicAPIRouter().expressRouter() + new PagesRouter(pages).expressRouter() ); api.use(express.json({ type: '*/*', limit: maxUploadSize })); diff --git a/src/Routers/FunctionsRouter.js b/src/Routers/FunctionsRouter.js index 2e56a1b426..9720e4679c 100644 --- a/src/Routers/FunctionsRouter.js +++ b/src/Routers/FunctionsRouter.js @@ -18,7 +18,7 @@ function parseObject(obj, config) { return Object.assign(new Date(obj.iso), obj); } else if (obj && obj.__type == 'File') { return Parse.File.fromJSON(obj); - } else if (obj && obj.__type == 'Pointer' && config.encodeParseObjectInCloudFunction) { + } else if (obj && obj.__type == 'Pointer') { return Parse.Object.fromJSON({ __type: 'Pointer', className: obj.className, diff --git a/src/Routers/PublicAPIRouter.js b/src/Routers/PublicAPIRouter.js deleted file mode 100644 index 2ec993f390..0000000000 --- a/src/Routers/PublicAPIRouter.js +++ /dev/null @@ -1,332 +0,0 @@ -import PromiseRouter from '../PromiseRouter'; -import Config from '../Config'; -import express from 'express'; -import path from 'path'; -import fs from 'fs'; -import qs from 'querystring'; -import { Parse } from 'parse/node'; -import Deprecator from '../Deprecator/Deprecator'; - -const public_html = path.resolve(__dirname, '../../public_html'); -const views = path.resolve(__dirname, '../../views'); - -export class PublicAPIRouter extends PromiseRouter { - constructor() { - super(); - Deprecator.logRuntimeDeprecation({ - usage: 'PublicAPIRouter', - solution: 'pages.enableRouter' - }); - } - verifyEmail(req) { - const { token: rawToken } = req.query; - const token = rawToken && typeof rawToken !== 'string' ? rawToken.toString() : rawToken; - - const appId = req.params.appId; - const config = Config.get(appId); - - if (!config) { - this.invalidRequest(); - } - - if (!config.publicServerURL) { - return this.missingPublicServerURL(); - } - - if (!token) { - return this.invalidLink(req); - } - - const userController = config.userController; - return userController.verifyEmail(token).then( - () => { - return Promise.resolve({ - status: 302, - location: `${config.verifyEmailSuccessURL}`, - }); - }, - () => { - return this.invalidVerificationLink(req, token); - } - ); - } - - resendVerificationEmail(req) { - const username = req.body?.username; - const appId = req.params.appId; - const config = Config.get(appId); - - if (!config) { - this.invalidRequest(); - } - - if (!config.publicServerURL) { - return this.missingPublicServerURL(); - } - - const token = req.body.token; - - if (!username && !token) { - return this.invalidLink(req); - } - - const userController = config.userController; - - return userController.resendVerificationEmail(username, req, token).then( - () => { - return Promise.resolve({ - status: 302, - location: `${config.linkSendSuccessURL}`, - }); - }, - () => { - return Promise.resolve({ - status: 302, - location: `${config.linkSendFailURL}`, - }); - } - ); - } - - changePassword(req) { - return new Promise((resolve, reject) => { - const config = Config.get(req.query.id); - - if (!config) { - this.invalidRequest(); - } - - if (!config.publicServerURL) { - return resolve({ - status: 404, - text: 'Not found.', - }); - } - // Should we keep the file in memory or leave like that? - fs.readFile(path.resolve(views, 'choose_password'), 'utf-8', (err, data) => { - if (err) { - return reject(err); - } - data = data.replace('PARSE_SERVER_URL', `'${config.publicServerURL}'`); - resolve({ - text: data, - }); - }); - }); - } - - requestResetPassword(req) { - const config = req.config; - - if (!config) { - this.invalidRequest(); - } - - if (!config.publicServerURL) { - return this.missingPublicServerURL(); - } - - const { token: rawToken } = req.query; - const token = rawToken && typeof rawToken !== 'string' ? rawToken.toString() : rawToken; - - if (!token) { - return this.invalidLink(req); - } - - return config.userController.checkResetTokenValidity(token).then( - () => { - const params = qs.stringify({ - token, - id: config.applicationId, - app: config.appName, - }); - return Promise.resolve({ - status: 302, - location: `${config.choosePasswordURL}?${params}`, - }); - }, - () => { - return this.invalidLink(req); - } - ); - } - - resetPassword(req) { - const config = req.config; - - if (!config) { - this.invalidRequest(); - } - - if (!config.publicServerURL) { - return this.missingPublicServerURL(); - } - - const { new_password, token: rawToken } = req.body || {}; - const token = rawToken && typeof rawToken !== 'string' ? rawToken.toString() : rawToken; - - if ((!token || !new_password) && req.xhr === false) { - return this.invalidLink(req); - } - - if (!token) { - throw new Parse.Error(Parse.Error.OTHER_CAUSE, 'Missing token'); - } - - if (!new_password) { - throw new Parse.Error(Parse.Error.PASSWORD_MISSING, 'Missing password'); - } - - return config.userController - .updatePassword(token, new_password) - .then( - () => { - return Promise.resolve({ - success: true, - }); - }, - err => { - return Promise.resolve({ - success: false, - err, - }); - } - ) - .then(result => { - const queryString = { - token: token, - id: config.applicationId, - error: result.err, - app: config.appName, - }; - - if (result?.err === 'The password reset link has expired') { - delete queryString.token; - queryString.token = token; - } - const params = qs.stringify(queryString); - - if (req.xhr) { - if (result.success) { - return Promise.resolve({ - status: 200, - response: 'Password successfully reset', - }); - } - if (result.err) { - throw new Parse.Error(Parse.Error.OTHER_CAUSE, `${result.err}`); - } - } - - const location = result.success - ? `${config.passwordResetSuccessURL}` - : `${config.choosePasswordURL}?${params}`; - - return Promise.resolve({ - status: 302, - location, - }); - }); - } - - invalidLink(req) { - return Promise.resolve({ - status: 302, - location: req.config.invalidLinkURL, - }); - } - - invalidVerificationLink(req, token) { - const config = req.config; - if (req.params.appId) { - const params = qs.stringify({ - appId: req.params.appId, - token, - }); - return Promise.resolve({ - status: 302, - location: `${config.invalidVerificationLinkURL}?${params}`, - }); - } else { - return this.invalidLink(req); - } - } - - missingPublicServerURL() { - return Promise.resolve({ - text: 'Not found.', - status: 404, - }); - } - - invalidRequest() { - const error = new Error(); - error.status = 403; - error.message = 'unauthorized'; - throw error; - } - - setConfig(req) { - req.config = Config.get(req.params.appId); - return Promise.resolve(); - } - - mountRoutes() { - this.route( - 'GET', - '/apps/:appId/verify_email', - req => { - this.setConfig(req); - }, - req => { - return this.verifyEmail(req); - } - ); - - this.route( - 'POST', - '/apps/:appId/resend_verification_email', - req => { - this.setConfig(req); - }, - req => { - return this.resendVerificationEmail(req); - } - ); - - this.route('GET', '/apps/choose_password', req => { - return this.changePassword(req); - }); - - this.route( - 'POST', - '/apps/:appId/request_password_reset', - req => { - this.setConfig(req); - }, - req => { - return this.resetPassword(req); - } - ); - - this.route( - 'GET', - '/apps/:appId/request_password_reset', - req => { - this.setConfig(req); - }, - req => { - return this.requestResetPassword(req); - } - ); - } - - expressRouter() { - const router = express.Router(); - router.use('/apps', express.static(public_html)); - router.use('/', super.expressRouter()); - return router; - } -} - -export default PublicAPIRouter; diff --git a/src/cloud-code/Parse.Cloud.js b/src/cloud-code/Parse.Cloud.js index a057f8b3e6..3fc38c3aad 100644 --- a/src/cloud-code/Parse.Cloud.js +++ b/src/cloud-code/Parse.Cloud.js @@ -82,12 +82,12 @@ const getRoute = parseClass => { '@Config' : 'config', }[parseClass] || 'classes'; if (parseClass === '@File') { - return `/${route}/:id?(.*)`; + return `/${route}{/*id}`; } if (parseClass === '@Config') { return `/${route}`; } - return `/${route}/${parseClass}/:id?(.*)`; + return `/${route}/${parseClass}{/*id}`; }; /** @namespace * @name Parse diff --git a/src/middlewares.js b/src/middlewares.js index 2fedce8f08..e01b380751 100644 --- a/src/middlewares.js +++ b/src/middlewares.js @@ -322,7 +322,7 @@ const handleRateLimit = async (req, res, next) => { try { await Promise.all( rateLimits.map(async limit => { - const pathExp = new RegExp(limit.path); + const pathExp = limit.path.regexp || limit.path; if (pathExp.test(req.url)) { await limit.handler(req, res, err => { if (err) { @@ -560,12 +560,8 @@ export const addRateLimit = (route, config, cloud) => { }, }); } - let transformPath = route.requestPath.split('/*').join('/(.*)'); - if (transformPath === '*') { - transformPath = '(.*)'; - } config.rateLimits.push({ - path: pathToRegexp(transformPath), + path: pathToRegexp(route.requestPath), handler: rateLimit({ windowMs: route.requestTimeWindow, max: route.requestCount, diff --git a/src/rest.js b/src/rest.js index 66763715ea..60ae4bd425 100644 --- a/src/rest.js +++ b/src/rest.js @@ -37,7 +37,7 @@ async function runFindTriggers( const { isGet } = options; if (restOptions && restOptions.explain && !auth.isMaster) { - const allowPublicExplain = config.databaseOptions?.allowPublicExplain ?? true; + const allowPublicExplain = config.databaseOptions?.allowPublicExplain ?? false; if (!allowPublicExplain) { throw new Parse.Error( diff --git a/types/Options/index.d.ts b/types/Options/index.d.ts index ad11050648..42e64022e7 100644 --- a/types/Options/index.d.ts +++ b/types/Options/index.d.ts @@ -84,7 +84,6 @@ export interface ParseServerOptions { passwordPolicy?: PasswordPolicyOptions; cacheAdapter?: Adapter; emailAdapter?: Adapter; - encodeParseObjectInCloudFunction?: boolean; publicServerURL?: string | (() => string) | (() => Promise); pages?: PagesOptions; customPages?: CustomPagesOptions;