diff --git a/CHANGELOG.md b/CHANGELOG.md index f40de2cec..d057b7963 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,35 @@ +## [1.11.3](https://github.com/payloadcms/payload/compare/v1.11.2...v1.11.3) (2023-07-19) + + +### Bug Fixes + +* adds backdrop blur to button ([#3006](https://github.com/payloadcms/payload/issues/3006)) ([4233426](https://github.com/payloadcms/payload/commit/42334263bbc6219be92c5728f1a4ac6c8d2d1306)) +* rich text link element not validating on create ([#3014](https://github.com/payloadcms/payload/issues/3014)) ([60fca40](https://github.com/payloadcms/payload/commit/60fca40780d4ddd8e684a455de55c566ec91e223)) + + +### Features + +* auto-login in config capability ([#3009](https://github.com/payloadcms/payload/issues/3009)) ([733fc0b](https://github.com/payloadcms/payload/commit/733fc0b2d0cf0f2d58c8a28e84776f883774b0e0)) +* returns queried user alongside refreshed token ([#2813](https://github.com/payloadcms/payload/issues/2813)) ([2fc03f1](https://github.com/payloadcms/payload/commit/2fc03f196e4e5fa0ad3369ec976c0b6889ebda88)) +* support logger destination ([#2896](https://github.com/payloadcms/payload/issues/2896)) ([cd0bf68](https://github.com/payloadcms/payload/commit/cd0bf68a6150b1adbdb9ee318ac0a06c4476aa4d)) + +## [1.11.2](https://github.com/payloadcms/payload/compare/v1.11.1...v1.11.2) (2023-07-14) + + +### Features + +* adds array, collapsible, tab and group error states ([4925f90](https://github.com/payloadcms/payload/commit/4925f90b5f5c8fb8092bf4e8d88d5e0c1846b094)) + +## [1.11.1](https://github.com/payloadcms/payload/compare/v1.11.0...v1.11.1) (2023-07-11) + + +### Bug Fixes + +* [#2980](https://github.com/payloadcms/payload/issues/2980), locale=all was not iterating through arrays / blocks ([d6bfba7](https://github.com/payloadcms/payload/commit/d6bfba72a6b1a84bc5bb9dd14c7ce31d7afcbc1c)) +* anchor Button component respect margins ([#2648](https://github.com/payloadcms/payload/issues/2648)) ([1877d22](https://github.com/payloadcms/payload/commit/1877d2247c89ca5c8e1f0e1f989154d54768fed8)) + # [1.11.0](https://github.com/payloadcms/payload/compare/v1.10.5...v1.11.0) (2023-07-05) diff --git a/contributing.md b/contributing.md index a07ea3b59..f352c1962 100644 --- a/contributing.md +++ b/contributing.md @@ -49,6 +49,8 @@ The directory split up in this way specifically to reduce friction when creating The following command will start Payload with your config: `yarn dev my-test-dir`. This command will start up Payload using your config and refresh a test database on every restart. +By default, it will automatically log you in with the default credentials. To disable that, you can either pass in the --no-auto-login flag (example: `yarn dev my-test-dir --no-auto-login`) or set the `PAYLOAD_PUBLIC_DISABLE_AUTO_LOGIN` environment variable to `false`. + If you wish to use to your own Mongo database for the `test` directory instead of using the in memory database, all you need to do is add the following env vars to the `test/dev.ts` file: - `process.env.NODE_ENV` diff --git a/database/index.ts b/database/index.ts new file mode 100644 index 000000000..0ab870f9c --- /dev/null +++ b/database/index.ts @@ -0,0 +1 @@ +// export { baseDatabaseAdapter } from '../dist/database/baseAdapter'; diff --git a/docs/admin/components.mdx b/docs/admin/components.mdx index 04864f0da..b9c88c2a7 100644 --- a/docs/admin/components.mdx +++ b/docs/admin/components.mdx @@ -84,13 +84,9 @@ You can override components on a Collection-by-Collection basis via each Collect | **`edit.PublishButton`** | Replace the default `Publish` button with a custom component. Drafts must be enabled. | | **`edit.PreviewButton`** | Replace the default `Preview` button with a custom component. | | **`BeforeList`** | Array of components to inject _before_ the built-in List view | -| | | **`BeforeListTable`** | Array of components to inject _before_ the built-in List view's table | -| | | **`AfterListTable`** | Array of components to inject _after_ the built-in List view's table | -| | | **`AfterList`** | Array of components to inject _after_ the built-in List view | -| | #### Examples diff --git a/docs/admin/overview.mdx b/docs/admin/overview.mdx index f3da913be..c67a3b702 100644 --- a/docs/admin/overview.mdx +++ b/docs/admin/overview.mdx @@ -25,7 +25,7 @@ _Screenshot of the Admin panel while editing a document from an example `AllFiel All options for the Admin panel are defined in your base Payload config file. | Option | Description | -| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --- | +| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `user` | The `slug` of a Collection that you want be used to log in to the Admin dashboard. [More](/docs/admin/overview#the-admin-user-collection) | | `buildPath` | Specify an absolute path for where to store the built Admin panel bundle used in production. Defaults to `path.resolve(process.cwd(), 'build')`. | | `meta` | Base meta data to use for the Admin panel. Included properties are `titleSuffix`, `ogImage`, and `favicon`. | @@ -36,7 +36,7 @@ All options for the Admin panel are defined in your base Payload config file. | `dateFormat` | Global date format that will be used for all dates in the Admin panel. Any valid [date-fns](https://date-fns.org/) format pattern can be used. | | `avatar` | Set account profile picture. Options: `gravatar`, `default` or a custom React component. | | `components` | Component overrides that affect the entirety of the Admin panel. [More](/docs/admin/components) | -| `webpack` | Customize the Webpack config that's used to generate the Admin panel. [More](/docs/admin/webpack) | | +| `webpack` | Customize the Webpack config that's used to generate the Admin panel. [More](/docs/admin/webpack) | | **`logoutRoute`** | The route for the `logout` page. | | **`inactivityRoute`** | The route for the `logout` inactivity page. | diff --git a/docs/authentication/config.mdx b/docs/authentication/config.mdx index 5fc2e6b79..585dde866 100644 --- a/docs/authentication/config.mdx +++ b/docs/authentication/config.mdx @@ -63,6 +63,22 @@ const response = await fetch("http://localhost:3000/api/pages", { Payload ensures that the same, uniform access control is used across all authentication strategies. This enables you to utilize your existing access control configurations with both API keys and the standard email/password authentication. This consistency can aid in maintaining granular control over your API keys. +#### API Key *Only* Authentication + +If you want to use API keys as the only authentication method for a collection, you can disable the default local strategy by setting `disableLocalStrategy` to `true` on the collection's `auth` property. This will disable the ability to authenticate with email and password, and will only allow for authentication via API key. + +```ts +import { CollectionConfig } from 'payload/types'; + +export const Customers: CollectionConfig = { + slug: 'customers', + auth: { + useAPIKey: true, + disableLocalStrategy: true, + } +}; +``` + ### Forgot Password You can customize how the Forgot Password workflow operates with the following options on the `auth.forgotPassword` property: diff --git a/docs/authentication/overview.mdx b/docs/authentication/overview.mdx index f107f5711..0bf7b6a92 100644 --- a/docs/authentication/overview.mdx +++ b/docs/authentication/overview.mdx @@ -6,6 +6,11 @@ desc: Payload provides highly secure user Authentication out of the box, and you keywords: authentication, config, configuration, overview, documentation, Content Management System, cms, headless, javascript, node, react, express --- + + Payload provides for highly secure and customizable user Authentication out of the box, which allows for users to identify themselves to Payload. diff --git a/docs/cloud/configuration.mdx b/docs/cloud/configuration.mdx index 450236004..7e836805d 100644 --- a/docs/cloud/configuration.mdx +++ b/docs/cloud/configuration.mdx @@ -13,22 +13,22 @@ Once you have created a project, you will need to select your plan. This will de Note: All Payload Cloud teams that deploy a project require a card on file. This helps us prevent fraud and abuse on our platform. If you select a plan - with a free trial, You will not be charged until your trial period is over. + with a free trial, you will not be charged until your trial period is over. We’ll remind you 7 days before your trial ends and you can cancel anytime. ### Project Details -| Option | Description | -| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **Region** | Select the region closest to your audience. This will ensure the fastest communication between your data and your client. | -| **Project Name** | A name for your project. You can change this at any time. | -| **Project Slug** | Choose a unique slug to identify your project. This needs to be unique for your team and you can change it any time. | -| **Team** | Select the team you want to create the project under. If this is your first project, a personal team will be created for your automatically. You can modify your team settings and invite new members at any time from the Team Settings page. | +| Option | Description | +| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Region** | Select the region closest to your audience. This will ensure the fastest communication between your data and your client. | +| **Project Name** | A name for your project. You can change this at any time. | +| **Project Slug** | Choose a unique slug to identify your project. This needs to be unique for your team and you can change it any time. | +| **Team** | Select the team you want to create the project under. If this is your first project, a personal team will be created for you automatically. You can modify your team settings and invite new members at any time from the Team Settings page. | ### Build Settings -If you are deploying a new project from a template, the following settings will all be automatically configured for you. If you are using your own repository, you will need to make sure your build settings are accurate for your project to deploy correctly. +If you are deploying a new project from a template, the following settings will be automatically configured for you. If you are using your own repository, you need to make sure your build settings are accurate for your project to deploy correctly. | Option | Description | | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | @@ -56,7 +56,7 @@ Payment methods can be set per project and can be updated any time. You can use Note: All Payload Cloud teams that deploy a project require a card on file. This helps us prevent fraud and abuse on our platform. If you - select a plan with a free trial, You will not be charged until your trial + select a plan with a free trial, you will not be charged until your trial period is over. We’ll remind you 7 days before your trial ends and you can cancel anytime. diff --git a/docs/cloud/creating-a-project.mdx b/docs/cloud/creating-a-project.mdx index 1c56603bb..b8fdaa302 100644 --- a/docs/cloud/creating-a-project.mdx +++ b/docs/cloud/creating-a-project.mdx @@ -6,42 +6,42 @@ desc: Get started with Payload Cloud, a deployment solution specifically designe keywords: cloud, hosted, database, storage, email, deployment, serverless, node, mongodb, s3, aws, cloudflare, atlas, resend, payload, cms --- -A deployment solution specifically designed for Node + MongoDB applications, offering seamless deployment of your entire stack in one place. You can get started in minutes with a one-click template, or bring your own codebase with you. +A deployment solution specifically designed for Node.js + MongoDB applications, offering seamless deployment of your entire stack in one place. You can get started in minutes with a one-click template or bring your own codebase with you. -Payload Cloud offers different plans tailored to meet your specific needs, including a MongoDB Atlas database, S3 file storage, and email delivery powered by Resend. To see the full breakdown of features and plans, see our [Cloud Pricing page](https://payloadcms.com/cloud-pricing). +Payload Cloud offers various plans tailored to meet your specific needs, including a MongoDB Atlas database, S3 file storage, and email delivery powered by [Resend](https://resend.com). To see a full breakdown of features and plans, see our [Cloud Pricing page](https://payloadcms.com/cloud-pricing). -To get started, you will first need to create an account. Head over to [the login screen](https://payloadcms.com/login) and **Register for Free**. +To get started, you first need to create an account. Head over to [the login screen](https://payloadcms.com/login) and **Register for Free**. To create your first project, you can either select [a - template](#starting-from-a-template), or [import an existing + template](#starting-from-a-template) or [import an existing project](#importing-from-an-existing-codebase) from GitHub. ## Starting from a Template -Templates come preconfigured and provide a one-click, simple solution to quickly deploy a new application. +Templates come preconfigured and provide a one-click solution to quickly deploy a new application. ![Screen for creating a new project from a template](https://payloadcms.com/images/docs/cloud/create-from-template.jpg) _Creating a new project from a template._ -After creating an account, select your desired template from the Projects page. At this point, you will need to connect to Authorize the Payload Cloud application with your GitHub account. Click Continue with GitHub and follow the prompts to authorize the app. +After creating an account, select your desired template from the Projects page. At this point, you need to connect to authorize the Payload Cloud application with your GitHub account. Click Continue with GitHub and follow the prompts to authorize the app. -Next, select your `GitHub Scope`. If you belong to multiple organizations they will show up here. If do not see the organization you are looking for, you may need to adjust your GitHub app permissions. +Next, select your `GitHub Scope`. If you belong to multiple organizations, they will show up here. If you do not see the organization you are looking for, you may need to adjust your GitHub app permissions. After selecting your scope, create a unique `repository name` and select whether you want your repository to be public or private on GitHub. Note: Public repositories can be accessed by anyone online, - while private repositories only grant access to you and anyone you explicitly + while private repositories grant access only to you and anyone you explicitly authorize. -Once you are ready, click **Create Project**. This will clone the selected template to a new respository in your GitHub account, and take you to the configuration page to set up your project for deployment. +Once you are ready, click **Create Project**. This will clone the selected template to a new repository in your GitHub account, and take you to the configuration page to set up your project for deployment. ## Importing from an Existing Codebase -Payload Cloud works for any Node + MongoDB app. From the New Project page, select **import an existing Git codebase**. Choose the organization and select the repository you want to import. From here, you will be taken to the configuration page to set up your project for deployment. +Payload Cloud works for any Node.js + MongoDB app. From the New Project page, select **import an existing Git codebase**. Choose the organization and select the repository you want to import. From here, you will be taken to the configuration page to set up your project for deployment. ![Screen for creating a new project from an existing repository](https://payloadcms.com/images/docs/cloud/create-from-existing.jpg) _Creating a new project from an existing repository._ diff --git a/docs/cloud/projects.mdx b/docs/cloud/projects.mdx index efb9289a8..3fc72b5f9 100644 --- a/docs/cloud/projects.mdx +++ b/docs/cloud/projects.mdx @@ -10,7 +10,7 @@ keywords: cloud, payload cloud, projects, project, overview, database, file stor The overview tab shows your most recent deployment, along with build and - deploy logs. From here, you can see your live URL, deployment details like + deployment logs. From here, you can see your live URL, deployment details like timestamps and commit hash, as well as the status of your deployment. You can also trigger a redeployment manually, which will rebuild your project using the current configuration. @@ -21,7 +21,7 @@ _A screenshot of the Overview page for a Cloud project._ ### Database -Your Payload Cloud project comes with a MongoDB serverless Atlas DB instance or Dedicated Atlas cluster, depending on your plan. To interact with your cloud database, you will be provided with a MongoDB connection string. This can be found under the **Database** tab of your project. +Your Payload Cloud project comes with a MongoDB serverless Atlas DB instance or a Dedicated Atlas cluster, depending on your plan. To interact with your cloud database, you will be provided with a MongoDB connection string. This can be found under the **Database** tab of your project. `mongodb+srv://your_connection_string` @@ -49,14 +49,14 @@ From the Environment Variables page of the Settings tab, you can add, update and With Payload Cloud, you can add custom domain names to your project. To do so, first go to the Domains page of the Settings tab of your project. Here you can see your default domain. To add a new domain, type in the domain name you wish to use. - Note: do not include protocol (http:// or https://) or any routes (/page). - Only include the the domain name and extension, and optionally a subdomain. - + Note: do not include the protocol (http:// or https://) or any routes (/page). + Only include the domain name and extension, and optionally a subdomain. - your-domain.com - backend.your-domain.com Once you click save, a DNS record will be generated for your domain name to point to your live project. Add this record into your DNS provider’s records, and once the records are resolving properly (this can take 1hr to 48hrs in some cases), your domain will now to point to your live project. -You will also need to configure your Payload project to use your specified domain. in your `payload.config.ts` file, specify your serverURL with your domain: +You will also need to configure your Payload project to use your specified domain. In your `payload.config.ts` file, specify your `serverURL` with your domain: ```ts export default buildConfig({ @@ -67,9 +67,9 @@ export default buildConfig({ ### Email -Powered by Resend, Payload Cloud comes with integrated email support out of the box. No configuration is needed, and you can use `payload.sendEmail()` to send email right from your Payload app. To learn more about sending email with Payload, checkout the [Email Configuration](https://payloadcms.com/docs/email/overview) overview. +Powered by [Resend](https://resend.com), Payload Cloud comes with integrated email support out of the box. No configuration is needed, and you can use `payload.sendEmail()` to send email right from your Payload app. To learn more about sending email with Payload, checkout the [Email Configuration](https://payloadcms.com/docs/email/overview) overview. -If you are on the Pro or Enterprise plan, you can add your own custom Email domain name. From the Email page of your project’s Settings page, add the domain you wish to use for email delivery. This will generate a set of DNS records. Add these records to your DNS provider and click verify to check that your records are resolving properly. Once verified, your emails will now be sent from your custom domain name. +If you are on the Pro or Enterprise plan, you can add your own custom Email domain name. From the Email page of your project’s Settings, add the domain you wish to use for email delivery. This will generate a set of DNS records. Add these records to your DNS provider and click verify to check that your records are resolving properly. Once verified, your emails will now be sent from your custom domain name. ### Developing Locally diff --git a/docs/cloud/teams.mdx b/docs/cloud/teams.mdx index 6b94339c6..80d367cd5 100644 --- a/docs/cloud/teams.mdx +++ b/docs/cloud/teams.mdx @@ -16,11 +16,11 @@ _A screenshot of the Team Settings page._ ### Members -Each team has members that can interact with your projects. You can invite multiple people to your team and each individual can belong to more than one team. You can delegate whether they have `owner` or `user` permissions. Owners are able to make admin-only changes, such as deleting projects, and editing billing information. +Each team has members that can interact with your projects. You can invite multiple people to your team and each individual can belong to more than one team. You can assign them either `owner` or `user` permissions. Owners are able to make admin-only changes, such as deleting projects, and editing billing information. ### Adding Members -To add a new member to your team, visit your Team’s Settings page, and click “Invite Teammate”. You can then add their email address, and assign their role. Press “Save” to send invitations, which will send an email to the invited team member where they can create a new account. +To add a new member to your team, visit your Team’s Settings page, and click “Invite Teammate”. You can then add their email address, and assign their role. Press “Save” to send the invitations, which will send an email to the invited team member where they can create a new account. ### Billing diff --git a/docs/getting-started/installation.mdx b/docs/getting-started/installation.mdx index 768f3799a..fe25be642 100644 --- a/docs/getting-started/installation.mdx +++ b/docs/getting-started/installation.mdx @@ -140,6 +140,10 @@ A boolean that when set to `true` tells Payload to start in local-only mode whic Specify options for the built-in Pino logger that Payload uses for internal logging. See [Pino Docs](https://getpino.io/#/docs/api?id=options) for more info on what is available. +##### `loggerDestination` + +Specify destination stream for the built-in Pino logger that Payload uses for internal logging. See [Pino Docs](https://getpino.io/#/docs/api?id=pino-destination) for more info on what is available. + ##### `onInit` A function that is called immediately following startup that receives the Payload instance as it's only argument. diff --git a/examples/auth/cms/.env.example b/examples/auth/cms/.env.example index e2ac454f6..fa7239982 100644 --- a/examples/auth/cms/.env.example +++ b/examples/auth/cms/.env.example @@ -1,7 +1,7 @@ -PAYLOAD_PUBLIC_SITE_URL=http://localhost:3000 -PAYLOAD_PUBLIC_SERVER_URL=http://localhost:8000 -MONGODB_URI=mongodb://localhost/payload-example-auth +PAYLOAD_PUBLIC_SITE_URL=http://localhost:3001 +PAYLOAD_PUBLIC_SERVER_URL=http://localhost:3000 +MONGODB_URI=mongodb://127.0.0.1/payload-example-auth PAYLOAD_SECRET=PAYLOAD_AUTH_EXAMPLE_SECRET_KEY COOKIE_DOMAIN=localhost - - +PAYLOAD_SEED=true +PAYLOAD_DROP_DATABASE=true diff --git a/examples/auth/cms/.npmrc b/examples/auth/cms/.npmrc deleted file mode 100644 index 521a9f7c0..000000000 --- a/examples/auth/cms/.npmrc +++ /dev/null @@ -1 +0,0 @@ -legacy-peer-deps=true diff --git a/examples/auth/cms/README.md b/examples/auth/cms/README.md index 9e7f1ccf9..54f62a4e0 100644 --- a/examples/auth/cms/README.md +++ b/examples/auth/cms/README.md @@ -1,8 +1,11 @@ # Payload Auth Example -This example demonstrates how to implement [Payload Authentication](https://payloadcms.com/docs/authentication/overview). +This example demonstrates how to implement [Payload Authentication](https://payloadcms.com/docs/authentication/overview). Follow the [Quick Start](#quick-start) to get up and running quickly. There are various fully working front-ends made explicitly for this example, including: -There is a fully working Next.js app made explicitly for this example which can be found [here](../nextjs). Follow the instructions there to get started. If you are setting up authentication for another front-end, please consider contributing to this repo with your own example! +- [Next.js App Router](../next-app) +- [Next.js Pages Router](../next-pages) + +Follow the instructions in each respective README to get started. If you are setting up authentication for another front-end, please consider contributing to this repo with your own example! ## Quick Start @@ -11,8 +14,8 @@ To spin up this example locally, follow these steps: 1. First clone the repo 1. Then `cd YOUR_PROJECT_REPO && cp .env.example .env` 1. Next `yarn && yarn dev` -1. Now `open http://localhost:8000/admin` to access the admin panel -1. Login with email `dev@payloadcms.com` and password `test` +1. Now `open http://localhost:3000/admin` to access the admin panel +1. Login with email `demo@payloadcms.com` and password `demo` That's it! Changes made in `./src` will be reflected in your app. See the [Development](#development) section for more details. @@ -46,7 +49,7 @@ To spin up this example locally, follow the [Quick Start](#quick-start). ### Seed -On boot, a seed script is included to create a user with email `dev@payloadcms.com`, password `test`, the role `admin`. +On boot, a seed script is included to create a user with email `demo@payloadcms.com`, password `demo`, the role `admin`. > NOTICE: seeding the database is destructive because it drops your current database to populate a fresh one from the seed template. Only run this command if you are starting a new project or can afford to lose your current data. diff --git a/examples/auth/cms/package.json b/examples/auth/cms/package.json index 91e6148d6..fe2b56f6a 100644 --- a/examples/auth/cms/package.json +++ b/examples/auth/cms/package.json @@ -19,7 +19,7 @@ "dependencies": { "dotenv": "^8.2.0", "express": "^4.17.1", - "payload": "^1.7.5" + "payload": "^1.11.0" }, "devDependencies": { "@payloadcms/eslint-config": "^0.0.1", diff --git a/examples/auth/cms/src/collections/Users.ts b/examples/auth/cms/src/collections/Users.ts index 7006e42cb..c02b1a5ec 100644 --- a/examples/auth/cms/src/collections/Users.ts +++ b/examples/auth/cms/src/collections/Users.ts @@ -43,6 +43,7 @@ export const Users: CollectionConfig = { name: 'roles', type: 'select', hasMany: true, + saveToJWT: true, hooks: { beforeChange: [protectRoles], }, diff --git a/examples/auth/cms/src/collections/hooks/protectRoles.ts b/examples/auth/cms/src/collections/hooks/protectRoles.ts index 2d1cb36ab..7a80f5a77 100644 --- a/examples/auth/cms/src/collections/hooks/protectRoles.ts +++ b/examples/auth/cms/src/collections/hooks/protectRoles.ts @@ -3,13 +3,14 @@ import type { FieldHook } from 'payload/types' // ensure there is always a `user` role // do not let non-admins change roles -// eslint-disable-next-line consistent-return export const protectRoles: FieldHook = async ({ req, data }) => { - const isAdmin = req.user?.roles.includes('admin') || data.email === 'dev@payloadcms.com' // for the seed script + const isAdmin = req.user?.roles.includes('admin') || data.email === 'demo@payloadcms.com' // for the seed script if (!isAdmin) { return ['user'] } - return [...(data?.roles || []), 'user'] + const userRoles = new Set(data?.roles || []) + userRoles.add('user') + return [...userRoles] } diff --git a/examples/auth/cms/src/payload-types.ts b/examples/auth/cms/src/payload-types.ts index 0af85b65f..b768d7203 100644 --- a/examples/auth/cms/src/payload-types.ts +++ b/examples/auth/cms/src/payload-types.ts @@ -1,4 +1,5 @@ /* tslint:disable */ +/* eslint-disable */ /** * This file was automatically generated by Payload. * DO NOT MODIFY IT BY HAND. Instead, modify your source Payload config, @@ -7,21 +8,23 @@ export interface Config { collections: { - users: User - } - globals: {} + users: User; + }; + globals: {}; } export interface User { - id: string - firstName?: string - lastName?: string - roles?: Array<'admin' | 'user'> - email?: string - resetPasswordToken?: string - resetPasswordExpiration?: string - loginAttempts?: number - lockUntil?: string - createdAt: string - updatedAt: string - password?: string + id: string; + firstName?: string; + lastName?: string; + roles?: ('admin' | 'user')[]; + updatedAt: string; + createdAt: string; + email: string; + resetPasswordToken?: string; + resetPasswordExpiration?: string; + salt?: string; + hash?: string; + loginAttempts?: number; + lockUntil?: string; + password?: string; } diff --git a/examples/auth/cms/src/payload.config.ts b/examples/auth/cms/src/payload.config.ts index 43deca14c..c1a18603f 100644 --- a/examples/auth/cms/src/payload.config.ts +++ b/examples/auth/cms/src/payload.config.ts @@ -5,8 +5,14 @@ import { Users } from './collections/Users' export default buildConfig({ collections: [Users], - cors: [process.env.PAYLOAD_PUBLIC_SERVER_URL, process.env.PAYLOAD_PUBLIC_SITE_URL], - csrf: [process.env.PAYLOAD_PUBLIC_SERVER_URL, process.env.PAYLOAD_PUBLIC_SITE_URL], + cors: [ + process.env.PAYLOAD_PUBLIC_SERVER_URL || '', + process.env.PAYLOAD_PUBLIC_SITE_URL || '', + ].filter(Boolean), + csrf: [ + process.env.PAYLOAD_PUBLIC_SERVER_URL || '', + process.env.PAYLOAD_PUBLIC_SITE_URL || '', + ].filter(Boolean), typescript: { outputFile: path.resolve(__dirname, 'payload-types.ts'), }, diff --git a/examples/auth/cms/src/seed/index.ts b/examples/auth/cms/src/seed/index.ts index 57666e992..478dd065f 100644 --- a/examples/auth/cms/src/seed/index.ts +++ b/examples/auth/cms/src/seed/index.ts @@ -4,8 +4,8 @@ export const seed = async (payload: Payload): Promise => { await payload.create({ collection: 'users', data: { - email: 'dev@payloadcms.com', - password: 'test', + email: 'demo@payloadcms.com', + password: 'demo', roles: ['admin'], }, }) diff --git a/examples/auth/cms/src/server.ts b/examples/auth/cms/src/server.ts index 04f44ff40..761ff9450 100644 --- a/examples/auth/cms/src/server.ts +++ b/examples/auth/cms/src/server.ts @@ -30,7 +30,7 @@ const start = async (): Promise => { await seed(payload) } - app.listen(8000) + app.listen(3000) } start() diff --git a/examples/auth/cms/tsconfig.json b/examples/auth/cms/tsconfig.json index 2ac7c29fe..92509a492 100644 --- a/examples/auth/cms/tsconfig.json +++ b/examples/auth/cms/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "es5", + "target": "es2019", "lib": [ "dom", "dom.iterable", @@ -14,10 +14,15 @@ "rootDir": "./src", "jsx": "react", "sourceMap": true, + "moduleResolution": "node", "resolveJsonModule": true, "paths": { - "payload/generated-types": ["./src/payload-types.ts"], - "node_modules/*": ["./node_modules/*"] + "payload/generated-types": [ + "./src/payload-types.ts" + ], + "node_modules/*": [ + "./node_modules/*" + ] }, }, "include": [ @@ -31,4 +36,4 @@ "ts-node": { "transpileOnly": true } -} +} \ No newline at end of file diff --git a/examples/auth/cms/yarn.lock b/examples/auth/cms/yarn.lock index f183994df..bea660682 100644 --- a/examples/auth/cms/yarn.lock +++ b/examples/auth/cms/yarn.lock @@ -9,23 +9,28 @@ dependencies: "@babel/highlight" "^7.18.6" -"@babel/helper-module-imports@^7.0.0": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" - integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== +"@babel/helper-module-imports@^7.16.7": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz#1a8f4c9f4027d23f520bd76b364d44434a72660c" + integrity sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg== dependencies: - "@babel/types" "^7.18.6" + "@babel/types" "^7.22.5" -"@babel/helper-string-parser@^7.19.4": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" - integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== +"@babel/helper-string-parser@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" + integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== -"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": +"@babel/helper-validator-identifier@^7.18.6": version "7.19.1" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== +"@babel/helper-validator-identifier@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193" + integrity sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ== + "@babel/highlight@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" @@ -35,20 +40,27 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/runtime@^7.1.2", "@babel/runtime@^7.12.13", "@babel/runtime@^7.14.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.19.0", "@babel/runtime@^7.20.6", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": +"@babel/runtime@^7.1.2", "@babel/runtime@^7.12.13", "@babel/runtime@^7.14.5", "@babel/runtime@^7.19.0", "@babel/runtime@^7.20.6", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7": version "7.20.13" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.13.tgz#7055ab8a7cff2b8f6058bf6ae45ff84ad2aded4b" integrity sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA== dependencies: regenerator-runtime "^0.13.11" -"@babel/types@^7.18.6": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.7.tgz#54ec75e252318423fc07fb644dc6a58a64c09b7f" - integrity sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg== +"@babel/runtime@^7.12.0", "@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3", "@babel/runtime@^7.21.0": + version "7.22.6" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.6.tgz#57d64b9ae3cff1d67eb067ae117dac087f5bd438" + integrity sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ== dependencies: - "@babel/helper-string-parser" "^7.19.4" - "@babel/helper-validator-identifier" "^7.19.1" + regenerator-runtime "^0.13.11" + +"@babel/types@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.5.tgz#cd93eeaab025880a3a47ec881f4b096a5b786fbe" + integrity sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA== + dependencies: + "@babel/helper-string-parser" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.5" to-fast-properties "^2.0.0" "@bcherny/json-schema-ref-parser@9.0.9": @@ -179,7 +191,7 @@ dependencies: "@date-io/core" "^2.16.0" -"@discoveryjs/json-ext@^0.5.0": +"@discoveryjs/json-ext@0.5.7", "@discoveryjs/json-ext@^0.5.0": version "0.5.7" resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== @@ -215,82 +227,104 @@ dependencies: tslib "^2.0.0" -"@emotion/cache@^10.0.27", "@emotion/cache@^10.0.9": - version "10.0.29" - resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-10.0.29.tgz#87e7e64f412c060102d589fe7c6dc042e6f9d1e0" - integrity sha512-fU2VtSVlHiF27empSbxi1O2JFdNWZO+2NFHfwO0pxgTep6Xa3uGb+3pVKfLww2l/IBGLNEZl5Xf/++A4wAYDYQ== +"@emotion/babel-plugin@^11.11.0": + version "11.11.0" + resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz#c2d872b6a7767a9d176d007f5b31f7d504bb5d6c" + integrity sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ== dependencies: - "@emotion/sheet" "0.9.4" - "@emotion/stylis" "0.8.5" - "@emotion/utils" "0.11.3" - "@emotion/weak-memoize" "0.2.5" + "@babel/helper-module-imports" "^7.16.7" + "@babel/runtime" "^7.18.3" + "@emotion/hash" "^0.9.1" + "@emotion/memoize" "^0.8.1" + "@emotion/serialize" "^1.1.2" + babel-plugin-macros "^3.1.0" + convert-source-map "^1.5.0" + escape-string-regexp "^4.0.0" + find-root "^1.1.0" + source-map "^0.5.7" + stylis "4.2.0" -"@emotion/core@^10.0.9": - version "10.3.1" - resolved "https://registry.yarnpkg.com/@emotion/core/-/core-10.3.1.tgz#4021b6d8b33b3304d48b0bb478485e7d7421c69d" - integrity sha512-447aUEjPIm0MnE6QYIaFz9VQOHSXf4Iu6EWOIqq11EAPqinkSZmfymPTmlOE3QjLv846lH4JVZBUOtwGbuQoww== +"@emotion/cache@^11.11.0", "@emotion/cache@^11.4.0": + version "11.11.0" + resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.11.0.tgz#809b33ee6b1cb1a625fef7a45bc568ccd9b8f3ff" + integrity sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ== dependencies: - "@babel/runtime" "^7.5.5" - "@emotion/cache" "^10.0.27" - "@emotion/css" "^10.0.27" - "@emotion/serialize" "^0.11.15" - "@emotion/sheet" "0.9.4" - "@emotion/utils" "0.11.3" + "@emotion/memoize" "^0.8.1" + "@emotion/sheet" "^1.2.2" + "@emotion/utils" "^1.2.1" + "@emotion/weak-memoize" "^0.3.1" + stylis "4.2.0" -"@emotion/css@^10.0.27", "@emotion/css@^10.0.9": - version "10.0.27" - resolved "https://registry.yarnpkg.com/@emotion/css/-/css-10.0.27.tgz#3a7458198fbbebb53b01b2b87f64e5e21241e14c" - integrity sha512-6wZjsvYeBhyZQYNrGoR5yPMYbMBNEnanDrqmsqS1mzDm1cOTu12shvl2j4QHNS36UaTE0USIJawCH9C8oW34Zw== +"@emotion/css@^11.10.5": + version "11.11.2" + resolved "https://registry.yarnpkg.com/@emotion/css/-/css-11.11.2.tgz#e5fa081d0c6e335352e1bc2b05953b61832dca5a" + integrity sha512-VJxe1ucoMYMS7DkiMdC2T7PWNbrEI0a39YRiyDvK2qq4lXwjRbVP/z4lpG+odCsRzadlR+1ywwrTzhdm5HNdew== dependencies: - "@emotion/serialize" "^0.11.15" - "@emotion/utils" "0.11.3" - babel-plugin-emotion "^10.0.27" + "@emotion/babel-plugin" "^11.11.0" + "@emotion/cache" "^11.11.0" + "@emotion/serialize" "^1.1.2" + "@emotion/sheet" "^1.2.2" + "@emotion/utils" "^1.2.1" -"@emotion/hash@0.8.0": - version "0.8.0" - resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413" - integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow== +"@emotion/hash@^0.9.1": + version "0.9.1" + resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.1.tgz#4ffb0055f7ef676ebc3a5a91fb621393294e2f43" + integrity sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ== -"@emotion/memoize@0.7.4": - version "0.7.4" - resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb" - integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw== +"@emotion/memoize@^0.8.1": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.1.tgz#c1ddb040429c6d21d38cc945fe75c818cfb68e17" + integrity sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA== -"@emotion/serialize@^0.11.15", "@emotion/serialize@^0.11.16": - version "0.11.16" - resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-0.11.16.tgz#dee05f9e96ad2fb25a5206b6d759b2d1ed3379ad" - integrity sha512-G3J4o8by0VRrO+PFeSc3js2myYNOXVJ3Ya+RGVxnshRYgsvErfAOglKAiy1Eo1vhzxqtUvjCyS5gtewzkmvSSg== +"@emotion/react@^11.8.1": + version "11.11.1" + resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.11.1.tgz#b2c36afac95b184f73b08da8c214fdf861fa4157" + integrity sha512-5mlW1DquU5HaxjLkfkGN1GA/fvVGdyHURRiX/0FHl2cfIfRxSOfmxEH5YS43edp0OldZrZ+dkBKbngxcNCdZvA== dependencies: - "@emotion/hash" "0.8.0" - "@emotion/memoize" "0.7.4" - "@emotion/unitless" "0.7.5" - "@emotion/utils" "0.11.3" - csstype "^2.5.7" + "@babel/runtime" "^7.18.3" + "@emotion/babel-plugin" "^11.11.0" + "@emotion/cache" "^11.11.0" + "@emotion/serialize" "^1.1.2" + "@emotion/use-insertion-effect-with-fallbacks" "^1.0.1" + "@emotion/utils" "^1.2.1" + "@emotion/weak-memoize" "^0.3.1" + hoist-non-react-statics "^3.3.1" -"@emotion/sheet@0.9.4": - version "0.9.4" - resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-0.9.4.tgz#894374bea39ec30f489bbfc3438192b9774d32e5" - integrity sha512-zM9PFmgVSqBw4zL101Q0HrBVTGmpAxFZH/pYx/cjJT5advXguvcgjHFTCaIO3enL/xr89vK2bh0Mfyj9aa0ANA== +"@emotion/serialize@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.1.2.tgz#017a6e4c9b8a803bd576ff3d52a0ea6fa5a62b51" + integrity sha512-zR6a/fkFP4EAcCMQtLOhIgpprZOwNmCldtpaISpvz348+DP4Mz8ZoKaGGCQpbzepNIUWbq4w6hNZkwDyKoS+HA== + dependencies: + "@emotion/hash" "^0.9.1" + "@emotion/memoize" "^0.8.1" + "@emotion/unitless" "^0.8.1" + "@emotion/utils" "^1.2.1" + csstype "^3.0.2" -"@emotion/stylis@0.8.5": - version "0.8.5" - resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.5.tgz#deacb389bd6ee77d1e7fcaccce9e16c5c7e78e04" - integrity sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ== +"@emotion/sheet@^1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.2.2.tgz#d58e788ee27267a14342303e1abb3d508b6d0fec" + integrity sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA== -"@emotion/unitless@0.7.5": - version "0.7.5" - resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" - integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== +"@emotion/unitless@^0.8.1": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.1.tgz#182b5a4704ef8ad91bde93f7a860a88fd92c79a3" + integrity sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ== -"@emotion/utils@0.11.3": - version "0.11.3" - resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.11.3.tgz#a759863867befa7e583400d322652a3f44820924" - integrity sha512-0o4l6pZC+hI88+bzuaX/6BgOvQVhbt2PfmxauVaYOGgbsAw14wdKyvMCZXnsnsHys94iadcF+RG/wZyx6+ZZBw== +"@emotion/use-insertion-effect-with-fallbacks@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz#08de79f54eb3406f9daaf77c76e35313da963963" + integrity sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw== -"@emotion/weak-memoize@0.2.5": - version "0.2.5" - resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46" - integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA== +"@emotion/utils@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.2.1.tgz#bbab58465738d31ae4cb3dbb6fc00a5991f755e4" + integrity sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg== + +"@emotion/weak-memoize@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz#d0fce5d07b0620caa282b5131c297bb60f9d87e6" + integrity sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww== "@eslint/eslintrc@^1.4.1": version "1.4.1" @@ -327,6 +361,18 @@ resolved "https://registry.yarnpkg.com/@faceless-ui/window-info/-/window-info-2.1.1.tgz#ed1474a60ab794295bca4c29e295b1e11a584d22" integrity sha512-gMAgda7beR4CNpBIXjgRVn97ek0LG3PAj9lxmoYdg574IEzLFZAh3eAYtTaS2XLKgb4+IHhsuBzlGmHbeOo2Aw== +"@floating-ui/core@^1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.3.1.tgz#4d795b649cc3b1cbb760d191c80dcb4353c9a366" + integrity sha512-Bu+AMaXNjrpjh41znzHqaz3r2Nr8hHuHZT6V2LBKMhyMl0FgKA62PNYbqnfgmzOhoWZj70Zecisbo4H1rotP5g== + +"@floating-ui/dom@^1.0.1": + version "1.4.4" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.4.4.tgz#cf859dde33995a4e7b6ded16c98cb73b2ebfffd0" + integrity sha512-21hhDEPOiWkGp0Ys4Wi6Neriah7HweToKra626CIK712B5m9qkdz54OP9gVldUg+URnBTpv/j/bi/skmGdstXQ== + dependencies: + "@floating-ui/core" "^1.3.1" + "@hapi/hoek@^9.0.0": version "9.3.0" resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" @@ -358,13 +404,24 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== -"@hypnosphi/create-react-context@^0.3.1": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@hypnosphi/create-react-context/-/create-react-context-0.3.1.tgz#f8bfebdc7665f5d426cba3753e0e9c7d3154d7c6" - integrity sha512-V1klUed202XahrWJLLOT3EXNeCpFHCcJntdFGI15ntCwau+jfT386w7OFTMaCqOgXUH1fa0w/I1oZs+i/Rfr0A== +"@jest/schemas@^29.6.0": + version "29.6.0" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.0.tgz#0f4cb2c8e3dca80c135507ba5635a4fd755b0040" + integrity sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ== dependencies: - gud "^1.0.0" - warning "^4.0.3" + "@sinclair/typebox" "^0.27.8" + +"@jest/types@^29.6.0": + version "29.6.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.0.tgz#717646103c5715394d78c011a08b3cbb83d738e8" + integrity sha512-8XCgL9JhqbJTFnMRjEAO+TuW251+MoMd5BSzLiE3vvzpQ8RlBxy8NoyNkDhs3K3OL3HeVinlOl9or5p7GTeOLg== + dependencies: + "@jest/schemas" "^29.6.0" + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^17.0.8" + chalk "^4.0.0" "@jridgewell/gen-mapping@^0.3.0": version "0.3.2" @@ -393,6 +450,14 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" +"@jridgewell/source-map@^0.3.3": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.5.tgz#a3bb4d5c6825aab0d281268f47f6ad5853431e91" + integrity sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + "@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": version "1.4.14" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" @@ -406,25 +471,37 @@ "@jridgewell/resolve-uri" "3.1.0" "@jridgewell/sourcemap-codec" "1.4.14" +"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.18": + version "0.3.18" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz#25783b2086daf6ff1dcb53c9249ae480e4dd4cd6" + integrity sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA== + dependencies: + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" + "@jsdevtools/ono@^7.1.3": version "7.1.3" resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796" integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg== -"@monaco-editor/loader@^1.3.2": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@monaco-editor/loader/-/loader-1.3.2.tgz#04effbb87052d19cd7d3c9d81c0635490f9bb6d8" - integrity sha512-BTDbpHl3e47r3AAtpfVFTlAi7WXv4UQ/xZmz8atKl4q7epQV5e7+JbigFDViWF71VBi4IIBdcWP57Hj+OWuc9g== +"@juggle/resize-observer@^3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60" + integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA== + +"@monaco-editor/loader@^1.3.3": + version "1.3.3" + resolved "https://registry.yarnpkg.com/@monaco-editor/loader/-/loader-1.3.3.tgz#7f1742bd3cc21c0362a46a4056317f6e5215cfca" + integrity sha512-6KKF4CTzcJiS8BJwtxtfyYt9shBiEv32ateQ9T4UVogwn4HM/uPo9iJd2Dmbkpz8CM6Y0PDUpjnZzCwC+eYo2Q== dependencies: state-local "^1.0.6" -"@monaco-editor/react@^4.4.6": - version "4.4.6" - resolved "https://registry.yarnpkg.com/@monaco-editor/react/-/react-4.4.6.tgz#8ae500b0edf85276d860ed702e7056c316548218" - integrity sha512-Gr3uz3LYf33wlFE3eRnta4RxP5FSNxiIV9ENn2D2/rN8KgGAD8ecvcITRtsbbyuOuNkwbuHYxfeaz2Vr+CtyFA== +"@monaco-editor/react@^4.5.1": + version "4.5.1" + resolved "https://registry.yarnpkg.com/@monaco-editor/react/-/react-4.5.1.tgz#fbc76c692aee9a33b9ab24ae0c5f219b8f002fdb" + integrity sha512-NNDFdP+2HojtNhCkRfE6/D6ro6pBNihaOzMbGK84lNWzRu+CfBjwzGt4jmnqimLuqp5yE5viHS2vi+QOAnD5FQ== dependencies: - "@monaco-editor/loader" "^1.3.2" - prop-types "^15.7.2" + "@monaco-editor/loader" "^1.3.3" "@nodelib/fs.scandir@2.1.5": version "2.1.5" @@ -457,6 +534,11 @@ resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1" integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g== +"@popperjs/core@^2.9.2": + version "2.11.8" + resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f" + integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A== + "@sideway/address@^4.1.3": version "4.1.4" resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0" @@ -474,6 +556,11 @@ resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== +"@sinclair/typebox@^0.27.8": + version "0.27.8" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" + integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== + "@swc/core-darwin-arm64@1.3.32": version "1.3.32" resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.32.tgz#841b0a244c2c75e67bb9d3cb665b2ede601e4e3a" @@ -595,10 +682,10 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== -"@types/estree@^0.0.51": - version "0.0.51" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" - integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== +"@types/estree@^1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.1.tgz#aa22750962f3bf0e79d753d3cc067f010c95f194" + integrity sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA== "@types/express-serve-static-core@^4.17.33": version "4.17.33" @@ -627,14 +714,6 @@ "@types/minimatch" "*" "@types/node" "*" -"@types/hoist-non-react-statics@^3.3.0": - version "3.3.1" - resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" - integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA== - dependencies: - "@types/react" "*" - hoist-non-react-statics "^3.3.0" - "@types/html-minifier-terser@^6.0.0": version "6.1.0" resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" @@ -645,6 +724,25 @@ resolved "https://registry.yarnpkg.com/@types/is-hotkey/-/is-hotkey-0.1.7.tgz#30ec6d4234895230b576728ef77e70a52962f3b3" integrity sha512-yB5C7zcOM7idwYZZ1wKQ3pTfjA9BbvFqRWvKB46GFddxnJtHwi/b9y84ykQtxQPg5qhdpg4Q/kWU3EGoCTmLzQ== +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" + integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== + +"@types/istanbul-lib-report@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" + integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" + integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== + dependencies: + "@types/istanbul-lib-report" "*" + "@types/json-schema@*", "@types/json-schema@^7.0.11", "@types/json-schema@^7.0.6", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": version "7.0.11" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" @@ -705,15 +803,12 @@ resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== -"@types/react-redux@^7.1.20": - version "7.1.25" - resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.25.tgz#de841631205b24f9dfb4967dd4a7901e048f9a88" - integrity sha512-bAGh4e+w5D8dajd6InASVIyCo4pZLJ66oLb80F9OBLO1gKESbZcRCJpTT6uLXX+HAB57zw1WTdwJdAsewuTweg== +"@types/react-transition-group@^4.4.0": + version "4.4.6" + resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.6.tgz#18187bcda5281f8e10dfc48f0943e2fdf4f75e2e" + integrity sha512-VnCdSxfcm08KjsJVQcfBmhEQAPnLB8G08hAxn39azX1qYBQ/5RVQuoHuKIcfKOdncuaUvEpFKFzEvbtIMsfVew== dependencies: - "@types/hoist-non-react-statics" "^3.3.0" "@types/react" "*" - hoist-non-react-statics "^3.3.0" - redux "^4.0.0" "@types/react@*": version "18.0.27" @@ -771,6 +866,18 @@ "@types/node" "*" "@types/webidl-conversions" "*" +"@types/yargs-parser@*": + version "21.0.0" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" + integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== + +"@types/yargs@^17.0.8": + version "17.0.24" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.24.tgz#b3ef8d50ad4aa6aecf6ddc97c580a00f5aa11902" + integrity sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw== + dependencies: + "@types/yargs-parser" "*" + "@typescript-eslint/eslint-plugin@^5.51.0": version "5.52.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.52.0.tgz#5fb0d43574c2411f16ea80f5fc335b8eaa7b28a8" @@ -855,125 +962,125 @@ "@typescript-eslint/types" "5.52.0" eslint-visitor-keys "^3.3.0" -"@webassemblyjs/ast@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" - integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== +"@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.6.tgz#db046555d3c413f8966ca50a95176a0e2c642e24" + integrity sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q== dependencies: - "@webassemblyjs/helper-numbers" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/helper-numbers" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" -"@webassemblyjs/floating-point-hex-parser@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" - integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== +"@webassemblyjs/floating-point-hex-parser@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431" + integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw== -"@webassemblyjs/helper-api-error@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" - integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== +"@webassemblyjs/helper-api-error@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" + integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== -"@webassemblyjs/helper-buffer@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" - integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== +"@webassemblyjs/helper-buffer@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz#b66d73c43e296fd5e88006f18524feb0f2c7c093" + integrity sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA== -"@webassemblyjs/helper-numbers@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" - integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== +"@webassemblyjs/helper-numbers@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5" + integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g== dependencies: - "@webassemblyjs/floating-point-hex-parser" "1.11.1" - "@webassemblyjs/helper-api-error" "1.11.1" + "@webassemblyjs/floating-point-hex-parser" "1.11.6" + "@webassemblyjs/helper-api-error" "1.11.6" "@xtuc/long" "4.2.2" -"@webassemblyjs/helper-wasm-bytecode@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" - integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== +"@webassemblyjs/helper-wasm-bytecode@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" + integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== -"@webassemblyjs/helper-wasm-section@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" - integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== +"@webassemblyjs/helper-wasm-section@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz#ff97f3863c55ee7f580fd5c41a381e9def4aa577" + integrity sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g== dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/helper-buffer" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/wasm-gen" "1.11.6" -"@webassemblyjs/ieee754@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" - integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== +"@webassemblyjs/ieee754@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a" + integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg== dependencies: "@xtuc/ieee754" "^1.2.0" -"@webassemblyjs/leb128@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" - integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== +"@webassemblyjs/leb128@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7" + integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ== dependencies: "@xtuc/long" "4.2.2" -"@webassemblyjs/utf8@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" - integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== +"@webassemblyjs/utf8@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" + integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== -"@webassemblyjs/wasm-edit@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" - integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== +"@webassemblyjs/wasm-edit@^1.11.5": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz#c72fa8220524c9b416249f3d94c2958dfe70ceab" + integrity sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw== dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/helper-wasm-section" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - "@webassemblyjs/wasm-opt" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - "@webassemblyjs/wast-printer" "1.11.1" + "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/helper-buffer" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/helper-wasm-section" "1.11.6" + "@webassemblyjs/wasm-gen" "1.11.6" + "@webassemblyjs/wasm-opt" "1.11.6" + "@webassemblyjs/wasm-parser" "1.11.6" + "@webassemblyjs/wast-printer" "1.11.6" -"@webassemblyjs/wasm-gen@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" - integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== +"@webassemblyjs/wasm-gen@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz#fb5283e0e8b4551cc4e9c3c0d7184a65faf7c268" + integrity sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA== dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/ieee754" "1.11.1" - "@webassemblyjs/leb128" "1.11.1" - "@webassemblyjs/utf8" "1.11.1" + "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" -"@webassemblyjs/wasm-opt@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" - integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== +"@webassemblyjs/wasm-opt@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz#d9a22d651248422ca498b09aa3232a81041487c2" + integrity sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g== dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" + "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/helper-buffer" "1.11.6" + "@webassemblyjs/wasm-gen" "1.11.6" + "@webassemblyjs/wasm-parser" "1.11.6" -"@webassemblyjs/wasm-parser@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" - integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== +"@webassemblyjs/wasm-parser@1.11.6", "@webassemblyjs/wasm-parser@^1.11.5": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz#bb85378c527df824004812bbdb784eea539174a1" + integrity sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ== dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-api-error" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/ieee754" "1.11.1" - "@webassemblyjs/leb128" "1.11.1" - "@webassemblyjs/utf8" "1.11.1" + "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/helper-api-error" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" -"@webassemblyjs/wast-printer@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" - integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== +"@webassemblyjs/wast-printer@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz#a7bf8dd7e362aeb1668ff43f35cb849f188eff20" + integrity sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A== dependencies: - "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/ast" "1.11.6" "@xtuc/long" "4.2.2" "@webpack-cli/configtest@^1.2.0": @@ -1015,7 +1122,7 @@ abort-controller@^3.0.0: dependencies: event-target-shim "^5.0.0" -accepts@^1.3.7, accepts@~1.3.5, accepts@~1.3.8: +accepts@~1.3.5, accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== @@ -1023,10 +1130,10 @@ accepts@^1.3.7, accepts@~1.3.5, accepts@~1.3.8: mime-types "~2.1.34" negotiator "0.6.3" -acorn-import-assertions@^1.7.6: - version "1.8.0" - resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" - integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== +acorn-import-assertions@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" + integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== acorn-jsx@^5.3.2: version "5.3.2" @@ -1043,6 +1150,11 @@ acorn@^8.0.4, acorn@^8.5.0, acorn@^8.7.1, acorn@^8.8.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== +acorn@^8.8.2: + version "8.10.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" + integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== + ajv-formats@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" @@ -1055,7 +1167,7 @@ ajv-keywords@^3.5.2: resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv-keywords@^5.0.0: +ajv-keywords@^5.0.0, ajv-keywords@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== @@ -1072,7 +1184,7 @@ ajv@^6.10.0, ajv@^6.12.4, ajv@^6.12.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^8.0.0, ajv@^8.6.3, ajv@^8.8.0: +ajv@^8.0.0, ajv@^8.6.3, ajv@^8.8.0, ajv@^8.9.0: version "8.12.0" resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== @@ -1187,35 +1299,14 @@ available-typed-arrays@^1.0.5: resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== -babel-plugin-emotion@^10.0.27: - version "10.2.2" - resolved "https://registry.yarnpkg.com/babel-plugin-emotion/-/babel-plugin-emotion-10.2.2.tgz#a1fe3503cff80abfd0bdda14abd2e8e57a79d17d" - integrity sha512-SMSkGoqTbTyUTDeuVuPIWifPdUGkTk1Kf9BWRiXIOIcuyMfsdp2EjeiiFvOzX8NOBvEh/ypKYvUh2rkgAJMCLA== +babel-plugin-macros@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1" + integrity sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg== dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@emotion/hash" "0.8.0" - "@emotion/memoize" "0.7.4" - "@emotion/serialize" "^0.11.16" - babel-plugin-macros "^2.0.0" - babel-plugin-syntax-jsx "^6.18.0" - convert-source-map "^1.5.0" - escape-string-regexp "^1.0.5" - find-root "^1.1.0" - source-map "^0.5.7" - -babel-plugin-macros@^2.0.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz#0f958a7cc6556b1e65344465d99111a1e5e10138" - integrity sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg== - dependencies: - "@babel/runtime" "^7.7.2" - cosmiconfig "^6.0.0" - resolve "^1.12.0" - -babel-plugin-syntax-jsx@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" - integrity sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw== + "@babel/runtime" "^7.12.5" + cosmiconfig "^7.0.0" + resolve "^1.19.0" balanced-match@^1.0.0: version "1.0.2" @@ -1296,7 +1387,7 @@ braces@^3.0.2, braces@~3.0.2: dependencies: fill-range "^7.0.1" -browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.16.6, browserslist@^4.21.4: +browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.21.4: version "4.21.5" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.5.tgz#75c5dae60063ee641f977e00edd3cfb2fb7af6a7" integrity sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w== @@ -1449,7 +1540,12 @@ chrome-trace-event@^1.0.2: resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== -classnames@^2.2.5, classnames@^2.2.6: +ci-info@^3.2.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.8.0.tgz#81408265a5380c929f0bc665d62256628ce9ef91" + integrity sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw== + +classnames@^2.2.5, classnames@^2.2.6, classnames@^2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.2.tgz#351d813bf0137fcc6a76a16b88208d2560a0d924" integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw== @@ -1540,10 +1636,10 @@ colord@^2.9.1: resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.3.tgz#4f8ce919de456f1d5c1c368c307fe20f3e59fb43" integrity sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw== -colorette@^1.2.2: - version "1.4.0" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" - integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== +colorette@^2.0.10: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== colorette@^2.0.14, colorette@^2.0.7: version "2.0.19" @@ -1623,7 +1719,7 @@ content-disposition@0.5.4: dependencies: safe-buffer "5.2.1" -content-type@^1.0.4, content-type@~1.0.4: +content-type@~1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== @@ -1661,17 +1757,6 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== -cosmiconfig@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" - integrity sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg== - dependencies: - "@types/parse-json" "^4.0.0" - import-fresh "^3.1.0" - parse-json "^5.0.0" - path-type "^4.0.0" - yaml "^1.7.2" - cosmiconfig@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6" @@ -1683,16 +1768,6 @@ cosmiconfig@^7.0.0: path-type "^4.0.0" yaml "^1.10.0" -create-emotion@^10.0.14, create-emotion@^10.0.27: - version "10.0.27" - resolved "https://registry.yarnpkg.com/create-emotion/-/create-emotion-10.0.27.tgz#cb4fa2db750f6ca6f9a001a33fbf1f6c46789503" - integrity sha512-fIK73w82HPPn/RsAij7+Zt8eCE8SptcJ3WoRMfxMtjteYxud8GDTKKld7MYwAX2TVhrw29uR1N/bVGxeStHILg== - dependencies: - "@emotion/cache" "^10.0.27" - "@emotion/serialize" "^0.11.15" - "@emotion/sheet" "0.9.4" - "@emotion/utils" "0.11.3" - create-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" @@ -1726,13 +1801,6 @@ css-blank-pseudo@^3.0.3: dependencies: postcss-selector-parser "^6.0.9" -css-box-model@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/css-box-model/-/css-box-model-1.2.1.tgz#59951d3b81fd6b2074a62d49444415b0d2b4d7c1" - integrity sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw== - dependencies: - tiny-invariant "^1.0.6" - css-declaration-sorter@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.3.1.tgz#be5e1d71b7a992433fb1c542c7a1b835e45682ec" @@ -1761,17 +1829,17 @@ css-loader@^5.2.7: schema-utils "^3.0.0" semver "^7.3.5" -css-minimizer-webpack-plugin@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz#ab78f781ced9181992fe7b6e4f3422e76429878f" - integrity sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q== +css-minimizer-webpack-plugin@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-5.0.1.tgz#33effe662edb1a0bf08ad633c32fa75d0f7ec565" + integrity sha512-3caImjKFQkS+ws1TGcFn0V1HyDJFq1Euy589JlD6/3rV2kj+w7r5G9WDMgSHvpvXHNZ2calVypZWuEDQd9wfLg== dependencies: - cssnano "^5.0.6" - jest-worker "^27.0.2" - postcss "^8.3.5" - schema-utils "^4.0.0" - serialize-javascript "^6.0.0" - source-map "^0.6.1" + "@jridgewell/trace-mapping" "^0.3.18" + cssnano "^6.0.1" + jest-worker "^29.4.3" + postcss "^8.4.24" + schema-utils "^4.0.1" + serialize-javascript "^6.0.1" css-prefers-color-scheme@^6.0.3: version "6.0.3" @@ -1789,15 +1857,34 @@ css-select@^4.1.3: domutils "^2.8.0" nth-check "^2.0.1" -css-tree@^1.1.2, css-tree@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" - integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q== +css-select@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6" + integrity sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg== dependencies: - mdn-data "2.0.14" - source-map "^0.6.1" + boolbase "^1.0.0" + css-what "^6.1.0" + domhandler "^5.0.2" + domutils "^3.0.1" + nth-check "^2.0.1" -css-what@^6.0.1: +css-tree@^2.2.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-2.3.1.tgz#10264ce1e5442e8572fc82fbe490644ff54b5c20" + integrity sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw== + dependencies: + mdn-data "2.0.30" + source-map-js "^1.0.1" + +css-tree@~2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-2.2.1.tgz#36115d382d60afd271e377f9c5f67d02bd48c032" + integrity sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA== + dependencies: + mdn-data "2.0.28" + source-map-js "^1.0.1" + +css-what@^6.0.1, css-what@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== @@ -1817,66 +1904,60 @@ cssfilter@0.0.10: resolved "https://registry.yarnpkg.com/cssfilter/-/cssfilter-0.0.10.tgz#c6d2672632a2e5c83e013e6864a42ce8defd20ae" integrity sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw== -cssnano-preset-default@^5.2.13: - version "5.2.13" - resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.2.13.tgz#e7353b0c57975d1bdd97ac96e68e5c1b8c68e990" - integrity sha512-PX7sQ4Pb+UtOWuz8A1d+Rbi+WimBIxJTRyBdgGp1J75VU0r/HFQeLnMYgHiCAp6AR4rqrc7Y4R+1Rjk3KJz6DQ== +cssnano-preset-default@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-6.0.1.tgz#2a93247140d214ddb9f46bc6a3562fa9177fe301" + integrity sha512-7VzyFZ5zEB1+l1nToKyrRkuaJIx0zi/1npjvZfbBwbtNTzhLtlvYraK/7/uqmX2Wb2aQtd983uuGw79jAjLSuQ== dependencies: css-declaration-sorter "^6.3.1" - cssnano-utils "^3.1.0" - postcss-calc "^8.2.3" - postcss-colormin "^5.3.0" - postcss-convert-values "^5.1.3" - postcss-discard-comments "^5.1.2" - postcss-discard-duplicates "^5.1.0" - postcss-discard-empty "^5.1.1" - postcss-discard-overridden "^5.1.0" - postcss-merge-longhand "^5.1.7" - postcss-merge-rules "^5.1.3" - postcss-minify-font-values "^5.1.0" - postcss-minify-gradients "^5.1.1" - postcss-minify-params "^5.1.4" - postcss-minify-selectors "^5.2.1" - postcss-normalize-charset "^5.1.0" - postcss-normalize-display-values "^5.1.0" - postcss-normalize-positions "^5.1.1" - postcss-normalize-repeat-style "^5.1.1" - postcss-normalize-string "^5.1.0" - postcss-normalize-timing-functions "^5.1.0" - postcss-normalize-unicode "^5.1.1" - postcss-normalize-url "^5.1.0" - postcss-normalize-whitespace "^5.1.1" - postcss-ordered-values "^5.1.3" - postcss-reduce-initial "^5.1.1" - postcss-reduce-transforms "^5.1.0" - postcss-svgo "^5.1.0" - postcss-unique-selectors "^5.1.1" + cssnano-utils "^4.0.0" + postcss-calc "^9.0.0" + postcss-colormin "^6.0.0" + postcss-convert-values "^6.0.0" + postcss-discard-comments "^6.0.0" + postcss-discard-duplicates "^6.0.0" + postcss-discard-empty "^6.0.0" + postcss-discard-overridden "^6.0.0" + postcss-merge-longhand "^6.0.0" + postcss-merge-rules "^6.0.1" + postcss-minify-font-values "^6.0.0" + postcss-minify-gradients "^6.0.0" + postcss-minify-params "^6.0.0" + postcss-minify-selectors "^6.0.0" + postcss-normalize-charset "^6.0.0" + postcss-normalize-display-values "^6.0.0" + postcss-normalize-positions "^6.0.0" + postcss-normalize-repeat-style "^6.0.0" + postcss-normalize-string "^6.0.0" + postcss-normalize-timing-functions "^6.0.0" + postcss-normalize-unicode "^6.0.0" + postcss-normalize-url "^6.0.0" + postcss-normalize-whitespace "^6.0.0" + postcss-ordered-values "^6.0.0" + postcss-reduce-initial "^6.0.0" + postcss-reduce-transforms "^6.0.0" + postcss-svgo "^6.0.0" + postcss-unique-selectors "^6.0.0" -cssnano-utils@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-3.1.0.tgz#95684d08c91511edfc70d2636338ca37ef3a6861" - integrity sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA== +cssnano-utils@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-4.0.0.tgz#d1da885ec04003ab19505ff0e62e029708d36b08" + integrity sha512-Z39TLP+1E0KUcd7LGyF4qMfu8ZufI0rDzhdyAMsa/8UyNUU8wpS0fhdBxbQbv32r64ea00h4878gommRVg2BHw== -cssnano@^5.0.6: - version "5.1.14" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.1.14.tgz#07b0af6da73641276fe5a6d45757702ebae2eb05" - integrity sha512-Oou7ihiTocbKqi0J1bB+TRJIQX5RMR3JghA8hcWSw9mjBLQ5Y3RWqEDoYG3sRNlAbCIXpqMoZGbq5KDR3vdzgw== +cssnano@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-6.0.1.tgz#87c38c4cd47049c735ab756d7e77ac3ca855c008" + integrity sha512-fVO1JdJ0LSdIGJq68eIxOqFpIJrZqXUsBt8fkrBcztCQqAjQD51OhZp7tc0ImcbwXD4k7ny84QTV90nZhmqbkg== dependencies: - cssnano-preset-default "^5.2.13" - lilconfig "^2.0.3" - yaml "^1.10.2" + cssnano-preset-default "^6.0.1" + lilconfig "^2.1.0" -csso@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" - integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA== +csso@^5.0.5: + version "5.0.5" + resolved "https://registry.yarnpkg.com/csso/-/csso-5.0.5.tgz#f9b7fe6cc6ac0b7d90781bb16d5e9874303e2ca6" + integrity sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ== dependencies: - css-tree "^1.1.2" - -csstype@^2.5.7: - version "2.6.21" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.21.tgz#2efb85b7cc55c80017c66a5ad7cbd931fda3a90e" - integrity sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w== + css-tree "~2.2.0" csstype@^3.0.2: version "3.1.1" @@ -1896,7 +1977,14 @@ dataloader@^2.1.0: resolved "https://registry.yarnpkg.com/dataloader/-/dataloader-2.2.1.tgz#f07ab712514313a34b1507a308dbb7dc14bac715" integrity sha512-Zn+tVZo1RKu120rgoe0JsRk56UiKdefPSH47QROJsMHrX8/S9UJvi5A/A6+Sbuk6rE88z5JoM/wIJ09Z7BTfYA== -date-fns@^2.0.1, date-fns@^2.29.3: +date-fns@^2.24.0: + version "2.30.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.30.0.tgz#f367e644839ff57894ec6ac480de40cae4b0f4d0" + integrity sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw== + dependencies: + "@babel/runtime" "^7.21.0" + +date-fns@^2.29.3: version "2.29.3" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.3.tgz#27402d2fc67eb442b511b70bbdf98e6411cd68a8" integrity sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA== @@ -1948,18 +2036,6 @@ decompress-response@^6.0.0: dependencies: mimic-response "^3.1.0" -deep-equal@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" - integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== - dependencies: - is-arguments "^1.0.4" - is-date-object "^1.0.1" - is-regex "^1.0.4" - object-is "^1.0.1" - object-keys "^1.1.1" - regexp.prototype.flags "^1.2.0" - deep-equal@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.2.0.tgz#5caeace9c781028b9ff459f33b779346637c43e6" @@ -2016,11 +2092,6 @@ depd@2.0.0: resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== - destroy@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" @@ -2036,6 +2107,11 @@ diff@^4.0.1: resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== +diff@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.1.0.tgz#bc52d298c5ea8df9194800224445ed43ffc87e40" + integrity sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -2086,7 +2162,16 @@ dom-serializer@^1.0.1: domhandler "^4.2.0" entities "^2.0.0" -domelementtype@^2.0.1, domelementtype@^2.2.0: +dom-serializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53" + integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.2" + entities "^4.2.0" + +domelementtype@^2.0.1, domelementtype@^2.2.0, domelementtype@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== @@ -2098,6 +2183,13 @@ domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1: dependencies: domelementtype "^2.2.0" +domhandler@^5.0.2, domhandler@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" + integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== + dependencies: + domelementtype "^2.3.0" + domutils@^2.5.2, domutils@^2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" @@ -2107,6 +2199,15 @@ domutils@^2.5.2, domutils@^2.8.0: domelementtype "^2.2.0" domhandler "^4.2.0" +domutils@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.1.0.tgz#c47f551278d3dc4b0b1ab8cbb42d751a6f0d824e" + integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA== + dependencies: + dom-serializer "^2.0.0" + domelementtype "^2.3.0" + domhandler "^5.0.3" + dot-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" @@ -2159,14 +2260,6 @@ emojis-list@^3.0.0: resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== -emotion@^10.0.14: - version "10.0.27" - resolved "https://registry.yarnpkg.com/emotion/-/emotion-10.0.27.tgz#f9ca5df98630980a23c819a56262560562e5d75e" - integrity sha512-2xdDzdWWzue8R8lu4G76uWX5WhyQuzATon9LmNeCy/2BHVC6dsEpfhN1a0qhELgtDVdjyEA6J8Y/VlI5ZnaH0g== - dependencies: - babel-plugin-emotion "^10.0.27" - create-emotion "^10.0.27" - encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -2179,10 +2272,10 @@ end-of-stream@^1.1.0, end-of-stream@^1.4.1: dependencies: once "^1.4.0" -enhanced-resolve@^5.10.0: - version "5.12.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz#300e1c90228f5b570c4d35babf263f6da7155634" - integrity sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ== +enhanced-resolve@^5.15.0: + version "5.15.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz#1af946c7d93603eb88e9896cee4904dc012e9c35" + integrity sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" @@ -2192,6 +2285,11 @@ entities@^2.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== +entities@^4.2.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + env-paths@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" @@ -2263,10 +2361,10 @@ es-get-iterator@^1.1.2: isarray "^2.0.5" stop-iteration-iterator "^1.0.0" -es-module-lexer@^0.9.0: - version "0.9.3" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" - integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== +es-module-lexer@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.3.0.tgz#6be9c9e0b4543a60cd166ff6f8b4e9dae0b0c16f" + integrity sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA== es-set-tostringtag@^2.0.1: version "2.0.1" @@ -2567,16 +2665,6 @@ express-fileupload@1.4.0: dependencies: busboy "^1.6.0" -express-graphql@0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/express-graphql/-/express-graphql-0.12.0.tgz#58deabc309909ca2c9fe2f83f5fbe94429aa23df" - integrity sha512-DwYaJQy0amdy3pgNtiTDuGGM2BLdj+YO2SgbKoLliCfuHv3VVTt7vNG/ZqK2hRYjtYHE2t2KB705EU94mE64zg== - dependencies: - accepts "^1.3.7" - content-type "^1.0.4" - http-errors "1.8.0" - raw-body "^2.4.1" - express-rate-limit@^5.5.1: version "5.5.1" resolved "https://registry.yarnpkg.com/express-rate-limit/-/express-rate-limit-5.5.1.tgz#110c23f6a65dfa96ab468eda95e71697bc6987a2" @@ -2824,10 +2912,10 @@ fs-extra@^10.1.0: jsonfile "^6.0.1" universalify "^2.0.0" -fs-monkey@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.3.tgz#ae3ac92d53bb328efe0e9a1d9541f6ad8d48e2d3" - integrity sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q== +fs-monkey@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.4.tgz#ee8c1b53d3fe8bb7e5d2c5c5dfc0168afdd2f747" + integrity sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ== fs.realpath@^1.0.0: version "1.0.0" @@ -2859,11 +2947,6 @@ functions-have-names@^1.2.2: resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== -generaterr@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/generaterr/-/generaterr-1.5.0.tgz#b0ceb6cc5164df2a061338cc340a8615395c52fc" - integrity sha512-JgcGRv2yUKeboLvvNrq9Bm90P4iJBu7/vd5wSLYqMG5GJ6SxZT46LAAkMfNhQ+EK3jzC+cRBm7P8aUWYyphgcQ== - get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" @@ -2891,6 +2974,13 @@ get-symbol-description@^1.0.0: call-bind "^1.0.2" get-intrinsic "^1.1.1" +get-tsconfig@^4.4.0: + version "4.6.2" + resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.6.2.tgz#831879a5e6c2aa24fe79b60340e2233a1e0f472e" + integrity sha512-E5XrT4CbbXcXWy+1jChlZmrmCwd5KGx502kDCXJJ7y898TtWW9FwoG5HfOLVRKmlmDGkWN2HM9Ho+/Y8F0sJDg== + dependencies: + resolve-pkg-maps "^1.0.0" + github-from-package@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" @@ -2988,6 +3078,11 @@ grapheme-splitter@^1.0.4: resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== +graphql-http@^1.17.1: + version "1.19.0" + resolved "https://registry.yarnpkg.com/graphql-http/-/graphql-http-1.19.0.tgz#6f0fff0dbd9a8e797c99b5ac0ca160566e7927da" + integrity sha512-fOD3hfp/G+Lhx2FWW5HsfmtJSsw6CikcpOboG7/mFo/pPUzn3yOwKdTFRnJ8MVY4ru69MT1nSPr/1gI/iuGNlw== + graphql-playground-html@^1.6.30: version "1.6.30" resolved "https://registry.yarnpkg.com/graphql-playground-html/-/graphql-playground-html-1.6.30.tgz#14c2a8eb7fc17bfeb1a746bbb28a11e34bf0b391" @@ -3026,11 +3121,6 @@ graphql@^16.6.0: resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.6.0.tgz#c2dcffa4649db149f6282af726c8c83f1c7c5fdb" integrity sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw== -gud@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/gud/-/gud-1.0.0.tgz#a489581b17e6a70beca9abe3ae57de7a499852c0" - integrity sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw== - gzip-size@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462" @@ -3109,7 +3199,7 @@ history@^4.9.0: tiny-warning "^1.0.0" value-equal "^1.0.1" -hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: +hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.1: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== @@ -3162,17 +3252,6 @@ htmlparser2@^6.1.0: domutils "^2.5.2" entities "^2.0.0" -http-errors@1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.0.tgz#75d1bbe497e1044f51e4ee9e704a62f28d336507" - integrity sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A== - dependencies: - depd "~1.1.2" - inherits "2.0.4" - setprototypeof "1.2.0" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - http-errors@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" @@ -3245,7 +3324,7 @@ immutable@^4.0.0: resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.2.4.tgz#83260d50889526b4b531a5e293709a77f7c55a2a" integrity sha512-WDxL3Hheb1JkRN3sQkyujNlL/xRjAo3rJtaU5xeufUauG66JdMr32bLj4gF+vWl84DIA3Zxw7tiAjneYzRRw+w== -import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1: +import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== @@ -3308,7 +3387,7 @@ ipaddr.js@1.9.1: resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== -is-arguments@^1.0.4, is-arguments@^1.1.1: +is-arguments@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== @@ -3457,7 +3536,7 @@ is-promise@^2.2.2: resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== -is-regex@^1.0.4, is-regex@^1.1.4: +is-regex@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== @@ -3555,7 +3634,19 @@ isomorphic-fetch@^3.0.0: node-fetch "^2.6.1" whatwg-fetch "^3.4.1" -jest-worker@^27.0.2, jest-worker@^27.4.5: +jest-util@^29.6.0: + version "29.6.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.6.0.tgz#4071050c5d70f5d4d48105e8883773f3a6b94f8d" + integrity sha512-S0USx9YwcvEm4pQ5suisVm/RVxBmi0GFR7ocJhIeaCuW5AXnAnffXbaVKvIFodyZNOc9ygzVtTxmBf40HsHXaA== + dependencies: + "@jest/types" "^29.6.0" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + +jest-worker@^27.4.5: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== @@ -3564,6 +3655,16 @@ jest-worker@^27.0.2, jest-worker@^27.4.5: merge-stream "^2.0.0" supports-color "^8.0.0" +jest-worker@^29.4.3: + version "29.6.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.6.0.tgz#e0c40226d073fdb8f0dfe87d7f90f8fd987d8ba3" + integrity sha512-oiQHH1SnKmZIwwPnpOrXTq4kHBk3lKGY/07DpnH0sAu+x7J8rXlbLDROZsU6vy9GwB0hPiZeZpu6YlJ48QoKcA== + dependencies: + "@types/node" "*" + jest-util "^29.6.0" + merge-stream "^2.0.0" + supports-color "^8.0.0" + joi@^17.7.0: version "17.7.0" resolved "https://registry.yarnpkg.com/joi/-/joi-17.7.0.tgz#591a33b1fe1aca2bc27f290bcad9b9c1c570a6b3" @@ -3602,7 +3703,7 @@ json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== -json-schema-to-typescript@^11.0.2: +json-schema-to-typescript@11.0.3: version "11.0.3" resolved "https://registry.yarnpkg.com/json-schema-to-typescript/-/json-schema-to-typescript-11.0.3.tgz#9b401c2b78329959f1c4c4e0639a6bdcf6a6ed77" integrity sha512-EaEE9Y4VZ8b9jW5zce5a9L3+p4C9AqgIRHbNVDJahfMnoKzcd4sDb98BLxLdQhJEuRAXyKLg4H66NKm80W8ilg== @@ -3718,10 +3819,10 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" -lilconfig@^2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.6.tgz#32a384558bd58af3d4c6e077dd1ad1d397bc69d4" - integrity sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg== +lilconfig@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" + integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== lines-and-columns@^1.1.6: version "1.2.4" @@ -3847,13 +3948,6 @@ make-error@^1.1.1: resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== -map-age-cleaner@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" - integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== - dependencies: - p-defer "^1.0.0" - md5@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f" @@ -3863,35 +3957,32 @@ md5@^2.3.0: crypt "0.0.2" is-buffer "~1.1.6" -mdn-data@2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" - integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== +mdn-data@2.0.28: + version "2.0.28" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.28.tgz#5ec48e7bef120654539069e1ae4ddc81ca490eba" + integrity sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g== + +mdn-data@2.0.30: + version "2.0.30" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.30.tgz#ce4df6f80af6cfbe218ecd5c552ba13c4dfa08cc" + integrity sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA== media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== -mem@^8.1.1: - version "8.1.1" - resolved "https://registry.yarnpkg.com/mem/-/mem-8.1.1.tgz#cf118b357c65ab7b7e0817bdf00c8062297c0122" - integrity sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA== +memfs@^3.4.12: + version "3.6.0" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.6.0.tgz#d7a2110f86f79dd950a8b6df6d57bc984aa185f6" + integrity sha512-EGowvkkgbMcIChjMTMkESFDbZeSh8xZ7kNSF0hAiAN4Jh6jgHCRS0Ga/+C8y6Au+oqpezRHCfPsmJ2+DwAgiwQ== dependencies: - map-age-cleaner "^0.1.3" - mimic-fn "^3.1.0" + fs-monkey "^1.0.4" -memfs@^3.2.2: - version "3.4.13" - resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.13.tgz#248a8bd239b3c240175cd5ec548de5227fc4f345" - integrity sha512-omTM41g3Skpvx5dSYeZIbXKcXoAVc/AoMNwn9TKx++L/gaen/+4TTttmu8ZSch5vfVJ8uJvGbroTsIlslRg6lg== - dependencies: - fs-monkey "^1.0.3" - -memoize-one@^5.0.0, memoize-one@^5.0.4, memoize-one@^5.1.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" - integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q== +memoize-one@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-6.0.0.tgz#b2591b871ed82948aee4727dc6abceeeac8c1045" + integrity sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw== memoizee@^0.4.15: version "0.4.15" @@ -3960,7 +4051,7 @@ mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@^2.1.27, mime-types@^2.1.30, mime-types@~2.1.24, mime-types@~2.1.34: +mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== @@ -3977,7 +4068,7 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -mimic-fn@^3.0.0, mimic-fn@^3.1.0: +mimic-fn@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-3.1.0.tgz#65755145bbf3e36954b949c16450427451d5ca74" integrity sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ== @@ -4025,6 +4116,11 @@ mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== +monaco-editor@^0.38.0: + version "0.38.0" + resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.38.0.tgz#7b3cd16f89b1b8867fcd3c96e67fccee791ff05c" + integrity sha512-11Fkh6yzEmwx7O0YoLxeae0qEGFwmyPRlVxpg7oF9czOOCB/iCjdJrG5I67da5WiXK3YJCxoz9TJFE8Tfq/v9A== + mongodb-connection-string-url@^2.5.2: version "2.6.0" resolved "https://registry.yarnpkg.com/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz#57901bf352372abdde812c81be47b75c6b2ec5cf" @@ -4114,6 +4210,11 @@ nanoid@^3.3.4: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== +nanoid@^3.3.6: + version "3.3.6" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" + integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== + napi-build-utils@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806" @@ -4231,11 +4332,6 @@ normalize-range@^0.1.2: resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== -normalize-url@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" - integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== - nth-check@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" @@ -4253,7 +4349,7 @@ object-inspect@^1.12.2, object-inspect@^1.9.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== -object-is@^1.0.1, object-is@^1.1.5: +object-is@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== @@ -4338,11 +4434,6 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" -p-defer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" - integrity sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw== - p-limit@^2.0.0, p-limit@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" @@ -4444,15 +4535,6 @@ passport-jwt@^4.0.1: jsonwebtoken "^9.0.0" passport-strategy "^1.0.0" -passport-local-mongoose@^7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/passport-local-mongoose/-/passport-local-mongoose-7.1.2.tgz#0a89876ef8a8e18787e59a39740e61c5653eb25e" - integrity sha512-hNLIKi/6IhElr/PhOze8wLDh7T4+ZYhc8GFWYApLgG7FrjI55tuGZELPtsUBqODz77OwlUUf+ngPgHN09zxGLg== - dependencies: - generaterr "^1.5.0" - passport-local "^1.0.0" - scmp "^2.1.0" - passport-local@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/passport-local/-/passport-local-1.0.0.tgz#1fe63268c92e75606626437e3b906662c15ba6ee" @@ -4526,10 +4608,10 @@ pause@0.0.1: resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d" integrity sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg== -payload@^1.6.4: - version "1.6.4" - resolved "https://registry.yarnpkg.com/payload/-/payload-1.6.4.tgz#dea570003d6011ad61c45b8c24ef1bdc5abccb2e" - integrity sha512-IzxYvO8/cqgWfyRIZjzv7iF9GKkjEZ/kfxxmAO90mFyZ26UkuQezTl+AyOMIkxP1bHVwO9AMnOD8WVqIiLgX6g== +payload@^1.11.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/payload/-/payload-1.11.0.tgz#9f2a16c343c9733ee8e22f94b343fcf5f222801c" + integrity sha512-rs7Cgyg07Aa4/wsA2PG9UFYx4fQSvw1WJz6H9iut32jvEB553RBaZsquKUA0XYPDFlmQFCvjcP5LUYTrjgcnRg== dependencies: "@date-io/date-fns" "^2.16.0" "@dnd-kit/core" "^6.0.7" @@ -4537,7 +4619,7 @@ payload@^1.6.4: "@faceless-ui/modal" "^2.0.1" "@faceless-ui/scroll-info" "^1.3.0" "@faceless-ui/window-info" "^2.1.1" - "@monaco-editor/react" "^4.4.6" + "@monaco-editor/react" "^4.5.1" "@swc/core" "^1.3.26" "@swc/register" "^0.1.10" "@types/sharp" "^0.31.1" @@ -4547,7 +4629,7 @@ payload@^1.6.4: conf "^10.2.0" connect-history-api-fallback "^1.6.0" css-loader "^5.2.7" - css-minimizer-webpack-plugin "^3.4.1" + css-minimizer-webpack-plugin "^5.0.0" dataloader "^2.1.0" date-fns "^2.29.3" deep-equal "^2.2.0" @@ -4555,14 +4637,15 @@ payload@^1.6.4: dotenv "^8.6.0" express "^4.18.2" express-fileupload "1.4.0" - express-graphql "0.12.0" express-rate-limit "^5.5.1" file-loader "^6.2.0" file-type "16.5.4" find-up "4.1.0" flatley "^5.2.0" fs-extra "^10.1.0" + get-tsconfig "^4.4.0" graphql "^16.6.0" + graphql-http "^1.17.1" graphql-playground-middleware-express "^1.7.23" graphql-query-complexity "^0.12.0" graphql-scalars "^1.20.1" @@ -4576,7 +4659,7 @@ payload@^1.6.4: is-plain-object "^5.0.0" isomorphic-fetch "^3.0.0" joi "^17.7.0" - json-schema-to-typescript "^11.0.2" + json-schema-to-typescript "11.0.3" jsonwebtoken "^9.0.0" jwt-decode "^3.1.2" md5 "^2.3.0" @@ -4585,6 +4668,7 @@ payload@^1.6.4: mini-css-extract-plugin "1.6.2" minimist "^1.2.7" mkdirp "^1.0.4" + monaco-editor "^0.38.0" mongoose "6.5.0" mongoose-aggregate-paginate-v2 "^1.0.6" mongoose-paginate-v2 "^1.6.1" @@ -4595,7 +4679,6 @@ payload@^1.6.4: passport-headerapikey "^1.2.2" passport-jwt "^4.0.1" passport-local "^1.0.0" - passport-local-mongoose "^7.1.2" path-browserify "^1.0.1" pino "^6.4.1" pino-pretty "^9.1.1" @@ -4609,36 +4692,37 @@ payload@^1.6.4: qs-middleware "^1.0.3" react "^18.2.0" react-animate-height "^2.1.2" - react-beautiful-dnd "^13.1.1" - react-datepicker "^3.8.0" - react-diff-viewer "^3.1.1" + react-datepicker "^4.10.0" + react-diff-viewer-continued "^3.2.6" react-dom "^18.2.0" react-helmet "^6.1.0" react-i18next "^11.18.6" react-router-dom "^5.3.4" react-router-navigation-prompt "^1.9.6" - react-select "^3.2.0" + react-select "^5.7.3" react-toastify "^8.2.0" sanitize-filename "^1.6.3" sass "^1.57.1" sass-loader "^12.6.0" + scheduler "^0.23.0" + scmp "^2.1.0" sharp "^0.31.3" - slate "^0.88.1" + slate "^0.91.4" slate-history "^0.86.0" slate-hyperscript "^0.81.3" - slate-react "^0.88.0" + slate-react "^0.92.0" style-loader "^2.0.0" swc-loader "^0.2.3" - swc-minify-webpack-plugin "^1.0.1" + swc-minify-webpack-plugin "^2.1.0" terser-webpack-plugin "^5.3.6" ts-essentials "^7.0.3" url-loader "^4.1.1" use-context-selector "^1.4.1" uuid "^8.3.2" - webpack "^5.75.0" - webpack-bundle-analyzer "^4.7.0" + webpack "^5.78.0" + webpack-bundle-analyzer "^4.8.0" webpack-cli "^4.10.0" - webpack-dev-middleware "^4.3.0" + webpack-dev-middleware "6.0.1" webpack-hot-middleware "^2.25.3" peek-readable@^4.1.0: @@ -4651,7 +4735,7 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -4726,11 +4810,6 @@ pluralize@^8.0.0: resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== -popper.js@^1.14.4: - version "1.16.1" - resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b" - integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ== - postcss-attribute-case-insensitive@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.2.tgz#03d761b24afc04c09e757e92ff53716ae8ea2741" @@ -4738,12 +4817,12 @@ postcss-attribute-case-insensitive@^5.0.2: dependencies: postcss-selector-parser "^6.0.10" -postcss-calc@^8.2.3: - version "8.2.4" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-8.2.4.tgz#77b9c29bfcbe8a07ff6693dc87050828889739a5" - integrity sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q== +postcss-calc@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-9.0.1.tgz#a744fd592438a93d6de0f1434c572670361eb6c6" + integrity sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ== dependencies: - postcss-selector-parser "^6.0.9" + postcss-selector-parser "^6.0.11" postcss-value-parser "^4.2.0" postcss-clamp@^4.1.0: @@ -4774,20 +4853,20 @@ postcss-color-rebeccapurple@^7.1.1: dependencies: postcss-value-parser "^4.2.0" -postcss-colormin@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.3.0.tgz#3cee9e5ca62b2c27e84fce63affc0cfb5901956a" - integrity sha512-WdDO4gOFG2Z8n4P8TWBpshnL3JpmNmJwdnfP2gbk2qBA8PWwOYcmjmI/t3CmMeL72a7Hkd+x/Mg9O2/0rD54Pg== +postcss-colormin@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-6.0.0.tgz#d4250652e952e1c0aca70c66942da93d3cdeaafe" + integrity sha512-EuO+bAUmutWoZYgHn2T1dG1pPqHU6L4TjzPlu4t1wZGXQ/fxV16xg2EJmYi0z+6r+MGV1yvpx1BHkUaRrPa2bw== dependencies: - browserslist "^4.16.6" + browserslist "^4.21.4" caniuse-api "^3.0.0" colord "^2.9.1" postcss-value-parser "^4.2.0" -postcss-convert-values@^5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz#04998bb9ba6b65aa31035d669a6af342c5f9d393" - integrity sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA== +postcss-convert-values@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-6.0.0.tgz#ec94a954957e5c3f78f0e8f65dfcda95280b8996" + integrity sha512-U5D8QhVwqT++ecmy8rnTb+RL9n/B806UVaS3m60lqle4YDFcpbS3ae5bTQIh3wOGUSDHSEtMYLs/38dNG7EYFw== dependencies: browserslist "^4.21.4" postcss-value-parser "^4.2.0" @@ -4820,25 +4899,25 @@ postcss-dir-pseudo-class@^6.0.5: dependencies: postcss-selector-parser "^6.0.10" -postcss-discard-comments@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz#8df5e81d2925af2780075840c1526f0660e53696" - integrity sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ== +postcss-discard-comments@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-6.0.0.tgz#9ca335e8b68919f301b24ba47dde226a42e535fe" + integrity sha512-p2skSGqzPMZkEQvJsgnkBhCn8gI7NzRH2683EEjrIkoMiwRELx68yoUJ3q3DGSGuQ8Ug9Gsn+OuDr46yfO+eFw== -postcss-discard-duplicates@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz#9eb4fe8456706a4eebd6d3b7b777d07bad03e848" - integrity sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw== +postcss-discard-duplicates@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-6.0.0.tgz#c26177a6c33070922e67e9a92c0fd23d443d1355" + integrity sha512-bU1SXIizMLtDW4oSsi5C/xHKbhLlhek/0/yCnoMQany9k3nPBq+Ctsv/9oMmyqbR96HYHxZcHyK2HR5P/mqoGA== -postcss-discard-empty@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz#e57762343ff7f503fe53fca553d18d7f0c369c6c" - integrity sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A== +postcss-discard-empty@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-6.0.0.tgz#06c1c4fce09e22d2a99e667c8550eb8a3a1b9aee" + integrity sha512-b+h1S1VT6dNhpcg+LpyiUrdnEZfICF0my7HAKgJixJLW7BnNmpRH34+uw/etf5AhOlIhIAuXApSzzDzMI9K/gQ== -postcss-discard-overridden@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz#7e8c5b53325747e9d90131bb88635282fb4a276e" - integrity sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw== +postcss-discard-overridden@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-6.0.0.tgz#49c5262db14e975e349692d9024442de7cd8e234" + integrity sha512-4VELwssYXDFigPYAZ8vL4yX4mUepF/oCBeeIT4OXsJPYOtvJumyz9WflmJWTfDwCUcpDR+z0zvCWBXgTx35SVw== postcss-double-position-gradients@^3.1.2: version "3.1.2" @@ -4918,53 +4997,53 @@ postcss-media-minmax@^5.0.0: resolved "https://registry.yarnpkg.com/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz#7140bddec173e2d6d657edbd8554a55794e2a5b5" integrity sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ== -postcss-merge-longhand@^5.1.7: - version "5.1.7" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz#24a1bdf402d9ef0e70f568f39bdc0344d568fb16" - integrity sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ== +postcss-merge-longhand@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-6.0.0.tgz#6f627b27db939bce316eaa97e22400267e798d69" + integrity sha512-4VSfd1lvGkLTLYcxFuISDtWUfFS4zXe0FpF149AyziftPFQIWxjvFSKhA4MIxMe4XM3yTDgQMbSNgzIVxChbIg== dependencies: postcss-value-parser "^4.2.0" - stylehacks "^5.1.1" + stylehacks "^6.0.0" -postcss-merge-rules@^5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.1.3.tgz#8f97679e67cc8d08677a6519afca41edf2220894" - integrity sha512-LbLd7uFC00vpOuMvyZop8+vvhnfRGpp2S+IMQKeuOZZapPRY4SMq5ErjQeHbHsjCUgJkRNrlU+LmxsKIqPKQlA== +postcss-merge-rules@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-6.0.1.tgz#39f165746404e646c0f5c510222ccde4824a86aa" + integrity sha512-a4tlmJIQo9SCjcfiCcCMg/ZCEe0XTkl/xK0XHBs955GWg9xDX3NwP9pwZ78QUOWB8/0XCjZeJn98Dae0zg6AAw== dependencies: browserslist "^4.21.4" caniuse-api "^3.0.0" - cssnano-utils "^3.1.0" + cssnano-utils "^4.0.0" postcss-selector-parser "^6.0.5" -postcss-minify-font-values@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz#f1df0014a726083d260d3bd85d7385fb89d1f01b" - integrity sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA== +postcss-minify-font-values@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-6.0.0.tgz#68d4a028f9fa5f61701974724b2cc9445d8e6070" + integrity sha512-zNRAVtyh5E8ndZEYXA4WS8ZYsAp798HiIQ1V2UF/C/munLp2r1UGHwf1+6JFu7hdEhJFN+W1WJQKBrtjhFgEnA== dependencies: postcss-value-parser "^4.2.0" -postcss-minify-gradients@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz#f1fe1b4f498134a5068240c2f25d46fcd236ba2c" - integrity sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw== +postcss-minify-gradients@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-6.0.0.tgz#22b5c88cc63091dadbad34e31ff958404d51d679" + integrity sha512-wO0F6YfVAR+K1xVxF53ueZJza3L+R3E6cp0VwuXJQejnNUH0DjcAFe3JEBeTY1dLwGa0NlDWueCA1VlEfiKgAA== dependencies: colord "^2.9.1" - cssnano-utils "^3.1.0" + cssnano-utils "^4.0.0" postcss-value-parser "^4.2.0" -postcss-minify-params@^5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz#c06a6c787128b3208b38c9364cfc40c8aa5d7352" - integrity sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw== +postcss-minify-params@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-6.0.0.tgz#2b3a85a9e3b990d7a16866f430f5fd1d5961b539" + integrity sha512-Fz/wMQDveiS0n5JPcvsMeyNXOIMrwF88n7196puSuQSWSa+/Ofc1gDOSY2xi8+A4PqB5dlYCKk/WfqKqsI+ReQ== dependencies: browserslist "^4.21.4" - cssnano-utils "^3.1.0" + cssnano-utils "^4.0.0" postcss-value-parser "^4.2.0" -postcss-minify-selectors@^5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz#d4e7e6b46147b8117ea9325a915a801d5fe656c6" - integrity sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg== +postcss-minify-selectors@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-6.0.0.tgz#5046c5e8680a586e5a0cad52cc9aa36d6be5bda2" + integrity sha512-ec/q9JNCOC2CRDNnypipGfOhbYPuUkewGwLnbv6omue/PSASbHSU7s6uSQ0tcFRVv731oMIx8k0SP4ZX6be/0g== dependencies: postcss-selector-parser "^6.0.5" @@ -5004,66 +5083,65 @@ postcss-nesting@^10.2.0: "@csstools/selector-specificity" "^2.0.0" postcss-selector-parser "^6.0.10" -postcss-normalize-charset@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz#9302de0b29094b52c259e9b2cf8dc0879879f0ed" - integrity sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg== +postcss-normalize-charset@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-6.0.0.tgz#36cc12457259064969fb96f84df491652a4b0975" + integrity sha512-cqundwChbu8yO/gSWkuFDmKrCZ2vJzDAocheT2JTd0sFNA4HMGoKMfbk2B+J0OmO0t5GUkiAkSM5yF2rSLUjgQ== -postcss-normalize-display-values@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz#72abbae58081960e9edd7200fcf21ab8325c3da8" - integrity sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA== +postcss-normalize-display-values@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-6.0.0.tgz#8d2961415078644d8c6bbbdaf9a2fdd60f546cd4" + integrity sha512-Qyt5kMrvy7dJRO3OjF7zkotGfuYALETZE+4lk66sziWSPzlBEt7FrUshV6VLECkI4EN8Z863O6Nci4NXQGNzYw== dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-positions@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz#ef97279d894087b59325b45c47f1e863daefbb92" - integrity sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg== +postcss-normalize-positions@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-6.0.0.tgz#25b96df99a69f8925f730eaee0be74416865e301" + integrity sha512-mPCzhSV8+30FZyWhxi6UoVRYd3ZBJgTRly4hOkaSifo0H+pjDYcii/aVT4YE6QpOil15a5uiv6ftnY3rm0igPg== dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-repeat-style@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz#e9eb96805204f4766df66fd09ed2e13545420fb2" - integrity sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g== +postcss-normalize-repeat-style@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-6.0.0.tgz#ddf30ad8762feb5b1eb97f39f251acd7b8353299" + integrity sha512-50W5JWEBiOOAez2AKBh4kRFm2uhrT3O1Uwdxz7k24aKtbD83vqmcVG7zoIwo6xI2FZ/HDlbrCopXhLeTpQib1A== dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-string@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz#411961169e07308c82c1f8c55f3e8a337757e228" - integrity sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w== +postcss-normalize-string@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-6.0.0.tgz#948282647a51e409d69dde7910f0ac2ff97cb5d8" + integrity sha512-KWkIB7TrPOiqb8ZZz6homet2KWKJwIlysF5ICPZrXAylGe2hzX/HSf4NTX2rRPJMAtlRsj/yfkrWGavFuB+c0w== dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-timing-functions@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz#d5614410f8f0b2388e9f240aa6011ba6f52dafbb" - integrity sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg== +postcss-normalize-timing-functions@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-6.0.0.tgz#5f13e650b8c43351989fc5de694525cc2539841c" + integrity sha512-tpIXWciXBp5CiFs8sem90IWlw76FV4oi6QEWfQwyeREVwUy39VSeSqjAT7X0Qw650yAimYW5gkl2Gd871N5SQg== dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-unicode@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz#f67297fca3fea7f17e0d2caa40769afc487aa030" - integrity sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA== +postcss-normalize-unicode@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-6.0.0.tgz#741b3310f874616bdcf07764f5503695d3604730" + integrity sha512-ui5crYkb5ubEUDugDc786L/Me+DXp2dLg3fVJbqyAl0VPkAeALyAijF2zOsnZyaS1HyfPuMH0DwyY18VMFVNkg== dependencies: browserslist "^4.21.4" postcss-value-parser "^4.2.0" -postcss-normalize-url@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz#ed9d88ca82e21abef99f743457d3729a042adcdc" - integrity sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew== +postcss-normalize-url@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-6.0.0.tgz#d0a31e962a16401fb7deb7754b397a323fb650b4" + integrity sha512-98mvh2QzIPbb02YDIrYvAg4OUzGH7s1ZgHlD3fIdTHLgPLRpv1ZTKJDnSAKr4Rt21ZQFzwhGMXxpXlfrUBKFHw== dependencies: - normalize-url "^6.0.1" postcss-value-parser "^4.2.0" -postcss-normalize-whitespace@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz#08a1a0d1ffa17a7cc6efe1e6c9da969cc4493cfa" - integrity sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA== +postcss-normalize-whitespace@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-6.0.0.tgz#accb961caa42e25ca4179b60855b79b1f7129d4d" + integrity sha512-7cfE1AyLiK0+ZBG6FmLziJzqQCpTQY+8XjMhMAz8WSBSCsCNNUKujgIgjCAmDT3cJ+3zjTXFkoD15ZPsckArVw== dependencies: postcss-value-parser "^4.2.0" @@ -5072,12 +5150,12 @@ postcss-opacity-percentage@^1.1.2: resolved "https://registry.yarnpkg.com/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.3.tgz#5b89b35551a556e20c5d23eb5260fbfcf5245da6" integrity sha512-An6Ba4pHBiDtyVpSLymUUERMo2cU7s+Obz6BTrS+gxkbnSBNKSuD0AVUc+CpBMrpVPKKfoVz0WQCX+Tnst0i4A== -postcss-ordered-values@^5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz#b6fd2bd10f937b23d86bc829c69e7732ce76ea38" - integrity sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ== +postcss-ordered-values@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-6.0.0.tgz#374704cdff25560d44061d17ba3c6308837a3218" + integrity sha512-K36XzUDpvfG/nWkjs6d1hRBydeIxGpKS2+n+ywlKPzx1nMYDYpoGbcjhj5AwVYJK1qV2/SDoDEnHzlPD6s3nMg== dependencies: - cssnano-utils "^3.1.0" + cssnano-utils "^4.0.0" postcss-value-parser "^4.2.0" postcss-overflow-shorthand@^3.0.4: @@ -5161,18 +5239,18 @@ postcss-pseudo-class-any-link@^7.1.6: dependencies: postcss-selector-parser "^6.0.10" -postcss-reduce-initial@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-5.1.1.tgz#c18b7dfb88aee24b1f8e4936541c29adbd35224e" - integrity sha512-//jeDqWcHPuXGZLoolFrUXBDyuEGbr9S2rMo19bkTIjBQ4PqkaO+oI8wua5BOUxpfi97i3PCoInsiFIEBfkm9w== +postcss-reduce-initial@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-6.0.0.tgz#7d16e83e60e27e2fa42f56ec0b426f1da332eca7" + integrity sha512-s2UOnidpVuXu6JiiI5U+fV2jamAw5YNA9Fdi/GRK0zLDLCfXmSGqQtzpUPtfN66RtCbb9fFHoyZdQaxOB3WxVA== dependencies: browserslist "^4.21.4" caniuse-api "^3.0.0" -postcss-reduce-transforms@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz#333b70e7758b802f3dd0ddfe98bb1ccfef96b6e9" - integrity sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ== +postcss-reduce-transforms@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-6.0.0.tgz#28ff2601a6d9b96a2f039b3501526e1f4d584a46" + integrity sha512-FQ9f6xM1homnuy1wLe9lP1wujzxnwt1EwiigtWwuyf8FsqqXUDUp2Ulxf9A5yjlUOTdCJO6lonYjg1mgqIIi2w== dependencies: postcss-value-parser "^4.2.0" @@ -5196,18 +5274,26 @@ postcss-selector-parser@^6.0.10, postcss-selector-parser@^6.0.2, postcss-selecto cssesc "^3.0.0" util-deprecate "^1.0.2" -postcss-svgo@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-5.1.0.tgz#0a317400ced789f233a28826e77523f15857d80d" - integrity sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA== +postcss-selector-parser@^6.0.11: + version "6.0.13" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz#d05d8d76b1e8e173257ef9d60b706a8e5e99bf1b" + integrity sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-svgo@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-6.0.0.tgz#7b18742d38d4505a0455bbe70d52b49f00eaf69d" + integrity sha512-r9zvj/wGAoAIodn84dR/kFqwhINp5YsJkLoujybWG59grR/IHx+uQ2Zo+IcOwM0jskfYX3R0mo+1Kip1VSNcvw== dependencies: postcss-value-parser "^4.2.0" - svgo "^2.7.0" + svgo "^3.0.2" -postcss-unique-selectors@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz#a9f273d1eacd09e9aa6088f4b0507b18b1b541b6" - integrity sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA== +postcss-unique-selectors@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-6.0.0.tgz#c94e9b0f7bffb1203894e42294b5a1b3fb34fbe1" + integrity sha512-EPQzpZNxOxP7777t73RQpZE5e9TrnCrkvp7AH7a0l89JmZiPnS82y216JowHXwpBCQitfyxrof9TK3rYbi7/Yw== dependencies: postcss-selector-parser "^6.0.5" @@ -5216,7 +5302,7 @@ postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss@^8.2.15, postcss@^8.3.5, postcss@^8.4.21: +postcss@^8.2.15, postcss@^8.4.21: version "8.4.21" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.21.tgz#c639b719a57efc3187b13a1d765675485f4134f4" integrity sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg== @@ -5225,6 +5311,15 @@ postcss@^8.2.15, postcss@^8.3.5, postcss@^8.4.21: picocolors "^1.0.0" source-map-js "^1.0.2" +postcss@^8.4.24: + version "8.4.24" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.24.tgz#f714dba9b2284be3cc07dbd2fc57ee4dc972d2df" + integrity sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg== + dependencies: + nanoid "^3.3.6" + picocolors "^1.0.0" + source-map-js "^1.0.2" + prebuild-install@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.1.1.tgz#de97d5b34a70a0c81334fd24641f2a1702352e45" @@ -5297,7 +5392,7 @@ process@^0.11.10: resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== -prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -5361,11 +5456,6 @@ quick-format-unescaped@^4.0.3: resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7" integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg== -raf-schd@^4.0.2: - version "4.0.3" - resolved "https://registry.yarnpkg.com/raf-schd/-/raf-schd-4.0.3.tgz#5d6c34ef46f8b2a0e880a8fcdb743efc5bfdbc1a" - integrity sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ== - randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -5378,7 +5468,7 @@ range-parser@^1.2.1, range-parser@~1.2.1: resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -raw-body@2.5.1, raw-body@^2.4.1: +raw-body@2.5.1: version "2.5.1" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== @@ -5406,41 +5496,28 @@ react-animate-height@^2.1.2: classnames "^2.2.5" prop-types "^15.6.1" -react-beautiful-dnd@^13.1.1: - version "13.1.1" - resolved "https://registry.yarnpkg.com/react-beautiful-dnd/-/react-beautiful-dnd-13.1.1.tgz#b0f3087a5840920abf8bb2325f1ffa46d8c4d0a2" - integrity sha512-0Lvs4tq2VcrEjEgDXHjT98r+63drkKEgqyxdA7qD3mvKwga6a5SscbdLPO2IExotU1jW8L0Ksdl0Cj2AF67nPQ== - dependencies: - "@babel/runtime" "^7.9.2" - css-box-model "^1.2.0" - memoize-one "^5.1.1" - raf-schd "^4.0.2" - react-redux "^7.2.0" - redux "^4.0.4" - use-memo-one "^1.1.1" - -react-datepicker@^3.8.0: - version "3.8.0" - resolved "https://registry.yarnpkg.com/react-datepicker/-/react-datepicker-3.8.0.tgz#c3bccd3e3f47aa66864a2fa75651be097414430b" - integrity sha512-iFVNEp8DJoX5yEvEiciM7sJKmLGrvE70U38KhpG13XrulNSijeHw1RZkhd/0UmuXR71dcZB/kdfjiidifstZjw== +react-datepicker@^4.10.0: + version "4.15.0" + resolved "https://registry.yarnpkg.com/react-datepicker/-/react-datepicker-4.15.0.tgz#489834773fbcf87852273b4642f0c5bd3811cef7" + integrity sha512-kysEqVv6wRQkmAyn0wJi4Xx+JjBPBtXWfQSfh6sR3wdzZX1/LjYTPmaurnVI6ao177ecompg8ze7NCgtEGW78A== dependencies: + "@popperjs/core" "^2.9.2" classnames "^2.2.6" - date-fns "^2.0.1" + date-fns "^2.24.0" prop-types "^15.7.2" - react-onclickoutside "^6.10.0" - react-popper "^1.3.8" + react-onclickoutside "^6.12.2" + react-popper "^2.3.0" -react-diff-viewer@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/react-diff-viewer/-/react-diff-viewer-3.1.1.tgz#21ac9c891193d05a3734bfd6bd54b107ee6d46cc" - integrity sha512-rmvwNdcClp6ZWdS11m1m01UnBA4OwYaLG/li0dB781e/bQEzsGyj+qewVd6W5ztBwseQ72pO7nwaCcq5jnlzcw== +react-diff-viewer-continued@^3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/react-diff-viewer-continued/-/react-diff-viewer-continued-3.2.6.tgz#96382463b5de6838d95323c407442349b1c3a26e" + integrity sha512-GrzyqQnjIMoej+jMjWvtVSsQqhXgzEGqpXlJ2dAGfOk7Q26qcm8Gu6xtI430PBUyZsERe8BJSQf+7VZZo8IBNQ== dependencies: - classnames "^2.2.6" - create-emotion "^10.0.14" - diff "^4.0.1" - emotion "^10.0.14" - memoize-one "^5.0.4" - prop-types "^15.6.2" + "@emotion/css" "^11.10.5" + classnames "^2.3.1" + diff "^5.1.0" + memoize-one "^6.0.0" + prop-types "^15.8.1" react-dom@^18.2.0: version "18.2.0" @@ -5450,6 +5527,11 @@ react-dom@^18.2.0: loose-envify "^1.1.0" scheduler "^0.23.0" +react-fast-compare@^3.0.1: + version "3.2.2" + resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.2.tgz#929a97a532304ce9fee4bcae44234f1ce2c21d49" + integrity sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ== + react-fast-compare@^3.1.1: version "3.2.0" resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" @@ -5473,53 +5555,24 @@ react-i18next@^11.18.6: "@babel/runtime" "^7.14.5" html-parse-stringify "^3.0.1" -react-input-autosize@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-3.0.0.tgz#6b5898c790d4478d69420b55441fcc31d5c50a85" - integrity sha512-nL9uS7jEs/zu8sqwFE5MAPx6pPkNAriACQ2rGLlqmKr2sPGtN7TXTyDdQt4lbNXVx7Uzadb40x8qotIuru6Rhg== - dependencies: - prop-types "^15.5.8" - react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== -react-is@^17.0.2: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" - integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== +react-onclickoutside@^6.12.2: + version "6.13.0" + resolved "https://registry.yarnpkg.com/react-onclickoutside/-/react-onclickoutside-6.13.0.tgz#e165ea4e5157f3da94f4376a3ab3e22a565f4ffc" + integrity sha512-ty8So6tcUpIb+ZE+1HAhbLROvAIJYyJe/1vRrrcmW+jLsaM+/powDRqxzo6hSh9CuRZGSL1Q8mvcF5WRD93a0A== -react-onclickoutside@^6.10.0: - version "6.12.2" - resolved "https://registry.yarnpkg.com/react-onclickoutside/-/react-onclickoutside-6.12.2.tgz#8e6cf80c7d17a79f2c908399918158a7b02dda01" - integrity sha512-NMXGa223OnsrGVp5dJHkuKxQ4czdLmXSp5jSV9OqiCky9LOpPATn3vLldc+q5fK3gKbEHvr7J1u0yhBh/xYkpA== - -react-popper@^1.3.8: - version "1.3.11" - resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-1.3.11.tgz#a2cc3f0a67b75b66cfa62d2c409f9dd1fcc71ffd" - integrity sha512-VSA/bS+pSndSF2fiasHK/PTEEAyOpX60+H5EPAjoArr8JGm+oihu4UbrqcEBpQibJxBVCpYyjAX7abJ+7DoYVg== +react-popper@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-2.3.0.tgz#17891c620e1320dce318bad9fede46a5f71c70ba" + integrity sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q== dependencies: - "@babel/runtime" "^7.1.2" - "@hypnosphi/create-react-context" "^0.3.1" - deep-equal "^1.1.1" - popper.js "^1.14.4" - prop-types "^15.6.1" - typed-styles "^0.0.7" + react-fast-compare "^3.0.1" warning "^4.0.2" -react-redux@^7.2.0: - version "7.2.9" - resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.9.tgz#09488fbb9416a4efe3735b7235055442b042481d" - integrity sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ== - dependencies: - "@babel/runtime" "^7.15.4" - "@types/react-redux" "^7.1.20" - hoist-non-react-statics "^3.3.2" - loose-envify "^1.4.0" - prop-types "^15.7.2" - react-is "^17.0.2" - react-router-dom@^5.3.4: version "5.3.4" resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.3.4.tgz#2ed62ffd88cae6db134445f4a0c0ae8b91d2e5e6" @@ -5553,19 +5606,20 @@ react-router@5.3.4: tiny-invariant "^1.0.2" tiny-warning "^1.0.0" -react-select@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/react-select/-/react-select-3.2.0.tgz#de9284700196f5f9b5277c5d850a9ce85f5c72fe" - integrity sha512-B/q3TnCZXEKItO0fFN/I0tWOX3WJvi/X2wtdffmwSQVRwg5BpValScTO1vdic9AxlUgmeSzib2hAZAwIUQUZGQ== +react-select@^5.7.3: + version "5.7.3" + resolved "https://registry.yarnpkg.com/react-select/-/react-select-5.7.3.tgz#fa0dc9a23cad6ff3871ad3829f6083a4b54961a2" + integrity sha512-z8i3NCuFFWL3w27xq92rBkVI2onT0jzIIPe480HlBjXJ3b5o6Q+Clp4ydyeKrj9DZZ3lrjawwLC5NGl0FSvUDg== dependencies: - "@babel/runtime" "^7.4.4" - "@emotion/cache" "^10.0.9" - "@emotion/core" "^10.0.9" - "@emotion/css" "^10.0.9" - memoize-one "^5.0.0" + "@babel/runtime" "^7.12.0" + "@emotion/cache" "^11.4.0" + "@emotion/react" "^11.8.1" + "@floating-ui/dom" "^1.0.1" + "@types/react-transition-group" "^4.4.0" + memoize-one "^6.0.0" prop-types "^15.6.0" - react-input-autosize "^3.0.0" react-transition-group "^4.3.0" + use-isomorphic-layout-effect "^1.1.2" react-side-effect@^2.1.0: version "2.1.2" @@ -5659,19 +5713,12 @@ rechoir@^0.7.0: dependencies: resolve "^1.9.0" -redux@^4.0.0, redux@^4.0.4: - version "4.2.1" - resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.1.tgz#c08f4306826c49b5e9dc901dee0452ea8fce6197" - integrity sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w== - dependencies: - "@babel/runtime" "^7.9.2" - regenerator-runtime@^0.13.11: version "0.13.11" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== -regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.4.3: +regexp.prototype.flags@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== @@ -5733,7 +5780,21 @@ resolve-pathname@^3.0.0: resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd" integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng== -resolve@^1.12.0, resolve@^1.20.0, resolve@^1.22.1, resolve@^1.9.0: +resolve-pkg-maps@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" + integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== + +resolve@^1.19.0: + version "1.22.2" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" + integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== + dependencies: + is-core-module "^2.11.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +resolve@^1.20.0, resolve@^1.22.1, resolve@^1.9.0: version "1.22.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== @@ -5828,7 +5889,7 @@ scheduler@^0.23.0: dependencies: loose-envify "^1.1.0" -schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: +schema-utils@^3.0.0, schema-utils@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== @@ -5837,6 +5898,15 @@ schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: ajv "^6.12.5" ajv-keywords "^3.5.2" +schema-utils@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" + integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + schema-utils@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7" @@ -5847,6 +5917,16 @@ schema-utils@^4.0.0: ajv-formats "^2.1.1" ajv-keywords "^5.0.0" +schema-utils@^4.0.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.2.0.tgz#70d7c93e153a273a805801882ebd3bff20d89c8b" + integrity sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw== + dependencies: + "@types/json-schema" "^7.0.9" + ajv "^8.9.0" + ajv-formats "^2.1.1" + ajv-keywords "^5.1.0" + scmp@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/scmp/-/scmp-2.1.0.tgz#37b8e197c425bdeb570ab91cc356b311a11f9c9a" @@ -5900,7 +5980,7 @@ send@0.18.0: range-parser "~1.2.1" statuses "2.0.1" -serialize-javascript@^6.0.0: +serialize-javascript@^6.0.0, serialize-javascript@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.1.tgz#b206efb27c3da0b0ab6b52f48d170b7996458e5c" integrity sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w== @@ -6025,11 +6105,12 @@ slate-hyperscript@^0.81.3: dependencies: is-plain-object "^5.0.0" -slate-react@^0.88.0: - version "0.88.2" - resolved "https://registry.yarnpkg.com/slate-react/-/slate-react-0.88.2.tgz#e072d54980876ec11ca057703a0e386dd290c03e" - integrity sha512-r06i+b7c1deP9PH69D3kJLStB2cbwryCVUGC++3phG7G3Ie+qEeJ5AZqogdxtsXd2vZaVGYKEjSASd3bTnj3tw== +slate-react@^0.92.0: + version "0.92.0" + resolved "https://registry.yarnpkg.com/slate-react/-/slate-react-0.92.0.tgz#eb158ac2a33d962f48c466c4c8cc7bc14c1c6633" + integrity sha512-xEDKu5RKw5f0N95l1UeNQnrB0Pxh4JPjpIZR/BVsMo0ININnLAknR99gLo46bl/Ffql4mr7LeaxQRoXxbFtJOQ== dependencies: + "@juggle/resize-observer" "^3.4.0" "@types/is-hotkey" "^0.1.1" "@types/lodash" "^4.14.149" direction "^1.0.3" @@ -6039,10 +6120,10 @@ slate-react@^0.88.0: scroll-into-view-if-needed "^2.2.20" tiny-invariant "1.0.6" -slate@^0.88.1: - version "0.88.1" - resolved "https://registry.yarnpkg.com/slate/-/slate-0.88.1.tgz#0fc20f33b7baed7ea979fa848232c336e788cc31" - integrity sha512-DEj9RpkNwPfdh3zbE9eGpeOVGWdS8BYQt754S0Lk6IvJXOkYaxza7WEZLZl/vnp7vloMdTe24zccyxywA3XK8g== +slate@^0.91.4: + version "0.91.4" + resolved "https://registry.yarnpkg.com/slate/-/slate-0.91.4.tgz#759764d63c8a8a7aff29a29e598e593ed80277f9" + integrity sha512-aUJ3rpjrdi5SbJ5G1Qjr3arytfRkEStTmHjBfWq2A2Q8MybacIzkScSvGJjQkdTk3djCK9C9SEOt39sSeZFwTw== dependencies: immer "^9.0.6" is-plain-object "^5.0.0" @@ -6081,7 +6162,7 @@ source-list-map@^2.0.0: resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== -"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2: +"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.1, source-map-js@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== @@ -6099,7 +6180,7 @@ source-map@^0.5.7: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: +source-map@^0.6.0, source-map@~0.6.0, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== @@ -6116,11 +6197,6 @@ split2@^4.0.0: resolved "https://registry.yarnpkg.com/split2/-/split2-4.1.0.tgz#101907a24370f85bb782f08adaabe4e281ecf809" integrity sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ== -stable@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" - integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== - state-local@^1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/state-local/-/state-local-1.0.7.tgz#da50211d07f05748d53009bee46307a37db386d5" @@ -6131,11 +6207,6 @@ statuses@2.0.1: resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== -"statuses@>= 1.5.0 < 2": - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== - stop-iteration-iterator@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz#6a60be0b4ee757d1ed5254858ec66b10c49285e4" @@ -6239,14 +6310,19 @@ style-loader@^2.0.0: loader-utils "^2.0.0" schema-utils "^3.0.0" -stylehacks@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-5.1.1.tgz#7934a34eb59d7152149fa69d6e9e56f2fc34bcc9" - integrity sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw== +stylehacks@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-6.0.0.tgz#9fdd7c217660dae0f62e14d51c89f6c01b3cb738" + integrity sha512-+UT589qhHPwz6mTlCLSt/vMNTJx8dopeJlZAlBMJPWA3ORqu6wmQY7FBXf+qD+FsqoBJODyqNxOUP3jdntFRdw== dependencies: browserslist "^4.21.4" postcss-selector-parser "^6.0.4" +stylis@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.2.0.tgz#79daee0208964c8fe695a42fcffcac633a211a51" + integrity sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw== + supports-color@^5.3.0, supports-color@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -6273,28 +6349,27 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -svgo@^2.7.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.8.0.tgz#4ff80cce6710dc2795f0c7c74101e6764cfccd24" - integrity sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg== +svgo@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-3.0.2.tgz#5e99eeea42c68ee0dc46aa16da093838c262fe0a" + integrity sha512-Z706C1U2pb1+JGP48fbazf3KxHrWOsLme6Rv7imFBn5EnuanDW1GPaA/P1/dvObE670JDePC3mnj0k0B7P0jjQ== dependencies: "@trysound/sax" "0.2.0" commander "^7.2.0" - css-select "^4.1.3" - css-tree "^1.1.3" - csso "^4.2.0" + css-select "^5.1.0" + css-tree "^2.2.1" + csso "^5.0.5" picocolors "^1.0.0" - stable "^0.1.8" swc-loader@^0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/swc-loader/-/swc-loader-0.2.3.tgz#6792f1c2e4c9ae9bf9b933b3e010210e270c186d" integrity sha512-D1p6XXURfSPleZZA/Lipb3A8pZ17fP4NObZvFCDjK/OKljroqDpPmsBdTraWhVBqUNpcWBQY1imWdoPScRlQ7A== -swc-minify-webpack-plugin@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/swc-minify-webpack-plugin/-/swc-minify-webpack-plugin-1.0.1.tgz#8a19b88717e3bcaf13c0c559a5ac3537291f5deb" - integrity sha512-Zeg50WoMQc7gMbPoXryyXU4suxsQ4QBJb3Lsg3l2uFSLZ3ATDkXE4CUv1sGdyNsOGt9YIuc3aSnz9z+BoUHPSg== +swc-minify-webpack-plugin@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/swc-minify-webpack-plugin/-/swc-minify-webpack-plugin-2.1.1.tgz#2c63fe592d49541733d7557b3af8f97c7ffa78b9" + integrity sha512-/9ud/libNWUC5p71vXWhW/O2Nc0essW8D9pY4P4ol0ceM8OcFbNr41R9YFqTkmktqUL2t0WwXau+FkR4T1+PJA== tabbable@^5.3.3: version "5.3.3" @@ -6327,7 +6402,7 @@ tar-stream@^2.1.4: inherits "^2.0.3" readable-stream "^3.1.1" -terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.3.6: +terser-webpack-plugin@^5.3.6: version "5.3.6" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz#5590aec31aa3c6f771ce1b1acca60639eab3195c" integrity sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ== @@ -6338,6 +6413,17 @@ terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.3.6: serialize-javascript "^6.0.0" terser "^5.14.1" +terser-webpack-plugin@^5.3.7: + version "5.3.9" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz#832536999c51b46d468067f9e37662a3b96adfe1" + integrity sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA== + dependencies: + "@jridgewell/trace-mapping" "^0.3.17" + jest-worker "^27.4.5" + schema-utils "^3.1.1" + serialize-javascript "^6.0.1" + terser "^5.16.8" + terser@^5.10.0, terser@^5.14.1: version "5.16.3" resolved "https://registry.yarnpkg.com/terser/-/terser-5.16.3.tgz#3266017a9b682edfe019b8ecddd2abaae7b39c6b" @@ -6348,6 +6434,16 @@ terser@^5.10.0, terser@^5.14.1: commander "^2.20.0" source-map-support "~0.5.20" +terser@^5.16.8: + version "5.18.2" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.18.2.tgz#ff3072a0faf21ffd38f99acc9a0ddf7b5f07b948" + integrity sha512-Ah19JS86ypbJzTzvUCX7KOsEIhDaRONungA4aYBjEP3JZRf4ocuDzTg4QWZnPn9DEMiMYGJPiSOy7aykoCc70w== + dependencies: + "@jridgewell/source-map" "^0.3.3" + acorn "^8.8.2" + commander "^2.20.0" + source-map-support "~0.5.20" + text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -6388,7 +6484,7 @@ tiny-invariant@1.0.6: resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.0.6.tgz#b3f9b38835e36a41c843a3b0907a5a7b3755de73" integrity sha512-FOyLWWVjG+aC0UqG76V53yAWdXfH8bO6FNmyZOuUrzDzK8DI3/JRY25UD7+g49JWM1LXwymsKERB+DzI0dTEQA== -tiny-invariant@^1.0.2, tiny-invariant@^1.0.6: +tiny-invariant@^1.0.2: version "1.3.1" resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642" integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw== @@ -6410,11 +6506,6 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -toidentifier@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" - integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== - toidentifier@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" @@ -6554,11 +6645,6 @@ typed-array-length@^1.0.4: for-each "^0.3.3" is-typed-array "^1.1.9" -typed-styles@^0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/typed-styles/-/typed-styles-0.0.7.tgz#93392a008794c4595119ff62dde6809dbc40a3d9" - integrity sha512-pzP0PWoZUhsECYjABgCGQlRGL1n7tOHsgwYv3oIiEpJwGhFTuty/YNeduxQYzXXa3Ge5BdT6sHYIQYpl4uJ+5Q== - typescript@^4.8.4: version "4.9.5" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" @@ -6623,10 +6709,10 @@ use-context-selector@^1.4.1: resolved "https://registry.yarnpkg.com/use-context-selector/-/use-context-selector-1.4.1.tgz#eb96279965846b72915d7f899b8e6ef1d768b0ae" integrity sha512-Io2ArvcRO+6MWIhkdfMFt+WKQX+Vb++W8DS2l03z/Vw/rz3BclKpM0ynr4LYGyU85Eke+Yx5oIhTY++QR0ZDoA== -use-memo-one@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/use-memo-one/-/use-memo-one-1.1.3.tgz#2fd2e43a2169eabc7496960ace8c79efef975e99" - integrity sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ== +use-isomorphic-layout-effect@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz#497cefb13d863d687b08477d9e5a164ad8c1a6fb" + integrity sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA== utf8-byte-length@^1.0.1: version "1.0.4" @@ -6668,7 +6754,7 @@ void-elements@3.1.0: resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09" integrity sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w== -warning@^4.0.2, warning@^4.0.3: +warning@^4.0.2: version "4.0.3" resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3" integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w== @@ -6693,11 +6779,12 @@ webidl-conversions@^7.0.0: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== -webpack-bundle-analyzer@^4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.7.0.tgz#33c1c485a7fcae8627c547b5c3328b46de733c66" - integrity sha512-j9b8ynpJS4K+zfO5GGwsAcQX4ZHpWV+yRiHDiL+bE0XHJ8NiPYLTNVQdlFYWxtpg9lfAQNlwJg16J9AJtFSXRg== +webpack-bundle-analyzer@^4.8.0: + version "4.9.0" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.9.0.tgz#fc093c4ab174fd3dcbd1c30b763f56d10141209d" + integrity sha512-+bXGmO1LyiNx0i9enBu3H8mv42sj/BJWhZNFwjz92tVnBa9J3JMGo2an2IXlEleoDOPn/Hofl5hr/xCpObUDtw== dependencies: + "@discoveryjs/json-ext" "0.5.7" acorn "^8.0.4" acorn-walk "^8.0.0" chalk "^4.1.0" @@ -6726,17 +6813,16 @@ webpack-cli@^4.10.0: rechoir "^0.7.0" webpack-merge "^5.7.3" -webpack-dev-middleware@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-4.3.0.tgz#179cc40795882cae510b1aa7f3710cbe93c9333e" - integrity sha512-PjwyVY95/bhBh6VUqt6z4THplYcsvQ8YNNBTBM873xLVmw8FLeALn0qurHbs9EmcfhzQis/eoqypSnZeuUz26w== +webpack-dev-middleware@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-6.0.1.tgz#fd585127ed44dab3f253daf0d98f4d58a5088cc2" + integrity sha512-PZPZ6jFinmqVPJZbisfggDiC+2EeGZ1ZByyMP5sOFJcPPWSexalISz+cvm+j+oYPT7FIJyxT76esjnw9DhE5sw== dependencies: - colorette "^1.2.2" - mem "^8.1.1" - memfs "^3.2.2" - mime-types "^2.1.30" + colorette "^2.0.10" + memfs "^3.4.12" + mime-types "^2.1.31" range-parser "^1.2.1" - schema-utils "^3.0.0" + schema-utils "^4.0.0" webpack-hot-middleware@^2.25.3: version "2.25.3" @@ -6768,22 +6854,22 @@ webpack-sources@^3.2.3: resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== -webpack@^5.75.0: - version "5.75.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.75.0.tgz#1e440468647b2505860e94c9ff3e44d5b582c152" - integrity sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ== +webpack@^5.78.0: + version "5.88.1" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.88.1.tgz#21eba01e81bd5edff1968aea726e2fbfd557d3f8" + integrity sha512-FROX3TxQnC/ox4N+3xQoWZzvGXSuscxR32rbzjpXgEzWudJFEJBpdlkkob2ylrv5yzzufD1zph1OoFsLtm6stQ== dependencies: "@types/eslint-scope" "^3.7.3" - "@types/estree" "^0.0.51" - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/wasm-edit" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" + "@types/estree" "^1.0.0" + "@webassemblyjs/ast" "^1.11.5" + "@webassemblyjs/wasm-edit" "^1.11.5" + "@webassemblyjs/wasm-parser" "^1.11.5" acorn "^8.7.1" - acorn-import-assertions "^1.7.6" + acorn-import-assertions "^1.9.0" browserslist "^4.14.5" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.10.0" - es-module-lexer "^0.9.0" + enhanced-resolve "^5.15.0" + es-module-lexer "^1.2.1" eslint-scope "5.1.1" events "^3.2.0" glob-to-regexp "^0.4.1" @@ -6792,9 +6878,9 @@ webpack@^5.75.0: loader-runner "^4.2.0" mime-types "^2.1.27" neo-async "^2.6.2" - schema-utils "^3.1.0" + schema-utils "^3.2.0" tapable "^2.1.1" - terser-webpack-plugin "^5.1.3" + terser-webpack-plugin "^5.3.7" watchpack "^2.4.0" webpack-sources "^3.2.3" @@ -6911,7 +6997,7 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2: +yaml@^1.10.0: version "1.10.2" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== diff --git a/examples/auth/next-app/.env.example b/examples/auth/next-app/.env.example new file mode 100644 index 000000000..bfc5ec98e --- /dev/null +++ b/examples/auth/next-app/.env.example @@ -0,0 +1 @@ +NEXT_PUBLIC_CMS_URL=http://localhost:3000 diff --git a/examples/auth/next-app/.eslintrc.js b/examples/auth/next-app/.eslintrc.js new file mode 100644 index 000000000..b22424b3e --- /dev/null +++ b/examples/auth/next-app/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + root: true, + extends: ['plugin:@next/next/recommended', '@payloadcms'], + rules: { + 'import/extensions': 'off', + }, +} diff --git a/examples/auth/nextjs/.gitignore b/examples/auth/next-app/.gitignore similarity index 100% rename from examples/auth/nextjs/.gitignore rename to examples/auth/next-app/.gitignore diff --git a/examples/auth/nextjs/.prettierrc.js b/examples/auth/next-app/.prettierrc.js similarity index 100% rename from examples/auth/nextjs/.prettierrc.js rename to examples/auth/next-app/.prettierrc.js diff --git a/examples/auth/next-app/README.md b/examples/auth/next-app/README.md new file mode 100644 index 000000000..b6623743d --- /dev/null +++ b/examples/auth/next-app/README.md @@ -0,0 +1,41 @@ +# Payload Auth Example Front-End + +This is a [Payload](https://payloadcms.com) + [Next.js](https://nextjs.org) app using the [App Router](https://nextjs.org/docs/app) made explicitly for the [Payload Auth Example](https://github.com/payloadcms/payload/tree/master/examples/auth). It demonstrates how to authenticate your Next.js app using [Payload Authentication](https://payloadcms.com/docs/authentication/overview). + +> This example uses the App Router, the latest API of Next.js. If your app is using the legacy [Pages Router](https://nextjs.org/docs/pages), check out the official [Pages Router Example](https://github.com/payloadcms/payload/tree/master/examples/auth/next-pages). + +## Getting Started + +### Payload + +First you'll need a running Payload app. If you have not done so already, clone down the [`cms`](../cms) folder and follow the setup instructions there to get it up and running. This will provide all the necessary APIs that your Next.js app will be using for authentication. + +### Next.js + +1. Clone this repo +2. `cd` into this directory and run `yarn` or `npm install` +3. `cp .env.example .env` to copy the example environment variables +4. `yarn dev` or `npm run dev` to start the server +5. `open http://localhost:3001` to see the result + +Once running, a user is automatically seeded in your local environment with some basic instructions. See the [Payload Auth Example](https://github.com/payloadcms/payload/tree/master/examples/auth) for full details. + +## Learn More + +To learn more about Payload and Next.js, take a look at the following resources: + +- [Payload Documentation](https://payloadcms.com/docs) - learn about Payload features and API. +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Payload GitHub repository](https://github.com/payloadcms/payload) as well as [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! + +## Deployment + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new) from the creators of Next.js. You could also combine this app into a [single Express server](https://github.com/payloadcms/payload/tree/master/examples/custom-server) and deploy in to [Payload Cloud](https://payloadcms.com/new/import). + +Check out our [Payload deployment documentation](https://payloadcms.com/docs/production/deployment) or the [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. + +## Questions + +If you have any issues or questions, reach out to us on [Discord](https://discord.com/invite/payload) or start a [GitHub discussion](https://github.com/payloadcms/payload/discussions). diff --git a/examples/auth/next-app/app/_components/Button/index.module.scss b/examples/auth/next-app/app/_components/Button/index.module.scss new file mode 100644 index 000000000..aa8b5ac78 --- /dev/null +++ b/examples/auth/next-app/app/_components/Button/index.module.scss @@ -0,0 +1,40 @@ +@import '../../_css/type.scss'; + +.button { + border: none; + cursor: pointer; + display: inline-flex; + justify-content: center; + background-color: transparent; + text-decoration: none; + display: inline-flex; + padding: 12px 24px; +} + +.content { + display: flex; + align-items: center; + justify-content: space-around; +} + +.label { + @extend %label; + text-align: center; + display: flex; + align-items: center; +} + +.appearance--primary { + background-color: var(--theme-elevation-1000); + color: var(--theme-elevation-0); +} + +.appearance--secondary { + background-color: transparent; + box-shadow: inset 0 0 0 1px var(--theme-elevation-1000); +} + +.appearance--default { + padding: 0; + color: var(--theme-text); +} diff --git a/examples/auth/next-app/app/_components/Button/index.tsx b/examples/auth/next-app/app/_components/Button/index.tsx new file mode 100644 index 000000000..eb4e2737b --- /dev/null +++ b/examples/auth/next-app/app/_components/Button/index.tsx @@ -0,0 +1,75 @@ +'use client' + +import React, { ElementType } from 'react' +import Link from 'next/link' + +import classes from './index.module.scss' + +export type Props = { + label?: string + appearance?: 'default' | 'primary' | 'secondary' + el?: 'button' | 'link' | 'a' + onClick?: () => void + href?: string + newTab?: boolean + className?: string + type?: 'submit' | 'button' + disabled?: boolean + invert?: boolean +} + +export const Button: React.FC = ({ + el: elFromProps = 'link', + label, + newTab, + href, + appearance, + className: classNameFromProps, + onClick, + type = 'button', + disabled, + invert, +}) => { + let el = elFromProps + const newTabProps = newTab ? { target: '_blank', rel: 'noopener noreferrer' } : {} + + const className = [ + classes.button, + classNameFromProps, + classes[`appearance--${appearance}`], + invert && classes[`${appearance}--invert`], + ] + .filter(Boolean) + .join(' ') + + const content = ( +
+ {label} +
+ ) + + if (onClick || type === 'submit') el = 'button' + + if (el === 'link') { + return ( + + {content} + + ) + } + + const Element: ElementType = el + + return ( + + {content} + + ) +} diff --git a/examples/auth/next-app/app/_components/Gutter/index.module.scss b/examples/auth/next-app/app/_components/Gutter/index.module.scss new file mode 100644 index 000000000..be9e377a7 --- /dev/null +++ b/examples/auth/next-app/app/_components/Gutter/index.module.scss @@ -0,0 +1,13 @@ +.gutter { + max-width: 1920px; + margin-left: auto; + margin-right: auto; +} + +.gutterLeft { + padding-left: var(--gutter-h); +} + +.gutterRight { + padding-right: var(--gutter-h); +} diff --git a/examples/auth/nextjs/components/Gutter/index.tsx b/examples/auth/next-app/app/_components/Gutter/index.tsx similarity index 78% rename from examples/auth/nextjs/components/Gutter/index.tsx rename to examples/auth/next-app/app/_components/Gutter/index.tsx index 74fadcbae..3cabc4ac5 100644 --- a/examples/auth/nextjs/components/Gutter/index.tsx +++ b/examples/auth/next-app/app/_components/Gutter/index.tsx @@ -16,7 +16,12 @@ export const Gutter: React.FC = forwardRef((props, return (
diff --git a/examples/auth/next-app/app/_components/Header/Nav/index.module.scss b/examples/auth/next-app/app/_components/Header/Nav/index.module.scss new file mode 100644 index 000000000..6aa7cb85c --- /dev/null +++ b/examples/auth/next-app/app/_components/Header/Nav/index.module.scss @@ -0,0 +1,20 @@ +@use '../../../_css/queries.scss' as *; + +.nav { + display: flex; + gap: calc(var(--base) / 4) var(--base); + align-items: center; + flex-wrap: wrap; + opacity: 1; + transition: opacity 100ms linear; + visibility: visible; + + > * { + text-decoration: none; + } +} + +.hide { + opacity: 0; + visibility: hidden; +} diff --git a/examples/auth/next-app/app/_components/Header/Nav/index.tsx b/examples/auth/next-app/app/_components/Header/Nav/index.tsx new file mode 100644 index 000000000..0015b0ec8 --- /dev/null +++ b/examples/auth/next-app/app/_components/Header/Nav/index.tsx @@ -0,0 +1,38 @@ +'use client' + +import React from 'react' +import Link from 'next/link' + +import { useAuth } from '../../../_providers/Auth' + +import classes from './index.module.scss' + +export const HeaderNav: React.FC = () => { + const { user } = useAuth() + + return ( + + ) +} diff --git a/examples/auth/next-app/app/_components/Header/index.module.scss b/examples/auth/next-app/app/_components/Header/index.module.scss new file mode 100644 index 000000000..9478b92ec --- /dev/null +++ b/examples/auth/next-app/app/_components/Header/index.module.scss @@ -0,0 +1,22 @@ +@use '../../_css/queries.scss' as *; + +.header { + padding: var(--base) 0; +} + +.wrap { + display: flex; + justify-content: space-between; + flex-wrap: wrap; + gap: calc(var(--base) / 2) var(--base); +} + +.logo { + width: 150px; +} + +:global([data-theme="light"]) { + .logo { + filter: invert(1); + } +} diff --git a/examples/auth/next-app/app/_components/Header/index.tsx b/examples/auth/next-app/app/_components/Header/index.tsx new file mode 100644 index 000000000..ba6015f84 --- /dev/null +++ b/examples/auth/next-app/app/_components/Header/index.tsx @@ -0,0 +1,34 @@ +import React from 'react' +import Image from 'next/image' +import Link from 'next/link' + +import { Gutter } from '../Gutter' +import { HeaderNav } from './Nav' + +import classes from './index.module.scss' + +export function Header() { + return ( +
+ + + + + Payload Logo + + + + +
+ ) +} + +export default Header diff --git a/examples/auth/next-app/app/_components/Input/index.module.scss b/examples/auth/next-app/app/_components/Input/index.module.scss new file mode 100644 index 000000000..e2dfab23b --- /dev/null +++ b/examples/auth/next-app/app/_components/Input/index.module.scss @@ -0,0 +1,56 @@ +@import '../../_css/common'; + +.inputWrap { + width: 100%; +} + +.input { + width: 100%; + font-family: system-ui; + border-radius: 0; + box-shadow: none; + border: none; + background: none; + background-color: var(--theme-elevation-100); + color: var(--theme-elevation-1000); + height: calc(var(--base) * 2); + line-height: calc(var(--base) * 2); + padding: 0 calc(var(--base) / 2); + + &:focus { + border: none; + outline: none; + } + + &:-webkit-autofill, + &:-webkit-autofill:hover, + &:-webkit-autofill:focus { + -webkit-text-fill-color: var(--theme-text); + -webkit-box-shadow: 0 0 0px 1000px var(--theme-elevation-150) inset; + transition: background-color 5000s ease-in-out 0s; + } +} + +@media (prefers-color-scheme: dark) { + .input { + background-color: var(--theme-elevation-150); + } +} + +.error { + background-color: var(--theme-error-150); +} + +.label { + margin-bottom: 0; + display: block; + line-height: 1; + margin-bottom: calc(var(--base) / 2); +} + +.errorMessage { + font-size: small; + line-height: 1.25; + margin-top: 4px; + color: red; +} diff --git a/examples/auth/next-app/app/_components/Input/index.tsx b/examples/auth/next-app/app/_components/Input/index.tsx new file mode 100644 index 000000000..771626cf0 --- /dev/null +++ b/examples/auth/next-app/app/_components/Input/index.tsx @@ -0,0 +1,55 @@ +import React from 'react' +import { FieldValues, UseFormRegister, Validate } from 'react-hook-form' + +import classes from './index.module.scss' + +type Props = { + name: string + label: string + register: UseFormRegister + required?: boolean + error: any + type?: 'text' | 'number' | 'password' | 'email' + validate?: (value: string) => boolean | string +} + +export const Input: React.FC = ({ + name, + label, + required, + register, + error, + type = 'text', + validate, +}) => { + return ( +
+ + + {error && ( +
+ {!error?.message && error?.type === 'required' + ? 'This field is required' + : error?.message} +
+ )} +
+ ) +} diff --git a/examples/auth/next-app/app/_components/Message/index.module.scss b/examples/auth/next-app/app/_components/Message/index.module.scss new file mode 100644 index 000000000..21273d940 --- /dev/null +++ b/examples/auth/next-app/app/_components/Message/index.module.scss @@ -0,0 +1,46 @@ +@import '../../_css/common'; + +.message { + padding: calc(var(--base) / 2) calc(var(--base) / 2); + line-height: 1.25; + width: 100%; +} + +.default { + background-color: var(--theme-elevation-100); + color: var(--theme-elevation-1000); +} + +.warning { + background-color: var(--theme-warning-500); + color: var(--theme-warning-900); +} + +.error { + background-color: var(--theme-error-500); + color: var(--theme-error-900); +} + +.success { + background-color: var(--theme-success-500); + color: var(--theme-success-900); +} + +@media (prefers-color-scheme: dark) { + .default { + background-color: var(--theme-elevation-900); + color: var(--theme-elevation-100); + } + + .warning { + color: var(--theme-warning-100); + } + + .error { + color: var(--theme-error-100); + } + + .success { + color: var(--theme-success-100); + } +} diff --git a/examples/auth/next-app/app/_components/Message/index.tsx b/examples/auth/next-app/app/_components/Message/index.tsx new file mode 100644 index 000000000..3cd806086 --- /dev/null +++ b/examples/auth/next-app/app/_components/Message/index.tsx @@ -0,0 +1,33 @@ +import React from 'react' + +import classes from './index.module.scss' + +export const Message: React.FC<{ + message?: React.ReactNode + error?: React.ReactNode + success?: React.ReactNode + warning?: React.ReactNode + className?: string +}> = ({ message, error, success, warning, className }) => { + const messageToRender = message || error || success || warning + + if (messageToRender) { + return ( +
+ {messageToRender} +
+ ) + } + return null +} diff --git a/examples/auth/next-app/app/_components/RenderParams/index.tsx b/examples/auth/next-app/app/_components/RenderParams/index.tsx new file mode 100644 index 000000000..b758a3fa8 --- /dev/null +++ b/examples/auth/next-app/app/_components/RenderParams/index.tsx @@ -0,0 +1,29 @@ +'use client' + +import { useSearchParams } from 'next/navigation' + +import { Message } from '../Message' + +export const RenderParams: React.FC<{ + params?: string[] + message?: string + className?: string +}> = ({ params = ['error', 'message', 'success'], message, className }) => { + const searchParams = useSearchParams() + const paramValues = params.map(param => searchParams.get(param)).filter(Boolean) + + if (paramValues.length) { + return ( +
+ {paramValues.map(paramValue => ( + + ))} +
+ ) + } + + return null +} diff --git a/examples/auth/nextjs/components/RichText/index.module.scss b/examples/auth/next-app/app/_components/RichText/index.module.scss similarity index 55% rename from examples/auth/nextjs/components/RichText/index.module.scss rename to examples/auth/next-app/app/_components/RichText/index.module.scss index 172de55c3..884b2d95b 100644 --- a/examples/auth/nextjs/components/RichText/index.module.scss +++ b/examples/auth/next-app/app/_components/RichText/index.module.scss @@ -2,4 +2,8 @@ :first-child { margin-top: 0; } + + a { + text-decoration: underline; + } } diff --git a/examples/auth/nextjs/components/RichText/index.tsx b/examples/auth/next-app/app/_components/RichText/index.tsx similarity index 100% rename from examples/auth/nextjs/components/RichText/index.tsx rename to examples/auth/next-app/app/_components/RichText/index.tsx diff --git a/examples/auth/next-app/app/_components/RichText/serialize.tsx b/examples/auth/next-app/app/_components/RichText/serialize.tsx new file mode 100644 index 000000000..1067a9815 --- /dev/null +++ b/examples/auth/next-app/app/_components/RichText/serialize.tsx @@ -0,0 +1,92 @@ +import React, { Fragment } from 'react' +import escapeHTML from 'escape-html' +import { Text } from 'slate' + +// eslint-disable-next-line no-use-before-define +type Children = Leaf[] + +type Leaf = { + type: string + value?: { + url: string + alt: string + } + children: Children + url?: string + [key: string]: unknown +} + +const serialize = (children: Children): React.ReactNode[] => + children.map((node, i) => { + if (Text.isText(node)) { + let text = + + if (node.bold) { + text = {text} + } + + if (node.code) { + text = {text} + } + + if (node.italic) { + text = {text} + } + + if (node.underline) { + text = ( + + {text} + + ) + } + + if (node.strikethrough) { + text = ( + + {text} + + ) + } + + return {text} + } + + if (!node) { + return null + } + + switch (node.type) { + case 'h1': + return

{serialize(node.children)}

+ case 'h2': + return

{serialize(node.children)}

+ case 'h3': + return

{serialize(node.children)}

+ case 'h4': + return

{serialize(node.children)}

+ case 'h5': + return
{serialize(node.children)}
+ case 'h6': + return
{serialize(node.children)}
+ case 'blockquote': + return
{serialize(node.children)}
+ case 'ul': + return
    {serialize(node.children)}
+ case 'ol': + return
    {serialize(node.children)}
+ case 'li': + return
  • {serialize(node.children)}
  • + case 'link': + return ( + + {serialize(node.children)} + + ) + + default: + return

    {serialize(node.children)}

    + } + }) + +export default serialize diff --git a/examples/preview/nextjs/css/app.scss b/examples/auth/next-app/app/_css/app.scss similarity index 67% rename from examples/preview/nextjs/css/app.scss rename to examples/auth/next-app/app/_css/app.scss index 33b29989e..fcf6af756 100644 --- a/examples/preview/nextjs/css/app.scss +++ b/examples/auth/next-app/app/_css/app.scss @@ -1,14 +1,9 @@ @use './queries.scss' as *; @use './colors.scss' as *; @use './type.scss' as *; +@import "./theme.scss"; :root { - --breakpoint-xs-width : #{$breakpoint-xs-width}; - --breakpoint-s-width : #{$breakpoint-s-width}; - --breakpoint-m-width : #{$breakpoint-m-width}; - --breakpoint-l-width : #{$breakpoint-l-width}; - --scrollbar-width: 17px; - --base: 24px; --font-body: system-ui; --font-mono: 'Roboto Mono', monospace; @@ -16,9 +11,6 @@ --gutter-h: 180px; --block-padding: 120px; - --header-z-index: 100; - --modal-z-index: 90; - @include large-break { --gutter-h: 144px; --block-padding: 96px; @@ -30,17 +22,13 @@ } } -///////////////////////////// -// GLOBAL STYLES -///////////////////////////// - * { box-sizing: border-box; } html { @extend %body; - background: var(--color-white); + background: var(--theme-bg); -webkit-font-smoothing: antialiased; } @@ -52,18 +40,18 @@ body, body { font-family: var(--font-body); - color: var(--color-black); margin: 0; + color: var(--theme-text); } ::selection { - background: var(--color-green); - color: var(--color-black); + background: var(--theme-success-500); + color: var(--color-base-800); } ::-moz-selection { - background: var(--color-green); - color: var(--color-black); + background: var(--theme-success-500); + color: var(--color-base-800); } img { diff --git a/examples/auth/next-app/app/_css/colors.scss b/examples/auth/next-app/app/_css/colors.scss new file mode 100644 index 000000000..68bcbc2d5 --- /dev/null +++ b/examples/auth/next-app/app/_css/colors.scss @@ -0,0 +1,83 @@ +:root { + --color-base-0: rgb(255, 255, 255); + --color-base-50: rgb(245, 245, 245); + --color-base-100: rgb(235, 235, 235); + --color-base-150: rgb(221, 221, 221); + --color-base-200: rgb(208, 208, 208); + --color-base-250: rgb(195, 195, 195); + --color-base-300: rgb(181, 181, 181); + --color-base-350: rgb(168, 168, 168); + --color-base-400: rgb(154, 154, 154); + --color-base-450: rgb(141, 141, 141); + --color-base-500: rgb(128, 128, 128); + --color-base-550: rgb(114, 114, 114); + --color-base-600: rgb(101, 101, 101); + --color-base-650: rgb(87, 87, 87); + --color-base-700: rgb(74, 74, 74); + --color-base-750: rgb(60, 60, 60); + --color-base-800: rgb(47, 47, 47); + --color-base-850: rgb(34, 34, 34); + --color-base-900: rgb(20, 20, 20); + --color-base-950: rgb(7, 7, 7); + --color-base-1000: rgb(0, 0, 0); + + --color-success-50: rgb(247, 255, 251); + --color-success-100: rgb(240, 255, 247); + --color-success-150: rgb(232, 255, 243); + --color-success-200: rgb(224, 255, 239); + --color-success-250: rgb(217, 255, 235); + --color-success-300: rgb(209, 255, 230); + --color-success-350: rgb(201, 255, 226); + --color-success-400: rgb(193, 255, 222); + --color-success-450: rgb(186, 255, 218); + --color-success-500: rgb(178, 255, 214); + --color-success-550: rgb(160, 230, 193); + --color-success-600: rgb(142, 204, 171); + --color-success-650: rgb(125, 179, 150); + --color-success-700: rgb(107, 153, 128); + --color-success-750: rgb(89, 128, 107); + --color-success-800: rgb(71, 102, 86); + --color-success-850: rgb(53, 77, 64); + --color-success-900: rgb(36, 51, 43); + --color-success-950: rgb(18, 25, 21); + + --color-warning-50: rgb(255, 255, 246); + --color-warning-100: rgb(255, 255, 237); + --color-warning-150: rgb(254, 255, 228); + --color-warning-200: rgb(254, 255, 219); + --color-warning-250: rgb(254, 255, 210); + --color-warning-300: rgb(254, 255, 200); + --color-warning-350: rgb(254, 255, 191); + --color-warning-400: rgb(253, 255, 182); + --color-warning-450: rgb(253, 255, 173); + --color-warning-500: rgb(253, 255, 164); + --color-warning-550: rgb(228, 230, 148); + --color-warning-600: rgb(202, 204, 131); + --color-warning-650: rgb(177, 179, 115); + --color-warning-700: rgb(152, 153, 98); + --color-warning-750: rgb(127, 128, 82); + --color-warning-800: rgb(101, 102, 66); + --color-warning-850: rgb(76, 77, 49); + --color-warning-900: rgb(51, 51, 33); + --color-warning-950: rgb(25, 25, 16); + + --color-error-50: rgb(255, 241, 241); + --color-error-100: rgb(255, 226, 228); + --color-error-150: rgb(255, 212, 214); + --color-error-200: rgb(255, 197, 200); + --color-error-250: rgb(255, 183, 187); + --color-error-300: rgb(255, 169, 173); + --color-error-350: rgb(255, 154, 159); + --color-error-400: rgb(255, 140, 145); + --color-error-450: rgb(255, 125, 132); + --color-error-500: rgb(255, 111, 118); + --color-error-550: rgb(230, 100, 106); + --color-error-600: rgb(204, 89, 94); + --color-error-650: rgb(179, 78, 83); + --color-error-700: rgb(153, 67, 71); + --color-error-750: rgb(128, 56, 59); + --color-error-800: rgb(102, 44, 47); + --color-error-850: rgb(77, 33, 35); + --color-error-900: rgb(51, 22, 24); + --color-error-950: rgb(25, 11, 12); +} diff --git a/examples/auth/nextjs/css/common.scss b/examples/auth/next-app/app/_css/common.scss similarity index 54% rename from examples/auth/nextjs/css/common.scss rename to examples/auth/next-app/app/_css/common.scss index 6b0f85715..bebb9f3aa 100644 --- a/examples/auth/nextjs/css/common.scss +++ b/examples/auth/next-app/app/_css/common.scss @@ -1,2 +1 @@ @forward './queries.scss'; -@forward './type.scss'; \ No newline at end of file diff --git a/examples/auth/nextjs/css/queries.scss b/examples/auth/next-app/app/_css/queries.scss similarity index 85% rename from examples/auth/nextjs/css/queries.scss rename to examples/auth/next-app/app/_css/queries.scss index 74f23fb0d..8f84ac709 100644 --- a/examples/auth/nextjs/css/queries.scss +++ b/examples/auth/next-app/app/_css/queries.scss @@ -3,10 +3,6 @@ $breakpoint-s-width: 768px; $breakpoint-m-width: 1024px; $breakpoint-l-width: 1440px; -//////////////////////////// -// MEDIA QUERIES -///////////////////////////// - @mixin extra-small-break { @media (max-width: #{$breakpoint-xs-width}) { @content; @@ -29,4 +25,4 @@ $breakpoint-l-width: 1440px; @media (max-width: #{$breakpoint-l-width}) { @content; } -} \ No newline at end of file +} diff --git a/examples/auth/next-app/app/_css/theme.scss b/examples/auth/next-app/app/_css/theme.scss new file mode 100644 index 000000000..0c93d334f --- /dev/null +++ b/examples/auth/next-app/app/_css/theme.scss @@ -0,0 +1,241 @@ +@media (prefers-color-scheme: light) { + :root { + --theme-success-50: var(--color-success-50); + --theme-success-100: var(--color-success-100); + --theme-success-150: var(--color-success-150); + --theme-success-200: var(--color-success-200); + --theme-success-250: var(--color-success-250); + --theme-success-300: var(--color-success-300); + --theme-success-350: var(--color-success-350); + --theme-success-400: var(--color-success-400); + --theme-success-450: var(--color-success-450); + --theme-success-500: var(--color-success-500); + --theme-success-550: var(--color-success-550); + --theme-success-600: var(--color-success-600); + --theme-success-650: var(--color-success-650); + --theme-success-700: var(--color-success-700); + --theme-success-750: var(--color-success-750); + --theme-success-800: var(--color-success-800); + --theme-success-850: var(--color-success-850); + --theme-success-900: var(--color-success-900); + --theme-success-950: var(--color-success-950); + + --theme-warning-50: var(--color-warning-50); + --theme-warning-100: var(--color-warning-100); + --theme-warning-150: var(--color-warning-150); + --theme-warning-200: var(--color-warning-200); + --theme-warning-250: var(--color-warning-250); + --theme-warning-300: var(--color-warning-300); + --theme-warning-350: var(--color-warning-350); + --theme-warning-400: var(--color-warning-400); + --theme-warning-450: var(--color-warning-450); + --theme-warning-500: var(--color-warning-500); + --theme-warning-550: var(--color-warning-550); + --theme-warning-600: var(--color-warning-600); + --theme-warning-650: var(--color-warning-650); + --theme-warning-700: var(--color-warning-700); + --theme-warning-750: var(--color-warning-750); + --theme-warning-800: var(--color-warning-800); + --theme-warning-850: var(--color-warning-850); + --theme-warning-900: var(--color-warning-900); + --theme-warning-950: var(--color-warning-950); + + --theme-error-50: var(--color-error-50); + --theme-error-100: var(--color-error-100); + --theme-error-150: var(--color-error-150); + --theme-error-200: var(--color-error-200); + --theme-error-250: var(--color-error-250); + --theme-error-300: var(--color-error-300); + --theme-error-350: var(--color-error-350); + --theme-error-400: var(--color-error-400); + --theme-error-450: var(--color-error-450); + --theme-error-500: var(--color-error-500); + --theme-error-550: var(--color-error-550); + --theme-error-600: var(--color-error-600); + --theme-error-650: var(--color-error-650); + --theme-error-700: var(--color-error-700); + --theme-error-750: var(--color-error-750); + --theme-error-800: var(--color-error-800); + --theme-error-850: var(--color-error-850); + --theme-error-900: var(--color-error-900); + --theme-error-950: var(--color-error-950); + + --theme-elevation-0: var(--color-base-0); + --theme-elevation-50: var(--color-base-50); + --theme-elevation-100: var(--color-base-100); + --theme-elevation-150: var(--color-base-150); + --theme-elevation-200: var(--color-base-200); + --theme-elevation-250: var(--color-base-250); + --theme-elevation-300: var(--color-base-300); + --theme-elevation-350: var(--color-base-350); + --theme-elevation-400: var(--color-base-400); + --theme-elevation-450: var(--color-base-450); + --theme-elevation-500: var(--color-base-500); + --theme-elevation-550: var(--color-base-550); + --theme-elevation-600: var(--color-base-600); + --theme-elevation-650: var(--color-base-650); + --theme-elevation-700: var(--color-base-700); + --theme-elevation-750: var(--color-base-750); + --theme-elevation-800: var(--color-base-800); + --theme-elevation-850: var(--color-base-850); + --theme-elevation-900: var(--color-base-900); + --theme-elevation-950: var(--color-base-950); + --theme-elevation-1000: var(--color-base-1000); + + --theme-bg: var(--theme-elevation-0); + --theme-input-bg: var(--theme-elevation-50); + --theme-text: var(--theme-elevation-750); + --theme-border-color: var(--theme-elevation-150); + + color-scheme: light; + color: var(--theme-text); + + --highlight-default-bg-color: var(--theme-success-400); + --highlight-default-text-color: var(--theme-text); + + --highlight-danger-bg-color: var(--theme-error-150); + --highlight-danger-text-color: var(--theme-text); + } + + h1 a, + h2 a, + h3 a, + h4 a, + h5 a, + h6 a { + color: var(--theme-elevation-750); + + &:hover { + color: var(--theme-elevation-800); + } + + &:visited { + color: var(--theme-elevation-750); + + &:hover { + color: var(--theme-elevation-800); + } + } + } +} + +@media (prefers-color-scheme: dark) { + :root { + --theme-elevation-0: var(--color-base-1000); + --theme-elevation-50: var(--color-base-950); + --theme-elevation-100: var(--color-base-900); + --theme-elevation-150: var(--color-base-850); + --theme-elevation-200: var(--color-base-800); + --theme-elevation-250: var(--color-base-750); + --theme-elevation-300: var(--color-base-700); + --theme-elevation-350: var(--color-base-650); + --theme-elevation-400: var(--color-base-600); + --theme-elevation-450: var(--color-base-550); + --theme-elevation-500: var(--color-base-500); + --theme-elevation-550: var(--color-base-450); + --theme-elevation-600: var(--color-base-400); + --theme-elevation-650: var(--color-base-350); + --theme-elevation-700: var(--color-base-300); + --theme-elevation-750: var(--color-base-250); + --theme-elevation-800: var(--color-base-200); + --theme-elevation-850: var(--color-base-150); + --theme-elevation-900: var(--color-base-100); + --theme-elevation-950: var(--color-base-50); + --theme-elevation-1000: var(--color-base-0); + + --theme-success-50: var(--color-success-950); + --theme-success-100: var(--color-success-900); + --theme-success-150: var(--color-success-850); + --theme-success-200: var(--color-success-800); + --theme-success-250: var(--color-success-750); + --theme-success-300: var(--color-success-700); + --theme-success-350: var(--color-success-650); + --theme-success-400: var(--color-success-600); + --theme-success-450: var(--color-success-550); + --theme-success-500: var(--color-success-500); + --theme-success-550: var(--color-success-450); + --theme-success-600: var(--color-success-400); + --theme-success-650: var(--color-success-350); + --theme-success-700: var(--color-success-300); + --theme-success-750: var(--color-success-250); + --theme-success-800: var(--color-success-200); + --theme-success-850: var(--color-success-150); + --theme-success-900: var(--color-success-100); + --theme-success-950: var(--color-success-50); + + --theme-warning-50: var(--color-warning-950); + --theme-warning-100: var(--color-warning-900); + --theme-warning-150: var(--color-warning-850); + --theme-warning-200: var(--color-warning-800); + --theme-warning-250: var(--color-warning-750); + --theme-warning-300: var(--color-warning-700); + --theme-warning-350: var(--color-warning-650); + --theme-warning-400: var(--color-warning-600); + --theme-warning-450: var(--color-warning-550); + --theme-warning-500: var(--color-warning-500); + --theme-warning-550: var(--color-warning-450); + --theme-warning-600: var(--color-warning-400); + --theme-warning-650: var(--color-warning-350); + --theme-warning-700: var(--color-warning-300); + --theme-warning-750: var(--color-warning-250); + --theme-warning-800: var(--color-warning-200); + --theme-warning-850: var(--color-warning-150); + --theme-warning-900: var(--color-warning-100); + --theme-warning-950: var(--color-warning-50); + + --theme-error-50: var(--color-error-950); + --theme-error-100: var(--color-error-900); + --theme-error-150: var(--color-error-850); + --theme-error-200: var(--color-error-800); + --theme-error-250: var(--color-error-750); + --theme-error-300: var(--color-error-700); + --theme-error-350: var(--color-error-650); + --theme-error-400: var(--color-error-600); + --theme-error-450: var(--color-error-550); + --theme-error-500: var(--color-error-500); + --theme-error-550: var(--color-error-450); + --theme-error-600: var(--color-error-400); + --theme-error-650: var(--color-error-350); + --theme-error-700: var(--color-error-300); + --theme-error-750: var(--color-error-250); + --theme-error-800: var(--color-error-200); + --theme-error-850: var(--color-error-150); + --theme-error-900: var(--color-error-100); + --theme-error-950: var(--color-error-50); + + --theme-bg: var(--theme-elevation-100); + --theme-text: var(--theme-elevation-900); + --theme-input-bg: var(--theme-elevation-150); + --theme-border-color: var(--theme-elevation-250); + + color-scheme: dark; + color: var(--theme-text); + + --highlight-default-bg-color: var(--theme-success-100); + --highlight-default-text-color: var(--theme-success-600); + + --highlight-danger-bg-color: var(--theme-error-100); + --highlight-danger-text-color: var(--theme-error-550); + } + + h1 a, + h2 a, + h3 a, + h4 a, + h5 a, + h6 a { + color: var(--theme-success-600); + + &:hover { + color: var(--theme-success-400); + } + + &:visited { + color: var(--theme-success-700); + + &:hover { + color: var(--theme-success-500); + } + } + } +} diff --git a/examples/auth/next-app/app/_css/type.scss b/examples/auth/next-app/app/_css/type.scss new file mode 100644 index 000000000..f8d1d0716 --- /dev/null +++ b/examples/auth/next-app/app/_css/type.scss @@ -0,0 +1,110 @@ +@use 'queries' as *; + +%h1, +%h2, +%h3, +%h4, +%h5, +%h6 { + font-weight: 700; +} + +%h1 { + margin: 40px 0; + font-size: 64px; + line-height: 70px; + font-weight: bold; + + @include mid-break { + margin: 24px 0; + font-size: 42px; + line-height: 42px; + } +} + +%h2 { + margin: 28px 0; + font-size: 48px; + line-height: 54px; + font-weight: bold; + + @include mid-break { + margin: 22px 0; + font-size: 32px; + line-height: 40px; + } +} + +%h3 { + margin: 24px 0; + font-size: 32px; + line-height: 40px; + font-weight: bold; + + @include mid-break { + margin: 20px 0; + font-size: 26px; + line-height: 32px; + } +} + +%h4 { + margin: 20px 0; + font-size: 26px; + line-height: 32px; + font-weight: bold; + + @include mid-break { + font-size: 22px; + line-height: 30px; + } +} + +%h5 { + margin: 20px 0; + font-size: 22px; + line-height: 30px; + font-weight: bold; + + @include mid-break { + font-size: 18px; + line-height: 24px; + } +} + +%h6 { + margin: 20px 0; + font-size: inherit; + line-height: inherit; + font-weight: bold; +} + +%body { + font-size: 18px; + line-height: 32px; + + @include mid-break { + font-size: 15px; + line-height: 24px; + } +} + +%large-body { + font-size: 25px; + line-height: 32px; + + @include mid-break { + font-size: 22px; + line-height: 30px; + } +} + +%label { + font-size: 16px; + line-height: 24px; + text-transform: uppercase; + + @include mid-break { + font-size: 13px; + } +} diff --git a/examples/auth/next-app/app/_providers/Auth/gql.ts b/examples/auth/next-app/app/_providers/Auth/gql.ts new file mode 100644 index 000000000..690b49561 --- /dev/null +++ b/examples/auth/next-app/app/_providers/Auth/gql.ts @@ -0,0 +1,34 @@ +export const USER = ` + id + email + firstName + lastName +` + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export const gql = async (query: string): Promise => { + try { + const res = await fetch(`${process.env.NEXT_PUBLIC_CMS_URL}/api/graphql`, { + method: 'POST', + credentials: 'include', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + query, + }), + }) + + const { data, errors } = await res.json() + + if (errors) { + throw new Error(errors[0].message) + } + + if (res.ok && data) { + return data + } + } catch (e: unknown) { + throw new Error(e as string) + } +} diff --git a/examples/auth/next-app/app/_providers/Auth/index.tsx b/examples/auth/next-app/app/_providers/Auth/index.tsx new file mode 100644 index 000000000..a4480f1af --- /dev/null +++ b/examples/auth/next-app/app/_providers/Auth/index.tsx @@ -0,0 +1,177 @@ +'use client' + +import React, { createContext, useCallback, useContext, useEffect, useState } from 'react' + +import { User } from '../../payload-types' +import { gql, USER } from './gql' +import { rest } from './rest' +import { AuthContext, Create, ForgotPassword, Login, Logout, ResetPassword } from './types' + +const Context = createContext({} as AuthContext) + +export const AuthProvider: React.FC<{ children: React.ReactNode; api?: 'rest' | 'gql' }> = ({ + children, + api = 'rest', +}) => { + const [user, setUser] = useState() + + const create = useCallback( + async args => { + if (api === 'rest') { + const user = await rest(`${process.env.NEXT_PUBLIC_CMS_URL}/api/users`, args) + setUser(user) + return user + } + + if (api === 'gql') { + const { createUser: user } = await gql(`mutation { + createUser(data: { email: "${args.email}", password: "${args.password}", firstName: "${args.firstName}", lastName: "${args.lastName}" }) { + ${USER} + } + }`) + + setUser(user) + return user + } + }, + [api], + ) + + const login = useCallback( + async args => { + if (api === 'rest') { + const user = await rest(`${process.env.NEXT_PUBLIC_CMS_URL}/api/users/login`, args) + setUser(user) + return user + } + + if (api === 'gql') { + const { loginUser } = await gql(`mutation { + loginUser(email: "${args.email}", password: "${args.password}") { + user { + ${USER} + } + exp + } + }`) + + setUser(loginUser?.user) + return loginUser?.user + } + }, + [api], + ) + + const logout = useCallback(async () => { + if (api === 'rest') { + await rest(`${process.env.NEXT_PUBLIC_CMS_URL}/api/users/logout`) + setUser(null) + return + } + + if (api === 'gql') { + await gql(`mutation { + logoutUser + }`) + + setUser(null) + } + }, [api]) + + // On mount, get user and set + useEffect(() => { + const fetchMe = async () => { + if (api === 'rest') { + const user = await rest( + `${process.env.NEXT_PUBLIC_CMS_URL}/api/users/me`, + {}, + { + method: 'GET', + }, + ) + setUser(user) + } + + if (api === 'gql') { + const { meUser } = await gql(`query { + meUser { + user { + ${USER} + } + exp + } + }`) + + setUser(meUser.user) + } + } + + fetchMe() + }, [api]) + + const forgotPassword = useCallback( + async args => { + if (api === 'rest') { + const user = await rest( + `${process.env.NEXT_PUBLIC_CMS_URL}/api/users/forgot-password`, + args, + ) + setUser(user) + return user + } + + if (api === 'gql') { + const { forgotPasswordUser } = await gql(`mutation { + forgotPasswordUser(email: "${args.email}") + }`) + + return forgotPasswordUser + } + }, + [api], + ) + + const resetPassword = useCallback( + async args => { + if (api === 'rest') { + const user = await rest(`${process.env.NEXT_PUBLIC_CMS_URL}/api/users/reset-password`, args) + setUser(user) + return user + } + + if (api === 'gql') { + const { resetPasswordUser } = await gql(`mutation { + resetPasswordUser(password: "${args.password}", token: "${args.token}") { + user { + ${USER} + } + } + }`) + + setUser(resetPasswordUser.user) + return resetPasswordUser.user + } + }, + [api], + ) + + return ( + + {children} + + ) +} + +type UseAuth = () => AuthContext // eslint-disable-line no-unused-vars + +export const useAuth: UseAuth = () => useContext(Context) diff --git a/examples/auth/next-app/app/_providers/Auth/rest.ts b/examples/auth/next-app/app/_providers/Auth/rest.ts new file mode 100644 index 000000000..0d6fd3c2d --- /dev/null +++ b/examples/auth/next-app/app/_providers/Auth/rest.ts @@ -0,0 +1,34 @@ +import type { User } from '../../payload-types' + +export const rest = async ( + url: string, + args?: any, // eslint-disable-line @typescript-eslint/no-explicit-any + options?: RequestInit, +): Promise => { + const method = options?.method || 'POST' + + try { + const res = await fetch(url, { + method, + ...(method === 'POST' ? { body: JSON.stringify(args) } : {}), + credentials: 'include', + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + }, + ...options, + }) + + const { errors, user } = await res.json() + + if (errors) { + throw new Error(errors[0].message) + } + + if (res.ok) { + return user + } + } catch (e: unknown) { + throw new Error(e as string) + } +} diff --git a/examples/auth/nextjs/components/Auth/types.ts b/examples/auth/next-app/app/_providers/Auth/types.ts similarity index 100% rename from examples/auth/nextjs/components/Auth/types.ts rename to examples/auth/next-app/app/_providers/Auth/types.ts diff --git a/examples/auth/next-app/app/_utilities/getMeUser.ts b/examples/auth/next-app/app/_utilities/getMeUser.ts new file mode 100644 index 000000000..8d361bb42 --- /dev/null +++ b/examples/auth/next-app/app/_utilities/getMeUser.ts @@ -0,0 +1,41 @@ +import { cookies } from 'next/headers' +import { redirect } from 'next/navigation' + +import type { User } from '../payload-types' + +export const getMeUser = async (args?: { + nullUserRedirect?: string + validUserRedirect?: string +}): Promise<{ + user: User + token: string | undefined +}> => { + const { nullUserRedirect, validUserRedirect } = args || {} + const cookieStore = cookies() + const token = cookieStore.get('payload-token')?.value + + const meUserReq = await fetch(`${process.env.NEXT_PUBLIC_CMS_URL}/api/users/me`, { + headers: { + Authorization: `JWT ${token}`, + }, + }) + + const { + user, + }: { + user: User + } = await meUserReq.json() + + if (validUserRedirect && meUserReq.ok && user) { + redirect(validUserRedirect) + } + + if (nullUserRedirect && (!meUserReq.ok || !user)) { + redirect(nullUserRedirect) + } + + return { + user, + token, + } +} diff --git a/examples/auth/next-app/app/account/AccountForm/index.module.scss b/examples/auth/next-app/app/account/AccountForm/index.module.scss new file mode 100644 index 000000000..568d504e0 --- /dev/null +++ b/examples/auth/next-app/app/account/AccountForm/index.module.scss @@ -0,0 +1,24 @@ +@import "../../_css/common"; + +.form { + margin-bottom: var(--base); + display: flex; + flex-direction: column; + gap: calc(var(--base) / 2); + align-items: flex-start; + width: 66.66%; + + @include mid-break { + width: 100%; + } +} + +.changePassword { + all: unset; + cursor: pointer; + text-decoration: underline; +} + +.submit { + margin-top: calc(var(--base) / 2); +} diff --git a/examples/auth/next-app/app/account/AccountForm/index.tsx b/examples/auth/next-app/app/account/AccountForm/index.tsx new file mode 100644 index 000000000..5fe2f8d35 --- /dev/null +++ b/examples/auth/next-app/app/account/AccountForm/index.tsx @@ -0,0 +1,152 @@ +'use client' + +import React, { Fragment, useCallback, useEffect, useRef, useState } from 'react' +import { useForm } from 'react-hook-form' +import { useRouter } from 'next/navigation' + +import { Button } from '../../_components/Button' +import { Input } from '../../_components/Input' +import { Message } from '../../_components/Message' +import { useAuth } from '../../_providers/Auth' + +import classes from './index.module.scss' + +type FormData = { + email: string + name: string + password: string + passwordConfirm: string +} + +export const AccountForm: React.FC = () => { + const [error, setError] = useState('') + const [success, setSuccess] = useState('') + const { user, setUser } = useAuth() + const [changePassword, setChangePassword] = useState(false) + const router = useRouter() + + const { + register, + handleSubmit, + formState: { errors, isLoading }, + reset, + watch, + } = useForm() + + const password = useRef({}) + password.current = watch('password', '') + + const onSubmit = useCallback( + async (data: FormData) => { + if (user) { + const response = await fetch(`${process.env.NEXT_PUBLIC_CMS_URL}/api/users/${user.id}`, { + // Make sure to include cookies with fetch + credentials: 'include', + method: 'PATCH', + body: JSON.stringify(data), + headers: { + 'Content-Type': 'application/json', + }, + }) + + if (response.ok) { + const json = await response.json() + setUser(json.doc) + setSuccess('Successfully updated account.') + setError('') + setChangePassword(false) + reset({ + email: json.doc.email, + name: json.doc.name, + password: '', + passwordConfirm: '', + }) + } else { + setError('There was a problem updating your account.') + } + } + }, + [user, setUser, reset], + ) + + useEffect(() => { + if (user === null) { + router.push(`/login?unauthorized=account`) + } + + // Once user is loaded, reset form to have default values + if (user) { + reset({ + email: user.email, + password: '', + passwordConfirm: '', + }) + } + }, [user, router, reset, changePassword]) + + return ( +
    + + {!changePassword ? ( + +

    + {'To change your password, '} + + . +

    + +
    + ) : ( + +

    + {'Change your password below, or '} + + . +

    + + value === password.current || 'The passwords do not match'} + error={errors.passwordConfirm} + /> +
    + )} +
    + + )} + {success && ( + +

    Request submitted

    +

    Check your email for a link that will allow you to securely reset your password.

    +
    + )} + + ) +} diff --git a/examples/auth/next-app/app/recover-password/index.module.scss b/examples/auth/next-app/app/recover-password/index.module.scss new file mode 100644 index 000000000..2967d35ee --- /dev/null +++ b/examples/auth/next-app/app/recover-password/index.module.scss @@ -0,0 +1,5 @@ +@import "../_css/common"; + +.recoverPassword { + margin-bottom: var(--block-padding); +} diff --git a/examples/auth/next-app/app/recover-password/page.tsx b/examples/auth/next-app/app/recover-password/page.tsx new file mode 100644 index 000000000..48c9661e3 --- /dev/null +++ b/examples/auth/next-app/app/recover-password/page.tsx @@ -0,0 +1,14 @@ +import React from 'react' + +import { Gutter } from '../_components/Gutter' +import { RecoverPasswordForm } from './RecoverPasswordForm' + +import classes from './index.module.scss' + +export default async function RecoverPassword() { + return ( + + + + ) +} diff --git a/examples/auth/next-app/app/reset-password/ResetPasswordForm/index.module.scss b/examples/auth/next-app/app/reset-password/ResetPasswordForm/index.module.scss new file mode 100644 index 000000000..2f7734603 --- /dev/null +++ b/examples/auth/next-app/app/reset-password/ResetPasswordForm/index.module.scss @@ -0,0 +1,13 @@ +@import "../../_css/common"; + +.form { + width: 66.66%; + + @include mid-break { + width: 100%; + } +} + +.submit { + margin-top: var(--base); +} diff --git a/examples/auth/next-app/app/reset-password/ResetPasswordForm/index.tsx b/examples/auth/next-app/app/reset-password/ResetPasswordForm/index.tsx new file mode 100644 index 000000000..80e59f731 --- /dev/null +++ b/examples/auth/next-app/app/reset-password/ResetPasswordForm/index.tsx @@ -0,0 +1,84 @@ +'use client' + +import React, { useCallback, useEffect, useState } from 'react' +import { useForm } from 'react-hook-form' +import { useRouter, useSearchParams } from 'next/navigation' + +import { Button } from '../../_components/Button' +import { Input } from '../../_components/Input' +import { Message } from '../../_components/Message' +import { useAuth } from '../../_providers/Auth' + +import classes from './index.module.scss' + +type FormData = { + password: string + token: string +} + +export const ResetPasswordForm: React.FC = () => { + const [error, setError] = useState('') + const { login } = useAuth() + const router = useRouter() + const searchParams = useSearchParams() + const token = searchParams.get('token') + + const { + register, + handleSubmit, + formState: { errors }, + reset, + } = useForm() + + const onSubmit = useCallback( + async (data: FormData) => { + const response = await fetch(`${process.env.NEXT_PUBLIC_CMS_URL}/api/users/reset-password`, { + method: 'POST', + body: JSON.stringify(data), + headers: { + 'Content-Type': 'application/json', + }, + }) + + if (response.ok) { + const json = await response.json() + + // Automatically log the user in after they successfully reset password + await login({ email: json.user.email, password: data.password }) + + // Redirect them to `/account` with success message in URL + router.push('/account?success=Password reset successfully.') + } else { + setError('There was a problem while resetting your password. Please try again later.') + } + }, + [router, login], + ) + + // when Next.js populates token within router, + // reset form with new token value + useEffect(() => { + reset({ token: token || undefined }) + }, [reset, token]) + + return ( +
    + + + + + {' to change your password.'} +

    + + + ) : ( + +

    + {'Change your password below, or '} + + . +

    + + value === password.current || 'The passwords do not match'} + error={errors.passwordConfirm} + /> +
    + )} + - - Log out - - ) -} - -export default Account diff --git a/examples/auth/nextjs/pages/app.module.css b/examples/auth/nextjs/pages/app.module.css deleted file mode 100644 index c3692377d..000000000 --- a/examples/auth/nextjs/pages/app.module.css +++ /dev/null @@ -1,12 +0,0 @@ -.app { - font-family: system-ui; - max-width: 800px; - margin: 0 auto; - padding: 0 30px; -} - -.header { - display: flex; - justify-content: space-between; - margin: 25px 0; -} diff --git a/examples/auth/nextjs/pages/create-account/index.module.css b/examples/auth/nextjs/pages/create-account/index.module.css deleted file mode 100644 index c873f1ac8..000000000 --- a/examples/auth/nextjs/pages/create-account/index.module.css +++ /dev/null @@ -1,8 +0,0 @@ -.form { - margin-bottom: 30px; -} - -.error { - color: red; - margin-bottom: 30px; -} diff --git a/examples/auth/nextjs/pages/create-account/index.tsx b/examples/auth/nextjs/pages/create-account/index.tsx deleted file mode 100644 index 217b1d99e..000000000 --- a/examples/auth/nextjs/pages/create-account/index.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import React, { useCallback, useState } from 'react' -import { useForm } from 'react-hook-form' -import Link from 'next/link' - -import { useAuth } from '../../components/Auth' -import { Gutter } from '../../components/Gutter' -import { Input } from '../../components/Input' -import classes from './index.module.css' - -type FormData = { - email: string - password: string - firstName: string - lastName: string -} - -const CreateAccount: React.FC = () => { - const [error, setError] = useState('') - const [success, setSuccess] = useState(false) - const { login, create, user } = useAuth() - - const { - register, - handleSubmit, - formState: { errors }, - } = useForm() - - const onSubmit = useCallback( - async (data: FormData) => { - try { - await create(data as Parameters[0]) - // Automatically log the user in after creating their account - await login({ email: data.email, password: data.password }) - setSuccess(true) - } catch (err) { - setError(err?.message || 'An error occurred while attempting to create your account.') - } - }, - [login, create], - ) - - return ( - - {!success && ( - -

    Create Account

    - {error &&
    {error}
    } -
    - - - - - -
    -

    - {'Already have an account? '} - Login -

    -
    - )} - {success && ( - -

    Account created successfully

    -

    You are now logged in.

    - Go to your account -
    - )} -
    - ) -} - -export default CreateAccount diff --git a/examples/auth/nextjs/pages/index.tsx b/examples/auth/nextjs/pages/index.tsx deleted file mode 100644 index 9be8a3cdc..000000000 --- a/examples/auth/nextjs/pages/index.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import React from 'react' -import Link from 'next/link' - -import { Gutter } from '../components/Gutter' - -const Home: React.FC = () => { - return ( - -

    Home

    -

    - {'This is a '} - Next.js - {" app made explicitly for Payload's "} - - Auth Example - - {". This example demonstrates how to implement Payload's "} - Authentication - {' strategies in both the REST and GraphQL APIs.'} -

    -

    - {'Visit the '} - Login - {' page to start the authentication flow. Once logged in, you will be redirected to the '} - Account - {` page which is restricted to user's only. To toggle APIs, simply toggle the "api" prop in _app.tsx between "rest" and "gql".`} -

    -
    - ) -} - -export default Home diff --git a/examples/auth/nextjs/pages/login/index.module.css b/examples/auth/nextjs/pages/login/index.module.css deleted file mode 100644 index c873f1ac8..000000000 --- a/examples/auth/nextjs/pages/login/index.module.css +++ /dev/null @@ -1,8 +0,0 @@ -.form { - margin-bottom: 30px; -} - -.error { - color: red; - margin-bottom: 30px; -} diff --git a/examples/auth/nextjs/pages/login/index.tsx b/examples/auth/nextjs/pages/login/index.tsx deleted file mode 100644 index dec13ecdd..000000000 --- a/examples/auth/nextjs/pages/login/index.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import React, { useCallback, useEffect, useState } from 'react' -import { useForm } from 'react-hook-form' -import Link from 'next/link' -import { useRouter } from 'next/router' - -import { useAuth } from '../../components/Auth' -import { Gutter } from '../../components/Gutter' -import { Input } from '../../components/Input' -import classes from './index.module.css' - -type FormData = { - email: string - password: string -} - -const Login: React.FC = () => { - const [error, setError] = useState('') - const router = useRouter() - const { login } = useAuth() - - const { - register, - handleSubmit, - formState: { errors }, - } = useForm() - - const onSubmit = useCallback( - async (data: FormData) => { - try { - await login(data) - router.push('/account') - } catch (err) { - setError(err?.message || 'An error occurred while attempting to login.') - } - }, - [login, router], - ) - - useEffect(() => { - if (router.query.unauthorized) { - setError(`To visit the ${router.query.unauthorized} page, you need to be logged in.`) - } - }, [router]) - - return ( - -

    Log in

    -

    - To log in, use the email dev@payloadcms.com with the password test. -

    - {error &&
    {error}
    } -
    - - - -
    - Create an account -
    - Recover your password -
    - ) -} - -export default Login diff --git a/examples/auth/nextjs/pages/logout/index.module.css b/examples/auth/nextjs/pages/logout/index.module.css deleted file mode 100644 index 7d2f0a0af..000000000 --- a/examples/auth/nextjs/pages/logout/index.module.css +++ /dev/null @@ -1,4 +0,0 @@ -.error { - color: red; - margin-bottom: 30px; -} diff --git a/examples/auth/nextjs/pages/logout/index.tsx b/examples/auth/nextjs/pages/logout/index.tsx deleted file mode 100644 index bebbef343..000000000 --- a/examples/auth/nextjs/pages/logout/index.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React, { Fragment, useEffect, useState } from 'react' -import Link from 'next/link' - -import { useAuth } from '../../components/Auth' -import { Gutter } from '../../components/Gutter' -import classes from './index.module.css' - -const Logout: React.FC = () => { - const { logout } = useAuth() - const [success, setSuccess] = useState('') - const [error, setError] = useState('') - - useEffect(() => { - const performLogout = async () => { - try { - await logout() - setSuccess('Logged out successfully.') - } catch (err) { - setError(err?.message || 'An error occurred while attempting to logout.') - } - } - - performLogout() - }, [logout]) - - return ( - - {success &&

    {success}

    } - {error &&
    {error}
    } -

    - {'What would you like to do next? '} - - {' To log back in, '} - click here - {'.'} - -

    -
    - ) -} - -export default Logout diff --git a/examples/auth/nextjs/pages/recover-password/index.module.css b/examples/auth/nextjs/pages/recover-password/index.module.css deleted file mode 100644 index 7d2f0a0af..000000000 --- a/examples/auth/nextjs/pages/recover-password/index.module.css +++ /dev/null @@ -1,4 +0,0 @@ -.error { - color: red; - margin-bottom: 30px; -} diff --git a/examples/auth/nextjs/pages/recover-password/index.tsx b/examples/auth/nextjs/pages/recover-password/index.tsx deleted file mode 100644 index fac6f3099..000000000 --- a/examples/auth/nextjs/pages/recover-password/index.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import React, { useCallback, useState } from 'react' -import { useForm } from 'react-hook-form' - -import { useAuth } from '../../components/Auth' -import { Gutter } from '../../components/Gutter' -import { Input } from '../../components/Input' -import classes from './index.module.css' - -type FormData = { - email: string -} - -const RecoverPassword: React.FC = () => { - const [error, setError] = useState('') - const [success, setSuccess] = useState(false) - const { forgotPassword } = useAuth() - - const { - register, - handleSubmit, - formState: { errors }, - } = useForm() - - const onSubmit = useCallback( - async (data: FormData) => { - try { - const user = await forgotPassword(data as Parameters[0]) - - if (user) { - setSuccess(true) - setError('') - } - } catch (err) { - setError(err?.message || 'An error occurred while attempting to recover password.') - } - }, - [forgotPassword], - ) - - return ( - - {!success && ( - -

    Recover Password

    -

    - Please enter your email below. You will receive an email message with instructions on - how to reset your password. -

    - {error &&
    {error}
    } -
    - - -
    -
    - )} - {success && ( - -

    Request submitted

    -

    Check your email for a link that will allow you to securely reset your password.

    -
    - )} -
    - ) -} - -export default RecoverPassword diff --git a/examples/auth/nextjs/pages/reset-password/index.module.css b/examples/auth/nextjs/pages/reset-password/index.module.css deleted file mode 100644 index 7d2f0a0af..000000000 --- a/examples/auth/nextjs/pages/reset-password/index.module.css +++ /dev/null @@ -1,4 +0,0 @@ -.error { - color: red; - margin-bottom: 30px; -} diff --git a/examples/auth/nextjs/pages/reset-password/index.tsx b/examples/auth/nextjs/pages/reset-password/index.tsx deleted file mode 100644 index 1030e5bb5..000000000 --- a/examples/auth/nextjs/pages/reset-password/index.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import React, { useCallback, useEffect, useState } from 'react' -import { useForm } from 'react-hook-form' -import { useRouter } from 'next/router' - -import { useAuth } from '../../components/Auth' -import { Gutter } from '../../components/Gutter' -import { Input } from '../../components/Input' -import classes from './index.module.css' - -type FormData = { - password: string - token: string -} - -const ResetPassword: React.FC = () => { - const [error, setError] = useState('') - const { login, resetPassword } = useAuth() - const router = useRouter() - - const token = typeof router.query.token === 'string' ? router.query.token : undefined - - const { - register, - handleSubmit, - formState: { errors }, - reset, - } = useForm() - - const onSubmit = useCallback( - async (data: FormData) => { - try { - const user = await resetPassword(data as Parameters[0]) - - if (user) { - // Automatically log the user in after they successfully reset password - // Then redirect them to /account with success message in URL - await login({ email: user.email, password: data.password }) - router.push('/account?success=Password reset successfully.') - } - } catch (err) { - setError(err?.message || 'An error occurred while attempting to reset password.') - } - }, - [router, login, resetPassword], - ) - - // When Next.js populates token within router, reset form with new token value - useEffect(() => { - reset({ token }) - }, [reset, token]) - - return ( - -

    Reset Password

    -

    Please enter a new password below.

    - {error &&
    {error}
    } -
    - - - -
    -
    - ) -} - -export default ResetPassword diff --git a/examples/auth/nextjs/public/favicon.ico b/examples/auth/nextjs/public/favicon.ico deleted file mode 100644 index 718d6fea4..000000000 Binary files a/examples/auth/nextjs/public/favicon.ico and /dev/null differ diff --git a/examples/auth/nextjs/yarn.lock b/examples/auth/nextjs/yarn.lock deleted file mode 100644 index 0abe5a1a3..000000000 --- a/examples/auth/nextjs/yarn.lock +++ /dev/null @@ -1,1686 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@eslint/eslintrc@^1.3.3": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.4.1.tgz#af58772019a2d271b7e2d4c23ff4ddcba3ccfb3e" - integrity sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA== - dependencies: - ajv "^6.12.4" - debug "^4.3.2" - espree "^9.4.0" - globals "^13.19.0" - ignore "^5.2.0" - import-fresh "^3.2.1" - js-yaml "^4.1.0" - minimatch "^3.1.2" - strip-json-comments "^3.1.1" - -"@humanwhocodes/config-array@^0.10.5": - version "0.10.7" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.10.7.tgz#6d53769fd0c222767e6452e8ebda825c22e9f0dc" - integrity sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w== - dependencies: - "@humanwhocodes/object-schema" "^1.2.1" - debug "^4.1.1" - minimatch "^3.0.4" - -"@humanwhocodes/module-importer@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" - integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== - -"@humanwhocodes/object-schema@^1.2.1": - version "1.2.1" - resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" - integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== - -"@next/env@13.1.6": - version "13.1.6" - resolved "https://registry.yarnpkg.com/@next/env/-/env-13.1.6.tgz#c4925609f16142ded1a5cb833359ab17359b7a93" - integrity sha512-s+W9Fdqh5MFk6ECrbnVmmAOwxKQuhGMT7xXHrkYIBMBcTiOqNWhv5KbJIboKR5STXxNXl32hllnvKaffzFaWQg== - -"@next/eslint-plugin-next@^13.1.6": - version "13.1.6" - resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-13.1.6.tgz#ad8be22dd3d8aee9a9bd9a2507e2c55a2f7ebdd9" - integrity sha512-o7cauUYsXjzSJkay8wKjpKJf2uLzlggCsGUkPu3lP09Pv97jYlekTC20KJrjQKmSv5DXV0R/uks2ZXhqjNkqAw== - dependencies: - glob "7.1.7" - -"@next/swc-android-arm-eabi@13.1.6": - version "13.1.6" - resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-13.1.6.tgz#d766dfc10e27814d947b20f052067c239913dbcc" - integrity sha512-F3/6Z8LH/pGlPzR1AcjPFxx35mPqjE5xZcf+IL+KgbW9tMkp7CYi1y7qKrEWU7W4AumxX/8OINnDQWLiwLasLQ== - -"@next/swc-android-arm64@13.1.6": - version "13.1.6" - resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-13.1.6.tgz#f37a98d5f18927d8c9970d750d516ac779465176" - integrity sha512-cMwQjnB8vrYkWyK/H0Rf2c2pKIH4RGjpKUDvbjVAit6SbwPDpmaijLio0LWFV3/tOnY6kvzbL62lndVA0mkYpw== - -"@next/swc-darwin-arm64@13.1.6": - version "13.1.6" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.1.6.tgz#ec1b90fd9bf809d8b81004c5182e254dced4ad96" - integrity sha512-KKRQH4DDE4kONXCvFMNBZGDb499Hs+xcFAwvj+rfSUssIDrZOlyfJNy55rH5t2Qxed1e4K80KEJgsxKQN1/fyw== - -"@next/swc-darwin-x64@13.1.6": - version "13.1.6" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.1.6.tgz#e869ac75d16995eee733a7d1550322d9051c1eb4" - integrity sha512-/uOky5PaZDoaU99ohjtNcDTJ6ks/gZ5ykTQDvNZDjIoCxFe3+t06bxsTPY6tAO6uEAw5f6vVFX5H5KLwhrkZCA== - -"@next/swc-freebsd-x64@13.1.6": - version "13.1.6" - resolved "https://registry.yarnpkg.com/@next/swc-freebsd-x64/-/swc-freebsd-x64-13.1.6.tgz#84a7b2e423a2904afc2edca21c2f1ba6b53fa4c1" - integrity sha512-qaEALZeV7to6weSXk3Br80wtFQ7cFTpos/q+m9XVRFggu+8Ib895XhMWdJBzew6aaOcMvYR6KQ6JmHA2/eMzWw== - -"@next/swc-linux-arm-gnueabihf@13.1.6": - version "13.1.6" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-13.1.6.tgz#980eed1f655ff8a72187d8a6ef9e73ac39d20d23" - integrity sha512-OybkbC58A1wJ+JrJSOjGDvZzrVEQA4sprJejGqMwiZyLqhr9Eo8FXF0y6HL+m1CPCpPhXEHz/2xKoYsl16kNqw== - -"@next/swc-linux-arm64-gnu@13.1.6": - version "13.1.6" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.1.6.tgz#87a71db21cded3f7c63d1d19079845c59813c53d" - integrity sha512-yCH+yDr7/4FDuWv6+GiYrPI9kcTAO3y48UmaIbrKy8ZJpi7RehJe3vIBRUmLrLaNDH3rY1rwoHi471NvR5J5NQ== - -"@next/swc-linux-arm64-musl@13.1.6": - version "13.1.6" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.1.6.tgz#c5aac8619331b9fd030603bbe2b36052011e11de" - integrity sha512-ECagB8LGX25P9Mrmlc7Q/TQBb9rGScxHbv/kLqqIWs2fIXy6Y/EiBBiM72NTwuXUFCNrWR4sjUPSooVBJJ3ESQ== - -"@next/swc-linux-x64-gnu@13.1.6": - version "13.1.6" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.1.6.tgz#9513d36d540bbfea575576746736054c31aacdea" - integrity sha512-GT5w2mruk90V/I5g6ScuueE7fqj/d8Bui2qxdw6lFxmuTgMeol5rnzAv4uAoVQgClOUO/MULilzlODg9Ib3Y4Q== - -"@next/swc-linux-x64-musl@13.1.6": - version "13.1.6" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.1.6.tgz#d61fc6884899f5957251f4ce3f522e34a2c479b7" - integrity sha512-keFD6KvwOPzmat4TCnlnuxJCQepPN+8j3Nw876FtULxo8005Y9Ghcl7ACcR8GoiKoddAq8gxNBrpjoxjQRHeAQ== - -"@next/swc-win32-arm64-msvc@13.1.6": - version "13.1.6" - resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.1.6.tgz#fac2077a8ae9768e31444c9ae90807e64117cda7" - integrity sha512-OwertslIiGQluFvHyRDzBCIB07qJjqabAmINlXUYt7/sY7Q7QPE8xVi5beBxX/rxTGPIbtyIe3faBE6Z2KywhQ== - -"@next/swc-win32-ia32-msvc@13.1.6": - version "13.1.6" - resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.1.6.tgz#498bc11c91b4c482a625bf4b978f98ae91111e46" - integrity sha512-g8zowiuP8FxUR9zslPmlju7qYbs2XBtTLVSxVikPtUDQedhcls39uKYLvOOd1JZg0ehyhopobRoH1q+MHlIN/w== - -"@next/swc-win32-x64-msvc@13.1.6": - version "13.1.6" - resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.1.6.tgz#17ed919c723426b7d0ce1cd73d40ce3dcd342089" - integrity sha512-Ls2OL9hi3YlJKGNdKv8k3X/lLgc3VmLG3a/DeTkAd+lAituJp8ZHmRmm9f9SL84fT3CotlzcgbdaCDfFwFA6bA== - -"@nodelib/fs.scandir@2.1.5": - version "2.1.5" - resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== - dependencies: - "@nodelib/fs.stat" "2.0.5" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": - version "2.0.5" - resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== - -"@nodelib/fs.walk@^1.2.3": - version "1.2.8" - resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== - dependencies: - "@nodelib/fs.scandir" "2.1.5" - fastq "^1.6.0" - -"@payloadcms/eslint-config@^0.0.1": - version "0.0.1" - resolved "https://registry.yarnpkg.com/@payloadcms/eslint-config/-/eslint-config-0.0.1.tgz#4324702ddef6c773b3f3033795a13e6b50c95a92" - integrity sha512-Il59+0C4E/bI6uM2hont3I+oABWkJZbfbItubje5SGMrXkymUq8jT/UZRk0eCt918bB7gihxDXx8guFnR/aNIw== - -"@swc/helpers@0.4.14": - version "0.4.14" - resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.4.14.tgz#1352ac6d95e3617ccb7c1498ff019654f1e12a74" - integrity sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw== - dependencies: - tslib "^2.4.0" - -"@types/json-schema@^7.0.9": - version "7.0.11" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" - integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== - -"@types/json5@^0.0.29": - version "0.0.29" - resolved "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" - integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== - -"@types/node@18.11.3": - version "18.11.3" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.3.tgz#78a6d7ec962b596fc2d2ec102c4dd3ef073fea6a" - integrity sha512-fNjDQzzOsZeKZu5NATgXUPsaFaTxeRgFXoosrHivTl8RGeV733OLawXsGfEk9a8/tySyZUyiZ6E8LcjPFZ2y1A== - -"@types/prop-types@*": - version "15.7.5" - resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" - integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== - -"@types/react@18.0.21": - version "18.0.21" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.21.tgz#b8209e9626bb00a34c76f55482697edd2b43cc67" - integrity sha512-7QUCOxvFgnD5Jk8ZKlUAhVcRj7GuJRjnjjiY/IUBWKgOlnvDvTMLD4RTF7NPyVmbRhNrbomZiOepg7M/2Kj1mA== - dependencies: - "@types/prop-types" "*" - "@types/scheduler" "*" - csstype "^3.0.2" - -"@types/scheduler@*": - version "0.16.2" - resolved "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" - integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== - -"@types/semver@^7.3.12": - version "7.3.13" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.13.tgz#da4bfd73f49bd541d28920ab0e2bf0ee80f71c91" - integrity sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw== - -"@typescript-eslint/eslint-plugin@^5.51.0": - version "5.52.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.52.0.tgz#5fb0d43574c2411f16ea80f5fc335b8eaa7b28a8" - integrity sha512-lHazYdvYVsBokwCdKOppvYJKaJ4S41CgKBcPvyd0xjZNbvQdhn/pnJlGtQksQ/NhInzdaeaSarlBjDXHuclEbg== - dependencies: - "@typescript-eslint/scope-manager" "5.52.0" - "@typescript-eslint/type-utils" "5.52.0" - "@typescript-eslint/utils" "5.52.0" - debug "^4.3.4" - grapheme-splitter "^1.0.4" - ignore "^5.2.0" - natural-compare-lite "^1.4.0" - regexpp "^3.2.0" - semver "^7.3.7" - tsutils "^3.21.0" - -"@typescript-eslint/parser@^5.51.0": - version "5.52.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.52.0.tgz#73c136df6c0133f1d7870de7131ccf356f5be5a4" - integrity sha512-e2KiLQOZRo4Y0D/b+3y08i3jsekoSkOYStROYmPUnGMEoA0h+k2qOH5H6tcjIc68WDvGwH+PaOrP1XRzLJ6QlA== - dependencies: - "@typescript-eslint/scope-manager" "5.52.0" - "@typescript-eslint/types" "5.52.0" - "@typescript-eslint/typescript-estree" "5.52.0" - debug "^4.3.4" - -"@typescript-eslint/scope-manager@5.52.0": - version "5.52.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.52.0.tgz#a993d89a0556ea16811db48eabd7c5b72dcb83d1" - integrity sha512-AR7sxxfBKiNV0FWBSARxM8DmNxrwgnYMPwmpkC1Pl1n+eT8/I2NAUPuwDy/FmDcC6F8pBfmOcaxcxRHspgOBMw== - dependencies: - "@typescript-eslint/types" "5.52.0" - "@typescript-eslint/visitor-keys" "5.52.0" - -"@typescript-eslint/type-utils@5.52.0": - version "5.52.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.52.0.tgz#9fd28cd02e6f21f5109e35496df41893f33167aa" - integrity sha512-tEKuUHfDOv852QGlpPtB3lHOoig5pyFQN/cUiZtpw99D93nEBjexRLre5sQZlkMoHry/lZr8qDAt2oAHLKA6Jw== - dependencies: - "@typescript-eslint/typescript-estree" "5.52.0" - "@typescript-eslint/utils" "5.52.0" - debug "^4.3.4" - tsutils "^3.21.0" - -"@typescript-eslint/types@5.52.0": - version "5.52.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.52.0.tgz#19e9abc6afb5bd37a1a9bea877a1a836c0b3241b" - integrity sha512-oV7XU4CHYfBhk78fS7tkum+/Dpgsfi91IIDy7fjCyq2k6KB63M6gMC0YIvy+iABzmXThCRI6xpCEyVObBdWSDQ== - -"@typescript-eslint/typescript-estree@5.52.0": - version "5.52.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.52.0.tgz#6408cb3c2ccc01c03c278cb201cf07e73347dfca" - integrity sha512-WeWnjanyEwt6+fVrSR0MYgEpUAuROxuAH516WPjUblIrClzYJj0kBbjdnbQXLpgAN8qbEuGywiQsXUVDiAoEuQ== - dependencies: - "@typescript-eslint/types" "5.52.0" - "@typescript-eslint/visitor-keys" "5.52.0" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - semver "^7.3.7" - tsutils "^3.21.0" - -"@typescript-eslint/utils@5.52.0": - version "5.52.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.52.0.tgz#b260bb5a8f6b00a0ed51db66bdba4ed5e4845a72" - integrity sha512-As3lChhrbwWQLNk2HC8Ree96hldKIqk98EYvypd3It8Q1f8d5zWyIoaZEp2va5667M4ZyE7X8UUR+azXrFl+NA== - dependencies: - "@types/json-schema" "^7.0.9" - "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.52.0" - "@typescript-eslint/types" "5.52.0" - "@typescript-eslint/typescript-estree" "5.52.0" - eslint-scope "^5.1.1" - eslint-utils "^3.0.0" - semver "^7.3.7" - -"@typescript-eslint/visitor-keys@5.52.0": - version "5.52.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.52.0.tgz#e38c971259f44f80cfe49d97dbffa38e3e75030f" - integrity sha512-qMwpw6SU5VHCPr99y274xhbm+PRViK/NATY6qzt+Et7+mThGuFSl/ompj2/hrBlRP/kq+BFdgagnOSgw9TB0eA== - dependencies: - "@typescript-eslint/types" "5.52.0" - eslint-visitor-keys "^3.3.0" - -acorn-jsx@^5.3.2: - version "5.3.2" - resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - -acorn@^8.8.0: - version "8.8.0" - resolved "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" - integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w== - -ajv@^6.10.0, ajv@^6.12.4: - version "6.12.6" - resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -array-includes@^3.1.4: - version "3.1.5" - resolved "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz#2c320010db8d31031fd2a5f6b3bbd4b1aad31bdb" - integrity sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.19.5" - get-intrinsic "^1.1.1" - is-string "^1.0.7" - -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - -array.prototype.flat@^1.2.5: - version "1.3.0" - resolved "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz#0b0c1567bf57b38b56b4c97b8aa72ab45e4adc7b" - integrity sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.2" - es-shim-unscopables "^1.0.0" - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^3.0.2: - version "3.0.2" - resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -call-bind@^1.0.0, call-bind@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== - dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -caniuse-lite@^1.0.30001406: - version "1.0.30001452" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001452.tgz#dff7b8bb834b3a91808f0a9ff0453abb1fbba02a" - integrity sha512-Lkp0vFjMkBB3GTpLR8zk4NwW5EdRdnitwYJHDOOKIU85x4ckYCPQ+9WlVvSVClHxVReefkUMtWZH2l9KGlD51w== - -chalk@^4.0.0: - version "4.1.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -client-only@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" - integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -cross-spawn@^7.0.2: - version "7.0.3" - resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -csstype@^3.0.2: - version "3.1.0" - resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz#4ddcac3718d787cf9df0d1b7d15033925c8f29f2" - integrity sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA== - -debug@^2.6.9: - version "2.6.9" - resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@^3.2.7: - version "3.2.7" - resolved "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== - dependencies: - ms "^2.1.1" - -debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: - version "4.3.4" - resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - -deep-is@^0.1.3: - version "0.1.4" - resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" - integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== - -define-properties@^1.1.3, define-properties@^1.1.4: - version "1.1.4" - resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" - integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== - dependencies: - has-property-descriptors "^1.0.0" - object-keys "^1.1.1" - -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -doctrine@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" - integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== - dependencies: - esutils "^2.0.2" - -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - -es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19.5: - version "1.20.1" - resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz#027292cd6ef44bd12b1913b828116f54787d1814" - integrity sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA== - dependencies: - call-bind "^1.0.2" - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - function.prototype.name "^1.1.5" - get-intrinsic "^1.1.1" - get-symbol-description "^1.0.0" - has "^1.0.3" - has-property-descriptors "^1.0.0" - has-symbols "^1.0.3" - internal-slot "^1.0.3" - is-callable "^1.2.4" - is-negative-zero "^2.0.2" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.2" - is-string "^1.0.7" - is-weakref "^1.0.2" - object-inspect "^1.12.0" - object-keys "^1.1.1" - object.assign "^4.1.2" - regexp.prototype.flags "^1.4.3" - string.prototype.trimend "^1.0.5" - string.prototype.trimstart "^1.0.5" - unbox-primitive "^1.0.2" - -es-shim-unscopables@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" - integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w== - dependencies: - has "^1.0.3" - -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -escape-html@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -eslint-config-prettier@^8.5.0: - version "8.6.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.6.0.tgz#dec1d29ab728f4fa63061774e1672ac4e363d207" - integrity sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA== - -eslint-import-resolver-node@^0.3.6: - version "0.3.6" - resolved "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz#4048b958395da89668252001dbd9eca6b83bacbd" - integrity sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw== - dependencies: - debug "^3.2.7" - resolve "^1.20.0" - -eslint-module-utils@^2.7.2: - version "2.7.4" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz#4f3e41116aaf13a20792261e61d3a2e7e0583974" - integrity sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA== - dependencies: - debug "^3.2.7" - -eslint-plugin-filenames@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-filenames/-/eslint-plugin-filenames-1.3.2.tgz#7094f00d7aefdd6999e3ac19f72cea058e590cf7" - integrity sha512-tqxJTiEM5a0JmRCUYQmxw23vtTxrb2+a3Q2mMOPhFxvt7ZQQJmdiuMby9B/vUAuVMghyP7oET+nIf6EO6CBd/w== - dependencies: - lodash.camelcase "4.3.0" - lodash.kebabcase "4.1.1" - lodash.snakecase "4.1.1" - lodash.upperfirst "4.3.1" - -eslint-plugin-import@2.25.4: - version "2.25.4" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.25.4.tgz#322f3f916a4e9e991ac7af32032c25ce313209f1" - integrity sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA== - dependencies: - array-includes "^3.1.4" - array.prototype.flat "^1.2.5" - debug "^2.6.9" - doctrine "^2.1.0" - eslint-import-resolver-node "^0.3.6" - eslint-module-utils "^2.7.2" - has "^1.0.3" - is-core-module "^2.8.0" - is-glob "^4.0.3" - minimatch "^3.0.4" - object.values "^1.1.5" - resolve "^1.20.0" - tsconfig-paths "^3.12.0" - -eslint-plugin-prettier@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz#651cbb88b1dab98bfd42f017a12fa6b2d993f94b" - integrity sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ== - dependencies: - prettier-linter-helpers "^1.0.0" - -eslint-plugin-react-hooks@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3" - integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g== - -eslint-plugin-simple-import-sort@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-10.0.0.tgz#cc4ceaa81ba73252427062705b64321946f61351" - integrity sha512-AeTvO9UCMSNzIHRkg8S6c3RPy5YEwKWSQPx3DYghLedo2ZQxowPFLGDN1AZ2evfg6r6mjBSZSLxLFsWSu3acsw== - -eslint-scope@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" - integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== - dependencies: - esrecurse "^4.3.0" - estraverse "^4.1.1" - -eslint-scope@^7.1.1: - version "7.1.1" - resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642" - integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw== - dependencies: - esrecurse "^4.3.0" - estraverse "^5.2.0" - -eslint-utils@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" - integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== - dependencies: - eslint-visitor-keys "^2.0.0" - -eslint-visitor-keys@^2.0.0: - version "2.1.0" - resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" - integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== - -eslint-visitor-keys@^3.3.0: - version "3.3.0" - resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" - integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== - -eslint@8.25.0: - version "8.25.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.25.0.tgz#00eb962f50962165d0c4ee3327708315eaa8058b" - integrity sha512-DVlJOZ4Pn50zcKW5bYH7GQK/9MsoQG2d5eDH0ebEkE8PbgzTTmtt/VTH9GGJ4BfeZCpBLqFfvsjX35UacUL83A== - dependencies: - "@eslint/eslintrc" "^1.3.3" - "@humanwhocodes/config-array" "^0.10.5" - "@humanwhocodes/module-importer" "^1.0.1" - ajv "^6.10.0" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.3.2" - doctrine "^3.0.0" - escape-string-regexp "^4.0.0" - eslint-scope "^7.1.1" - eslint-utils "^3.0.0" - eslint-visitor-keys "^3.3.0" - espree "^9.4.0" - esquery "^1.4.0" - esutils "^2.0.2" - fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" - find-up "^5.0.0" - glob-parent "^6.0.1" - globals "^13.15.0" - globby "^11.1.0" - grapheme-splitter "^1.0.4" - ignore "^5.2.0" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - js-sdsl "^4.1.4" - js-yaml "^4.1.0" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash.merge "^4.6.2" - minimatch "^3.1.2" - natural-compare "^1.4.0" - optionator "^0.9.1" - regexpp "^3.2.0" - strip-ansi "^6.0.1" - strip-json-comments "^3.1.0" - text-table "^0.2.0" - -espree@^9.4.0: - version "9.4.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.4.1.tgz#51d6092615567a2c2cff7833445e37c28c0065bd" - integrity sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg== - dependencies: - acorn "^8.8.0" - acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.3.0" - -esquery@^1.4.0: - version "1.4.0" - resolved "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" - integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== - dependencies: - estraverse "^5.1.0" - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -estraverse@^5.1.0, estraverse@^5.2.0: - version "5.3.0" - resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-diff@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" - integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== - -fast-glob@^3.2.9: - version "3.2.11" - resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" - integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - -fast-json-stable-stringify@^2.0.0: - version "2.1.0" - resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-levenshtein@^2.0.6: - version "2.0.6" - resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== - -fastq@^1.6.0: - version "1.13.0" - resolved "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" - integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== - dependencies: - reusify "^1.0.4" - -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== - dependencies: - flat-cache "^3.0.4" - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - -flat-cache@^3.0.4: - version "3.0.4" - resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" - integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== - dependencies: - flatted "^3.1.0" - rimraf "^3.0.2" - -flatted@^3.1.0: - version "3.2.6" - resolved "https://registry.npmjs.org/flatted/-/flatted-3.2.6.tgz#022e9218c637f9f3fc9c35ab9c9193f05add60b2" - integrity sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ== - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -function.prototype.name@^1.1.5: - version "1.1.5" - resolved "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" - integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.0" - functions-have-names "^1.2.2" - -functions-have-names@^1.2.2: - version "1.2.3" - resolved "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" - integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== - -get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: - version "1.1.2" - resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz#336975123e05ad0b7ba41f152ee4aadbea6cf598" - integrity sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.3" - -get-symbol-description@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" - integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" - -glob-parent@^5.1.2: - version "5.1.2" - resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob-parent@^6.0.1: - version "6.0.2" - resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== - dependencies: - is-glob "^4.0.3" - -glob@7.1.7: - version "7.1.7" - resolved "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" - integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.1.3: - version "7.2.3" - resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.1.1" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^13.15.0: - version "13.17.0" - resolved "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz#902eb1e680a41da93945adbdcb5a9f361ba69bd4" - integrity sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw== - dependencies: - type-fest "^0.20.2" - -globals@^13.19.0: - version "13.20.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82" - integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ== - dependencies: - type-fest "^0.20.2" - -globby@^11.1.0: - version "11.1.0" - resolved "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" - integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.2.9" - ignore "^5.2.0" - merge2 "^1.4.1" - slash "^3.0.0" - -grapheme-splitter@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" - integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== - -has-bigints@^1.0.1, has-bigints@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" - integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-property-descriptors@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" - integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== - dependencies: - get-intrinsic "^1.1.1" - -has-symbols@^1.0.2, has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - -has-tostringtag@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== - dependencies: - has-symbols "^1.0.2" - -has@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -ignore@^5.2.0: - version "5.2.0" - resolved "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" - integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== - -immer@^9.0.6: - version "9.0.15" - resolved "https://registry.npmjs.org/immer/-/immer-9.0.15.tgz#0b9169e5b1d22137aba7d43f8a81a495dd1b62dc" - integrity sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ== - -import-fresh@^3.0.0, import-fresh@^3.2.1: - version "3.3.0" - resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2: - version "2.0.4" - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -internal-slot@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" - integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== - dependencies: - get-intrinsic "^1.1.0" - has "^1.0.3" - side-channel "^1.0.4" - -is-bigint@^1.0.1: - version "1.0.4" - resolved "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" - integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== - dependencies: - has-bigints "^1.0.1" - -is-boolean-object@^1.1.0: - version "1.1.2" - resolved "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" - integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-callable@^1.1.4, is-callable@^1.2.4: - version "1.2.4" - resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" - integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== - -is-core-module@^2.8.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" - integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== - dependencies: - has "^1.0.3" - -is-core-module@^2.9.0: - version "2.10.0" - resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz#9012ede0a91c69587e647514e1d5277019e728ed" - integrity sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg== - dependencies: - has "^1.0.3" - -is-date-object@^1.0.1: - version "1.0.5" - resolved "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== - dependencies: - has-tostringtag "^1.0.0" - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: - version "4.0.3" - resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-negative-zero@^2.0.2: - version "2.0.2" - resolved "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" - integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== - -is-number-object@^1.0.4: - version "1.0.7" - resolved "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" - integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== - dependencies: - has-tostringtag "^1.0.0" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-plain-object@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" - integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== - -is-regex@^1.1.4: - version "1.1.4" - resolved "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-shared-array-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" - integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== - dependencies: - call-bind "^1.0.2" - -is-string@^1.0.5, is-string@^1.0.7: - version "1.0.7" - resolved "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" - integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== - dependencies: - has-tostringtag "^1.0.0" - -is-symbol@^1.0.2, is-symbol@^1.0.3: - version "1.0.4" - resolved "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" - integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== - dependencies: - has-symbols "^1.0.2" - -is-weakref@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" - integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== - dependencies: - call-bind "^1.0.2" - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -js-sdsl@^4.1.4: - version "4.3.0" - resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.3.0.tgz#aeefe32a451f7af88425b11fdb5f58c90ae1d711" - integrity sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ== - -"js-tokens@^3.0.0 || ^4.0.0": - version "4.0.0" - resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== - -json5@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== - dependencies: - minimist "^1.2.0" - -levn@^0.4.1: - version "0.4.1" - resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - dependencies: - prelude-ls "^1.2.1" - type-check "~0.4.0" - -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - -lodash.camelcase@4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" - integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== - -lodash.kebabcase@4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36" - integrity sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g== - -lodash.merge@^4.6.2: - version "4.6.2" - resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -lodash.snakecase@4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz#39d714a35357147837aefd64b5dcbb16becd8f8d" - integrity sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw== - -lodash.upperfirst@4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz#1365edf431480481ef0d1c68957a5ed99d49f7ce" - integrity sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg== - -loose-envify@^1.1.0: - version "1.4.0" - resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -merge2@^1.3.0, merge2@^1.4.1: - version "1.4.1" - resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -micromatch@^4.0.4: - version "4.0.5" - resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== - dependencies: - braces "^3.0.2" - picomatch "^2.3.1" - -minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: - version "3.1.2" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimist@^1.2.0, minimist@^1.2.6: - version "1.2.6" - resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" - integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@^2.1.1: - version "2.1.3" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -nanoid@^3.3.4: - version "3.3.4" - resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" - integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== - -natural-compare-lite@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" - integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g== - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== - -next@^13.1.6: - version "13.1.6" - resolved "https://registry.yarnpkg.com/next/-/next-13.1.6.tgz#054babe20b601f21f682f197063c9b0b32f1a27c" - integrity sha512-hHlbhKPj9pW+Cymvfzc15lvhaOZ54l+8sXDXJWm3OBNBzgrVj6hwGPmqqsXg40xO1Leq+kXpllzRPuncpC0Phw== - dependencies: - "@next/env" "13.1.6" - "@swc/helpers" "0.4.14" - caniuse-lite "^1.0.30001406" - postcss "8.4.14" - styled-jsx "5.1.1" - optionalDependencies: - "@next/swc-android-arm-eabi" "13.1.6" - "@next/swc-android-arm64" "13.1.6" - "@next/swc-darwin-arm64" "13.1.6" - "@next/swc-darwin-x64" "13.1.6" - "@next/swc-freebsd-x64" "13.1.6" - "@next/swc-linux-arm-gnueabihf" "13.1.6" - "@next/swc-linux-arm64-gnu" "13.1.6" - "@next/swc-linux-arm64-musl" "13.1.6" - "@next/swc-linux-x64-gnu" "13.1.6" - "@next/swc-linux-x64-musl" "13.1.6" - "@next/swc-win32-arm64-msvc" "13.1.6" - "@next/swc-win32-ia32-msvc" "13.1.6" - "@next/swc-win32-x64-msvc" "13.1.6" - -object-inspect@^1.12.0, object-inspect@^1.9.0: - version "1.12.2" - resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" - integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== - -object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.2: - version "4.1.4" - resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" - integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - has-symbols "^1.0.3" - object-keys "^1.1.1" - -object.values@^1.1.5: - version "1.1.5" - resolved "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz#959f63e3ce9ef108720333082131e4a459b716ac" - integrity sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - dependencies: - wrappy "1" - -optionator@^0.9.1: - version "0.9.1" - resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" - integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== - dependencies: - deep-is "^0.1.3" - fast-levenshtein "^2.0.6" - levn "^0.4.1" - prelude-ls "^1.2.1" - type-check "^0.4.0" - word-wrap "^1.2.3" - -p-limit@^3.0.2: - version "3.1.0" - resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== - dependencies: - p-limit "^3.0.2" - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - -path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - -picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -postcss@8.4.14: - version "8.4.14" - resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz#ee9274d5622b4858c1007a74d76e42e56fd21caf" - integrity sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig== - dependencies: - nanoid "^3.3.4" - picocolors "^1.0.0" - source-map-js "^1.0.2" - -prelude-ls@^1.2.1: - version "1.2.1" - resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== - -prettier-linter-helpers@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" - integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== - dependencies: - fast-diff "^1.1.2" - -prettier@^2.7.1: - version "2.7.1" - resolved "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64" - integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g== - -punycode@^2.1.0: - version "2.1.1" - resolved "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -queue-microtask@^1.2.2: - version "1.2.3" - resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -react-dom@18.2.0: - version "18.2.0" - resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" - integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== - dependencies: - loose-envify "^1.1.0" - scheduler "^0.23.0" - -react-hook-form@^7.34.2: - version "7.34.2" - resolved "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.34.2.tgz#9ac6d1a309a7c4aaa369d1269357a70e9e9bf4de" - integrity sha512-1lYWbEqr0GW7HHUjMScXMidGvV0BE2RJV3ap2BL7G0EJirkqpccTaawbsvBO8GZaB3JjCeFBEbnEWI1P8ZoLRQ== - -react@18.2.0: - version "18.2.0" - resolved "https://registry.npmjs.org/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" - integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== - dependencies: - loose-envify "^1.1.0" - -regexp.prototype.flags@^1.4.3: - version "1.4.3" - resolved "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" - integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - functions-have-names "^1.2.2" - -regexpp@^3.2.0: - version "3.2.0" - resolved "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" - integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve@^1.20.0: - version "1.22.1" - resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" - integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== - dependencies: - is-core-module "^2.9.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - -run-parallel@^1.1.9: - version "1.2.0" - resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== - dependencies: - queue-microtask "^1.2.2" - -scheduler@^0.23.0: - version "0.23.0" - resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" - integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw== - dependencies: - loose-envify "^1.1.0" - -semver@^7.3.7: - version "7.3.7" - resolved "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" - integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== - dependencies: - lru-cache "^6.0.0" - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -side-channel@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" - integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== - dependencies: - call-bind "^1.0.0" - get-intrinsic "^1.0.2" - object-inspect "^1.9.0" - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -slate@^0.82.0: - version "0.82.0" - resolved "https://registry.npmjs.org/slate/-/slate-0.82.0.tgz#3a948347df58af2800bef162179cebc467c08b34" - integrity sha512-2O2NQunBoIWp3M6HP9w1RnNYR6eC52jW4cAXiUDthTxeiwTjL+wrSncls+9jmfqVrUnUb13qbgOEmw6/EdE1yA== - dependencies: - immer "^9.0.6" - is-plain-object "^5.0.0" - tiny-warning "^1.0.3" - -source-map-js@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" - integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== - -string.prototype.trimend@^1.0.5: - version "1.0.5" - resolved "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0" - integrity sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.19.5" - -string.prototype.trimstart@^1.0.5: - version "1.0.5" - resolved "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz#5466d93ba58cfa2134839f81d7f42437e8c01fef" - integrity sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.19.5" - -strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== - -strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -styled-jsx@5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.1.1.tgz#839a1c3aaacc4e735fed0781b8619ea5d0009d1f" - integrity sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw== - dependencies: - client-only "0.0.1" - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== - -tiny-warning@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" - integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -tsconfig-paths@^3.12.0: - version "3.14.1" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz#ba0734599e8ea36c862798e920bcf163277b137a" - integrity sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ== - dependencies: - "@types/json5" "^0.0.29" - json5 "^1.0.1" - minimist "^1.2.6" - strip-bom "^3.0.0" - -tslib@^1.8.1: - version "1.14.1" - resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - -tslib@^2.4.0: - version "2.4.0" - resolved "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" - integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== - -tsutils@^3.21.0: - version "3.21.0" - resolved "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" - integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== - dependencies: - tslib "^1.8.1" - -type-check@^0.4.0, type-check@~0.4.0: - version "0.4.0" - resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - dependencies: - prelude-ls "^1.2.1" - -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - -typescript@4.8.4: - version "4.8.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.4.tgz#c464abca159669597be5f96b8943500b238e60e6" - integrity sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ== - -unbox-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" - integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== - dependencies: - call-bind "^1.0.2" - has-bigints "^1.0.2" - has-symbols "^1.0.3" - which-boxed-primitive "^1.0.2" - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -which-boxed-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== - dependencies: - is-bigint "^1.0.1" - is-boolean-object "^1.1.0" - is-number-object "^1.0.4" - is-string "^1.0.5" - is-symbol "^1.0.3" - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -word-wrap@^1.2.3: - version "1.2.3" - resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== - -wrappy@1: - version "1.0.2" - resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/examples/custom-server/.env.example b/examples/custom-server/.env.example index 02b36af14..bb16827c8 100644 --- a/examples/custom-server/.env.example +++ b/examples/custom-server/.env.example @@ -1,4 +1,4 @@ -MONGODB_URI=mongodb://localhost/payload-example-custom-server +MONGODB_URI=mongodb://127.0.0.1/payload-example-custom-server PAYLOAD_SECRET=PAYLOAD_CUSTOM_SERVER_EXAMPLE_SECRET_KEY PAYLOAD_PUBLIC_SERVER_URL=http://localhost:3000 NEXT_PUBLIC_SERVER_URL=http://localhost:3000 diff --git a/examples/custom-server/.eslintrc.js b/examples/custom-server/.eslintrc.js index 19b786c12..8dc3d9095 100644 --- a/examples/custom-server/.eslintrc.js +++ b/examples/custom-server/.eslintrc.js @@ -1,5 +1,5 @@ module.exports = { root: true, - extends: ['@payloadcms'], + extends: ['plugin:@next/next/recommended', '@payloadcms'], ignorePatterns: ['**/payload-types.ts'], } diff --git a/examples/custom-server/README.md b/examples/custom-server/README.md index a214ae0f0..7f9302c63 100644 --- a/examples/custom-server/README.md +++ b/examples/custom-server/README.md @@ -84,13 +84,9 @@ Check out the [package.json](./src/package.json) in this repository for a comple ## Eject -To eject Next.js from this template and replace it with another front-end framework, follow these steps: +If you prefer another front-end framework or would like to use Payload as a standalone CMS, you can easily eject the front-end from this template. To eject, simply run `yarn eject`. This will uninstall all Next.js related dependencies and delete all files and folders related to the Next.js front-end. It also removes all custom routing from your `server.ts` file and updates your `eslintrc.js`. -1. Remove the `next`, `react`, and `react-dom` dependencies from your `package.json` file -1. Remove the `next.config.js` and `next-env.d.ts` files from your project root -1. Remove the `./src/app` directory and all of its contents - -Now you can install and setup any other framework you'd like. Follow the [Express](#express) instructions above to make the necessary changes to build and serve your front-end. +> Note: Your eject script may not work as expected if you've made significant modifications to your project. If you run into any issues, compare your project's dependencies and file structure with this template, see [./src/eject](./src/eject) for full details. ## Development diff --git a/examples/custom-server/eject.ts b/examples/custom-server/eject.ts new file mode 100644 index 000000000..cc91361df --- /dev/null +++ b/examples/custom-server/eject.ts @@ -0,0 +1,36 @@ +import fs from 'fs' +import path from 'path' + +// Run this script to eject the front-end from this template +// This will remove all template-specific files and directories +// See `yarn eject` in `package.json` for the exact command +// See `./README.md#eject` for more information + +const files = ['./next.config.js', './next-env.d.ts'] +const directories = ['./src/app'] + +const eject = async (): Promise => { + files.forEach(file => { + fs.unlinkSync(path.join(__dirname, file)) + }) + + directories.forEach(directory => { + fs.rm(path.join(__dirname, directory), { recursive: true }, err => { + if (err) throw err + }) + }) + + // create a new `./src/server.ts` file + // use contents from `./src/server.default.ts` + const serverFile = path.join(__dirname, './src/server.ts') + const serverDefaultFile = path.join(__dirname, './src/server.default.ts') + fs.copyFileSync(serverDefaultFile, serverFile) + + // remove `'plugin:@next/next/recommended', ` from `./.eslintrc.js` + const eslintConfigFile = path.join(__dirname, './.eslintrc.js') + const eslintConfig = fs.readFileSync(eslintConfigFile, 'utf8') + const updatedEslintConfig = eslintConfig.replace(`'plugin:@next/next/recommended', `, '') + fs.writeFileSync(eslintConfigFile, updatedEslintConfig, 'utf8') +} + +eject() diff --git a/examples/custom-server/package.json b/examples/custom-server/package.json index 7dedc5e23..15eabbf3d 100644 --- a/examples/custom-server/package.json +++ b/examples/custom-server/package.json @@ -12,6 +12,7 @@ "build:next": "cross-env PAYLOAD_CONFIG_PATH=dist/payload.config.js NEXT_BUILD=true node dist/server.js", "build": "cross-env NODE_ENV=production yarn build:payload && yarn build:server && yarn copyfiles && yarn build:next", "serve": "cross-env PAYLOAD_CONFIG_PATH=dist/payload.config.js NODE_ENV=production node dist/server.js", + "eject": "yarn remove next react react-dom @next/eslint-plugin-next && ts-node eject.ts", "copyfiles": "copyfiles -u 1 \"src/**/*.{html,css,scss,ttf,woff,woff2,eot,svg,jpg,png}\" dist/", "generate:types": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts payload generate:types", "generate:graphQLSchema": "PAYLOAD_CONFIG_PATH=src/payload.config.ts payload generate:graphQLSchema", @@ -22,17 +23,19 @@ "dotenv": "^8.2.0", "escape-html": "^1.0.3", "express": "^4.17.1", - "next": "^13.4.7", + "next": "^13.4.8", "payload": "^1.8.2", "react": "^18.2.0", "react-dom": "^18.2.0" }, "devDependencies": { - "@payloadcms/eslint-config": "^0.0.1", + "@next/eslint-plugin-next": "^13.1.6", + "@payloadcms/eslint-config": "^0.0.2", "@types/escape-html": "^1.0.2", "@types/express": "^4.17.9", "@types/node": "18.11.3", - "@types/react": "18.0.21", + "@types/react": "^18.2.14", + "@types/react-dom": "^18.2.6", "@typescript-eslint/eslint-plugin": "^5.51.0", "@typescript-eslint/parser": "^5.51.0", "copyfiles": "^2.4.1", diff --git a/examples/custom-server/src/app/globals.scss b/examples/custom-server/src/app/app.scss similarity index 96% rename from examples/custom-server/src/app/globals.scss rename to examples/custom-server/src/app/app.scss index eae04652f..21f01bb94 100644 --- a/examples/custom-server/src/app/globals.scss +++ b/examples/custom-server/src/app/app.scss @@ -1,16 +1,17 @@ $breakpoint: 1000px; :root { - --max-width: 1100px; - --border-radius: 12px; + --max-width: 1600px; --foreground-rgb: 0, 0, 0; --background-rgb: 255, 255, 255; --block-spacing: 2rem; --gutter-h: 4rem; + --base: 1rem; @media (max-width: $breakpoint) { --block-spacing: 1rem; --gutter-h: 2rem; + --base: 0.75rem; } } diff --git a/examples/custom-server/src/app/layout.module.scss b/examples/custom-server/src/app/layout.module.scss index 2aa678797..f43a839c6 100644 --- a/examples/custom-server/src/app/layout.module.scss +++ b/examples/custom-server/src/app/layout.module.scss @@ -3,10 +3,6 @@ min-height: 100vh; } -.logo { - width: 200px; -} - .header { margin-bottom: 4rem; display: flex; @@ -14,3 +10,7 @@ align-items: center; justify-content: center; } + +.logo { + width: 200px; +} diff --git a/examples/custom-server/src/app/layout.tsx b/examples/custom-server/src/app/layout.tsx index 66760106b..0099dd423 100644 --- a/examples/custom-server/src/app/layout.tsx +++ b/examples/custom-server/src/app/layout.tsx @@ -1,6 +1,7 @@ import React from 'react' +import Link from 'next/link' -import './globals.scss' +import './app.scss' import classes from './layout.module.scss' @@ -14,7 +15,7 @@ export default function RootLayout({ children }: { children: React.ReactNode })
    - + - +
    {children} diff --git a/examples/custom-server/src/server.default.ts b/examples/custom-server/src/server.default.ts new file mode 100644 index 000000000..e0e911233 --- /dev/null +++ b/examples/custom-server/src/server.default.ts @@ -0,0 +1,45 @@ +import dotenv from 'dotenv' +import path from 'path' + +// This file is used to replace `server.ts` when ejecting i.e. `yarn eject` +// See `../eject.ts` for exact details on how this file is used +// See `./README.md#eject` for more information + +dotenv.config({ + path: path.resolve(__dirname, '../.env'), +}) + +import express from 'express' +import payload from 'payload' + +import { seed } from './seed' + +const app = express() +const PORT = process.env.PORT || 3000 + +// Redirect root to the admin panel +app.get('/', (_, res) => { + res.redirect('/admin') +}) + +const start = async (): Promise => { + await payload.init({ + secret: process.env.PAYLOAD_SECRET || '', + mongoURL: process.env.MONGODB_URI || '', + express: app, + onInit: () => { + payload.logger.info(`Payload Admin URL: ${payload.getAdminURL()}`) + }, + }) + + if (process.env.PAYLOAD_SEED === 'true') { + payload.logger.info('---- SEEDING DATABASE ----') + await seed(payload) + } + + app.listen(PORT, async () => { + payload.logger.info(`App URL: ${process.env.PAYLOAD_PUBLIC_SERVER_URL}`) + }) +} + +start() diff --git a/examples/custom-server/src/server.ts b/examples/custom-server/src/server.ts index c0b5ba213..727ca6e99 100644 --- a/examples/custom-server/src/server.ts +++ b/examples/custom-server/src/server.ts @@ -53,7 +53,7 @@ const start = async (): Promise => { payload.logger.info('Next.js started') app.listen(PORT, async () => { - payload.logger.info(`Server listening on ${PORT}...`) + payload.logger.info(`Next.js App URL: ${process.env.PAYLOAD_PUBLIC_SERVER_URL}`) }) }) } diff --git a/examples/custom-server/yarn.lock b/examples/custom-server/yarn.lock index 65bcf0b3b..fdbf7765e 100644 --- a/examples/custom-server/yarn.lock +++ b/examples/custom-server/yarn.lock @@ -517,55 +517,62 @@ dependencies: "@monaco-editor/loader" "^1.3.3" -"@next/env@13.4.7": - version "13.4.7" - resolved "https://registry.yarnpkg.com/@next/env/-/env-13.4.7.tgz#ca12d341edb128ca70384635bd2794125ffb1c01" - integrity sha512-ZlbiFulnwiFsW9UV1ku1OvX/oyIPLtMk9p/nnvDSwI0s7vSoZdRtxXNsaO+ZXrLv/pMbXVGq4lL8TbY9iuGmVw== +"@next/env@13.4.8": + version "13.4.8" + resolved "https://registry.yarnpkg.com/@next/env/-/env-13.4.8.tgz#8048ef3c3d770a3f3d1dd51d159593acfbd4e517" + integrity sha512-twuSf1klb3k9wXI7IZhbZGtFCWvGD4wXTY2rmvzIgVhXhs7ISThrbNyutBx3jWIL8Y/Hk9+woytFz5QsgtcRKQ== -"@next/swc-darwin-arm64@13.4.7": - version "13.4.7" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.7.tgz#5e36c26dda5b0bc0ea15d8555d0abd71a1ef4b5d" - integrity sha512-VZTxPv1b59KGiv/pZHTO5Gbsdeoxcj2rU2cqJu03btMhHpn3vwzEK0gUSVC/XW96aeGO67X+cMahhwHzef24/w== +"@next/eslint-plugin-next@^13.1.6": + version "13.4.8" + resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-13.4.8.tgz#2aa7a0bbfc87fbed5aa0e938d0d16dca85061ee4" + integrity sha512-cmfVHpxWjjcETFt2WHnoFU6EmY69QcPJRlRNAooQlNe53Ke90vg1Ci/dkPffryJZaxxiRziP9bQrV8lDVCn3Fw== + dependencies: + glob "7.1.7" -"@next/swc-darwin-x64@13.4.7": - version "13.4.7" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.7.tgz#4c14ec14b200373cd602589086cb1253a28cd803" - integrity sha512-gO2bw+2Ymmga+QYujjvDz9955xvYGrWofmxTq7m70b9pDPvl7aDFABJOZ2a8SRCuSNB5mXU8eTOmVVwyp/nAew== +"@next/swc-darwin-arm64@13.4.8": + version "13.4.8" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.8.tgz#3838d7c96750b7f427ac47b97503fc013734f6e6" + integrity sha512-MSFplVM4dTWOuKAUv0XR9gY7AWtMSBu9os9f+kp+s5rWhM1I2CdR3obFttd6366nS/W/VZxbPM5oEIdlIa46zA== -"@next/swc-linux-arm64-gnu@13.4.7": - version "13.4.7" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.7.tgz#e7819167ec876ddac5a959e4c7bce4d001f0e924" - integrity sha512-6cqp3vf1eHxjIDhEOc7Mh/s8z1cwc/l5B6ZNkOofmZVyu1zsbEM5Hmx64s12Rd9AYgGoiCz4OJ4M/oRnkE16/Q== +"@next/swc-darwin-x64@13.4.8": + version "13.4.8" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.8.tgz#3de9c26a2ee7b189f22433bf8137256a2517f258" + integrity sha512-Reox+UXgonon9P0WNDE6w85DGtyBqGitl/ryznOvn6TvfxEaZIpTgeu3ZrJLU9dHSMhiK7YAM793mE/Zii2/Qw== -"@next/swc-linux-arm64-musl@13.4.7": - version "13.4.7" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.7.tgz#0cac0f01d4e308b439e6c33182bed77835fe383b" - integrity sha512-T1kD2FWOEy5WPidOn1si0rYmWORNch4a/NR52Ghyp4q7KyxOCuiOfZzyhVC5tsLIBDH3+cNdB5DkD9afpNDaOw== +"@next/swc-linux-arm64-gnu@13.4.8": + version "13.4.8" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.8.tgz#9536314c931b9e78f20e4a424eace9993015c6e1" + integrity sha512-kdyzYvAYtqQVgzIKNN7e1rLU8aZv86FDSRqPlOkKZlvqudvTO0iohuTPmnEEDlECeBM6qRPShNffotDcU/R2KA== -"@next/swc-linux-x64-gnu@13.4.7": - version "13.4.7" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.7.tgz#feb61e16a68c67f3ef230f30d9562a3783c7bd59" - integrity sha512-zaEC+iEiAHNdhl6fuwl0H0shnTzQoAoJiDYBUze8QTntE/GNPfTYpYboxF5LRYIjBwETUatvE0T64W6SKDipvg== +"@next/swc-linux-arm64-musl@13.4.8": + version "13.4.8" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.8.tgz#a894ec6a078edd28f5cfab60593a61e05b6b605b" + integrity sha512-oWxx4yRkUGcR81XwbI+T0zhZ3bDF6V1aVLpG+C7hSG50ULpV8gC39UxVO22/bv93ZlcfMY4zl8xkz9Klct6dpQ== -"@next/swc-linux-x64-musl@13.4.7": - version "13.4.7" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.7.tgz#02179ecfa6d24a2956c2b54f7d27a050568bbf24" - integrity sha512-X6r12F8d8SKAtYJqLZBBMIwEqcTRvUdVm+xIq+l6pJqlgT2tNsLLf2i5Cl88xSsIytBICGsCNNHd+siD2fbWBA== +"@next/swc-linux-x64-gnu@13.4.8": + version "13.4.8" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.8.tgz#b8af198dc0b4a8c64deb0494ae285e3e1a465910" + integrity sha512-anhtvuO6eE9YRhYnaEGTfbpH3L5gT/9qPFcNoi6xS432r/4DAtpJY8kNktqkTVevVIC/pVumqO8tV59PR3zbNg== -"@next/swc-win32-arm64-msvc@13.4.7": - version "13.4.7" - resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.7.tgz#274b7f00a2ec5934af73db15da8459e8647bfaed" - integrity sha512-NPnmnV+vEIxnu6SUvjnuaWRglZzw4ox5n/MQTxeUhb5iwVWFedolPFebMNwgrWu4AELwvTdGtWjqof53AiWHcw== +"@next/swc-linux-x64-musl@13.4.8": + version "13.4.8" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.8.tgz#d2ad24001020665a78405f595995c22750ec63c4" + integrity sha512-aR+J4wWfNgH1DwCCBNjan7Iumx0lLtn+2/rEYuhIrYLY4vnxqSVGz9u3fXcgUwo6Q9LT8NFkaqK1vPprdq+BXg== -"@next/swc-win32-ia32-msvc@13.4.7": - version "13.4.7" - resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.7.tgz#4a95c106a6db2eee3a4c1352b77995e298d7446a" - integrity sha512-6Hxijm6/a8XqLQpOOf/XuwWRhcuc/g4rBB2oxjgCMuV9Xlr2bLs5+lXyh8w9YbAUMYR3iC9mgOlXbHa79elmXw== +"@next/swc-win32-arm64-msvc@13.4.8": + version "13.4.8" + resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.8.tgz#e5c4bfaa105fbe2bdb21a6d01467edd39a29cf37" + integrity sha512-OWBKIrJwQBTqrat0xhxEB/jcsjJR3+diD9nc/Y8F1mRdQzsn4bPsomgJyuqPVZs6Lz3K18qdIkvywmfSq75SsQ== -"@next/swc-win32-x64-msvc@13.4.7": - version "13.4.7" - resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.7.tgz#5137780f58d7f0230adc293a0429821bfa7d8c21" - integrity sha512-sW9Yt36Db1nXJL+mTr2Wo0y+VkPWeYhygvcHj1FF0srVtV+VoDjxleKtny21QHaG05zdeZnw2fCtf2+dEqgwqA== +"@next/swc-win32-ia32-msvc@13.4.8": + version "13.4.8" + resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.8.tgz#c49c4d9f91845855bf544d5d14e8e13311da9931" + integrity sha512-agiPWGjUndXGTOn4ChbKipQXRA6/UPkywAWIkx7BhgGv48TiJfHTK6MGfBoL9tS6B4mtW39++uy0wFPnfD0JWg== + +"@next/swc-win32-x64-msvc@13.4.8": + version "13.4.8" + resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.8.tgz#22c5c8fa05680f2775a29c6c5a74cf04b8cc9d90" + integrity sha512-UIRKoByVKbuR6SnFG4JM8EMFlJrfEGuUQ1ihxzEleWcNwRMMiVaCj1KyqfTOW8VTQhJ0u8P1Ngg6q1RwnIBTtw== "@nodelib/fs.scandir@2.1.5": version "2.1.5" @@ -588,10 +595,10 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@payloadcms/eslint-config@^0.0.1": - version "0.0.1" - resolved "https://registry.yarnpkg.com/@payloadcms/eslint-config/-/eslint-config-0.0.1.tgz#4324702ddef6c773b3f3033795a13e6b50c95a92" - integrity sha512-Il59+0C4E/bI6uM2hont3I+oABWkJZbfbItubje5SGMrXkymUq8jT/UZRk0eCt918bB7gihxDXx8guFnR/aNIw== +"@payloadcms/eslint-config@^0.0.2": + version "0.0.2" + resolved "https://registry.yarnpkg.com/@payloadcms/eslint-config/-/eslint-config-0.0.2.tgz#cadb97ccd6476204a38e057b3cf57dc80efb209f" + integrity sha512-EcS7qyX4++eBP/MS4QgrFOzzplsVMaPDfEcxWYoH9OLJCUTlGz8UmfMZPWU7DeAuyehJdij+BywSrcprqun9rA== "@polka/url@^1.0.0-next.20": version "1.0.0-next.21" @@ -905,6 +912,13 @@ resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== +"@types/react-dom@^18.2.6": + version "18.2.6" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.6.tgz#ad621fa71a8db29af7c31b41b2ea3d8a6f4144d1" + integrity sha512-2et4PDvg6PVCyS7fuTc4gPoksV58bW0RwSxWKcPRcHZf0PRUGq03TKcD/rUHe3azfV6/5/biUBJw+HhCQjaP0A== + dependencies: + "@types/react" "*" + "@types/react-transition-group@^4.4.0": version "4.4.6" resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.6.tgz#18187bcda5281f8e10dfc48f0943e2fdf4f75e2e" @@ -912,7 +926,7 @@ dependencies: "@types/react" "*" -"@types/react@*": +"@types/react@*", "@types/react@^18.2.14": version "18.2.14" resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.14.tgz#fa7a6fecf1ce35ca94e74874f70c56ce88f7a127" integrity sha512-A0zjq+QN/O0Kpe30hA1GidzyFjatVvrpIvWLxD+xv67Vt91TWWgco9IvrJBkeyHm1trGaFS/FSGqPlhyeZRm0g== @@ -921,15 +935,6 @@ "@types/scheduler" "*" csstype "^3.0.2" -"@types/react@18.0.21": - version "18.0.21" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.21.tgz#b8209e9626bb00a34c76f55482697edd2b43cc67" - integrity sha512-7QUCOxvFgnD5Jk8ZKlUAhVcRj7GuJRjnjjiY/IUBWKgOlnvDvTMLD4RTF7NPyVmbRhNrbomZiOepg7M/2Kj1mA== - dependencies: - "@types/prop-types" "*" - "@types/scheduler" "*" - csstype "^3.0.2" - "@types/scheduler@*": version "0.16.3" resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.3.tgz#cef09e3ec9af1d63d2a6cc5b383a737e24e6dcf5" @@ -3130,6 +3135,18 @@ glob-to-regexp@^0.4.1: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== +glob@7.1.7: + version "7.1.7" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" + integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + glob@^7.0.5, glob@^7.1.3, glob@^7.1.6: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" @@ -4367,12 +4384,12 @@ next-tick@1, next-tick@^1.1.0: resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== -next@^13.4.7: - version "13.4.7" - resolved "https://registry.yarnpkg.com/next/-/next-13.4.7.tgz#2ab20e6fada2e25cb81bd17f68956705ffd9824e" - integrity sha512-M8z3k9VmG51SRT6v5uDKdJXcAqLzP3C+vaKfLIAM0Mhx1um1G7MDnO63+m52qPdZfrTFzMZNzfsgvm3ghuVHIQ== +next@^13.4.8: + version "13.4.8" + resolved "https://registry.yarnpkg.com/next/-/next-13.4.8.tgz#72245bf4fdf328970147ee30de97142c39b1cb3f" + integrity sha512-lxUjndYKjZHGK3CWeN2RI+/6ni6EUvjiqGWXAYPxUfGIdFGQ5XoisrqAJ/dF74aP27buAfs8MKIbIMMdxjqSBg== dependencies: - "@next/env" "13.4.7" + "@next/env" "13.4.8" "@swc/helpers" "0.5.1" busboy "1.6.0" caniuse-lite "^1.0.30001406" @@ -4381,15 +4398,15 @@ next@^13.4.7: watchpack "2.4.0" zod "3.21.4" optionalDependencies: - "@next/swc-darwin-arm64" "13.4.7" - "@next/swc-darwin-x64" "13.4.7" - "@next/swc-linux-arm64-gnu" "13.4.7" - "@next/swc-linux-arm64-musl" "13.4.7" - "@next/swc-linux-x64-gnu" "13.4.7" - "@next/swc-linux-x64-musl" "13.4.7" - "@next/swc-win32-arm64-msvc" "13.4.7" - "@next/swc-win32-ia32-msvc" "13.4.7" - "@next/swc-win32-x64-msvc" "13.4.7" + "@next/swc-darwin-arm64" "13.4.8" + "@next/swc-darwin-x64" "13.4.8" + "@next/swc-linux-arm64-gnu" "13.4.8" + "@next/swc-linux-arm64-musl" "13.4.8" + "@next/swc-linux-x64-gnu" "13.4.8" + "@next/swc-linux-x64-musl" "13.4.8" + "@next/swc-win32-arm64-msvc" "13.4.8" + "@next/swc-win32-ia32-msvc" "13.4.8" + "@next/swc-win32-x64-msvc" "13.4.8" no-case@^3.0.4: version "3.0.4" diff --git a/examples/email/.env.example b/examples/email/.env.example index abee5859d..5c28152cf 100644 --- a/examples/email/.env.example +++ b/examples/email/.env.example @@ -1,4 +1,4 @@ -MONGODB_URI=mongodb://localhost/payload-example-email +MONGODB_URI=mongodb://127.0.0.1/payload-example-email PAYLOAD_SECRET= NODE_ENV=development PAYLOAD_PUBLIC_SERVER_URL=http://localhost:8000 diff --git a/examples/form-builder/cms/.env.example b/examples/form-builder/cms/.env.example index a1766fe3b..9a692c644 100644 --- a/examples/form-builder/cms/.env.example +++ b/examples/form-builder/cms/.env.example @@ -1,4 +1,4 @@ -MONGODB_URI=mongodb://localhost/payload-example-form-builder +MONGODB_URI=mongodb://127.0.0.1/payload-example-form-builder PAYLOAD_SECRET=ENTER-STRING-HERE PAYLOAD_PUBLIC_SITE_URL=http://localhost:3000 PAYLOAD_PUBLIC_SERVER_URL=http://localhost:8000 diff --git a/examples/multi-tenant/.env.example b/examples/multi-tenant/.env.example index f80d4ca14..d0bf69170 100644 --- a/examples/multi-tenant/.env.example +++ b/examples/multi-tenant/.env.example @@ -1,4 +1,4 @@ -MONGODB_URI=mongodb://localhost/payload-example-auth +MONGODB_URI=mongodb://127.0.0.1/payload-example-auth PAYLOAD_SECRET=PAYLOAD_AUTH_EXAMPLE_SECRET_KEY PAYLOAD_PUBLIC_SERVER_URL=http://localhost:3000 PAYLOAD_SEED=true diff --git a/examples/preview/cms/.env.example b/examples/preview/cms/.env.example index e0515a9e4..758bbbdc8 100644 --- a/examples/preview/cms/.env.example +++ b/examples/preview/cms/.env.example @@ -1,6 +1,9 @@ -MONGODB_URI=mongodb://localhost/payload-example-preview +MONGODB_URI=mongodb://127.0.0.1/payload-example-preview PAYLOAD_SECRET=ENTER-STRING-HERE -PAYLOAD_PUBLIC_SITE_URL=http://localhost:3000 -PAYLOAD_PUBLIC_SERVER_URL=http://localhost:8000 +PAYLOAD_PUBLIC_SERVER_URL=http://localhost:3000 +PAYLOAD_PUBLIC_SITE_URL=http://localhost:3001 +PAYLOAD_PUBLIC_DRAFT_SECRET=EXAMPLE_DRAFT_SECRET COOKIE_DOMAIN=localhost REVALIDATION_KEY=EXAMPLE_REVALIDATION_KEY +PAYLOAD_SEED=true +PAYLOAD_DROP_DATABASE=true diff --git a/examples/preview/cms/.npmrc b/examples/preview/cms/.npmrc deleted file mode 100644 index 521a9f7c0..000000000 --- a/examples/preview/cms/.npmrc +++ /dev/null @@ -1 +0,0 @@ -legacy-peer-deps=true diff --git a/examples/preview/cms/README.md b/examples/preview/cms/README.md index 867a4c4d1..bfbd61524 100644 --- a/examples/preview/cms/README.md +++ b/examples/preview/cms/README.md @@ -1,8 +1,8 @@ # Payload Preview Example -This example demonstrates how to implement preview into Payload using [Versions](https://payloadcms.com/docs/versions/overview) and [Drafts](https://payloadcms.com/docs/versions/drafts). +This example demonstrates how to implement preview in [Payload](https://github.com/payloadcms/payload) using [Versions](https://payloadcms.com/docs/versions/overview) and [Drafts](https://payloadcms.com/docs/versions/drafts). Preview allows you to see draft content on your front-end before it is published. -There is a fully working Next.js app made explicitly for this example which can be found [here](../nextjs). Follow the instructions there to get started. If you are setting up preview for another front-end, please consider contributing to this repo with your own example! +There is a fully working Next.js app made explicitly for this example which can be found [here](../next-app). Follow the instructions there to get started. If you are setting up preview for another front-end, please consider contributing to this repo with your own example! ## Quick Start @@ -10,47 +10,76 @@ There is a fully working Next.js app made explicitly for this example which can 2. `cd` into this directory and run `yarn` or `npm install` 3. `cp .env.example .env` to copy the example environment variables 4. `yarn dev` or `npm run dev` to start the server and seed the database -5. `open http://localhost:8000/admin` to access the admin panel -6. Login with email `dev@payloadcms.com` and password `test` +5. `open http://localhost:3000/admin` to access the admin panel +6. Login with email `demo@payloadcms.com` and password `demo` That's it! Changes made in `./src` will be reflected in your app. See the [Development](#development) section for more details. ## How it works -A `pages` collection is created with `versions: { drafts: true }` and access control that restricts access to only logged-in users and `published` pages. On your front-end, a query similar to this can be used to fetch data and bypass access control in preview mode: +Preview works by sending the user to your front-end with a `secret` along with their http-only cookies. Your front-end catches the request, verifies the authenticity, then enters into it's own preview mode. Once in preview mode, your front-end can begin securely requesting draft documents from Payload. -```ts - const preview = true; // set this based on your own front-end environment (see `Preview Mode` below) - const pageSlug = 'example-page'; // same here - const searchParams = `?where[slug][equals]=${pageSlug}&depth=1${preview ? `&draft=true` : ''}` +### Collections - // when previewing, send the payload token to bypass draft access control - const pageReq = await fetch(`${process.env.NEXT_PUBLIC_CMS_URL}/api/pages${searchParams}`, { - headers: { - ...preview ? { - Authorization: `JWT ${payloadToken}`, - } : {}, - }, - }) -``` +See the [Collections](https://payloadcms.com/docs/configuration/collections) docs for details on how to extend any of this functionality. -The [`cors`](https://payloadcms.com/docs/production/preventing-abuse#cross-origin-resource-sharing-cors), [`csrf`](https://payloadcms.com/docs/production/preventing-abuse#cross-site-request-forgery-csrf), and [`cookies`](https://payloadcms.com/docs/authentication/config#options) settings are also configured to ensure that the admin panel and front-end can communicate with each other securely. +- #### Users + + The `users` collection is auth-enabled which provides access to the admin panel. When previewing documents on your front-end, the user's JWT is used to authenticate the request. See [Pages](#pages) for more details. + + For additional help with authentication, see the [Authentication](https://payloadcms.com/docs/authentication/overview#authentication-overview) docs or the official [Auth Example](https://github.com/payloadcms/payload/tree/master/examples/auth/cms#readme). + +- #### Pages + + The `pages` collection is draft-enabled and has access control that restricts public users from viewing pages with a `draft` status. To fetch draft documents on your front-end, simply include the `draft=true` query param along with the `Authorization` header once you have entered [Preview Mode](#preview-mode). + + ```ts + const preview = true; // set this based on your own front-end environment (see `Preview Mode` below) + const pageSlug = 'example-page'; // same here + const searchParams = `?where[slug][equals]=${pageSlug}&depth=1${preview ? `&draft=true` : ''}` + + // when previewing, send the payload token to bypass draft access control + const pageReq = await fetch(`${process.env.NEXT_PUBLIC_CMS_URL}/api/pages${searchParams}`, { + headers: { + ...preview ? { + Authorization: `JWT ${payloadToken}`, + } : {}, + }, + }) + ``` + + For more details on how to extend this functionality, see the [Authentication](https://payloadcms.com/docs/authentication) docs. ### Preview Mode -To enter preview mode we format a custom URL using a [preview function](https://payloadcms.com/docs/configuration/collections#preview) in the collection config. When a user clicks the "Preview" button, they are routed to this URL along with their http-only cookies and revalidation key. Your front-end can then use the `payload-token` and revalidation key to verify the request and enter into its own preview mode. +To enter preview mode, the user first needs to have at least one draft document saved. When they click the "preview" button from the Payload admin panel, a custom [preview function](https://payloadcms.com/docs/configuration/collections#preview) routes them to your front-end with a `secret` and their http-only cookies. An API route on your front-end will verify the secret and token before entering into it's own preview mode. Once in preview mode, it can begin requesting drafts from Payload using the `Authorization` header, see [Pages](#pages) for more details. -### ISR +> "Preview mode" looks differently for every front-end framework. For instance, check out the differences between Next.js [Preview Mode](https://nextjs.org/docs/pages/building-your-application/configuring/preview-mode) in the Pages Router and [Draft Mode](https://nextjs.org/docs/pages/building-your-application/configuring/draft-mode) in the App Router. In Next.js, methods are provided that set cookies in your browser, but this may not be the case for all frameworks. -If your front-end is statically generated then you may also want to regenerate the HTML for each page as they are published, sometimes referred to as Incremental Static Regeneration. To do this, we add an `afterChange` hook to the collection that fires a request to your front-end in the background each time the document is updated. You can handle this request on your front-end and regenerate the HTML for your page however needed. +### On-demand Revalidation + +If your front-end is statically generated then you may also want to regenerate the HTML for each page individually as they are published, referred to as On-demand Revalidation. This will prevent your static site from having to fully rebuild every page in order to deploy content changes. To do this, we add an `afterChange` hook to the collection that fires a request to your front-end in the background each time the document is updated. You can handle this request on your front-end to revalidate the HTML for your page. + +> On-demand revalidation looks differently for every front-end framework. For instance, check out the differences between Next.js on-demand revalidation in the [Pages Router](https://nextjs.org/docs/pages/building-your-application/data-fetching/incremental-static-regeneration) and the [App Router](https://nextjs.org/docs/app/building-your-application/data-fetching/revalidating#on-demand-revalidation). In Next.js, methods are provided that regenerate the HTML for each page, but this may not be the case for all frameworks. + +### Admin Bar + +You might also want to render an admin bar on your front-end so that logged-in users can quickly navigate between the front-end and Payload as they're editing. For React apps, check out the official [Payload Admin Bar](https://github.com/payloadcms/payload-admin-bar). For other frameworks, simply hit the `/me` route with `credentials: include` and render your own admin bar if the user is logged in in order to display quick links to your CMS. + +### CORS + +The [`cors`](https://payloadcms.com/docs/production/preventing-abuse#cross-origin-resource-sharing-cors), [`csrf`](https://payloadcms.com/docs/production/preventing-abuse#cross-site-request-forgery-csrf), and [`cookies`](https://payloadcms.com/docs/authentication/config#options) settings are configured to ensure that the admin panel and front-end can communicate with each other securely. If you are combining your front-end and admin panel into a single application that runs of a shared port and domain, you can remove these settings from your config. + +For more details on this, see the [CORS](https://payloadcms.com/docs/production/preventing-abuse#cross-origin-resource-sharing-cors) docs. ## Development To spin up this example locally, follow the [Quick Start](#quick-start). + ### Seed -On boot, a seed script is included to create a user, a home page, and an example page with two versions, one published and one draft. +On boot, a seed script is included to scaffold a basic database for you to use as an example. This is done by setting the `PAYLOAD_DROP_DATABASE` and `PAYLOAD_SEED` environment variables which are included in the `.env.example` by default. You can remove these from your `.env` to prevent this behavior. You can also freshly seed your project at any time by running `yarn seed`. This seed creates a user with email `demo@payloadcms.com` and password `demo` along with a home page and an example page with two versions, one published and the other draft. > NOTICE: seeding the database is destructive because it drops your current database to populate a fresh one from the seed template. Only run this command if you are starting a new project or can afford to lose your current data. @@ -63,7 +92,7 @@ To run Payload in production, you need to build and serve the Admin panel. To do ### Deployment -The easiest way to deploy your project is to use [Payload Cloud](https://payloadcms.com/new/import), a one-click hosting solution to deploy production-ready instances of your Payload apps directly from your GitHub repo. You can also deploy your app manually, check out the [deployment documentation](https://payloadcms.com/docs/production/deployment) for full details. +The easiest way to deploy your project is to use [Payload Cloud](https://payloadcms.com/new/import), a one-click hosting solution to deploy production-ready instances of your Payload apps directly from your GitHub repo. You can also choose to self-host your app, check out the [Deployment](https://payloadcms.com/docs/production/deployment) docs for more details. ## Questions diff --git a/examples/preview/cms/package.json b/examples/preview/cms/package.json index 82979dfcf..7a6dd3e97 100644 --- a/examples/preview/cms/package.json +++ b/examples/preview/cms/package.json @@ -5,7 +5,8 @@ "main": "dist/server.js", "license": "MIT", "scripts": { - "dev": "cross-env PAYLOAD_SEED=true PAYLOAD_DROP_DATABASE=true PAYLOAD_CONFIG_PATH=src/payload.config.ts nodemon", + "dev": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts nodemon", + "seed": "rm -rf media && cross-env PAYLOAD_SEED=true PAYLOAD_DROP_DATABASE=true PAYLOAD_CONFIG_PATH=src/payload.config.ts ts-node src/server.ts", "build:payload": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts payload build", "build:server": "tsc", "build": "yarn copyfiles && yarn build:payload && yarn build:server", @@ -19,10 +20,10 @@ "dependencies": { "dotenv": "^8.2.0", "express": "^4.17.1", - "payload": "^1.7.5" + "payload": "^1.11.0" }, "devDependencies": { - "@payloadcms/eslint-config": "^0.0.1", + "@payloadcms/eslint-config": "^0.0.2", "@types/express": "^4.17.9", "@types/node": "18.11.3", "@types/react": "18.0.21", diff --git a/examples/preview/cms/src/collections/Pages/index.ts b/examples/preview/cms/src/collections/Pages/index.ts index d9a95818b..f4bde2e1a 100644 --- a/examples/preview/cms/src/collections/Pages/index.ts +++ b/examples/preview/cms/src/collections/Pages/index.ts @@ -1,4 +1,5 @@ -import { CollectionConfig } from 'payload/types' +import type { CollectionConfig } from 'payload/types' + import richText from '../../fields/richText' import { loggedIn } from './access/loggedIn' import { publishedOrLoggedIn } from './access/publishedOrLoggedIn' @@ -10,8 +11,13 @@ export const Pages: CollectionConfig = { admin: { useAsTitle: 'title', defaultColumns: ['title', 'slug', 'updatedAt'], - preview: doc => - `${process.env.PAYLOAD_PUBLIC_SITE_URL}/api/preview?url=${formatAppURL({ doc })}`, + preview: doc => { + return `${process.env.PAYLOAD_PUBLIC_SITE_URL}/api/preview?url=${encodeURIComponent( + formatAppURL({ + doc, + }), + )}&secret=${process.env.PAYLOAD_PUBLIC_DRAFT_SECRET}` + }, }, versions: { drafts: true, diff --git a/examples/preview/cms/src/fields/link.ts b/examples/preview/cms/src/fields/link.ts index b4da03254..a9abc3a9d 100644 --- a/examples/preview/cms/src/fields/link.ts +++ b/examples/preview/cms/src/fields/link.ts @@ -1,4 +1,5 @@ import type { Field } from 'payload/types' + import deepMerge from '../utilities/deepMerge' export const appearanceOptions = { diff --git a/examples/preview/cms/src/fields/richText/index.ts b/examples/preview/cms/src/fields/richText/index.ts index c7c4546f4..b000334c1 100644 --- a/examples/preview/cms/src/fields/richText/index.ts +++ b/examples/preview/cms/src/fields/richText/index.ts @@ -1,8 +1,9 @@ import type { RichTextElement, RichTextField, RichTextLeaf } from 'payload/dist/fields/config/types' + import deepMerge from '../../utilities/deepMerge' +import link from '../link' import elements from './elements' import leaves from './leaves' -import link from '../link' type RichText = ( overrides?: Partial, diff --git a/examples/preview/cms/src/globals/MainMenu.ts b/examples/preview/cms/src/globals/MainMenu.ts index 6078a9fde..430039d0b 100644 --- a/examples/preview/cms/src/globals/MainMenu.ts +++ b/examples/preview/cms/src/globals/MainMenu.ts @@ -1,4 +1,5 @@ import type { GlobalConfig } from 'payload/types' + import link from '../fields/link' export const MainMenu: GlobalConfig = { diff --git a/examples/preview/cms/src/payload-types.ts b/examples/preview/cms/src/payload-types.ts index 6e1e2bf5e..f7100b59a 100644 --- a/examples/preview/cms/src/payload-types.ts +++ b/examples/preview/cms/src/payload-types.ts @@ -1,4 +1,5 @@ /* tslint:disable */ +/* eslint-disable */ /** * This file was automatically generated by Payload. * DO NOT MODIFY IT BY HAND. Instead, modify your source Payload config, @@ -7,49 +8,52 @@ export interface Config { collections: { - pages: Page - users: User - } + pages: Page; + users: User; + }; globals: { - 'main-menu': MainMenu - } + 'main-menu': MainMenu; + }; } export interface Page { - id: string - title: string - slug?: string - richText: Array<{ - [k: string]: unknown - }> - _status?: 'draft' | 'published' - createdAt: string - updatedAt: string - password?: string + id: string; + title: string; + slug?: string; + richText: { + [k: string]: unknown; + }[]; + updatedAt: string; + createdAt: string; + _status?: 'draft' | 'published'; } export interface User { - id: string - email?: string - resetPasswordToken?: string - resetPasswordExpiration?: string - loginAttempts?: number - lockUntil?: string - createdAt: string - updatedAt: string - password?: string + id: string; + updatedAt: string; + createdAt: string; + email: string; + resetPasswordToken?: string; + resetPasswordExpiration?: string; + salt?: string; + hash?: string; + loginAttempts?: number; + lockUntil?: string; + password?: string; } export interface MainMenu { - id: string - navItems: Array<{ + id: string; + navItems?: { link: { - type?: 'reference' | 'custom' - newTab?: boolean + type?: 'reference' | 'custom'; + newTab?: boolean; reference: { - value: string | Page - relationTo: 'pages' - } - url: string - label: string - } - id?: string - }> + value: string | Page; + relationTo: 'pages'; + }; + url: string; + label: string; + }; + id?: string; + }[]; + updatedAt?: string; + createdAt?: string; } diff --git a/examples/preview/cms/src/payload.config.ts b/examples/preview/cms/src/payload.config.ts index b3bfb75a0..55f4047fd 100644 --- a/examples/preview/cms/src/payload.config.ts +++ b/examples/preview/cms/src/payload.config.ts @@ -1,13 +1,21 @@ -import { buildConfig } from 'payload/config' import path from 'path' -import { Users } from './collections/Users' +import { buildConfig } from 'payload/config' + import { Pages } from './collections/Pages' +import { Users } from './collections/Users' import { MainMenu } from './globals/MainMenu' export default buildConfig({ collections: [Pages, Users], - cors: [process.env.PAYLOAD_PUBLIC_SERVER_URL, process.env.PAYLOAD_PUBLIC_SITE_URL], - csrf: [process.env.PAYLOAD_PUBLIC_SERVER_URL, process.env.PAYLOAD_PUBLIC_SITE_URL], + serverURL: process.env.PAYLOAD_PUBLIC_SERVER_URL, + cors: [ + process.env.PAYLOAD_PUBLIC_SERVER_URL || '', + process.env.PAYLOAD_PUBLIC_SITE_URL || '', + ].filter(Boolean), + csrf: [ + process.env.PAYLOAD_PUBLIC_SERVER_URL || '', + process.env.PAYLOAD_PUBLIC_SITE_URL || '', + ].filter(Boolean), globals: [MainMenu], typescript: { outputFile: path.resolve(__dirname, 'payload-types.ts'), diff --git a/examples/preview/cms/src/seed/home.ts b/examples/preview/cms/src/seed/home.ts index 3b2fac01f..9601b768b 100644 --- a/examples/preview/cms/src/seed/home.ts +++ b/examples/preview/cms/src/seed/home.ts @@ -45,18 +45,10 @@ export const home: Partial = { { children: [{ text: '' }] }, { children: [ - { text: 'Visit the ' }, { type: 'link', linkType: 'custom', - url: 'http://localhost:3000/example-page', - children: [{ text: 'example page' }], - }, - { text: ' to see how access to draft content is controlled. ' }, - { - type: 'link', - linkType: 'custom', - url: 'http://localhost:8000/admin', + url: 'http://localhost:3000/admin', newTab: true, children: [{ text: 'Log in' }], }, @@ -69,8 +61,15 @@ export const home: Partial = { children: [{ text: 'Payload Admin Bar' }], }, { - text: ' appear at the top of the viewport so you can seamlessly navigate between the two apps.', + text: ' appear at the top of the viewport. This will allow you to seamlessly navigate between the two apps. Then, navigate to the ', }, + { + type: 'link', + linkType: 'custom', + url: 'http://localhost:3001/example-page', + children: [{ text: 'example page' }], + }, + { text: ' to see how access to draft content is controlled. ' }, ], }, ], diff --git a/examples/preview/cms/src/seed/index.ts b/examples/preview/cms/src/seed/index.ts index 4a2d2573b..c43a521ad 100644 --- a/examples/preview/cms/src/seed/index.ts +++ b/examples/preview/cms/src/seed/index.ts @@ -1,14 +1,15 @@ import type { Payload } from 'payload' + +import { home } from './home' import { examplePage } from './page' import { examplePageDraft } from './pageDraft' -import { home } from './home' export const seed = async (payload: Payload): Promise => { await payload.create({ collection: 'users', data: { - email: 'dev@payloadcms.com', - password: 'test', + email: 'demo@payloadcms.com', + password: 'demo', }, }) @@ -26,7 +27,7 @@ export const seed = async (payload: Payload): Promise => { const homepageJSON = JSON.parse(JSON.stringify(home).replace('{{DRAFT_PAGE_ID}}', examplePageID)) - await payload.create({ + const { id: homePageID } = await payload.create({ collection: 'pages', data: homepageJSON, }) @@ -37,10 +38,13 @@ export const seed = async (payload: Payload): Promise => { navItems: [ { link: { - type: 'custom', - reference: null, - label: 'Dashboard', - url: 'http://localhost:8000/admin', + type: 'reference', + reference: { + relationTo: 'pages', + value: homePageID, + }, + label: 'Home', + url: '', }, }, { @@ -54,6 +58,14 @@ export const seed = async (payload: Payload): Promise => { url: '', }, }, + { + link: { + type: 'custom', + reference: null, + label: 'Dashboard', + url: 'http://localhost:3000/admin', + }, + }, ], }, }) diff --git a/examples/preview/cms/src/seed/page.ts b/examples/preview/cms/src/seed/page.ts index 3e4d7aee1..ddf69df7e 100644 --- a/examples/preview/cms/src/seed/page.ts +++ b/examples/preview/cms/src/seed/page.ts @@ -20,12 +20,12 @@ export const examplePage: Partial = { { type: 'link', linkType: 'custom', - url: 'http://localhost:8000/admin', + url: 'http://localhost:3000/admin', newTab: true, children: [{ text: 'Log in' }], }, { - text: ' to the admin panel and click "preview" to return to this page and view the latest draft content in Next.js preview mode.', + text: ' to the admin panel and click "preview" to return to this page and view the latest draft content in Next.js preview mode. To make additional changes to the draft, click "save draft" before returning to the preview.', }, ], }, diff --git a/examples/preview/cms/src/seed/pageDraft.ts b/examples/preview/cms/src/seed/pageDraft.ts index 25b8e032d..ce289a752 100644 --- a/examples/preview/cms/src/seed/pageDraft.ts +++ b/examples/preview/cms/src/seed/pageDraft.ts @@ -17,12 +17,12 @@ export const examplePageDraft: Partial = { { type: 'link', linkType: 'custom', - url: 'http://localhost:8000/admin/logout', + url: 'http://localhost:3000/admin/logout', newTab: true, children: [{ text: 'Log out' }], }, { - text: ' or exit Next.js preview mode to see the latest published content.', + text: ' or click "exit preview mode" from the Payload Admin Bar to see the latest published content. To make additional changes to the draft, click "save draft" before returning to the preview.', }, ], }, diff --git a/examples/preview/cms/src/server.ts b/examples/preview/cms/src/server.ts index 72762bdbc..985169f2e 100644 --- a/examples/preview/cms/src/server.ts +++ b/examples/preview/cms/src/server.ts @@ -1,13 +1,15 @@ +import dotenv from 'dotenv' import path from 'path' -import express from 'express' -import payload from 'payload' -import { seed } from './seed' -// eslint-disable-next-line -require('dotenv').config({ +dotenv.config({ path: path.resolve(__dirname, '../.env'), }) +import express from 'express' +import payload from 'payload' + +import { seed } from './seed' + const app = express() app.get('/', (_, res) => { @@ -29,7 +31,7 @@ const start = async (): Promise => { await seed(payload) } - app.listen(8000) + app.listen(3000) } start() diff --git a/examples/preview/cms/yarn.lock b/examples/preview/cms/yarn.lock index f183994df..64d8199d0 100644 --- a/examples/preview/cms/yarn.lock +++ b/examples/preview/cms/yarn.lock @@ -9,17 +9,17 @@ dependencies: "@babel/highlight" "^7.18.6" -"@babel/helper-module-imports@^7.0.0": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" - integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== +"@babel/helper-module-imports@^7.16.7": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz#ac88b2f76093637489e718a90cec6cf8a9b029af" + integrity sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg== dependencies: - "@babel/types" "^7.18.6" + "@babel/types" "^7.21.4" -"@babel/helper-string-parser@^7.19.4": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" - integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== +"@babel/helper-string-parser@^7.21.5": + version "7.21.5" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.21.5.tgz#2b3eea65443c6bdc31c22d037c65f6d323b6b2bd" + integrity sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w== "@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": version "7.19.1" @@ -35,19 +35,26 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/runtime@^7.1.2", "@babel/runtime@^7.12.13", "@babel/runtime@^7.14.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.19.0", "@babel/runtime@^7.20.6", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": +"@babel/runtime@^7.1.2", "@babel/runtime@^7.12.13", "@babel/runtime@^7.14.5", "@babel/runtime@^7.19.0", "@babel/runtime@^7.20.6", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7": version "7.20.13" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.13.tgz#7055ab8a7cff2b8f6058bf6ae45ff84ad2aded4b" integrity sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA== dependencies: regenerator-runtime "^0.13.11" -"@babel/types@^7.18.6": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.7.tgz#54ec75e252318423fc07fb644dc6a58a64c09b7f" - integrity sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg== +"@babel/runtime@^7.12.0", "@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3", "@babel/runtime@^7.21.0": + version "7.21.5" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.5.tgz#8492dddda9644ae3bda3b45eabe87382caee7200" + integrity sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q== dependencies: - "@babel/helper-string-parser" "^7.19.4" + regenerator-runtime "^0.13.11" + +"@babel/types@^7.21.4": + version "7.21.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.5.tgz#18dfbd47c39d3904d5db3d3dc2cc80bedb60e5b6" + integrity sha512-m4AfNvVF2mVC/F7fDEdH2El3HzUg9It/XsCxZiOTTA3m3qYfcSVSbTfM6Q9xG+hYDniZssYhlXKKUMD5m8tF4Q== + dependencies: + "@babel/helper-string-parser" "^7.21.5" "@babel/helper-validator-identifier" "^7.19.1" to-fast-properties "^2.0.0" @@ -179,7 +186,7 @@ dependencies: "@date-io/core" "^2.16.0" -"@discoveryjs/json-ext@^0.5.0": +"@discoveryjs/json-ext@0.5.7", "@discoveryjs/json-ext@^0.5.0": version "0.5.7" resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== @@ -215,82 +222,104 @@ dependencies: tslib "^2.0.0" -"@emotion/cache@^10.0.27", "@emotion/cache@^10.0.9": - version "10.0.29" - resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-10.0.29.tgz#87e7e64f412c060102d589fe7c6dc042e6f9d1e0" - integrity sha512-fU2VtSVlHiF27empSbxi1O2JFdNWZO+2NFHfwO0pxgTep6Xa3uGb+3pVKfLww2l/IBGLNEZl5Xf/++A4wAYDYQ== +"@emotion/babel-plugin@^11.11.0": + version "11.11.0" + resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz#c2d872b6a7767a9d176d007f5b31f7d504bb5d6c" + integrity sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ== dependencies: - "@emotion/sheet" "0.9.4" - "@emotion/stylis" "0.8.5" - "@emotion/utils" "0.11.3" - "@emotion/weak-memoize" "0.2.5" + "@babel/helper-module-imports" "^7.16.7" + "@babel/runtime" "^7.18.3" + "@emotion/hash" "^0.9.1" + "@emotion/memoize" "^0.8.1" + "@emotion/serialize" "^1.1.2" + babel-plugin-macros "^3.1.0" + convert-source-map "^1.5.0" + escape-string-regexp "^4.0.0" + find-root "^1.1.0" + source-map "^0.5.7" + stylis "4.2.0" -"@emotion/core@^10.0.9": - version "10.3.1" - resolved "https://registry.yarnpkg.com/@emotion/core/-/core-10.3.1.tgz#4021b6d8b33b3304d48b0bb478485e7d7421c69d" - integrity sha512-447aUEjPIm0MnE6QYIaFz9VQOHSXf4Iu6EWOIqq11EAPqinkSZmfymPTmlOE3QjLv846lH4JVZBUOtwGbuQoww== +"@emotion/cache@^11.11.0", "@emotion/cache@^11.4.0": + version "11.11.0" + resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.11.0.tgz#809b33ee6b1cb1a625fef7a45bc568ccd9b8f3ff" + integrity sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ== dependencies: - "@babel/runtime" "^7.5.5" - "@emotion/cache" "^10.0.27" - "@emotion/css" "^10.0.27" - "@emotion/serialize" "^0.11.15" - "@emotion/sheet" "0.9.4" - "@emotion/utils" "0.11.3" + "@emotion/memoize" "^0.8.1" + "@emotion/sheet" "^1.2.2" + "@emotion/utils" "^1.2.1" + "@emotion/weak-memoize" "^0.3.1" + stylis "4.2.0" -"@emotion/css@^10.0.27", "@emotion/css@^10.0.9": - version "10.0.27" - resolved "https://registry.yarnpkg.com/@emotion/css/-/css-10.0.27.tgz#3a7458198fbbebb53b01b2b87f64e5e21241e14c" - integrity sha512-6wZjsvYeBhyZQYNrGoR5yPMYbMBNEnanDrqmsqS1mzDm1cOTu12shvl2j4QHNS36UaTE0USIJawCH9C8oW34Zw== +"@emotion/css@^11.10.5": + version "11.11.0" + resolved "https://registry.yarnpkg.com/@emotion/css/-/css-11.11.0.tgz#dad6a27a77d5e5cbb0287674c3ace76d762563ca" + integrity sha512-m4g6nKzZyiKyJ3WOfdwrBdcujVcpaScIWHAnyNKPm/A/xJKwfXPfQAbEVi1kgexWTDakmg+r2aDj0KvnMTo4oQ== dependencies: - "@emotion/serialize" "^0.11.15" - "@emotion/utils" "0.11.3" - babel-plugin-emotion "^10.0.27" + "@emotion/babel-plugin" "^11.11.0" + "@emotion/cache" "^11.11.0" + "@emotion/serialize" "^1.1.2" + "@emotion/sheet" "^1.2.2" + "@emotion/utils" "^1.2.1" -"@emotion/hash@0.8.0": - version "0.8.0" - resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413" - integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow== +"@emotion/hash@^0.9.1": + version "0.9.1" + resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.1.tgz#4ffb0055f7ef676ebc3a5a91fb621393294e2f43" + integrity sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ== -"@emotion/memoize@0.7.4": - version "0.7.4" - resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb" - integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw== +"@emotion/memoize@^0.8.1": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.1.tgz#c1ddb040429c6d21d38cc945fe75c818cfb68e17" + integrity sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA== -"@emotion/serialize@^0.11.15", "@emotion/serialize@^0.11.16": - version "0.11.16" - resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-0.11.16.tgz#dee05f9e96ad2fb25a5206b6d759b2d1ed3379ad" - integrity sha512-G3J4o8by0VRrO+PFeSc3js2myYNOXVJ3Ya+RGVxnshRYgsvErfAOglKAiy1Eo1vhzxqtUvjCyS5gtewzkmvSSg== +"@emotion/react@^11.8.1": + version "11.11.0" + resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.11.0.tgz#408196b7ef8729d8ad08fc061b03b046d1460e02" + integrity sha512-ZSK3ZJsNkwfjT3JpDAWJZlrGD81Z3ytNDsxw1LKq1o+xkmO5pnWfr6gmCC8gHEFf3nSSX/09YrG67jybNPxSUw== dependencies: - "@emotion/hash" "0.8.0" - "@emotion/memoize" "0.7.4" - "@emotion/unitless" "0.7.5" - "@emotion/utils" "0.11.3" - csstype "^2.5.7" + "@babel/runtime" "^7.18.3" + "@emotion/babel-plugin" "^11.11.0" + "@emotion/cache" "^11.11.0" + "@emotion/serialize" "^1.1.2" + "@emotion/use-insertion-effect-with-fallbacks" "^1.0.1" + "@emotion/utils" "^1.2.1" + "@emotion/weak-memoize" "^0.3.1" + hoist-non-react-statics "^3.3.1" -"@emotion/sheet@0.9.4": - version "0.9.4" - resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-0.9.4.tgz#894374bea39ec30f489bbfc3438192b9774d32e5" - integrity sha512-zM9PFmgVSqBw4zL101Q0HrBVTGmpAxFZH/pYx/cjJT5advXguvcgjHFTCaIO3enL/xr89vK2bh0Mfyj9aa0ANA== +"@emotion/serialize@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.1.2.tgz#017a6e4c9b8a803bd576ff3d52a0ea6fa5a62b51" + integrity sha512-zR6a/fkFP4EAcCMQtLOhIgpprZOwNmCldtpaISpvz348+DP4Mz8ZoKaGGCQpbzepNIUWbq4w6hNZkwDyKoS+HA== + dependencies: + "@emotion/hash" "^0.9.1" + "@emotion/memoize" "^0.8.1" + "@emotion/unitless" "^0.8.1" + "@emotion/utils" "^1.2.1" + csstype "^3.0.2" -"@emotion/stylis@0.8.5": - version "0.8.5" - resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.5.tgz#deacb389bd6ee77d1e7fcaccce9e16c5c7e78e04" - integrity sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ== +"@emotion/sheet@^1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.2.2.tgz#d58e788ee27267a14342303e1abb3d508b6d0fec" + integrity sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA== -"@emotion/unitless@0.7.5": - version "0.7.5" - resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" - integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== +"@emotion/unitless@^0.8.1": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.1.tgz#182b5a4704ef8ad91bde93f7a860a88fd92c79a3" + integrity sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ== -"@emotion/utils@0.11.3": - version "0.11.3" - resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.11.3.tgz#a759863867befa7e583400d322652a3f44820924" - integrity sha512-0o4l6pZC+hI88+bzuaX/6BgOvQVhbt2PfmxauVaYOGgbsAw14wdKyvMCZXnsnsHys94iadcF+RG/wZyx6+ZZBw== +"@emotion/use-insertion-effect-with-fallbacks@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz#08de79f54eb3406f9daaf77c76e35313da963963" + integrity sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw== -"@emotion/weak-memoize@0.2.5": - version "0.2.5" - resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46" - integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA== +"@emotion/utils@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.2.1.tgz#bbab58465738d31ae4cb3dbb6fc00a5991f755e4" + integrity sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg== + +"@emotion/weak-memoize@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz#d0fce5d07b0620caa282b5131c297bb60f9d87e6" + integrity sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww== "@eslint/eslintrc@^1.4.1": version "1.4.1" @@ -327,6 +356,18 @@ resolved "https://registry.yarnpkg.com/@faceless-ui/window-info/-/window-info-2.1.1.tgz#ed1474a60ab794295bca4c29e295b1e11a584d22" integrity sha512-gMAgda7beR4CNpBIXjgRVn97ek0LG3PAj9lxmoYdg574IEzLFZAh3eAYtTaS2XLKgb4+IHhsuBzlGmHbeOo2Aw== +"@floating-ui/core@^1.2.6": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.2.6.tgz#d21ace437cc919cdd8f1640302fa8851e65e75c0" + integrity sha512-EvYTiXet5XqweYGClEmpu3BoxmsQ4hkj3QaYA6qEnigCWffTP3vNRwBReTdrwDwo7OoJ3wM8Uoe9Uk4n+d4hfg== + +"@floating-ui/dom@^1.0.1": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.2.8.tgz#aee0f6ccc0787ab8fe741487a6e5e95b7b125375" + integrity sha512-XLwhYV90MxiHDq6S0rzFZj00fnDM+A1R9jhSioZoMsa7G0Q0i+Q4x40ajR8FHSdYDE1bgjG45mIWe6jtv9UPmg== + dependencies: + "@floating-ui/core" "^1.2.6" + "@hapi/hoek@^9.0.0": version "9.3.0" resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" @@ -358,13 +399,24 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== -"@hypnosphi/create-react-context@^0.3.1": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@hypnosphi/create-react-context/-/create-react-context-0.3.1.tgz#f8bfebdc7665f5d426cba3753e0e9c7d3154d7c6" - integrity sha512-V1klUed202XahrWJLLOT3EXNeCpFHCcJntdFGI15ntCwau+jfT386w7OFTMaCqOgXUH1fa0w/I1oZs+i/Rfr0A== +"@jest/schemas@^29.4.3": + version "29.4.3" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.4.3.tgz#39cf1b8469afc40b6f5a2baaa146e332c4151788" + integrity sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg== dependencies: - gud "^1.0.0" - warning "^4.0.3" + "@sinclair/typebox" "^0.25.16" + +"@jest/types@^29.5.0": + version "29.5.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.5.0.tgz#f59ef9b031ced83047c67032700d8c807d6e1593" + integrity sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog== + dependencies: + "@jest/schemas" "^29.4.3" + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^17.0.8" + chalk "^4.0.0" "@jridgewell/gen-mapping@^0.3.0": version "0.3.2" @@ -406,25 +458,37 @@ "@jridgewell/resolve-uri" "3.1.0" "@jridgewell/sourcemap-codec" "1.4.14" +"@jridgewell/trace-mapping@^0.3.17": + version "0.3.18" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz#25783b2086daf6ff1dcb53c9249ae480e4dd4cd6" + integrity sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA== + dependencies: + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" + "@jsdevtools/ono@^7.1.3": version "7.1.3" resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796" integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg== -"@monaco-editor/loader@^1.3.2": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@monaco-editor/loader/-/loader-1.3.2.tgz#04effbb87052d19cd7d3c9d81c0635490f9bb6d8" - integrity sha512-BTDbpHl3e47r3AAtpfVFTlAi7WXv4UQ/xZmz8atKl4q7epQV5e7+JbigFDViWF71VBi4IIBdcWP57Hj+OWuc9g== +"@juggle/resize-observer@^3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60" + integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA== + +"@monaco-editor/loader@^1.3.3": + version "1.3.3" + resolved "https://registry.yarnpkg.com/@monaco-editor/loader/-/loader-1.3.3.tgz#7f1742bd3cc21c0362a46a4056317f6e5215cfca" + integrity sha512-6KKF4CTzcJiS8BJwtxtfyYt9shBiEv32ateQ9T4UVogwn4HM/uPo9iJd2Dmbkpz8CM6Y0PDUpjnZzCwC+eYo2Q== dependencies: state-local "^1.0.6" -"@monaco-editor/react@^4.4.6": - version "4.4.6" - resolved "https://registry.yarnpkg.com/@monaco-editor/react/-/react-4.4.6.tgz#8ae500b0edf85276d860ed702e7056c316548218" - integrity sha512-Gr3uz3LYf33wlFE3eRnta4RxP5FSNxiIV9ENn2D2/rN8KgGAD8ecvcITRtsbbyuOuNkwbuHYxfeaz2Vr+CtyFA== +"@monaco-editor/react@^4.5.1": + version "4.5.1" + resolved "https://registry.yarnpkg.com/@monaco-editor/react/-/react-4.5.1.tgz#fbc76c692aee9a33b9ab24ae0c5f219b8f002fdb" + integrity sha512-NNDFdP+2HojtNhCkRfE6/D6ro6pBNihaOzMbGK84lNWzRu+CfBjwzGt4jmnqimLuqp5yE5viHS2vi+QOAnD5FQ== dependencies: - "@monaco-editor/loader" "^1.3.2" - prop-types "^15.7.2" + "@monaco-editor/loader" "^1.3.3" "@nodelib/fs.scandir@2.1.5": version "2.1.5" @@ -457,6 +521,11 @@ resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1" integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g== +"@popperjs/core@^2.9.2": + version "2.11.7" + resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.7.tgz#ccab5c8f7dc557a52ca3288c10075c9ccd37fff7" + integrity sha512-Cr4OjIkipTtcXKjAsm8agyleBuDHvxzeBoa1v543lbv1YaIwQjESsVcmjiWiPEbC1FIeHOG/Op9kdCmAmiS3Kw== + "@sideway/address@^4.1.3": version "4.1.4" resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0" @@ -474,6 +543,11 @@ resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== +"@sinclair/typebox@^0.25.16": + version "0.25.24" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.25.24.tgz#8c7688559979f7079aacaf31aa881c3aa410b718" + integrity sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ== + "@swc/core-darwin-arm64@1.3.32": version "1.3.32" resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.32.tgz#841b0a244c2c75e67bb9d3cb665b2ede601e4e3a" @@ -595,10 +669,10 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== -"@types/estree@^0.0.51": - version "0.0.51" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" - integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== +"@types/estree@^1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.1.tgz#aa22750962f3bf0e79d753d3cc067f010c95f194" + integrity sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA== "@types/express-serve-static-core@^4.17.33": version "4.17.33" @@ -627,14 +701,6 @@ "@types/minimatch" "*" "@types/node" "*" -"@types/hoist-non-react-statics@^3.3.0": - version "3.3.1" - resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" - integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA== - dependencies: - "@types/react" "*" - hoist-non-react-statics "^3.3.0" - "@types/html-minifier-terser@^6.0.0": version "6.1.0" resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" @@ -645,6 +711,25 @@ resolved "https://registry.yarnpkg.com/@types/is-hotkey/-/is-hotkey-0.1.7.tgz#30ec6d4234895230b576728ef77e70a52962f3b3" integrity sha512-yB5C7zcOM7idwYZZ1wKQ3pTfjA9BbvFqRWvKB46GFddxnJtHwi/b9y84ykQtxQPg5qhdpg4Q/kWU3EGoCTmLzQ== +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" + integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== + +"@types/istanbul-lib-report@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" + integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" + integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== + dependencies: + "@types/istanbul-lib-report" "*" + "@types/json-schema@*", "@types/json-schema@^7.0.11", "@types/json-schema@^7.0.6", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": version "7.0.11" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" @@ -705,15 +790,12 @@ resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== -"@types/react-redux@^7.1.20": - version "7.1.25" - resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.25.tgz#de841631205b24f9dfb4967dd4a7901e048f9a88" - integrity sha512-bAGh4e+w5D8dajd6InASVIyCo4pZLJ66oLb80F9OBLO1gKESbZcRCJpTT6uLXX+HAB57zw1WTdwJdAsewuTweg== +"@types/react-transition-group@^4.4.0": + version "4.4.6" + resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.6.tgz#18187bcda5281f8e10dfc48f0943e2fdf4f75e2e" + integrity sha512-VnCdSxfcm08KjsJVQcfBmhEQAPnLB8G08hAxn39azX1qYBQ/5RVQuoHuKIcfKOdncuaUvEpFKFzEvbtIMsfVew== dependencies: - "@types/hoist-non-react-statics" "^3.3.0" "@types/react" "*" - hoist-non-react-statics "^3.3.0" - redux "^4.0.0" "@types/react@*": version "18.0.27" @@ -771,6 +853,18 @@ "@types/node" "*" "@types/webidl-conversions" "*" +"@types/yargs-parser@*": + version "21.0.0" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" + integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== + +"@types/yargs@^17.0.8": + version "17.0.24" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.24.tgz#b3ef8d50ad4aa6aecf6ddc97c580a00f5aa11902" + integrity sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw== + dependencies: + "@types/yargs-parser" "*" + "@typescript-eslint/eslint-plugin@^5.51.0": version "5.52.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.52.0.tgz#5fb0d43574c2411f16ea80f5fc335b8eaa7b28a8" @@ -855,125 +949,125 @@ "@typescript-eslint/types" "5.52.0" eslint-visitor-keys "^3.3.0" -"@webassemblyjs/ast@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" - integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== +"@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.6.tgz#db046555d3c413f8966ca50a95176a0e2c642e24" + integrity sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q== dependencies: - "@webassemblyjs/helper-numbers" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/helper-numbers" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" -"@webassemblyjs/floating-point-hex-parser@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" - integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== +"@webassemblyjs/floating-point-hex-parser@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431" + integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw== -"@webassemblyjs/helper-api-error@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" - integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== +"@webassemblyjs/helper-api-error@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" + integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== -"@webassemblyjs/helper-buffer@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" - integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== +"@webassemblyjs/helper-buffer@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz#b66d73c43e296fd5e88006f18524feb0f2c7c093" + integrity sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA== -"@webassemblyjs/helper-numbers@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" - integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== +"@webassemblyjs/helper-numbers@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5" + integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g== dependencies: - "@webassemblyjs/floating-point-hex-parser" "1.11.1" - "@webassemblyjs/helper-api-error" "1.11.1" + "@webassemblyjs/floating-point-hex-parser" "1.11.6" + "@webassemblyjs/helper-api-error" "1.11.6" "@xtuc/long" "4.2.2" -"@webassemblyjs/helper-wasm-bytecode@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" - integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== +"@webassemblyjs/helper-wasm-bytecode@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" + integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== -"@webassemblyjs/helper-wasm-section@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" - integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== +"@webassemblyjs/helper-wasm-section@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz#ff97f3863c55ee7f580fd5c41a381e9def4aa577" + integrity sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g== dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/helper-buffer" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/wasm-gen" "1.11.6" -"@webassemblyjs/ieee754@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" - integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== +"@webassemblyjs/ieee754@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a" + integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg== dependencies: "@xtuc/ieee754" "^1.2.0" -"@webassemblyjs/leb128@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" - integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== +"@webassemblyjs/leb128@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7" + integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ== dependencies: "@xtuc/long" "4.2.2" -"@webassemblyjs/utf8@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" - integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== +"@webassemblyjs/utf8@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" + integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== -"@webassemblyjs/wasm-edit@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" - integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== +"@webassemblyjs/wasm-edit@^1.11.5": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz#c72fa8220524c9b416249f3d94c2958dfe70ceab" + integrity sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw== dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/helper-wasm-section" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - "@webassemblyjs/wasm-opt" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - "@webassemblyjs/wast-printer" "1.11.1" + "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/helper-buffer" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/helper-wasm-section" "1.11.6" + "@webassemblyjs/wasm-gen" "1.11.6" + "@webassemblyjs/wasm-opt" "1.11.6" + "@webassemblyjs/wasm-parser" "1.11.6" + "@webassemblyjs/wast-printer" "1.11.6" -"@webassemblyjs/wasm-gen@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" - integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== +"@webassemblyjs/wasm-gen@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz#fb5283e0e8b4551cc4e9c3c0d7184a65faf7c268" + integrity sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA== dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/ieee754" "1.11.1" - "@webassemblyjs/leb128" "1.11.1" - "@webassemblyjs/utf8" "1.11.1" + "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" -"@webassemblyjs/wasm-opt@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" - integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== +"@webassemblyjs/wasm-opt@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz#d9a22d651248422ca498b09aa3232a81041487c2" + integrity sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g== dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" + "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/helper-buffer" "1.11.6" + "@webassemblyjs/wasm-gen" "1.11.6" + "@webassemblyjs/wasm-parser" "1.11.6" -"@webassemblyjs/wasm-parser@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" - integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== +"@webassemblyjs/wasm-parser@1.11.6", "@webassemblyjs/wasm-parser@^1.11.5": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz#bb85378c527df824004812bbdb784eea539174a1" + integrity sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ== dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-api-error" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/ieee754" "1.11.1" - "@webassemblyjs/leb128" "1.11.1" - "@webassemblyjs/utf8" "1.11.1" + "@webassemblyjs/ast" "1.11.6" + "@webassemblyjs/helper-api-error" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" -"@webassemblyjs/wast-printer@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" - integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== +"@webassemblyjs/wast-printer@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz#a7bf8dd7e362aeb1668ff43f35cb849f188eff20" + integrity sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A== dependencies: - "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/ast" "1.11.6" "@xtuc/long" "4.2.2" "@webpack-cli/configtest@^1.2.0": @@ -1015,7 +1109,7 @@ abort-controller@^3.0.0: dependencies: event-target-shim "^5.0.0" -accepts@^1.3.7, accepts@~1.3.5, accepts@~1.3.8: +accepts@~1.3.5, accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== @@ -1023,10 +1117,10 @@ accepts@^1.3.7, accepts@~1.3.5, accepts@~1.3.8: mime-types "~2.1.34" negotiator "0.6.3" -acorn-import-assertions@^1.7.6: - version "1.8.0" - resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" - integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== +acorn-import-assertions@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" + integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== acorn-jsx@^5.3.2: version "5.3.2" @@ -1187,35 +1281,14 @@ available-typed-arrays@^1.0.5: resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== -babel-plugin-emotion@^10.0.27: - version "10.2.2" - resolved "https://registry.yarnpkg.com/babel-plugin-emotion/-/babel-plugin-emotion-10.2.2.tgz#a1fe3503cff80abfd0bdda14abd2e8e57a79d17d" - integrity sha512-SMSkGoqTbTyUTDeuVuPIWifPdUGkTk1Kf9BWRiXIOIcuyMfsdp2EjeiiFvOzX8NOBvEh/ypKYvUh2rkgAJMCLA== +babel-plugin-macros@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1" + integrity sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg== dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@emotion/hash" "0.8.0" - "@emotion/memoize" "0.7.4" - "@emotion/serialize" "^0.11.16" - babel-plugin-macros "^2.0.0" - babel-plugin-syntax-jsx "^6.18.0" - convert-source-map "^1.5.0" - escape-string-regexp "^1.0.5" - find-root "^1.1.0" - source-map "^0.5.7" - -babel-plugin-macros@^2.0.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz#0f958a7cc6556b1e65344465d99111a1e5e10138" - integrity sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg== - dependencies: - "@babel/runtime" "^7.7.2" - cosmiconfig "^6.0.0" - resolve "^1.12.0" - -babel-plugin-syntax-jsx@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" - integrity sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw== + "@babel/runtime" "^7.12.5" + cosmiconfig "^7.0.0" + resolve "^1.19.0" balanced-match@^1.0.0: version "1.0.2" @@ -1296,7 +1369,7 @@ braces@^3.0.2, braces@~3.0.2: dependencies: fill-range "^7.0.1" -browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.16.6, browserslist@^4.21.4: +browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.21.4: version "4.21.5" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.5.tgz#75c5dae60063ee641f977e00edd3cfb2fb7af6a7" integrity sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w== @@ -1449,7 +1522,12 @@ chrome-trace-event@^1.0.2: resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== -classnames@^2.2.5, classnames@^2.2.6: +ci-info@^3.2.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.8.0.tgz#81408265a5380c929f0bc665d62256628ce9ef91" + integrity sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw== + +classnames@^2.2.5, classnames@^2.2.6, classnames@^2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.2.tgz#351d813bf0137fcc6a76a16b88208d2560a0d924" integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw== @@ -1540,10 +1618,10 @@ colord@^2.9.1: resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.3.tgz#4f8ce919de456f1d5c1c368c307fe20f3e59fb43" integrity sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw== -colorette@^1.2.2: - version "1.4.0" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" - integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== +colorette@^2.0.10: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== colorette@^2.0.14, colorette@^2.0.7: version "2.0.19" @@ -1623,7 +1701,7 @@ content-disposition@0.5.4: dependencies: safe-buffer "5.2.1" -content-type@^1.0.4, content-type@~1.0.4: +content-type@~1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== @@ -1661,17 +1739,6 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== -cosmiconfig@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" - integrity sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg== - dependencies: - "@types/parse-json" "^4.0.0" - import-fresh "^3.1.0" - parse-json "^5.0.0" - path-type "^4.0.0" - yaml "^1.7.2" - cosmiconfig@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6" @@ -1683,16 +1750,6 @@ cosmiconfig@^7.0.0: path-type "^4.0.0" yaml "^1.10.0" -create-emotion@^10.0.14, create-emotion@^10.0.27: - version "10.0.27" - resolved "https://registry.yarnpkg.com/create-emotion/-/create-emotion-10.0.27.tgz#cb4fa2db750f6ca6f9a001a33fbf1f6c46789503" - integrity sha512-fIK73w82HPPn/RsAij7+Zt8eCE8SptcJ3WoRMfxMtjteYxud8GDTKKld7MYwAX2TVhrw29uR1N/bVGxeStHILg== - dependencies: - "@emotion/cache" "^10.0.27" - "@emotion/serialize" "^0.11.15" - "@emotion/sheet" "0.9.4" - "@emotion/utils" "0.11.3" - create-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" @@ -1726,13 +1783,6 @@ css-blank-pseudo@^3.0.3: dependencies: postcss-selector-parser "^6.0.9" -css-box-model@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/css-box-model/-/css-box-model-1.2.1.tgz#59951d3b81fd6b2074a62d49444415b0d2b4d7c1" - integrity sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw== - dependencies: - tiny-invariant "^1.0.6" - css-declaration-sorter@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.3.1.tgz#be5e1d71b7a992433fb1c542c7a1b835e45682ec" @@ -1761,16 +1811,16 @@ css-loader@^5.2.7: schema-utils "^3.0.0" semver "^7.3.5" -css-minimizer-webpack-plugin@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz#ab78f781ced9181992fe7b6e4f3422e76429878f" - integrity sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q== +css-minimizer-webpack-plugin@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-5.0.0.tgz#a2c2d1bc5cc37450519e873e13d942bbe4478ef5" + integrity sha512-1wZ/PYvg+ZKwi5FX6YrvbB31jMAdurS+CmRQLwWCVSlfzJC85l/a6RVICqUHFa+jXyhilfnCyjafzJGbmz5tcA== dependencies: - cssnano "^5.0.6" - jest-worker "^27.0.2" - postcss "^8.3.5" + cssnano "^6.0.0" + jest-worker "^29.4.3" + postcss "^8.4.21" schema-utils "^4.0.0" - serialize-javascript "^6.0.0" + serialize-javascript "^6.0.1" source-map "^0.6.1" css-prefers-color-scheme@^6.0.3: @@ -1789,15 +1839,34 @@ css-select@^4.1.3: domutils "^2.8.0" nth-check "^2.0.1" -css-tree@^1.1.2, css-tree@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" - integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q== +css-select@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6" + integrity sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg== dependencies: - mdn-data "2.0.14" - source-map "^0.6.1" + boolbase "^1.0.0" + css-what "^6.1.0" + domhandler "^5.0.2" + domutils "^3.0.1" + nth-check "^2.0.1" -css-what@^6.0.1: +css-tree@^2.2.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-2.3.1.tgz#10264ce1e5442e8572fc82fbe490644ff54b5c20" + integrity sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw== + dependencies: + mdn-data "2.0.30" + source-map-js "^1.0.1" + +css-tree@~2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-2.2.1.tgz#36115d382d60afd271e377f9c5f67d02bd48c032" + integrity sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA== + dependencies: + mdn-data "2.0.28" + source-map-js "^1.0.1" + +css-what@^6.0.1, css-what@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== @@ -1817,66 +1886,60 @@ cssfilter@0.0.10: resolved "https://registry.yarnpkg.com/cssfilter/-/cssfilter-0.0.10.tgz#c6d2672632a2e5c83e013e6864a42ce8defd20ae" integrity sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw== -cssnano-preset-default@^5.2.13: - version "5.2.13" - resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.2.13.tgz#e7353b0c57975d1bdd97ac96e68e5c1b8c68e990" - integrity sha512-PX7sQ4Pb+UtOWuz8A1d+Rbi+WimBIxJTRyBdgGp1J75VU0r/HFQeLnMYgHiCAp6AR4rqrc7Y4R+1Rjk3KJz6DQ== +cssnano-preset-default@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-6.0.1.tgz#2a93247140d214ddb9f46bc6a3562fa9177fe301" + integrity sha512-7VzyFZ5zEB1+l1nToKyrRkuaJIx0zi/1npjvZfbBwbtNTzhLtlvYraK/7/uqmX2Wb2aQtd983uuGw79jAjLSuQ== dependencies: css-declaration-sorter "^6.3.1" - cssnano-utils "^3.1.0" - postcss-calc "^8.2.3" - postcss-colormin "^5.3.0" - postcss-convert-values "^5.1.3" - postcss-discard-comments "^5.1.2" - postcss-discard-duplicates "^5.1.0" - postcss-discard-empty "^5.1.1" - postcss-discard-overridden "^5.1.0" - postcss-merge-longhand "^5.1.7" - postcss-merge-rules "^5.1.3" - postcss-minify-font-values "^5.1.0" - postcss-minify-gradients "^5.1.1" - postcss-minify-params "^5.1.4" - postcss-minify-selectors "^5.2.1" - postcss-normalize-charset "^5.1.0" - postcss-normalize-display-values "^5.1.0" - postcss-normalize-positions "^5.1.1" - postcss-normalize-repeat-style "^5.1.1" - postcss-normalize-string "^5.1.0" - postcss-normalize-timing-functions "^5.1.0" - postcss-normalize-unicode "^5.1.1" - postcss-normalize-url "^5.1.0" - postcss-normalize-whitespace "^5.1.1" - postcss-ordered-values "^5.1.3" - postcss-reduce-initial "^5.1.1" - postcss-reduce-transforms "^5.1.0" - postcss-svgo "^5.1.0" - postcss-unique-selectors "^5.1.1" + cssnano-utils "^4.0.0" + postcss-calc "^9.0.0" + postcss-colormin "^6.0.0" + postcss-convert-values "^6.0.0" + postcss-discard-comments "^6.0.0" + postcss-discard-duplicates "^6.0.0" + postcss-discard-empty "^6.0.0" + postcss-discard-overridden "^6.0.0" + postcss-merge-longhand "^6.0.0" + postcss-merge-rules "^6.0.1" + postcss-minify-font-values "^6.0.0" + postcss-minify-gradients "^6.0.0" + postcss-minify-params "^6.0.0" + postcss-minify-selectors "^6.0.0" + postcss-normalize-charset "^6.0.0" + postcss-normalize-display-values "^6.0.0" + postcss-normalize-positions "^6.0.0" + postcss-normalize-repeat-style "^6.0.0" + postcss-normalize-string "^6.0.0" + postcss-normalize-timing-functions "^6.0.0" + postcss-normalize-unicode "^6.0.0" + postcss-normalize-url "^6.0.0" + postcss-normalize-whitespace "^6.0.0" + postcss-ordered-values "^6.0.0" + postcss-reduce-initial "^6.0.0" + postcss-reduce-transforms "^6.0.0" + postcss-svgo "^6.0.0" + postcss-unique-selectors "^6.0.0" -cssnano-utils@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-3.1.0.tgz#95684d08c91511edfc70d2636338ca37ef3a6861" - integrity sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA== +cssnano-utils@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-4.0.0.tgz#d1da885ec04003ab19505ff0e62e029708d36b08" + integrity sha512-Z39TLP+1E0KUcd7LGyF4qMfu8ZufI0rDzhdyAMsa/8UyNUU8wpS0fhdBxbQbv32r64ea00h4878gommRVg2BHw== -cssnano@^5.0.6: - version "5.1.14" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.1.14.tgz#07b0af6da73641276fe5a6d45757702ebae2eb05" - integrity sha512-Oou7ihiTocbKqi0J1bB+TRJIQX5RMR3JghA8hcWSw9mjBLQ5Y3RWqEDoYG3sRNlAbCIXpqMoZGbq5KDR3vdzgw== +cssnano@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-6.0.1.tgz#87c38c4cd47049c735ab756d7e77ac3ca855c008" + integrity sha512-fVO1JdJ0LSdIGJq68eIxOqFpIJrZqXUsBt8fkrBcztCQqAjQD51OhZp7tc0ImcbwXD4k7ny84QTV90nZhmqbkg== dependencies: - cssnano-preset-default "^5.2.13" - lilconfig "^2.0.3" - yaml "^1.10.2" + cssnano-preset-default "^6.0.1" + lilconfig "^2.1.0" -csso@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" - integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA== +csso@^5.0.5: + version "5.0.5" + resolved "https://registry.yarnpkg.com/csso/-/csso-5.0.5.tgz#f9b7fe6cc6ac0b7d90781bb16d5e9874303e2ca6" + integrity sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ== dependencies: - css-tree "^1.1.2" - -csstype@^2.5.7: - version "2.6.21" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.21.tgz#2efb85b7cc55c80017c66a5ad7cbd931fda3a90e" - integrity sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w== + css-tree "~2.2.0" csstype@^3.0.2: version "3.1.1" @@ -1896,7 +1959,14 @@ dataloader@^2.1.0: resolved "https://registry.yarnpkg.com/dataloader/-/dataloader-2.2.1.tgz#f07ab712514313a34b1507a308dbb7dc14bac715" integrity sha512-Zn+tVZo1RKu120rgoe0JsRk56UiKdefPSH47QROJsMHrX8/S9UJvi5A/A6+Sbuk6rE88z5JoM/wIJ09Z7BTfYA== -date-fns@^2.0.1, date-fns@^2.29.3: +date-fns@^2.24.0: + version "2.30.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.30.0.tgz#f367e644839ff57894ec6ac480de40cae4b0f4d0" + integrity sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw== + dependencies: + "@babel/runtime" "^7.21.0" + +date-fns@^2.29.3: version "2.29.3" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.3.tgz#27402d2fc67eb442b511b70bbdf98e6411cd68a8" integrity sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA== @@ -1948,18 +2018,6 @@ decompress-response@^6.0.0: dependencies: mimic-response "^3.1.0" -deep-equal@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" - integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== - dependencies: - is-arguments "^1.0.4" - is-date-object "^1.0.1" - is-regex "^1.0.4" - object-is "^1.0.1" - object-keys "^1.1.1" - regexp.prototype.flags "^1.2.0" - deep-equal@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.2.0.tgz#5caeace9c781028b9ff459f33b779346637c43e6" @@ -2016,11 +2074,6 @@ depd@2.0.0: resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== - destroy@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" @@ -2036,6 +2089,11 @@ diff@^4.0.1: resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== +diff@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.1.0.tgz#bc52d298c5ea8df9194800224445ed43ffc87e40" + integrity sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -2086,7 +2144,16 @@ dom-serializer@^1.0.1: domhandler "^4.2.0" entities "^2.0.0" -domelementtype@^2.0.1, domelementtype@^2.2.0: +dom-serializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53" + integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.2" + entities "^4.2.0" + +domelementtype@^2.0.1, domelementtype@^2.2.0, domelementtype@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== @@ -2098,6 +2165,13 @@ domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1: dependencies: domelementtype "^2.2.0" +domhandler@^5.0.2, domhandler@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" + integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== + dependencies: + domelementtype "^2.3.0" + domutils@^2.5.2, domutils@^2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" @@ -2107,6 +2181,15 @@ domutils@^2.5.2, domutils@^2.8.0: domelementtype "^2.2.0" domhandler "^4.2.0" +domutils@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.1.0.tgz#c47f551278d3dc4b0b1ab8cbb42d751a6f0d824e" + integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA== + dependencies: + dom-serializer "^2.0.0" + domelementtype "^2.3.0" + domhandler "^5.0.3" + dot-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" @@ -2159,14 +2242,6 @@ emojis-list@^3.0.0: resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== -emotion@^10.0.14: - version "10.0.27" - resolved "https://registry.yarnpkg.com/emotion/-/emotion-10.0.27.tgz#f9ca5df98630980a23c819a56262560562e5d75e" - integrity sha512-2xdDzdWWzue8R8lu4G76uWX5WhyQuzATon9LmNeCy/2BHVC6dsEpfhN1a0qhELgtDVdjyEA6J8Y/VlI5ZnaH0g== - dependencies: - babel-plugin-emotion "^10.0.27" - create-emotion "^10.0.27" - encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -2179,10 +2254,10 @@ end-of-stream@^1.1.0, end-of-stream@^1.4.1: dependencies: once "^1.4.0" -enhanced-resolve@^5.10.0: - version "5.12.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz#300e1c90228f5b570c4d35babf263f6da7155634" - integrity sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ== +enhanced-resolve@^5.14.1: + version "5.14.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.14.1.tgz#de684b6803724477a4af5d74ccae5de52c25f6b3" + integrity sha512-Vklwq2vDKtl0y/vtwjSesgJ5MYS7Etuk5txS8VdKL4AOS1aUlD96zqIfsOSLQsdv3xgMRbtkWM8eG9XDfKUPow== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" @@ -2192,6 +2267,11 @@ entities@^2.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== +entities@^4.2.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + env-paths@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" @@ -2263,10 +2343,10 @@ es-get-iterator@^1.1.2: isarray "^2.0.5" stop-iteration-iterator "^1.0.0" -es-module-lexer@^0.9.0: - version "0.9.3" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" - integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== +es-module-lexer@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.2.1.tgz#ba303831f63e6a394983fde2f97ad77b22324527" + integrity sha512-9978wrXM50Y4rTMmW5kXIC09ZdXQZqkE4mxhwkd8VbzsGkXGPgV4zWuqQJgCEzYngdo2dYDa0l8xhX4fkSwJSg== es-set-tostringtag@^2.0.1: version "2.0.1" @@ -2567,16 +2647,6 @@ express-fileupload@1.4.0: dependencies: busboy "^1.6.0" -express-graphql@0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/express-graphql/-/express-graphql-0.12.0.tgz#58deabc309909ca2c9fe2f83f5fbe94429aa23df" - integrity sha512-DwYaJQy0amdy3pgNtiTDuGGM2BLdj+YO2SgbKoLliCfuHv3VVTt7vNG/ZqK2hRYjtYHE2t2KB705EU94mE64zg== - dependencies: - accepts "^1.3.7" - content-type "^1.0.4" - http-errors "1.8.0" - raw-body "^2.4.1" - express-rate-limit@^5.5.1: version "5.5.1" resolved "https://registry.yarnpkg.com/express-rate-limit/-/express-rate-limit-5.5.1.tgz#110c23f6a65dfa96ab468eda95e71697bc6987a2" @@ -2859,11 +2929,6 @@ functions-have-names@^1.2.2: resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== -generaterr@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/generaterr/-/generaterr-1.5.0.tgz#b0ceb6cc5164df2a061338cc340a8615395c52fc" - integrity sha512-JgcGRv2yUKeboLvvNrq9Bm90P4iJBu7/vd5wSLYqMG5GJ6SxZT46LAAkMfNhQ+EK3jzC+cRBm7P8aUWYyphgcQ== - get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" @@ -2891,6 +2956,11 @@ get-symbol-description@^1.0.0: call-bind "^1.0.2" get-intrinsic "^1.1.1" +get-tsconfig@^4.4.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.5.0.tgz#6d52d1c7b299bd3ee9cd7638561653399ac77b0f" + integrity sha512-MjhiaIWCJ1sAU4pIQ5i5OfOuHHxVo1oYeNsWTON7jxYkod8pHocXeh+SSbmu5OZZZK73B6cbJ2XADzXehLyovQ== + github-from-package@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" @@ -2988,6 +3058,11 @@ grapheme-splitter@^1.0.4: resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== +graphql-http@^1.17.1: + version "1.18.0" + resolved "https://registry.yarnpkg.com/graphql-http/-/graphql-http-1.18.0.tgz#6a72fc6d085e0761d9d483273c6fa9a6de5f6c4c" + integrity sha512-r2sIo6jCTQi1aj7s+Srg7oU3+r5pUUgxgDD5JDZOmFzrbXVGz+yMhIKhvqW0cV10DcnVIFCOzuFuc1qvnjJ7yQ== + graphql-playground-html@^1.6.30: version "1.6.30" resolved "https://registry.yarnpkg.com/graphql-playground-html/-/graphql-playground-html-1.6.30.tgz#14c2a8eb7fc17bfeb1a746bbb28a11e34bf0b391" @@ -3026,11 +3101,6 @@ graphql@^16.6.0: resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.6.0.tgz#c2dcffa4649db149f6282af726c8c83f1c7c5fdb" integrity sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw== -gud@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/gud/-/gud-1.0.0.tgz#a489581b17e6a70beca9abe3ae57de7a499852c0" - integrity sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw== - gzip-size@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462" @@ -3109,7 +3179,7 @@ history@^4.9.0: tiny-warning "^1.0.0" value-equal "^1.0.1" -hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: +hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.1: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== @@ -3162,17 +3232,6 @@ htmlparser2@^6.1.0: domutils "^2.5.2" entities "^2.0.0" -http-errors@1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.0.tgz#75d1bbe497e1044f51e4ee9e704a62f28d336507" - integrity sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A== - dependencies: - depd "~1.1.2" - inherits "2.0.4" - setprototypeof "1.2.0" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - http-errors@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" @@ -3245,7 +3304,7 @@ immutable@^4.0.0: resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.2.4.tgz#83260d50889526b4b531a5e293709a77f7c55a2a" integrity sha512-WDxL3Hheb1JkRN3sQkyujNlL/xRjAo3rJtaU5xeufUauG66JdMr32bLj4gF+vWl84DIA3Zxw7tiAjneYzRRw+w== -import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1: +import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== @@ -3308,7 +3367,7 @@ ipaddr.js@1.9.1: resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== -is-arguments@^1.0.4, is-arguments@^1.1.1: +is-arguments@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== @@ -3457,7 +3516,7 @@ is-promise@^2.2.2: resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== -is-regex@^1.0.4, is-regex@^1.1.4: +is-regex@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== @@ -3555,7 +3614,19 @@ isomorphic-fetch@^3.0.0: node-fetch "^2.6.1" whatwg-fetch "^3.4.1" -jest-worker@^27.0.2, jest-worker@^27.4.5: +jest-util@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.5.0.tgz#24a4d3d92fc39ce90425311b23c27a6e0ef16b8f" + integrity sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ== + dependencies: + "@jest/types" "^29.5.0" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + +jest-worker@^27.4.5: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== @@ -3564,6 +3635,16 @@ jest-worker@^27.0.2, jest-worker@^27.4.5: merge-stream "^2.0.0" supports-color "^8.0.0" +jest-worker@^29.4.3: + version "29.5.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.5.0.tgz#bdaefb06811bd3384d93f009755014d8acb4615d" + integrity sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA== + dependencies: + "@types/node" "*" + jest-util "^29.5.0" + merge-stream "^2.0.0" + supports-color "^8.0.0" + joi@^17.7.0: version "17.7.0" resolved "https://registry.yarnpkg.com/joi/-/joi-17.7.0.tgz#591a33b1fe1aca2bc27f290bcad9b9c1c570a6b3" @@ -3602,7 +3683,7 @@ json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== -json-schema-to-typescript@^11.0.2: +json-schema-to-typescript@11.0.3: version "11.0.3" resolved "https://registry.yarnpkg.com/json-schema-to-typescript/-/json-schema-to-typescript-11.0.3.tgz#9b401c2b78329959f1c4c4e0639a6bdcf6a6ed77" integrity sha512-EaEE9Y4VZ8b9jW5zce5a9L3+p4C9AqgIRHbNVDJahfMnoKzcd4sDb98BLxLdQhJEuRAXyKLg4H66NKm80W8ilg== @@ -3718,10 +3799,10 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" -lilconfig@^2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.6.tgz#32a384558bd58af3d4c6e077dd1ad1d397bc69d4" - integrity sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg== +lilconfig@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" + integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== lines-and-columns@^1.1.6: version "1.2.4" @@ -3847,13 +3928,6 @@ make-error@^1.1.1: resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== -map-age-cleaner@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" - integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== - dependencies: - p-defer "^1.0.0" - md5@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f" @@ -3863,35 +3937,32 @@ md5@^2.3.0: crypt "0.0.2" is-buffer "~1.1.6" -mdn-data@2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" - integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== +mdn-data@2.0.28: + version "2.0.28" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.28.tgz#5ec48e7bef120654539069e1ae4ddc81ca490eba" + integrity sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g== + +mdn-data@2.0.30: + version "2.0.30" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.30.tgz#ce4df6f80af6cfbe218ecd5c552ba13c4dfa08cc" + integrity sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA== media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== -mem@^8.1.1: - version "8.1.1" - resolved "https://registry.yarnpkg.com/mem/-/mem-8.1.1.tgz#cf118b357c65ab7b7e0817bdf00c8062297c0122" - integrity sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA== - dependencies: - map-age-cleaner "^0.1.3" - mimic-fn "^3.1.0" - -memfs@^3.2.2: - version "3.4.13" - resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.13.tgz#248a8bd239b3c240175cd5ec548de5227fc4f345" - integrity sha512-omTM41g3Skpvx5dSYeZIbXKcXoAVc/AoMNwn9TKx++L/gaen/+4TTttmu8ZSch5vfVJ8uJvGbroTsIlslRg6lg== +memfs@^3.4.12: + version "3.5.1" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.5.1.tgz#f0cd1e2bfaef58f6fe09bfb9c2288f07fea099ec" + integrity sha512-UWbFJKvj5k+nETdteFndTpYxdeTMox/ULeqX5k/dpaQJCCFmj5EeKv3dBcyO2xmkRAx2vppRu5dVG7SOtsGOzA== dependencies: fs-monkey "^1.0.3" -memoize-one@^5.0.0, memoize-one@^5.0.4, memoize-one@^5.1.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" - integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q== +memoize-one@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-6.0.0.tgz#b2591b871ed82948aee4727dc6abceeeac8c1045" + integrity sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw== memoizee@^0.4.15: version "0.4.15" @@ -3960,7 +4031,7 @@ mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@^2.1.27, mime-types@^2.1.30, mime-types@~2.1.24, mime-types@~2.1.34: +mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== @@ -3977,7 +4048,7 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -mimic-fn@^3.0.0, mimic-fn@^3.1.0: +mimic-fn@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-3.1.0.tgz#65755145bbf3e36954b949c16450427451d5ca74" integrity sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ== @@ -4025,6 +4096,11 @@ mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== +monaco-editor@^0.38.0: + version "0.38.0" + resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.38.0.tgz#7b3cd16f89b1b8867fcd3c96e67fccee791ff05c" + integrity sha512-11Fkh6yzEmwx7O0YoLxeae0qEGFwmyPRlVxpg7oF9czOOCB/iCjdJrG5I67da5WiXK3YJCxoz9TJFE8Tfq/v9A== + mongodb-connection-string-url@^2.5.2: version "2.6.0" resolved "https://registry.yarnpkg.com/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz#57901bf352372abdde812c81be47b75c6b2ec5cf" @@ -4231,11 +4307,6 @@ normalize-range@^0.1.2: resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== -normalize-url@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" - integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== - nth-check@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" @@ -4253,7 +4324,7 @@ object-inspect@^1.12.2, object-inspect@^1.9.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== -object-is@^1.0.1, object-is@^1.1.5: +object-is@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== @@ -4338,11 +4409,6 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" -p-defer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" - integrity sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw== - p-limit@^2.0.0, p-limit@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" @@ -4444,15 +4510,6 @@ passport-jwt@^4.0.1: jsonwebtoken "^9.0.0" passport-strategy "^1.0.0" -passport-local-mongoose@^7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/passport-local-mongoose/-/passport-local-mongoose-7.1.2.tgz#0a89876ef8a8e18787e59a39740e61c5653eb25e" - integrity sha512-hNLIKi/6IhElr/PhOze8wLDh7T4+ZYhc8GFWYApLgG7FrjI55tuGZELPtsUBqODz77OwlUUf+ngPgHN09zxGLg== - dependencies: - generaterr "^1.5.0" - passport-local "^1.0.0" - scmp "^2.1.0" - passport-local@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/passport-local/-/passport-local-1.0.0.tgz#1fe63268c92e75606626437e3b906662c15ba6ee" @@ -4526,10 +4583,10 @@ pause@0.0.1: resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d" integrity sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg== -payload@^1.6.4: - version "1.6.4" - resolved "https://registry.yarnpkg.com/payload/-/payload-1.6.4.tgz#dea570003d6011ad61c45b8c24ef1bdc5abccb2e" - integrity sha512-IzxYvO8/cqgWfyRIZjzv7iF9GKkjEZ/kfxxmAO90mFyZ26UkuQezTl+AyOMIkxP1bHVwO9AMnOD8WVqIiLgX6g== +payload@^1.11.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/payload/-/payload-1.11.0.tgz#9f2a16c343c9733ee8e22f94b343fcf5f222801c" + integrity sha512-rs7Cgyg07Aa4/wsA2PG9UFYx4fQSvw1WJz6H9iut32jvEB553RBaZsquKUA0XYPDFlmQFCvjcP5LUYTrjgcnRg== dependencies: "@date-io/date-fns" "^2.16.0" "@dnd-kit/core" "^6.0.7" @@ -4537,7 +4594,7 @@ payload@^1.6.4: "@faceless-ui/modal" "^2.0.1" "@faceless-ui/scroll-info" "^1.3.0" "@faceless-ui/window-info" "^2.1.1" - "@monaco-editor/react" "^4.4.6" + "@monaco-editor/react" "^4.5.1" "@swc/core" "^1.3.26" "@swc/register" "^0.1.10" "@types/sharp" "^0.31.1" @@ -4547,7 +4604,7 @@ payload@^1.6.4: conf "^10.2.0" connect-history-api-fallback "^1.6.0" css-loader "^5.2.7" - css-minimizer-webpack-plugin "^3.4.1" + css-minimizer-webpack-plugin "^5.0.0" dataloader "^2.1.0" date-fns "^2.29.3" deep-equal "^2.2.0" @@ -4555,14 +4612,15 @@ payload@^1.6.4: dotenv "^8.6.0" express "^4.18.2" express-fileupload "1.4.0" - express-graphql "0.12.0" express-rate-limit "^5.5.1" file-loader "^6.2.0" file-type "16.5.4" find-up "4.1.0" flatley "^5.2.0" fs-extra "^10.1.0" + get-tsconfig "^4.4.0" graphql "^16.6.0" + graphql-http "^1.17.1" graphql-playground-middleware-express "^1.7.23" graphql-query-complexity "^0.12.0" graphql-scalars "^1.20.1" @@ -4576,7 +4634,7 @@ payload@^1.6.4: is-plain-object "^5.0.0" isomorphic-fetch "^3.0.0" joi "^17.7.0" - json-schema-to-typescript "^11.0.2" + json-schema-to-typescript "11.0.3" jsonwebtoken "^9.0.0" jwt-decode "^3.1.2" md5 "^2.3.0" @@ -4585,6 +4643,7 @@ payload@^1.6.4: mini-css-extract-plugin "1.6.2" minimist "^1.2.7" mkdirp "^1.0.4" + monaco-editor "^0.38.0" mongoose "6.5.0" mongoose-aggregate-paginate-v2 "^1.0.6" mongoose-paginate-v2 "^1.6.1" @@ -4595,7 +4654,6 @@ payload@^1.6.4: passport-headerapikey "^1.2.2" passport-jwt "^4.0.1" passport-local "^1.0.0" - passport-local-mongoose "^7.1.2" path-browserify "^1.0.1" pino "^6.4.1" pino-pretty "^9.1.1" @@ -4609,36 +4667,37 @@ payload@^1.6.4: qs-middleware "^1.0.3" react "^18.2.0" react-animate-height "^2.1.2" - react-beautiful-dnd "^13.1.1" - react-datepicker "^3.8.0" - react-diff-viewer "^3.1.1" + react-datepicker "^4.10.0" + react-diff-viewer-continued "^3.2.6" react-dom "^18.2.0" react-helmet "^6.1.0" react-i18next "^11.18.6" react-router-dom "^5.3.4" react-router-navigation-prompt "^1.9.6" - react-select "^3.2.0" + react-select "^5.7.3" react-toastify "^8.2.0" sanitize-filename "^1.6.3" sass "^1.57.1" sass-loader "^12.6.0" + scheduler "^0.23.0" + scmp "^2.1.0" sharp "^0.31.3" - slate "^0.88.1" + slate "^0.91.4" slate-history "^0.86.0" slate-hyperscript "^0.81.3" - slate-react "^0.88.0" + slate-react "^0.92.0" style-loader "^2.0.0" swc-loader "^0.2.3" - swc-minify-webpack-plugin "^1.0.1" + swc-minify-webpack-plugin "^2.1.0" terser-webpack-plugin "^5.3.6" ts-essentials "^7.0.3" url-loader "^4.1.1" use-context-selector "^1.4.1" uuid "^8.3.2" - webpack "^5.75.0" - webpack-bundle-analyzer "^4.7.0" + webpack "^5.78.0" + webpack-bundle-analyzer "^4.8.0" webpack-cli "^4.10.0" - webpack-dev-middleware "^4.3.0" + webpack-dev-middleware "6.0.1" webpack-hot-middleware "^2.25.3" peek-readable@^4.1.0: @@ -4651,7 +4710,7 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -4726,11 +4785,6 @@ pluralize@^8.0.0: resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== -popper.js@^1.14.4: - version "1.16.1" - resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b" - integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ== - postcss-attribute-case-insensitive@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.2.tgz#03d761b24afc04c09e757e92ff53716ae8ea2741" @@ -4738,12 +4792,12 @@ postcss-attribute-case-insensitive@^5.0.2: dependencies: postcss-selector-parser "^6.0.10" -postcss-calc@^8.2.3: - version "8.2.4" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-8.2.4.tgz#77b9c29bfcbe8a07ff6693dc87050828889739a5" - integrity sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q== +postcss-calc@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-9.0.1.tgz#a744fd592438a93d6de0f1434c572670361eb6c6" + integrity sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ== dependencies: - postcss-selector-parser "^6.0.9" + postcss-selector-parser "^6.0.11" postcss-value-parser "^4.2.0" postcss-clamp@^4.1.0: @@ -4774,20 +4828,20 @@ postcss-color-rebeccapurple@^7.1.1: dependencies: postcss-value-parser "^4.2.0" -postcss-colormin@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.3.0.tgz#3cee9e5ca62b2c27e84fce63affc0cfb5901956a" - integrity sha512-WdDO4gOFG2Z8n4P8TWBpshnL3JpmNmJwdnfP2gbk2qBA8PWwOYcmjmI/t3CmMeL72a7Hkd+x/Mg9O2/0rD54Pg== +postcss-colormin@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-6.0.0.tgz#d4250652e952e1c0aca70c66942da93d3cdeaafe" + integrity sha512-EuO+bAUmutWoZYgHn2T1dG1pPqHU6L4TjzPlu4t1wZGXQ/fxV16xg2EJmYi0z+6r+MGV1yvpx1BHkUaRrPa2bw== dependencies: - browserslist "^4.16.6" + browserslist "^4.21.4" caniuse-api "^3.0.0" colord "^2.9.1" postcss-value-parser "^4.2.0" -postcss-convert-values@^5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz#04998bb9ba6b65aa31035d669a6af342c5f9d393" - integrity sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA== +postcss-convert-values@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-6.0.0.tgz#ec94a954957e5c3f78f0e8f65dfcda95280b8996" + integrity sha512-U5D8QhVwqT++ecmy8rnTb+RL9n/B806UVaS3m60lqle4YDFcpbS3ae5bTQIh3wOGUSDHSEtMYLs/38dNG7EYFw== dependencies: browserslist "^4.21.4" postcss-value-parser "^4.2.0" @@ -4820,25 +4874,25 @@ postcss-dir-pseudo-class@^6.0.5: dependencies: postcss-selector-parser "^6.0.10" -postcss-discard-comments@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz#8df5e81d2925af2780075840c1526f0660e53696" - integrity sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ== +postcss-discard-comments@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-6.0.0.tgz#9ca335e8b68919f301b24ba47dde226a42e535fe" + integrity sha512-p2skSGqzPMZkEQvJsgnkBhCn8gI7NzRH2683EEjrIkoMiwRELx68yoUJ3q3DGSGuQ8Ug9Gsn+OuDr46yfO+eFw== -postcss-discard-duplicates@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz#9eb4fe8456706a4eebd6d3b7b777d07bad03e848" - integrity sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw== +postcss-discard-duplicates@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-6.0.0.tgz#c26177a6c33070922e67e9a92c0fd23d443d1355" + integrity sha512-bU1SXIizMLtDW4oSsi5C/xHKbhLlhek/0/yCnoMQany9k3nPBq+Ctsv/9oMmyqbR96HYHxZcHyK2HR5P/mqoGA== -postcss-discard-empty@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz#e57762343ff7f503fe53fca553d18d7f0c369c6c" - integrity sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A== +postcss-discard-empty@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-6.0.0.tgz#06c1c4fce09e22d2a99e667c8550eb8a3a1b9aee" + integrity sha512-b+h1S1VT6dNhpcg+LpyiUrdnEZfICF0my7HAKgJixJLW7BnNmpRH34+uw/etf5AhOlIhIAuXApSzzDzMI9K/gQ== -postcss-discard-overridden@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz#7e8c5b53325747e9d90131bb88635282fb4a276e" - integrity sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw== +postcss-discard-overridden@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-6.0.0.tgz#49c5262db14e975e349692d9024442de7cd8e234" + integrity sha512-4VELwssYXDFigPYAZ8vL4yX4mUepF/oCBeeIT4OXsJPYOtvJumyz9WflmJWTfDwCUcpDR+z0zvCWBXgTx35SVw== postcss-double-position-gradients@^3.1.2: version "3.1.2" @@ -4918,53 +4972,53 @@ postcss-media-minmax@^5.0.0: resolved "https://registry.yarnpkg.com/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz#7140bddec173e2d6d657edbd8554a55794e2a5b5" integrity sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ== -postcss-merge-longhand@^5.1.7: - version "5.1.7" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz#24a1bdf402d9ef0e70f568f39bdc0344d568fb16" - integrity sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ== +postcss-merge-longhand@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-6.0.0.tgz#6f627b27db939bce316eaa97e22400267e798d69" + integrity sha512-4VSfd1lvGkLTLYcxFuISDtWUfFS4zXe0FpF149AyziftPFQIWxjvFSKhA4MIxMe4XM3yTDgQMbSNgzIVxChbIg== dependencies: postcss-value-parser "^4.2.0" - stylehacks "^5.1.1" + stylehacks "^6.0.0" -postcss-merge-rules@^5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.1.3.tgz#8f97679e67cc8d08677a6519afca41edf2220894" - integrity sha512-LbLd7uFC00vpOuMvyZop8+vvhnfRGpp2S+IMQKeuOZZapPRY4SMq5ErjQeHbHsjCUgJkRNrlU+LmxsKIqPKQlA== +postcss-merge-rules@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-6.0.1.tgz#39f165746404e646c0f5c510222ccde4824a86aa" + integrity sha512-a4tlmJIQo9SCjcfiCcCMg/ZCEe0XTkl/xK0XHBs955GWg9xDX3NwP9pwZ78QUOWB8/0XCjZeJn98Dae0zg6AAw== dependencies: browserslist "^4.21.4" caniuse-api "^3.0.0" - cssnano-utils "^3.1.0" + cssnano-utils "^4.0.0" postcss-selector-parser "^6.0.5" -postcss-minify-font-values@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz#f1df0014a726083d260d3bd85d7385fb89d1f01b" - integrity sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA== +postcss-minify-font-values@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-6.0.0.tgz#68d4a028f9fa5f61701974724b2cc9445d8e6070" + integrity sha512-zNRAVtyh5E8ndZEYXA4WS8ZYsAp798HiIQ1V2UF/C/munLp2r1UGHwf1+6JFu7hdEhJFN+W1WJQKBrtjhFgEnA== dependencies: postcss-value-parser "^4.2.0" -postcss-minify-gradients@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz#f1fe1b4f498134a5068240c2f25d46fcd236ba2c" - integrity sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw== +postcss-minify-gradients@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-6.0.0.tgz#22b5c88cc63091dadbad34e31ff958404d51d679" + integrity sha512-wO0F6YfVAR+K1xVxF53ueZJza3L+R3E6cp0VwuXJQejnNUH0DjcAFe3JEBeTY1dLwGa0NlDWueCA1VlEfiKgAA== dependencies: colord "^2.9.1" - cssnano-utils "^3.1.0" + cssnano-utils "^4.0.0" postcss-value-parser "^4.2.0" -postcss-minify-params@^5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz#c06a6c787128b3208b38c9364cfc40c8aa5d7352" - integrity sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw== +postcss-minify-params@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-6.0.0.tgz#2b3a85a9e3b990d7a16866f430f5fd1d5961b539" + integrity sha512-Fz/wMQDveiS0n5JPcvsMeyNXOIMrwF88n7196puSuQSWSa+/Ofc1gDOSY2xi8+A4PqB5dlYCKk/WfqKqsI+ReQ== dependencies: browserslist "^4.21.4" - cssnano-utils "^3.1.0" + cssnano-utils "^4.0.0" postcss-value-parser "^4.2.0" -postcss-minify-selectors@^5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz#d4e7e6b46147b8117ea9325a915a801d5fe656c6" - integrity sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg== +postcss-minify-selectors@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-6.0.0.tgz#5046c5e8680a586e5a0cad52cc9aa36d6be5bda2" + integrity sha512-ec/q9JNCOC2CRDNnypipGfOhbYPuUkewGwLnbv6omue/PSASbHSU7s6uSQ0tcFRVv731oMIx8k0SP4ZX6be/0g== dependencies: postcss-selector-parser "^6.0.5" @@ -5004,66 +5058,65 @@ postcss-nesting@^10.2.0: "@csstools/selector-specificity" "^2.0.0" postcss-selector-parser "^6.0.10" -postcss-normalize-charset@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz#9302de0b29094b52c259e9b2cf8dc0879879f0ed" - integrity sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg== +postcss-normalize-charset@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-6.0.0.tgz#36cc12457259064969fb96f84df491652a4b0975" + integrity sha512-cqundwChbu8yO/gSWkuFDmKrCZ2vJzDAocheT2JTd0sFNA4HMGoKMfbk2B+J0OmO0t5GUkiAkSM5yF2rSLUjgQ== -postcss-normalize-display-values@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz#72abbae58081960e9edd7200fcf21ab8325c3da8" - integrity sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA== +postcss-normalize-display-values@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-6.0.0.tgz#8d2961415078644d8c6bbbdaf9a2fdd60f546cd4" + integrity sha512-Qyt5kMrvy7dJRO3OjF7zkotGfuYALETZE+4lk66sziWSPzlBEt7FrUshV6VLECkI4EN8Z863O6Nci4NXQGNzYw== dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-positions@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz#ef97279d894087b59325b45c47f1e863daefbb92" - integrity sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg== +postcss-normalize-positions@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-6.0.0.tgz#25b96df99a69f8925f730eaee0be74416865e301" + integrity sha512-mPCzhSV8+30FZyWhxi6UoVRYd3ZBJgTRly4hOkaSifo0H+pjDYcii/aVT4YE6QpOil15a5uiv6ftnY3rm0igPg== dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-repeat-style@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz#e9eb96805204f4766df66fd09ed2e13545420fb2" - integrity sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g== +postcss-normalize-repeat-style@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-6.0.0.tgz#ddf30ad8762feb5b1eb97f39f251acd7b8353299" + integrity sha512-50W5JWEBiOOAez2AKBh4kRFm2uhrT3O1Uwdxz7k24aKtbD83vqmcVG7zoIwo6xI2FZ/HDlbrCopXhLeTpQib1A== dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-string@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz#411961169e07308c82c1f8c55f3e8a337757e228" - integrity sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w== +postcss-normalize-string@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-6.0.0.tgz#948282647a51e409d69dde7910f0ac2ff97cb5d8" + integrity sha512-KWkIB7TrPOiqb8ZZz6homet2KWKJwIlysF5ICPZrXAylGe2hzX/HSf4NTX2rRPJMAtlRsj/yfkrWGavFuB+c0w== dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-timing-functions@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz#d5614410f8f0b2388e9f240aa6011ba6f52dafbb" - integrity sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg== +postcss-normalize-timing-functions@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-6.0.0.tgz#5f13e650b8c43351989fc5de694525cc2539841c" + integrity sha512-tpIXWciXBp5CiFs8sem90IWlw76FV4oi6QEWfQwyeREVwUy39VSeSqjAT7X0Qw650yAimYW5gkl2Gd871N5SQg== dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-unicode@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz#f67297fca3fea7f17e0d2caa40769afc487aa030" - integrity sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA== +postcss-normalize-unicode@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-6.0.0.tgz#741b3310f874616bdcf07764f5503695d3604730" + integrity sha512-ui5crYkb5ubEUDugDc786L/Me+DXp2dLg3fVJbqyAl0VPkAeALyAijF2zOsnZyaS1HyfPuMH0DwyY18VMFVNkg== dependencies: browserslist "^4.21.4" postcss-value-parser "^4.2.0" -postcss-normalize-url@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz#ed9d88ca82e21abef99f743457d3729a042adcdc" - integrity sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew== +postcss-normalize-url@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-6.0.0.tgz#d0a31e962a16401fb7deb7754b397a323fb650b4" + integrity sha512-98mvh2QzIPbb02YDIrYvAg4OUzGH7s1ZgHlD3fIdTHLgPLRpv1ZTKJDnSAKr4Rt21ZQFzwhGMXxpXlfrUBKFHw== dependencies: - normalize-url "^6.0.1" postcss-value-parser "^4.2.0" -postcss-normalize-whitespace@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz#08a1a0d1ffa17a7cc6efe1e6c9da969cc4493cfa" - integrity sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA== +postcss-normalize-whitespace@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-6.0.0.tgz#accb961caa42e25ca4179b60855b79b1f7129d4d" + integrity sha512-7cfE1AyLiK0+ZBG6FmLziJzqQCpTQY+8XjMhMAz8WSBSCsCNNUKujgIgjCAmDT3cJ+3zjTXFkoD15ZPsckArVw== dependencies: postcss-value-parser "^4.2.0" @@ -5072,12 +5125,12 @@ postcss-opacity-percentage@^1.1.2: resolved "https://registry.yarnpkg.com/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.3.tgz#5b89b35551a556e20c5d23eb5260fbfcf5245da6" integrity sha512-An6Ba4pHBiDtyVpSLymUUERMo2cU7s+Obz6BTrS+gxkbnSBNKSuD0AVUc+CpBMrpVPKKfoVz0WQCX+Tnst0i4A== -postcss-ordered-values@^5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz#b6fd2bd10f937b23d86bc829c69e7732ce76ea38" - integrity sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ== +postcss-ordered-values@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-6.0.0.tgz#374704cdff25560d44061d17ba3c6308837a3218" + integrity sha512-K36XzUDpvfG/nWkjs6d1hRBydeIxGpKS2+n+ywlKPzx1nMYDYpoGbcjhj5AwVYJK1qV2/SDoDEnHzlPD6s3nMg== dependencies: - cssnano-utils "^3.1.0" + cssnano-utils "^4.0.0" postcss-value-parser "^4.2.0" postcss-overflow-shorthand@^3.0.4: @@ -5161,18 +5214,18 @@ postcss-pseudo-class-any-link@^7.1.6: dependencies: postcss-selector-parser "^6.0.10" -postcss-reduce-initial@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-5.1.1.tgz#c18b7dfb88aee24b1f8e4936541c29adbd35224e" - integrity sha512-//jeDqWcHPuXGZLoolFrUXBDyuEGbr9S2rMo19bkTIjBQ4PqkaO+oI8wua5BOUxpfi97i3PCoInsiFIEBfkm9w== +postcss-reduce-initial@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-6.0.0.tgz#7d16e83e60e27e2fa42f56ec0b426f1da332eca7" + integrity sha512-s2UOnidpVuXu6JiiI5U+fV2jamAw5YNA9Fdi/GRK0zLDLCfXmSGqQtzpUPtfN66RtCbb9fFHoyZdQaxOB3WxVA== dependencies: browserslist "^4.21.4" caniuse-api "^3.0.0" -postcss-reduce-transforms@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz#333b70e7758b802f3dd0ddfe98bb1ccfef96b6e9" - integrity sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ== +postcss-reduce-transforms@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-6.0.0.tgz#28ff2601a6d9b96a2f039b3501526e1f4d584a46" + integrity sha512-FQ9f6xM1homnuy1wLe9lP1wujzxnwt1EwiigtWwuyf8FsqqXUDUp2Ulxf9A5yjlUOTdCJO6lonYjg1mgqIIi2w== dependencies: postcss-value-parser "^4.2.0" @@ -5196,18 +5249,26 @@ postcss-selector-parser@^6.0.10, postcss-selector-parser@^6.0.2, postcss-selecto cssesc "^3.0.0" util-deprecate "^1.0.2" -postcss-svgo@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-5.1.0.tgz#0a317400ced789f233a28826e77523f15857d80d" - integrity sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA== +postcss-selector-parser@^6.0.11: + version "6.0.13" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz#d05d8d76b1e8e173257ef9d60b706a8e5e99bf1b" + integrity sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-svgo@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-6.0.0.tgz#7b18742d38d4505a0455bbe70d52b49f00eaf69d" + integrity sha512-r9zvj/wGAoAIodn84dR/kFqwhINp5YsJkLoujybWG59grR/IHx+uQ2Zo+IcOwM0jskfYX3R0mo+1Kip1VSNcvw== dependencies: postcss-value-parser "^4.2.0" - svgo "^2.7.0" + svgo "^3.0.2" -postcss-unique-selectors@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz#a9f273d1eacd09e9aa6088f4b0507b18b1b541b6" - integrity sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA== +postcss-unique-selectors@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-6.0.0.tgz#c94e9b0f7bffb1203894e42294b5a1b3fb34fbe1" + integrity sha512-EPQzpZNxOxP7777t73RQpZE5e9TrnCrkvp7AH7a0l89JmZiPnS82y216JowHXwpBCQitfyxrof9TK3rYbi7/Yw== dependencies: postcss-selector-parser "^6.0.5" @@ -5216,7 +5277,7 @@ postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss@^8.2.15, postcss@^8.3.5, postcss@^8.4.21: +postcss@^8.2.15, postcss@^8.4.21: version "8.4.21" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.21.tgz#c639b719a57efc3187b13a1d765675485f4134f4" integrity sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg== @@ -5297,7 +5358,7 @@ process@^0.11.10: resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== -prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -5361,11 +5422,6 @@ quick-format-unescaped@^4.0.3: resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7" integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg== -raf-schd@^4.0.2: - version "4.0.3" - resolved "https://registry.yarnpkg.com/raf-schd/-/raf-schd-4.0.3.tgz#5d6c34ef46f8b2a0e880a8fcdb743efc5bfdbc1a" - integrity sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ== - randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -5378,7 +5434,7 @@ range-parser@^1.2.1, range-parser@~1.2.1: resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -raw-body@2.5.1, raw-body@^2.4.1: +raw-body@2.5.1: version "2.5.1" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== @@ -5406,41 +5462,28 @@ react-animate-height@^2.1.2: classnames "^2.2.5" prop-types "^15.6.1" -react-beautiful-dnd@^13.1.1: - version "13.1.1" - resolved "https://registry.yarnpkg.com/react-beautiful-dnd/-/react-beautiful-dnd-13.1.1.tgz#b0f3087a5840920abf8bb2325f1ffa46d8c4d0a2" - integrity sha512-0Lvs4tq2VcrEjEgDXHjT98r+63drkKEgqyxdA7qD3mvKwga6a5SscbdLPO2IExotU1jW8L0Ksdl0Cj2AF67nPQ== - dependencies: - "@babel/runtime" "^7.9.2" - css-box-model "^1.2.0" - memoize-one "^5.1.1" - raf-schd "^4.0.2" - react-redux "^7.2.0" - redux "^4.0.4" - use-memo-one "^1.1.1" - -react-datepicker@^3.8.0: - version "3.8.0" - resolved "https://registry.yarnpkg.com/react-datepicker/-/react-datepicker-3.8.0.tgz#c3bccd3e3f47aa66864a2fa75651be097414430b" - integrity sha512-iFVNEp8DJoX5yEvEiciM7sJKmLGrvE70U38KhpG13XrulNSijeHw1RZkhd/0UmuXR71dcZB/kdfjiidifstZjw== +react-datepicker@^4.10.0: + version "4.11.0" + resolved "https://registry.yarnpkg.com/react-datepicker/-/react-datepicker-4.11.0.tgz#40e73b4729a284ed206fdb322b8e84eb566e11a3" + integrity sha512-50n93o7mQwBEhg05tbopjFKgs8qgi8VBCAOMC4VqrKut72eAjESc/wXS/k5hRtnP0oe2FCGw7MJuIwh37wuXOw== dependencies: + "@popperjs/core" "^2.9.2" classnames "^2.2.6" - date-fns "^2.0.1" + date-fns "^2.24.0" prop-types "^15.7.2" - react-onclickoutside "^6.10.0" - react-popper "^1.3.8" + react-onclickoutside "^6.12.2" + react-popper "^2.3.0" -react-diff-viewer@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/react-diff-viewer/-/react-diff-viewer-3.1.1.tgz#21ac9c891193d05a3734bfd6bd54b107ee6d46cc" - integrity sha512-rmvwNdcClp6ZWdS11m1m01UnBA4OwYaLG/li0dB781e/bQEzsGyj+qewVd6W5ztBwseQ72pO7nwaCcq5jnlzcw== +react-diff-viewer-continued@^3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/react-diff-viewer-continued/-/react-diff-viewer-continued-3.2.6.tgz#96382463b5de6838d95323c407442349b1c3a26e" + integrity sha512-GrzyqQnjIMoej+jMjWvtVSsQqhXgzEGqpXlJ2dAGfOk7Q26qcm8Gu6xtI430PBUyZsERe8BJSQf+7VZZo8IBNQ== dependencies: - classnames "^2.2.6" - create-emotion "^10.0.14" - diff "^4.0.1" - emotion "^10.0.14" - memoize-one "^5.0.4" - prop-types "^15.6.2" + "@emotion/css" "^11.10.5" + classnames "^2.3.1" + diff "^5.1.0" + memoize-one "^6.0.0" + prop-types "^15.8.1" react-dom@^18.2.0: version "18.2.0" @@ -5450,6 +5493,11 @@ react-dom@^18.2.0: loose-envify "^1.1.0" scheduler "^0.23.0" +react-fast-compare@^3.0.1: + version "3.2.2" + resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.2.tgz#929a97a532304ce9fee4bcae44234f1ce2c21d49" + integrity sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ== + react-fast-compare@^3.1.1: version "3.2.0" resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" @@ -5473,53 +5521,24 @@ react-i18next@^11.18.6: "@babel/runtime" "^7.14.5" html-parse-stringify "^3.0.1" -react-input-autosize@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-3.0.0.tgz#6b5898c790d4478d69420b55441fcc31d5c50a85" - integrity sha512-nL9uS7jEs/zu8sqwFE5MAPx6pPkNAriACQ2rGLlqmKr2sPGtN7TXTyDdQt4lbNXVx7Uzadb40x8qotIuru6Rhg== - dependencies: - prop-types "^15.5.8" - react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== -react-is@^17.0.2: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" - integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== +react-onclickoutside@^6.12.2: + version "6.13.0" + resolved "https://registry.yarnpkg.com/react-onclickoutside/-/react-onclickoutside-6.13.0.tgz#e165ea4e5157f3da94f4376a3ab3e22a565f4ffc" + integrity sha512-ty8So6tcUpIb+ZE+1HAhbLROvAIJYyJe/1vRrrcmW+jLsaM+/powDRqxzo6hSh9CuRZGSL1Q8mvcF5WRD93a0A== -react-onclickoutside@^6.10.0: - version "6.12.2" - resolved "https://registry.yarnpkg.com/react-onclickoutside/-/react-onclickoutside-6.12.2.tgz#8e6cf80c7d17a79f2c908399918158a7b02dda01" - integrity sha512-NMXGa223OnsrGVp5dJHkuKxQ4czdLmXSp5jSV9OqiCky9LOpPATn3vLldc+q5fK3gKbEHvr7J1u0yhBh/xYkpA== - -react-popper@^1.3.8: - version "1.3.11" - resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-1.3.11.tgz#a2cc3f0a67b75b66cfa62d2c409f9dd1fcc71ffd" - integrity sha512-VSA/bS+pSndSF2fiasHK/PTEEAyOpX60+H5EPAjoArr8JGm+oihu4UbrqcEBpQibJxBVCpYyjAX7abJ+7DoYVg== +react-popper@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-2.3.0.tgz#17891c620e1320dce318bad9fede46a5f71c70ba" + integrity sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q== dependencies: - "@babel/runtime" "^7.1.2" - "@hypnosphi/create-react-context" "^0.3.1" - deep-equal "^1.1.1" - popper.js "^1.14.4" - prop-types "^15.6.1" - typed-styles "^0.0.7" + react-fast-compare "^3.0.1" warning "^4.0.2" -react-redux@^7.2.0: - version "7.2.9" - resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.9.tgz#09488fbb9416a4efe3735b7235055442b042481d" - integrity sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ== - dependencies: - "@babel/runtime" "^7.15.4" - "@types/react-redux" "^7.1.20" - hoist-non-react-statics "^3.3.2" - loose-envify "^1.4.0" - prop-types "^15.7.2" - react-is "^17.0.2" - react-router-dom@^5.3.4: version "5.3.4" resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.3.4.tgz#2ed62ffd88cae6db134445f4a0c0ae8b91d2e5e6" @@ -5553,19 +5572,20 @@ react-router@5.3.4: tiny-invariant "^1.0.2" tiny-warning "^1.0.0" -react-select@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/react-select/-/react-select-3.2.0.tgz#de9284700196f5f9b5277c5d850a9ce85f5c72fe" - integrity sha512-B/q3TnCZXEKItO0fFN/I0tWOX3WJvi/X2wtdffmwSQVRwg5BpValScTO1vdic9AxlUgmeSzib2hAZAwIUQUZGQ== +react-select@^5.7.3: + version "5.7.3" + resolved "https://registry.yarnpkg.com/react-select/-/react-select-5.7.3.tgz#fa0dc9a23cad6ff3871ad3829f6083a4b54961a2" + integrity sha512-z8i3NCuFFWL3w27xq92rBkVI2onT0jzIIPe480HlBjXJ3b5o6Q+Clp4ydyeKrj9DZZ3lrjawwLC5NGl0FSvUDg== dependencies: - "@babel/runtime" "^7.4.4" - "@emotion/cache" "^10.0.9" - "@emotion/core" "^10.0.9" - "@emotion/css" "^10.0.9" - memoize-one "^5.0.0" + "@babel/runtime" "^7.12.0" + "@emotion/cache" "^11.4.0" + "@emotion/react" "^11.8.1" + "@floating-ui/dom" "^1.0.1" + "@types/react-transition-group" "^4.4.0" + memoize-one "^6.0.0" prop-types "^15.6.0" - react-input-autosize "^3.0.0" react-transition-group "^4.3.0" + use-isomorphic-layout-effect "^1.1.2" react-side-effect@^2.1.0: version "2.1.2" @@ -5659,19 +5679,12 @@ rechoir@^0.7.0: dependencies: resolve "^1.9.0" -redux@^4.0.0, redux@^4.0.4: - version "4.2.1" - resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.1.tgz#c08f4306826c49b5e9dc901dee0452ea8fce6197" - integrity sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w== - dependencies: - "@babel/runtime" "^7.9.2" - regenerator-runtime@^0.13.11: version "0.13.11" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== -regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.4.3: +regexp.prototype.flags@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== @@ -5733,7 +5746,16 @@ resolve-pathname@^3.0.0: resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd" integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng== -resolve@^1.12.0, resolve@^1.20.0, resolve@^1.22.1, resolve@^1.9.0: +resolve@^1.19.0: + version "1.22.2" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" + integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== + dependencies: + is-core-module "^2.11.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +resolve@^1.20.0, resolve@^1.22.1, resolve@^1.9.0: version "1.22.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== @@ -5828,7 +5850,7 @@ scheduler@^0.23.0: dependencies: loose-envify "^1.1.0" -schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: +schema-utils@^3.0.0, schema-utils@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== @@ -5837,6 +5859,15 @@ schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: ajv "^6.12.5" ajv-keywords "^3.5.2" +schema-utils@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.2.tgz#36c10abca6f7577aeae136c804b0c741edeadc99" + integrity sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + schema-utils@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7" @@ -5900,7 +5931,7 @@ send@0.18.0: range-parser "~1.2.1" statuses "2.0.1" -serialize-javascript@^6.0.0: +serialize-javascript@^6.0.0, serialize-javascript@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.1.tgz#b206efb27c3da0b0ab6b52f48d170b7996458e5c" integrity sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w== @@ -6025,11 +6056,12 @@ slate-hyperscript@^0.81.3: dependencies: is-plain-object "^5.0.0" -slate-react@^0.88.0: - version "0.88.2" - resolved "https://registry.yarnpkg.com/slate-react/-/slate-react-0.88.2.tgz#e072d54980876ec11ca057703a0e386dd290c03e" - integrity sha512-r06i+b7c1deP9PH69D3kJLStB2cbwryCVUGC++3phG7G3Ie+qEeJ5AZqogdxtsXd2vZaVGYKEjSASd3bTnj3tw== +slate-react@^0.92.0: + version "0.92.0" + resolved "https://registry.yarnpkg.com/slate-react/-/slate-react-0.92.0.tgz#eb158ac2a33d962f48c466c4c8cc7bc14c1c6633" + integrity sha512-xEDKu5RKw5f0N95l1UeNQnrB0Pxh4JPjpIZR/BVsMo0ININnLAknR99gLo46bl/Ffql4mr7LeaxQRoXxbFtJOQ== dependencies: + "@juggle/resize-observer" "^3.4.0" "@types/is-hotkey" "^0.1.1" "@types/lodash" "^4.14.149" direction "^1.0.3" @@ -6039,10 +6071,10 @@ slate-react@^0.88.0: scroll-into-view-if-needed "^2.2.20" tiny-invariant "1.0.6" -slate@^0.88.1: - version "0.88.1" - resolved "https://registry.yarnpkg.com/slate/-/slate-0.88.1.tgz#0fc20f33b7baed7ea979fa848232c336e788cc31" - integrity sha512-DEj9RpkNwPfdh3zbE9eGpeOVGWdS8BYQt754S0Lk6IvJXOkYaxza7WEZLZl/vnp7vloMdTe24zccyxywA3XK8g== +slate@^0.91.4: + version "0.91.4" + resolved "https://registry.yarnpkg.com/slate/-/slate-0.91.4.tgz#759764d63c8a8a7aff29a29e598e593ed80277f9" + integrity sha512-aUJ3rpjrdi5SbJ5G1Qjr3arytfRkEStTmHjBfWq2A2Q8MybacIzkScSvGJjQkdTk3djCK9C9SEOt39sSeZFwTw== dependencies: immer "^9.0.6" is-plain-object "^5.0.0" @@ -6081,7 +6113,7 @@ source-list-map@^2.0.0: resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== -"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2: +"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.1, source-map-js@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== @@ -6116,11 +6148,6 @@ split2@^4.0.0: resolved "https://registry.yarnpkg.com/split2/-/split2-4.1.0.tgz#101907a24370f85bb782f08adaabe4e281ecf809" integrity sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ== -stable@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" - integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== - state-local@^1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/state-local/-/state-local-1.0.7.tgz#da50211d07f05748d53009bee46307a37db386d5" @@ -6131,11 +6158,6 @@ statuses@2.0.1: resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== -"statuses@>= 1.5.0 < 2": - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== - stop-iteration-iterator@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz#6a60be0b4ee757d1ed5254858ec66b10c49285e4" @@ -6239,14 +6261,19 @@ style-loader@^2.0.0: loader-utils "^2.0.0" schema-utils "^3.0.0" -stylehacks@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-5.1.1.tgz#7934a34eb59d7152149fa69d6e9e56f2fc34bcc9" - integrity sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw== +stylehacks@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-6.0.0.tgz#9fdd7c217660dae0f62e14d51c89f6c01b3cb738" + integrity sha512-+UT589qhHPwz6mTlCLSt/vMNTJx8dopeJlZAlBMJPWA3ORqu6wmQY7FBXf+qD+FsqoBJODyqNxOUP3jdntFRdw== dependencies: browserslist "^4.21.4" postcss-selector-parser "^6.0.4" +stylis@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.2.0.tgz#79daee0208964c8fe695a42fcffcac633a211a51" + integrity sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw== + supports-color@^5.3.0, supports-color@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -6273,28 +6300,27 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -svgo@^2.7.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.8.0.tgz#4ff80cce6710dc2795f0c7c74101e6764cfccd24" - integrity sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg== +svgo@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-3.0.2.tgz#5e99eeea42c68ee0dc46aa16da093838c262fe0a" + integrity sha512-Z706C1U2pb1+JGP48fbazf3KxHrWOsLme6Rv7imFBn5EnuanDW1GPaA/P1/dvObE670JDePC3mnj0k0B7P0jjQ== dependencies: "@trysound/sax" "0.2.0" commander "^7.2.0" - css-select "^4.1.3" - css-tree "^1.1.3" - csso "^4.2.0" + css-select "^5.1.0" + css-tree "^2.2.1" + csso "^5.0.5" picocolors "^1.0.0" - stable "^0.1.8" swc-loader@^0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/swc-loader/-/swc-loader-0.2.3.tgz#6792f1c2e4c9ae9bf9b933b3e010210e270c186d" integrity sha512-D1p6XXURfSPleZZA/Lipb3A8pZ17fP4NObZvFCDjK/OKljroqDpPmsBdTraWhVBqUNpcWBQY1imWdoPScRlQ7A== -swc-minify-webpack-plugin@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/swc-minify-webpack-plugin/-/swc-minify-webpack-plugin-1.0.1.tgz#8a19b88717e3bcaf13c0c559a5ac3537291f5deb" - integrity sha512-Zeg50WoMQc7gMbPoXryyXU4suxsQ4QBJb3Lsg3l2uFSLZ3ATDkXE4CUv1sGdyNsOGt9YIuc3aSnz9z+BoUHPSg== +swc-minify-webpack-plugin@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/swc-minify-webpack-plugin/-/swc-minify-webpack-plugin-2.1.0.tgz#35f975595d2e090064f34cb57f4ac4fd98a67eaa" + integrity sha512-v4B+Wcr84q58w2uALmjdTmOKyoF0pWY1xoGzy5vMibuQXQ0dHXlTmhodfu1NCiOISkqMf3T10nFmFQutBLw/vA== tabbable@^5.3.3: version "5.3.3" @@ -6327,7 +6353,7 @@ tar-stream@^2.1.4: inherits "^2.0.3" readable-stream "^3.1.1" -terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.3.6: +terser-webpack-plugin@^5.3.6: version "5.3.6" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz#5590aec31aa3c6f771ce1b1acca60639eab3195c" integrity sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ== @@ -6338,6 +6364,17 @@ terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.3.6: serialize-javascript "^6.0.0" terser "^5.14.1" +terser-webpack-plugin@^5.3.7: + version "5.3.9" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz#832536999c51b46d468067f9e37662a3b96adfe1" + integrity sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA== + dependencies: + "@jridgewell/trace-mapping" "^0.3.17" + jest-worker "^27.4.5" + schema-utils "^3.1.1" + serialize-javascript "^6.0.1" + terser "^5.16.8" + terser@^5.10.0, terser@^5.14.1: version "5.16.3" resolved "https://registry.yarnpkg.com/terser/-/terser-5.16.3.tgz#3266017a9b682edfe019b8ecddd2abaae7b39c6b" @@ -6348,6 +6385,16 @@ terser@^5.10.0, terser@^5.14.1: commander "^2.20.0" source-map-support "~0.5.20" +terser@^5.16.8: + version "5.17.6" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.17.6.tgz#d810e75e1bb3350c799cd90ebefe19c9412c12de" + integrity sha512-V8QHcs8YuyLkLHsJO5ucyff1ykrLVsR4dNnS//L5Y3NiSXpbK1J+WMVUs67eI0KTxs9JtHhgEQpXQVHlHI92DQ== + dependencies: + "@jridgewell/source-map" "^0.3.2" + acorn "^8.5.0" + commander "^2.20.0" + source-map-support "~0.5.20" + text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -6388,7 +6435,7 @@ tiny-invariant@1.0.6: resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.0.6.tgz#b3f9b38835e36a41c843a3b0907a5a7b3755de73" integrity sha512-FOyLWWVjG+aC0UqG76V53yAWdXfH8bO6FNmyZOuUrzDzK8DI3/JRY25UD7+g49JWM1LXwymsKERB+DzI0dTEQA== -tiny-invariant@^1.0.2, tiny-invariant@^1.0.6: +tiny-invariant@^1.0.2: version "1.3.1" resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642" integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw== @@ -6410,11 +6457,6 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -toidentifier@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" - integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== - toidentifier@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" @@ -6554,11 +6596,6 @@ typed-array-length@^1.0.4: for-each "^0.3.3" is-typed-array "^1.1.9" -typed-styles@^0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/typed-styles/-/typed-styles-0.0.7.tgz#93392a008794c4595119ff62dde6809dbc40a3d9" - integrity sha512-pzP0PWoZUhsECYjABgCGQlRGL1n7tOHsgwYv3oIiEpJwGhFTuty/YNeduxQYzXXa3Ge5BdT6sHYIQYpl4uJ+5Q== - typescript@^4.8.4: version "4.9.5" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" @@ -6623,10 +6660,10 @@ use-context-selector@^1.4.1: resolved "https://registry.yarnpkg.com/use-context-selector/-/use-context-selector-1.4.1.tgz#eb96279965846b72915d7f899b8e6ef1d768b0ae" integrity sha512-Io2ArvcRO+6MWIhkdfMFt+WKQX+Vb++W8DS2l03z/Vw/rz3BclKpM0ynr4LYGyU85Eke+Yx5oIhTY++QR0ZDoA== -use-memo-one@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/use-memo-one/-/use-memo-one-1.1.3.tgz#2fd2e43a2169eabc7496960ace8c79efef975e99" - integrity sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ== +use-isomorphic-layout-effect@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz#497cefb13d863d687b08477d9e5a164ad8c1a6fb" + integrity sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA== utf8-byte-length@^1.0.1: version "1.0.4" @@ -6668,7 +6705,7 @@ void-elements@3.1.0: resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09" integrity sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w== -warning@^4.0.2, warning@^4.0.3: +warning@^4.0.2: version "4.0.3" resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3" integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w== @@ -6693,11 +6730,12 @@ webidl-conversions@^7.0.0: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== -webpack-bundle-analyzer@^4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.7.0.tgz#33c1c485a7fcae8627c547b5c3328b46de733c66" - integrity sha512-j9b8ynpJS4K+zfO5GGwsAcQX4ZHpWV+yRiHDiL+bE0XHJ8NiPYLTNVQdlFYWxtpg9lfAQNlwJg16J9AJtFSXRg== +webpack-bundle-analyzer@^4.8.0: + version "4.8.0" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.8.0.tgz#951b8aaf491f665d2ae325d8b84da229157b1d04" + integrity sha512-ZzoSBePshOKhr+hd8u6oCkZVwpVaXgpw23ScGLFpR6SjYI7+7iIWYarjN6OEYOfRt8o7ZyZZQk0DuMizJ+LEIg== dependencies: + "@discoveryjs/json-ext" "0.5.7" acorn "^8.0.4" acorn-walk "^8.0.0" chalk "^4.1.0" @@ -6726,17 +6764,16 @@ webpack-cli@^4.10.0: rechoir "^0.7.0" webpack-merge "^5.7.3" -webpack-dev-middleware@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-4.3.0.tgz#179cc40795882cae510b1aa7f3710cbe93c9333e" - integrity sha512-PjwyVY95/bhBh6VUqt6z4THplYcsvQ8YNNBTBM873xLVmw8FLeALn0qurHbs9EmcfhzQis/eoqypSnZeuUz26w== +webpack-dev-middleware@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-6.0.1.tgz#fd585127ed44dab3f253daf0d98f4d58a5088cc2" + integrity sha512-PZPZ6jFinmqVPJZbisfggDiC+2EeGZ1ZByyMP5sOFJcPPWSexalISz+cvm+j+oYPT7FIJyxT76esjnw9DhE5sw== dependencies: - colorette "^1.2.2" - mem "^8.1.1" - memfs "^3.2.2" - mime-types "^2.1.30" + colorette "^2.0.10" + memfs "^3.4.12" + mime-types "^2.1.31" range-parser "^1.2.1" - schema-utils "^3.0.0" + schema-utils "^4.0.0" webpack-hot-middleware@^2.25.3: version "2.25.3" @@ -6768,22 +6805,22 @@ webpack-sources@^3.2.3: resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== -webpack@^5.75.0: - version "5.75.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.75.0.tgz#1e440468647b2505860e94c9ff3e44d5b582c152" - integrity sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ== +webpack@^5.78.0: + version "5.84.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.84.0.tgz#011115617668744aece87a9eb68534487d84de1a" + integrity sha512-XezNK3kwJq6IyeoZmZ1uEqQs+42nTqIi4jYM/YjLwaJedUC1N3bwnCC0+UcnHJPfqWX0kGrQnMIvZZyWYaIZrA== dependencies: "@types/eslint-scope" "^3.7.3" - "@types/estree" "^0.0.51" - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/wasm-edit" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" + "@types/estree" "^1.0.0" + "@webassemblyjs/ast" "^1.11.5" + "@webassemblyjs/wasm-edit" "^1.11.5" + "@webassemblyjs/wasm-parser" "^1.11.5" acorn "^8.7.1" - acorn-import-assertions "^1.7.6" + acorn-import-assertions "^1.9.0" browserslist "^4.14.5" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.10.0" - es-module-lexer "^0.9.0" + enhanced-resolve "^5.14.1" + es-module-lexer "^1.2.1" eslint-scope "5.1.1" events "^3.2.0" glob-to-regexp "^0.4.1" @@ -6792,9 +6829,9 @@ webpack@^5.75.0: loader-runner "^4.2.0" mime-types "^2.1.27" neo-async "^2.6.2" - schema-utils "^3.1.0" + schema-utils "^3.1.2" tapable "^2.1.1" - terser-webpack-plugin "^5.1.3" + terser-webpack-plugin "^5.3.7" watchpack "^2.4.0" webpack-sources "^3.2.3" @@ -6911,7 +6948,7 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2: +yaml@^1.10.0: version "1.10.2" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== diff --git a/examples/preview/next-app/.env.example b/examples/preview/next-app/.env.example new file mode 100644 index 000000000..71b58a9a0 --- /dev/null +++ b/examples/preview/next-app/.env.example @@ -0,0 +1,3 @@ +NEXT_PUBLIC_CMS_URL=http://localhost:3000 +NEXT_PRIVATE_DRAFT_SECRET=EXAMPLE_DRAFT_SECRET +NEXT_PRIVATE_REVALIDATION_KEY=EXAMPLE_REVALIDATION_KEY diff --git a/examples/preview/next-app/.eslintrc.js b/examples/preview/next-app/.eslintrc.js new file mode 100644 index 000000000..b22424b3e --- /dev/null +++ b/examples/preview/next-app/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + root: true, + extends: ['plugin:@next/next/recommended', '@payloadcms'], + rules: { + 'import/extensions': 'off', + }, +} diff --git a/examples/preview/next-app/.gitignore b/examples/preview/next-app/.gitignore new file mode 100644 index 000000000..233d5a4d0 --- /dev/null +++ b/examples/preview/next-app/.gitignore @@ -0,0 +1,6 @@ +.next +dist +build +node_modules +.env +package-lock.json diff --git a/examples/preview/next-app/.prettierrc.js b/examples/preview/next-app/.prettierrc.js new file mode 100644 index 000000000..70c17c995 --- /dev/null +++ b/examples/preview/next-app/.prettierrc.js @@ -0,0 +1,8 @@ +module.exports = { + printWidth: 100, + parser: "typescript", + semi: false, + singleQuote: true, + trailingComma: "all", + arrowParens: "avoid", +}; diff --git a/examples/preview/next-app/README.md b/examples/preview/next-app/README.md new file mode 100644 index 000000000..df0e45c29 --- /dev/null +++ b/examples/preview/next-app/README.md @@ -0,0 +1,37 @@ +# Payload Preview Example Front-End + +This is a [Next.js](https://nextjs.org) app using the [App Router](https://nextjs.org/docs/app). It was made explicitly for Payload's [Preview Example](https://github.com/payloadcms/payload/tree/master/examples/preview/cms). + +> This example uses the App Router, the latest API of Next.js. If your app is using the legacy [Pages Router](https://nextjs.org/docs/pages), check out the official [Pages Router Example](https://github.com/payloadcms/payload/tree/master/examples/preview/next-pages). + +## Getting Started + +### Payload + +First you'll need a running [Payload](https://github.com/payloadcms/payload) app. If you have not done so already, open up the `cms` folder and follow the setup instructions. Take note of your `serverURL`, you'll need this in the next step. + +### Next.js + +1. Clone this repo +2. `cd` into this directory and run `yarn` or `npm install` +3. `cp .env.example .env` to copy the example environment variables +4. `yarn dev` or `npm run dev` to start the server +5. `open http://localhost:3001` to see the result + +Once running you will find a couple seeded pages on your local environment with some basic instructions. You can also start editing the pages by modifying the documents within Payload. See the [Preview Example](https://github.com/payloadcms/payload/tree/master/examples/preview/cms) for full details. + +## Learn More + +To learn more about Payload and Next.js, take a look at the following resources: + +- [Payload Documentation](https://payloadcms.com/docs) - learn about Payload features and API. +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Payload GitHub repository](https://github.com/payloadcms/payload) as well as [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! + +## Deployment + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new) from the creators of Next.js. You could also combine this app into a [single Express server](https://github.com/payloadcms/payload/tree/master/examples/custom-server) and deploy in to [Payload Cloud](https://payloadcms.com/new/import). + +Check out our [Payload deployment documentation](https://payloadcms.com/docs/production/deployment) or the [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/examples/preview/next-app/app/[slug]/index.module.scss b/examples/preview/next-app/app/[slug]/index.module.scss new file mode 100644 index 000000000..3ae99a675 --- /dev/null +++ b/examples/preview/next-app/app/[slug]/index.module.scss @@ -0,0 +1,3 @@ +.page { + margin-top: calc(var(--base) * 2); +} diff --git a/examples/preview/next-app/app/[slug]/page.tsx b/examples/preview/next-app/app/[slug]/page.tsx new file mode 100644 index 000000000..deb9b700d --- /dev/null +++ b/examples/preview/next-app/app/[slug]/page.tsx @@ -0,0 +1,46 @@ +import { draftMode } from 'next/headers' +import { notFound } from 'next/navigation' + +import { Page } from '../../payload-types' +import { Gutter } from '../_components/Gutter' +import RichText from '../_components/RichText' +import { fetchPage, fetchPages } from '../cms' + +import classes from './index.module.scss' + +interface PageParams { + params: { slug: string } +} + +export const PageTemplate: React.FC<{ page: Page | null | undefined }> = ({ page }) => ( +
    + +

    {page?.title}

    + +
    +
    +) + +export default async function Page({ params: { slug = 'home' } }: PageParams) { + const { isEnabled: isDraftMode } = draftMode() + + const page = await fetchPage(slug, isDraftMode) + + if (page === null) { + return notFound() + } + + return +} + +export async function generateStaticParams() { + const pages = await fetchPages() + + return pages.map(({ slug }) => + slug !== 'home' + ? { + slug, + } + : {}, + ) // eslint-disable-line function-paren-newline +} diff --git a/examples/preview/next-app/app/_components/AdminBar/index.client.tsx b/examples/preview/next-app/app/_components/AdminBar/index.client.tsx new file mode 100644 index 000000000..7d3ab631b --- /dev/null +++ b/examples/preview/next-app/app/_components/AdminBar/index.client.tsx @@ -0,0 +1,43 @@ +'use client' + +import React, { useState } from 'react' +import { PayloadAdminBar, PayloadAdminBarProps, PayloadMeUser } from 'payload-admin-bar' + +import { Gutter } from '../Gutter' + +import classes from './index.module.scss' + +const Title: React.FC = () => Dashboard + +export const AdminBarClient: React.FC = props => { + const [user, setUser] = useState() + + return ( +
    + + } + cmsURL={process.env.NEXT_PUBLIC_CMS_URL} + onPreviewExit={async () => { + await fetch(`/api/exit-preview`) + window.location.reload() + }} + onAuthChange={setUser} + className={classes.payloadAdminBar} + classNames={{ + user: classes.user, + logo: classes.logo, + controls: classes.controls, + }} + style={{ + position: 'relative', + zIndex: 'unset', + padding: 0, + backgroundColor: 'transparent', + }} + /> + +
    + ) +} diff --git a/examples/preview/nextjs/components/Header/AdminBar/index.module.scss b/examples/preview/next-app/app/_components/AdminBar/index.module.scss similarity index 61% rename from examples/preview/nextjs/components/Header/AdminBar/index.module.scss rename to examples/preview/next-app/app/_components/AdminBar/index.module.scss index 4b57f48eb..5a3ea0631 100644 --- a/examples/preview/nextjs/components/Header/AdminBar/index.module.scss +++ b/examples/preview/next-app/app/_components/AdminBar/index.module.scss @@ -1,20 +1,22 @@ .adminBar { z-index: 10; width: 100%; - background-color: var(--color-dark-gray); - color: var(--color-white); - padding: calc(var(--base) * 0.25) 0; - font-size: calc(#{var(--html-font-size)} * 1px); + background-color: rgb(var(--foreground-rgb)); + padding: calc(var(--base) * 0.5) 0; display: none; } +.payloadAdminBar { + color: rgb(var(--background-rgb)) !important; +} + .show { display: block; } .controls { & > *:not(:last-child) { - margin-right:calc(var(--base) * 0.5) !important; + margin-right: calc(var(--base) * 0.5) !important; } } @@ -39,6 +41,6 @@ bottom: 0; left: 0; width: 100%; - background-color: var(--color-light-gray); + background-color: rbg(var(--background-rgb)); height: 2px; } diff --git a/examples/preview/next-app/app/_components/AdminBar/index.tsx b/examples/preview/next-app/app/_components/AdminBar/index.tsx new file mode 100644 index 000000000..4386fb7d3 --- /dev/null +++ b/examples/preview/next-app/app/_components/AdminBar/index.tsx @@ -0,0 +1,16 @@ +import React from 'react' +import { draftMode } from 'next/headers' + +import { AdminBarClient } from './index.client' + +export function AdminBar() { + const { isEnabled: isPreviewMode } = draftMode() + + return ( + + ) +} diff --git a/examples/preview/nextjs/components/Button/index.module.scss b/examples/preview/next-app/app/_components/Button/index.module.scss similarity index 94% rename from examples/preview/nextjs/components/Button/index.module.scss rename to examples/preview/next-app/app/_components/Button/index.module.scss index 4eb46c219..c43dbc192 100644 --- a/examples/preview/nextjs/components/Button/index.module.scss +++ b/examples/preview/next-app/app/_components/Button/index.module.scss @@ -1,5 +1,3 @@ -@import '../../css/type.scss'; - .button { border: none; cursor: pointer; @@ -21,7 +19,6 @@ } .label { - @extend %label; text-align: center; display: flex; align-items: center; diff --git a/examples/preview/next-app/app/_components/Button/index.tsx b/examples/preview/next-app/app/_components/Button/index.tsx new file mode 100644 index 000000000..dab17349e --- /dev/null +++ b/examples/preview/next-app/app/_components/Button/index.tsx @@ -0,0 +1,71 @@ +import React, { ElementType } from 'react' +import Link from 'next/link' + +import classes from './index.module.scss' + +export type Props = { + label?: string + appearance?: 'default' | 'primary' | 'secondary' + el?: 'button' | 'link' | 'a' + onClick?: () => void + href?: string + newTab?: boolean + className?: string + type?: 'submit' | 'button' + disabled?: boolean +} + +export const Button: React.FC = ({ + el: elFromProps = 'link', + label, + newTab, + href, + appearance, + className: classNameFromProps, + onClick, + type = 'button', + disabled, +}) => { + let el = elFromProps + const newTabProps = newTab ? { target: '_blank', rel: 'noopener noreferrer' } : {} + const className = [ + classes.button, + classNameFromProps, + classes[`appearance--${appearance}`], + classes.button, + ] + .filter(Boolean) + .join(' ') + + const content = ( +
    + {/* */} + {label} +
    + ) + + if (onClick || type === 'submit') el = 'button' + + if (el === 'link') { + return ( + + {content} + + ) + } + + const Element: ElementType = el + + return ( + + {content} + + ) +} diff --git a/examples/preview/next-app/app/_components/CMSLink/index.tsx b/examples/preview/next-app/app/_components/CMSLink/index.tsx new file mode 100644 index 000000000..20315f95e --- /dev/null +++ b/examples/preview/next-app/app/_components/CMSLink/index.tsx @@ -0,0 +1,66 @@ +import React from 'react' +import Link from 'next/link' + +import { Page } from '../../../payload-types' +import { Button } from '../Button' + +export type CMSLinkType = { + type?: 'custom' | 'reference' + url?: string + newTab?: boolean + reference?: { + value: string | Page + relationTo: 'pages' + } + label?: string + appearance?: 'default' | 'primary' | 'secondary' + children?: React.ReactNode + className?: string +} + +export const CMSLink: React.FC = ({ + type, + url, + newTab, + reference, + label, + appearance, + children, + className, +}) => { + const href = + type === 'reference' && typeof reference?.value === 'object' && reference.value.slug + ? `/${reference.value.slug === 'home' ? '' : reference.value.slug}` + : url + + if (!appearance) { + const newTabProps = newTab ? { target: '_blank', rel: 'noopener noreferrer' } : {} + + if (type === 'custom') { + return ( + + {label && label} + {children && children} + + ) + } + + if (href) { + return ( + + {label && label} + {children && children} + + ) + } + } + + const buttonProps = { + newTab, + href, + appearance, + label, + } + + return +
  • )} - ); }; diff --git a/src/admin/components/forms/field-types/Blocks/BlockRow.tsx b/src/admin/components/forms/field-types/Blocks/BlockRow.tsx new file mode 100644 index 000000000..fab45bd43 --- /dev/null +++ b/src/admin/components/forms/field-types/Blocks/BlockRow.tsx @@ -0,0 +1,141 @@ +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { Props } from './types'; +import { Collapsible } from '../../../elements/Collapsible'; +import RenderFields from '../../RenderFields'; +import SectionTitle from './SectionTitle'; +import Pill from '../../../elements/Pill'; +import HiddenInput from '../HiddenInput'; +import { getTranslation } from '../../../../../utilities/getTranslation'; +import { createNestedFieldPath } from '../../Form/createNestedFieldPath'; +import { RowActions } from './RowActions'; +import type { UseDraggableSortableReturn } from '../../../elements/DraggableSortable/useDraggableSortable/types'; +import type { Row } from '../../Form/types'; +import type { Block } from '../../../../../fields/config/types'; +import { useFormSubmitted } from '../../Form/context'; +import { ErrorPill } from '../../../elements/ErrorPill'; + +const baseClass = 'blocks-field'; + +type BlockFieldProps = UseDraggableSortableReturn & Pick & { + addRow: (rowIndex: number, blockType: string) => void + duplicateRow: (rowIndex: number) => void + removeRow: (rowIndex: number) => void + moveRow: (fromIndex: number, toIndex: number) => void + setCollapse: (id: string, collapsed: boolean) => void + rowIndex: number + row: Row + readOnly: boolean + rowCount: number + blockToRender: Block +} +export const BlockRow: React.FC = ({ + path: parentPath, + addRow, + removeRow, + moveRow, + duplicateRow, + setCollapse, + transform, + listeners, + attributes, + setNodeRef, + row, + rowIndex, + rowCount, + indexPath, + readOnly, + labels, + fieldTypes, + permissions, + blocks, + blockToRender, +}) => { + const path = `${parentPath}.${rowIndex}`; + const { i18n } = useTranslation(); + const hasSubmitted = useFormSubmitted(); + + const childErrorPathsCount = row.childErrorPaths?.size; + const fieldHasErrors = hasSubmitted && childErrorPathsCount > 0; + + const classNames = [ + `${baseClass}__row`, + fieldHasErrors ? `${baseClass}__row--has-errors` : `${baseClass}__row--no-errors`, + ].filter(Boolean).join(' '); + + return ( +
    + setCollapse(row.id, collapsed)} + className={classNames} + collapsibleStyle={fieldHasErrors ? 'error' : 'default'} + key={row.id} + dragHandleProps={{ + id: row.id, + attributes, + listeners, + }} + header={( +
    + + {String(rowIndex + 1).padStart(2, '0')} + + + {getTranslation(blockToRender.labels.singular, i18n)} + + + {fieldHasErrors && ( + + )} +
    + )} + actions={!readOnly ? ( + + ) : undefined} + > + + ({ + ...field, + path: createNestedFieldPath(path, field), + }))} + indexPath={indexPath} + /> +
    +
    + ); +}; diff --git a/src/admin/components/forms/field-types/Blocks/RowActions.tsx b/src/admin/components/forms/field-types/Blocks/RowActions.tsx index 48f7c36eb..ac88b107e 100644 --- a/src/admin/components/forms/field-types/Blocks/RowActions.tsx +++ b/src/admin/components/forms/field-types/Blocks/RowActions.tsx @@ -4,7 +4,6 @@ import { Block, Labels } from '../../../../../fields/config/types'; import { ArrayAction } from '../../../elements/ArrayAction'; import { useDrawerSlug } from '../../../elements/Drawer/useDrawerSlug'; import { BlocksDrawer } from './BlocksDrawer'; -import { Row } from '../../Form/types'; export const RowActions: React.FC<{ addRow: (rowIndex: number, blockType: string) => void @@ -14,7 +13,7 @@ export const RowActions: React.FC<{ labels: Labels blocks: Block[] rowIndex: number - rows: Row[] + rowCount: number blockType: string }> = (props) => { const { @@ -25,7 +24,7 @@ export const RowActions: React.FC<{ labels, blocks, rowIndex, - rows, + rowCount, blockType, } = props; @@ -47,7 +46,7 @@ export const RowActions: React.FC<{ labels={labels} /> { openModal(drawerSlug); }} diff --git a/src/admin/components/forms/field-types/Blocks/SectionTitle/index.scss b/src/admin/components/forms/field-types/Blocks/SectionTitle/index.scss index 03255d43e..f5f98f240 100644 --- a/src/admin/components/forms/field-types/Blocks/SectionTitle/index.scss +++ b/src/admin/components/forms/field-types/Blocks/SectionTitle/index.scss @@ -1,7 +1,6 @@ @import '../../../../../scss/styles.scss'; .section-title { - margin-left: base(.375); position: relative; &:after { @@ -9,7 +8,7 @@ content: attr(data-value) ' '; visibility: hidden; white-space: nowrap; - min-width: base(3); + min-width: base(2.5); } &:after, @@ -47,4 +46,4 @@ box-shadow: none; } } -} \ No newline at end of file +} diff --git a/src/admin/components/forms/field-types/Blocks/index.scss b/src/admin/components/forms/field-types/Blocks/index.scss index ab5cdfe36..994daf0a3 100644 --- a/src/admin/components/forms/field-types/Blocks/index.scss +++ b/src/admin/components/forms/field-types/Blocks/index.scss @@ -17,6 +17,28 @@ width: 100%; } + &__heading-with-error { + display: flex; + align-items: center; + gap: base(.5); + } + + &--has-no-error { + >.array-field__header .array-field__heading-with-error { + color: var(--theme-text); + } + } + + &--has-error { + >.array-field__header { + color: var(--theme-error-500); + } + } + + &__error-pill { + align-self: center; + } + &__header-actions { list-style: none; margin: 0 0 0 auto; @@ -38,16 +60,17 @@ display: inline-flex; max-width: 100%; overflow: hidden; + gap: base(.375); } &__block-number { - margin-right: base(.375); flex-shrink: 0; } &__block-pill { flex-shrink: 0; display: block; + line-height: unset; } .section-title { @@ -78,3 +101,19 @@ } } } + +html[data-theme="light"] { + .blocks-field--has-error { + .section-title__input, .blocks-field__heading-with-error { + color: var(--theme-error-750); + } + } +} + +html[data-theme="dark"] { + .blocks-field--has-error { + .section-title__input, .blocks-field__heading-with-error { + color: var(--theme-error-500); + } + } +} diff --git a/src/admin/components/forms/field-types/Blocks/index.tsx b/src/admin/components/forms/field-types/Blocks/index.tsx index d7a0c1b2a..3356de7f2 100644 --- a/src/admin/components/forms/field-types/Blocks/index.tsx +++ b/src/admin/components/forms/field-types/Blocks/index.tsx @@ -4,7 +4,7 @@ import { useAuth } from '../../../utilities/Auth'; import { useLocale } from '../../../utilities/Locale'; import withCondition from '../../withCondition'; import { useDocumentInfo } from '../../../utilities/DocumentInfo'; -import { useForm } from '../../Form/context'; +import { useForm, useFormSubmitted } from '../../Form/context'; import buildStateFromSchema from '../../Form/buildStateFromSchema'; import Error from '../../Error'; import useField from '../../useField'; @@ -14,22 +14,17 @@ import Banner from '../../../elements/Banner'; import FieldDescription from '../../FieldDescription'; import { Props } from './types'; import { useOperation } from '../../../utilities/OperationProvider'; -import { Collapsible } from '../../../elements/Collapsible'; -import RenderFields from '../../RenderFields'; -import SectionTitle from './SectionTitle'; -import Pill from '../../../elements/Pill'; import { scrollToID } from '../../../../utilities/scrollToID'; -import HiddenInput from '../HiddenInput'; import { getTranslation } from '../../../../../utilities/getTranslation'; import { NullifyLocaleField } from '../../NullifyField'; import { useConfig } from '../../../utilities/Config'; -import { createNestedFieldPath } from '../../Form/createNestedFieldPath'; import DraggableSortable from '../../../elements/DraggableSortable'; import DraggableSortableItem from '../../../elements/DraggableSortable/DraggableSortableItem'; import { useDrawerSlug } from '../../../elements/Drawer/useDrawerSlug'; import Button from '../../../elements/Button'; -import { RowActions } from './RowActions'; import { DrawerToggler } from '../../../elements/Drawer'; +import { BlockRow } from './BlockRow'; +import { ErrorPill } from '../../../elements/ErrorPill'; import './index.scss'; @@ -63,13 +58,13 @@ const BlocksField: React.FC = (props) => { const path = pathFromProps || name; const { id, setDocFieldPreferences, getDocPreferences } = useDocumentInfo(); - const formContext = useForm(); + const { dispatchFields, setModified } = useForm(); const { user } = useAuth(); const locale = useLocale(); const operation = useOperation(); - const { dispatchFields, setModified } = formContext; const { localization } = useConfig(); const drawerSlug = useDrawerSlug('blocks-drawer'); + const submitted = useFormSubmitted(); const labels = { singular: t('block'), @@ -77,25 +72,29 @@ const BlocksField: React.FC = (props) => { ...labelsFromProps, }; - const checkSkipValidation = useCallback((value) => { - const defaultLocale = (localization && localization.defaultLocale) ? localization.defaultLocale : 'en'; - const isEditingDefaultLocale = locale === defaultLocale; - const fallbackEnabled = (localization && localization.fallback); - - if (value === null && !isEditingDefaultLocale && fallbackEnabled) return true; - return false; - }, [locale, localization]); + const editingDefaultLocale = (() => { + if (localization && localization.fallback) { + const defaultLocale = localization.defaultLocale || 'en'; + return locale === defaultLocale; + } + return true; + })(); const memoizedValidate = useCallback((value, options) => { - if (checkSkipValidation(value)) return true; + // alternative locales can be null + if (!editingDefaultLocale && value === null) { + return true; + } return validate(value, { ...options, minRows, maxRows, required }); - }, [maxRows, minRows, required, validate, checkSkipValidation]); + }, [maxRows, minRows, required, validate, editingDefaultLocale]); + const { showError, errorMessage, value, rows, + valid, } = useField({ path, validate: memoizedValidate, @@ -134,20 +133,24 @@ const BlocksField: React.FC = (props) => { setModified(true); }, [dispatchFields, path, setModified]); - const setCollapse = useCallback(async (rowID: string, collapsed: boolean) => { - dispatchFields({ type: 'SET_ROW_COLLAPSED', path, collapsed, rowID, setDocFieldPreferences }); - }, [dispatchFields, path, setDocFieldPreferences]); - const toggleCollapseAll = useCallback(async (collapsed: boolean) => { dispatchFields({ type: 'SET_ALL_ROWS_COLLAPSED', path, collapsed, setDocFieldPreferences }); }, [dispatchFields, path, setDocFieldPreferences]); + const setCollapse = useCallback(async (rowID: string, collapsed: boolean) => { + dispatchFields({ type: 'SET_ROW_COLLAPSED', path, collapsed, rowID, setDocFieldPreferences }); + }, [dispatchFields, path, setDocFieldPreferences]); + const hasMaxRows = maxRows && rows?.length >= maxRows; + const fieldErrorCount = rows.reduce((total, row) => total + (row?.childErrorPaths?.size || 0), 0); + const fieldHasErrors = submitted && fieldErrorCount + (valid ? 0 : 1) > 0; + const classes = [ 'field-type', baseClass, className, + fieldHasErrors ? `${baseClass}--has-error` : `${baseClass}--has-no-error`, ].filter(Boolean).join(' '); if (!rows) return null; @@ -165,7 +168,18 @@ const BlocksField: React.FC = (props) => {
    -

    {getTranslation(label || name, i18n)}

    +
    +

    + {getTranslation(label || name, i18n)} +

    + + {fieldHasErrors && fieldErrorCount > 0 && ( + + )} +
    • diff --git a/src/admin/components/forms/field-types/Checkbox/index.scss b/src/admin/components/forms/field-types/Checkbox/index.scss index b158d4b46..aabd160a2 100644 --- a/src/admin/components/forms/field-types/Checkbox/index.scss +++ b/src/admin/components/forms/field-types/Checkbox/index.scss @@ -8,7 +8,7 @@ display: none; } - .tooltip { + .tooltip:not([aria-hidden="true"]) { right: auto; position: relative; margin-bottom: .2em; @@ -92,4 +92,24 @@ } } } -} \ No newline at end of file +} + +html[data-theme=light] { + .checkbox { + &.error { + .custom-checkbox__input { + @include lightInputError; + } + } + } +} + +html[data-theme=dark] { + .checkbox { + &.error { + .custom-checkbox__input { + @include darkInputError; + } + } + } +} diff --git a/src/admin/components/forms/field-types/Code/index.scss b/src/admin/components/forms/field-types/Code/index.scss index 3f565ceb0..2d1acfb7e 100644 --- a/src/admin/components/forms/field-types/Code/index.scss +++ b/src/admin/components/forms/field-types/Code/index.scss @@ -8,5 +8,28 @@ textarea { border: 1px solid var(--theme-error-500) !important; } + .code-editor { + border-color: var(--theme-error-500); + } + } +} + +html[data-theme=light] { + .code-field{ + &.error { + .monaco-editor-background, .margin { + background-color: var(--theme-error-50); + } + } + } +} + +html[data-theme=dark] { + .code-field { + &.error { + .monaco-editor-background, .margin { + background-color: var(--theme-error-100); + } + } } } diff --git a/src/admin/components/forms/field-types/Collapsible/index.scss b/src/admin/components/forms/field-types/Collapsible/index.scss index c8a01833d..d3a4dd1a8 100644 --- a/src/admin/components/forms/field-types/Collapsible/index.scss +++ b/src/admin/components/forms/field-types/Collapsible/index.scss @@ -3,7 +3,14 @@ .collapsible-field { margin: 0 0 base(2); - &__label { + &__row-label-wrap { pointer-events: none; + display: flex; + align-items: center; + gap: base(.5); + } + + &--has-error { + border: 1px solid var(--theme-error-500); } } diff --git a/src/admin/components/forms/field-types/Collapsible/index.tsx b/src/admin/components/forms/field-types/Collapsible/index.tsx index 761cbce2b..93c26d2cd 100644 --- a/src/admin/components/forms/field-types/Collapsible/index.tsx +++ b/src/admin/components/forms/field-types/Collapsible/index.tsx @@ -9,6 +9,9 @@ import { useDocumentInfo } from '../../../utilities/DocumentInfo'; import FieldDescription from '../../FieldDescription'; import { RowLabel } from '../../RowLabel'; import { createNestedFieldPath } from '../../Form/createNestedFieldPath'; +import { WatchChildErrors } from '../../WatchChildErrors'; +import { useFormSubmitted } from '../../Form/context'; +import { ErrorPill } from '../../../elements/ErrorPill'; import './index.scss'; @@ -34,6 +37,8 @@ const CollapsibleField: React.FC = (props) => { const { preferencesKey } = useDocumentInfo(); const [collapsedOnMount, setCollapsedOnMount] = useState(); const fieldPreferencesKey = `collapsible-${indexPath.replace(/\./gi, '__')}`; + const [errorCount, setErrorCount] = useState(0); + const submitted = useFormSubmitted(); const onToggle = useCallback(async (newCollapsedState: boolean) => { const existingPreferences: DocumentPreferences = await getPreference(preferencesKey); @@ -76,20 +81,39 @@ const CollapsibleField: React.FC = (props) => { if (typeof collapsedOnMount !== 'boolean') return null; + const fieldHasErrors = submitted && errorCount > 0; + + const classes = [ + 'field-type', + baseClass, + className, + fieldHasErrors ? `${baseClass}--has-error` : `${baseClass}--has-no-error`, + ].filter(Boolean).join(' '); + return (
      + 0 ? 'error' : 'default'} header={( - +
      + + {errorCount > 0 && ( + + )} +
      )} onToggle={onToggle} > diff --git a/src/admin/components/forms/field-types/ConfirmPassword/index.scss b/src/admin/components/forms/field-types/ConfirmPassword/index.scss index 9a077a132..c8c29343d 100644 --- a/src/admin/components/forms/field-types/ConfirmPassword/index.scss +++ b/src/admin/components/forms/field-types/ConfirmPassword/index.scss @@ -7,10 +7,24 @@ input { @include formInput; } +} - &.error { - input { - background-color: var(--theme-error-200); +html[data-theme=light] { + .field-type.field-type.confirm-password { + &.error { + input { + @include lightInputError; + } + } + } +} + +html[data-theme=dark] { + .field-type.field-type.confirm-password { + &.error { + input { + @include darkInputError; + } } } } diff --git a/src/admin/components/forms/field-types/ConfirmPassword/index.tsx b/src/admin/components/forms/field-types/ConfirmPassword/index.tsx index 10fddd3cc..614d22373 100644 --- a/src/admin/components/forms/field-types/ConfirmPassword/index.tsx +++ b/src/admin/components/forms/field-types/ConfirmPassword/index.tsx @@ -4,7 +4,7 @@ import useField from '../../useField'; import Label from '../../Label'; import Error from '../../Error'; import { useFormFields } from '../../Form/context'; -import { Field } from '../../Form/types'; +import { FormField } from '../../Form/types'; import type { Props } from './types'; import './index.scss'; @@ -14,7 +14,7 @@ const ConfirmPassword: React.FC = (props) => { disabled, } = props; - const password = useFormFields(([fields]) => fields.password); + const password = useFormFields(([fields]) => fields.password); const { t } = useTranslation('fields'); const validate = useCallback((value: string) => { diff --git a/src/admin/components/forms/field-types/DateTime/index.scss b/src/admin/components/forms/field-types/DateTime/index.scss index d061e7e03..830c7713a 100644 --- a/src/admin/components/forms/field-types/DateTime/index.scss +++ b/src/admin/components/forms/field-types/DateTime/index.scss @@ -6,10 +6,24 @@ &__error-wrap { position: relative; } +} - &--has-error { - .react-datepicker__input-container input { - background-color: var(--theme-error-200); +html[data-theme=light] { + .date-time-field{ + &--has-error { + .react-datepicker__input-container input { + @include lightInputError; + } + } + } +} + +html[data-theme=dark] { + .date-time-field { + &--has-error { + .react-datepicker__input-container input { + @include darkInputError; + } } } } diff --git a/src/admin/components/forms/field-types/Email/index.scss b/src/admin/components/forms/field-types/Email/index.scss index 45deb8c46..98704d9af 100644 --- a/src/admin/components/forms/field-types/Email/index.scss +++ b/src/admin/components/forms/field-types/Email/index.scss @@ -14,3 +14,24 @@ } } } + + +html[data-theme=light] { + .field-type.email{ + &.error { + input { + @include lightInputError; + } + } + } +} + +html[data-theme=dark] { + .field-type.email { + &.error { + input { + @include darkInputError; + } + } + } +} diff --git a/src/admin/components/forms/field-types/Group/index.scss b/src/admin/components/forms/field-types/Group/index.scss index 819168786..da4529781 100644 --- a/src/admin/components/forms/field-types/Group/index.scss +++ b/src/admin/components/forms/field-types/Group/index.scss @@ -13,6 +13,7 @@ &:first-child { border-top: 0; padding-top: 0; + margin-top: 0; } &:last-child { @@ -54,6 +55,9 @@ &__header { margin-bottom: base(.75); + display: flex; + align-items: center; + gap: base(.5); } &__title { @@ -95,3 +99,25 @@ .group-field--within-tab+.group-field--within-row { padding-top: 0; } + +html[data-theme=light] { + .group-field { + &--has-error { + color: var(--theme-error-750); + &:after { + background: var(--theme-error-500); + } + } + } +} + +html[data-theme=dark] { + .group-field { + &--has-error { + color: var(--theme-error-500); + &:after { + background: var(--theme-error-500); + } + } + } +} diff --git a/src/admin/components/forms/field-types/Group/index.tsx b/src/admin/components/forms/field-types/Group/index.tsx index 6a7eb80ee..ebbe92179 100644 --- a/src/admin/components/forms/field-types/Group/index.tsx +++ b/src/admin/components/forms/field-types/Group/index.tsx @@ -10,6 +10,9 @@ import { useRow } from '../Row/provider'; import { useTabs } from '../Tabs/provider'; import { getTranslation } from '../../../../../utilities/getTranslation'; import { createNestedFieldPath } from '../../Form/createNestedFieldPath'; +import { useFormSubmitted } from '../../Form/context'; +import { WatchChildErrors } from '../../WatchChildErrors'; +import { ErrorPill } from '../../../elements/ErrorPill'; import './index.scss'; @@ -39,6 +42,9 @@ const Group: React.FC = (props) => { const isWithinRow = useRow(); const isWithinTab = useTabs(); const { i18n } = useTranslation(); + const submitted = useFormSubmitted(); + const [errorCount, setErrorCount] = React.useState(undefined); + const groupHasErrors = submitted && errorCount > 0; const path = pathFromProps || name; @@ -53,6 +59,7 @@ const Group: React.FC = (props) => { isWithinRow && `${baseClass}--within-row`, isWithinTab && `${baseClass}--within-tab`, (!hideGutter && isWithinGroup) && `${baseClass}--gutter`, + groupHasErrors && `${baseClass}--has-error`, className, ].filter(Boolean).join(' ')} style={{ @@ -60,20 +67,33 @@ const Group: React.FC = (props) => { width, }} > +
      - {(label || description) && ( -
      - {label && ( -

      {getTranslation(label, i18n)}

      - )} - + {(label || description) && ( +
      + {label && ( +

      {getTranslation(label, i18n)}

      + )} + +
      + )} + {groupHasErrors && ( + -
      - )} + )} +
      .relationship__wrap { + .rs__control { + @include lightInputError; + } + } + + button { + @include lightInputError; + } + } + } +} + +html[data-theme=dark] { + .relationship { + &.error { + >.relationship__wrap { + .rs__control { + @include darkInputError; + } + } + + button { + @include darkInputError; + } + } + } +} diff --git a/src/admin/components/forms/field-types/RichText/elements/link/LinkDrawer/baseFields.ts b/src/admin/components/forms/field-types/RichText/elements/link/LinkDrawer/baseFields.ts index 7bba95f8f..106522768 100644 --- a/src/admin/components/forms/field-types/RichText/elements/link/LinkDrawer/baseFields.ts +++ b/src/admin/components/forms/field-types/RichText/elements/link/LinkDrawer/baseFields.ts @@ -46,9 +46,7 @@ export const getBaseFields = (config: Config): Field[] => [ type: 'text', required: true, admin: { - condition: ({ linkType, url }) => { - return (typeof linkType === 'undefined' && url) || linkType === 'custom'; - }, + condition: ({ linkType }) => linkType !== 'internal', }, }, { diff --git a/src/admin/components/forms/field-types/RichText/index.scss b/src/admin/components/forms/field-types/RichText/index.scss index bbf25b490..6091a5eb6 100644 --- a/src/admin/components/forms/field-types/RichText/index.scss +++ b/src/admin/components/forms/field-types/RichText/index.scss @@ -169,3 +169,23 @@ [data-slate-node=element] { margin-bottom: base(0.25); } + +html[data-theme=light] { + .rich-text { + &.error { + .rich-text__editor, .rich-text__toolbar { + @include lightInputError; + } + } + } +} + +html[data-theme=dark] { + .rich-text { + &.error { + .rich-text__editor, .rich-text__toolbar { + @include darkInputError; + } + } + } +} diff --git a/src/admin/components/forms/field-types/Select/index.scss b/src/admin/components/forms/field-types/Select/index.scss index c77a275aa..25ecf5568 100644 --- a/src/admin/components/forms/field-types/Select/index.scss +++ b/src/admin/components/forms/field-types/Select/index.scss @@ -3,4 +3,24 @@ .field-type.select { position: relative; margin-bottom: $baseline; -} \ No newline at end of file +} + +html[data-theme=light] { + .field-type.select{ + &.error { + .rs__control { + @include lightInputError; + } + } + } +} + +html[data-theme=dark] { + .field-type.select { + &.error { + .rs__control { + @include darkInputError; + } + } + } +} diff --git a/src/admin/components/forms/field-types/Tabs/index.scss b/src/admin/components/forms/field-types/Tabs/index.scss index dc827c7d9..68f519efe 100644 --- a/src/admin/components/forms/field-types/Tabs/index.scss +++ b/src/admin/components/forms/field-types/Tabs/index.scss @@ -53,6 +53,7 @@ &__tab-button { @extend %btn-reset; @extend %h4; + display: flex; padding-bottom: base(.75); margin: 0 $baseline 0 0; cursor: pointer; @@ -60,6 +61,7 @@ position: relative; white-space: nowrap; flex-shrink: 0; + gap: base(.5); &:last-child { margin: 0; @@ -112,4 +114,26 @@ } } } -} \ No newline at end of file +} + +html[data-theme=light] { + .tabs-field { + &__tab-button--has-error { + color: var(--theme-error-750); + &:after { + background: var(--theme-error-500); + } + } + } +} + +html[data-theme=dark] { + .tabs-field { + &__tab-button--has-error { + color: var(--theme-error-500); + &:after { + background: var(--theme-error-500); + } + } + } +} diff --git a/src/admin/components/forms/field-types/Tabs/index.tsx b/src/admin/components/forms/field-types/Tabs/index.tsx index 495625be7..82ddc6d1e 100644 --- a/src/admin/components/forms/field-types/Tabs/index.tsx +++ b/src/admin/components/forms/field-types/Tabs/index.tsx @@ -4,6 +4,7 @@ import RenderFields from '../../RenderFields'; import withCondition from '../../withCondition'; import { Props } from './types'; import { tabHasName } from '../../../../../fields/config/types'; +import type { Tab } from '../../../../../fields/config/types'; import FieldDescription from '../../FieldDescription'; import toKebabCase from '../../../../../utilities/toKebabCase'; import { useCollapsible } from '../../../elements/Collapsible/provider'; @@ -13,11 +14,57 @@ import { usePreferences } from '../../../utilities/Preferences'; import { DocumentPreferences } from '../../../../../preferences/types'; import { useDocumentInfo } from '../../../utilities/DocumentInfo'; import { createNestedFieldPath } from '../../Form/createNestedFieldPath'; +import { WatchChildErrors } from '../../WatchChildErrors'; +import { ErrorPill } from '../../../elements/ErrorPill'; +import { useFormSubmitted } from '../../Form/context'; import './index.scss'; const baseClass = 'tabs-field'; +type TabProps = { + isActive?: boolean; + setIsActive: () => void; + tab: Tab; + parentPath: string +} +const Tab: React.FC = ({ tab, isActive, setIsActive, parentPath }) => { + const { i18n } = useTranslation(); + const [errorCount, setErrorCount] = useState(undefined); + const hasName = tabHasName(tab); + const submitted = useFormSubmitted(); + + const pathSegments = []; + if (parentPath) pathSegments.push(parentPath); + if (hasName) pathSegments.push(tab.name); + const path = pathSegments.join('.'); + const tabHasErrors = submitted && errorCount > 0; + + return ( + + + + + ); +}; + const TabsField: React.FC = (props) => { const { tabs, @@ -89,55 +136,51 @@ const TabsField: React.FC = (props) => {
      {tabs.map((tab, tabIndex) => { return ( - + setIsActive={() => handleTabChange(tabIndex)} + isActive={activeTabIndex === tabIndex} + parentPath={path} + tab={tab} + /> ); })}
      {activeTabConfig && ( -
      - - { - const pathSegments = []; + +
      + + { + const pathSegments = []; - if (path) pathSegments.push(path); - if (tabHasName(activeTabConfig)) pathSegments.push(activeTabConfig.name); + if (path) pathSegments.push(path); + if (tabHasName(activeTabConfig)) pathSegments.push(activeTabConfig.name); - return { - ...field, - path: createNestedFieldPath(pathSegments.join('.'), field), - }; - })} - indexPath={indexPath} - /> -
      + return { + ...field, + path: createNestedFieldPath(pathSegments.join('.'), field), + }; + })} + indexPath={indexPath} + /> +
      + )}
      diff --git a/src/admin/components/forms/field-types/Text/index.scss b/src/admin/components/forms/field-types/Text/index.scss index f66e22fc8..78fdde1be 100644 --- a/src/admin/components/forms/field-types/Text/index.scss +++ b/src/admin/components/forms/field-types/Text/index.scss @@ -7,10 +7,24 @@ input { @include formInput; } +} - &.error { - input { - background-color: var(--theme-error-200); +html[data-theme=light] { + .field-type.text { + &.error { + input { + @include lightInputError; + } + } + } +} + +html[data-theme=dark] { + .field-type.text { + &.error { + input { + @include darkInputError; + } } } } diff --git a/src/admin/components/forms/field-types/Text/index.tsx b/src/admin/components/forms/field-types/Text/index.tsx index 853b15b23..bb18d25e9 100644 --- a/src/admin/components/forms/field-types/Text/index.tsx +++ b/src/admin/components/forms/field-types/Text/index.tsx @@ -32,18 +32,16 @@ const Text: React.FC = (props) => { return validate(value, { ...options, minLength, maxLength, required }); }, [validate, minLength, maxLength, required]); - const field = useField({ - path, - validate: memoizedValidate, - condition, - }); - const { value, showError, setValue, errorMessage, - } = field; + } = useField({ + path, + validate: memoizedValidate, + condition, + }); return ( (options: Options): FieldType => { const { id } = useDocumentInfo(); const operation = useOperation(); const field = useFormFields(([fields]) => fields[path]); - - const dispatchField = useFormFields(([_, dispatch]) => dispatch); const { t } = useTranslation(); + const dispatchField = useFormFields(([_, dispatch]) => dispatch); const { getData, getSiblingData, setModified } = useForm(); @@ -72,7 +71,7 @@ const useField = (options: Options): FieldType => { // Store result from hook as ref // to prevent unnecessary rerenders - const result = useMemo(() => ({ + const result: FieldType = useMemo(() => ({ showError, errorMessage: field?.errorMessage, value, @@ -81,7 +80,18 @@ const useField = (options: Options): FieldType => { setValue, initialValue, rows: field?.rows, - }), [field, processing, setValue, showError, submitted, value, initialValue]); + valid: field?.valid, + }), [ + field?.errorMessage, + field?.rows, + field?.valid, + processing, + setValue, + showError, + submitted, + value, + initialValue, + ]); // Throttle the validate function useThrottledEffect(() => { diff --git a/src/admin/components/forms/useField/types.ts b/src/admin/components/forms/useField/types.ts index f60d2cd16..2092d1439 100644 --- a/src/admin/components/forms/useField/types.ts +++ b/src/admin/components/forms/useField/types.ts @@ -18,4 +18,5 @@ export type FieldType = { setValue: (val: unknown, modifyForm?: boolean) => void initialValue?: T rows?: Row[] + valid?: boolean } diff --git a/src/admin/components/utilities/Auth/index.tsx b/src/admin/components/utilities/Auth/index.tsx index 910520be2..8c7663dc0 100644 --- a/src/admin/components/utilities/Auth/index.tsx +++ b/src/admin/components/utilities/Auth/index.tsx @@ -3,6 +3,7 @@ import jwtDecode from 'jwt-decode'; import { useHistory, useLocation } from 'react-router-dom'; import { useModal } from '@faceless-ui/modal'; import { useTranslation } from 'react-i18next'; +import { toast } from 'react-toastify'; import { Permissions, User } from '../../../../auth/types'; import { useConfig } from '../Config'; import { requests } from '../../../api'; @@ -25,6 +26,7 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children admin: { user: userSlug, inactivityRoute: logoutInactivityRoute, + autoLogin, }, serverURL, routes: { @@ -44,29 +46,56 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children const id = user?.id; - const refreshCookie = useCallback(() => { + const refreshCookie = useCallback((forceRefresh?: boolean) => { const now = Math.round((new Date()).getTime() / 1000); const remainingTime = (exp as number || 0) - now; - if (exp && remainingTime < 120) { + if (forceRefresh || (exp && remainingTime < 120)) { setTimeout(async () => { - const request = await requests.post(`${serverURL}${api}/${userSlug}/refresh-token`, { - headers: { - 'Accept-Language': i18n.language, - }, - }); + try { + const request = await requests.post(`${serverURL}${api}/${userSlug}/refresh-token`, { + headers: { + 'Accept-Language': i18n.language, + }, + }); - if (request.status === 200) { - const json = await request.json(); - setUser(json.user); - } else { - setUser(null); - push(`${admin}${logoutInactivityRoute}?redirect=${encodeURIComponent(window.location.pathname)}`); + if (request.status === 200) { + const json = await request.json(); + setUser(json.user); + } else { + setUser(null); + push(`${admin}${logoutInactivityRoute}?redirect=${encodeURIComponent(window.location.pathname)}`); + } + } catch (e) { + toast.error(e.message); } }, 1000); } }, [exp, serverURL, api, userSlug, push, admin, logoutInactivityRoute, i18n]); + const refreshCookieAsync = useCallback(async (skipSetUser?: boolean): Promise => { + try { + const request = await requests.post(`${serverURL}${api}/${userSlug}/refresh-token`, { + headers: { + 'Accept-Language': i18n.language, + }, + }); + + if (request.status === 200) { + const json = await request.json(); + if (!skipSetUser) setUser(json.user); + return json.user; + } + + setUser(null); + push(`${admin}${logoutInactivityRoute}`); + return null; + } catch (e) { + toast.error(`Refreshing token failed: ${e.message}`); + return null; + } + }, [serverURL, api, userSlug, push, admin, logoutInactivityRoute, i18n]); + const setToken = useCallback((token: string) => { const decoded = jwtDecode(token); setUser(decoded); @@ -80,42 +109,74 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }, [serverURL, api, userSlug]); const refreshPermissions = useCallback(async () => { - const request = await requests.get(`${serverURL}${api}/access`, { - headers: { - 'Accept-Language': i18n.language, - }, - }); - - if (request.status === 200) { - const json: Permissions = await request.json(); - setPermissions(json); - } else { - throw new Error(`Fetching permissions failed with status code ${request.status}`); - } - }, [serverURL, api, i18n]); - - // On mount, get user and set - useEffect(() => { - const fetchMe = async () => { - const request = await requests.get(`${serverURL}${api}/${userSlug}/me`, { + try { + const request = await requests.get(`${serverURL}${api}/access`, { headers: { 'Accept-Language': i18n.language, }, }); if (request.status === 200) { - const json = await request.json(); + const json: Permissions = await request.json(); + setPermissions(json); + } else { + throw new Error(`Fetching permissions failed with status code ${request.status}`); + } + } catch (e) { + toast.error(`Refreshing permissions failed: ${e.message}`); + } + }, [serverURL, api, i18n]); - setUser(json?.user || null); + // On mount, get user and set + useEffect(() => { + const fetchMe = async () => { + try { + const request = await requests.get(`${serverURL}${api}/${userSlug}/me`, { + headers: { + 'Accept-Language': i18n.language, + }, + }); - if (json?.token) { - setToken(json.token); + if (request.status === 200) { + const json = await request.json(); + + if (json?.user) { + setUser(json.user); + } else if (json?.token) { + setToken(json.token); + } else if (autoLogin) { + // auto log-in with the provided autoLogin credentials. This is used in dev mode + // so you don't have to log in over and over again + const autoLoginResult = await requests.post(`${serverURL}${api}/${userSlug}/login`, { + body: JSON.stringify({ + email: autoLogin.email, + password: autoLogin.password, + }), + headers: { + 'Accept-Language': i18n.language, + 'Content-Type': 'application/json', + }, + }); + if (autoLoginResult.status === 200) { + const autoLoginJson = await autoLoginResult.json(); + setUser(autoLoginJson.user); + if (autoLoginJson?.token) { + setToken(autoLoginJson.token); + } + } else { + setUser(null); + } + } else { + setUser(null); + } } + } catch (e) { + toast.error(`Fetching user failed: ${e.message}`); } }; fetchMe(); - }, [i18n, setToken, api, serverURL, userSlug]); + }, [i18n, setToken, api, serverURL, userSlug, autoLogin]); // When location changes, refresh cookie useEffect(() => { @@ -172,8 +233,10 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children return ( = { user?: T | null + setUser: (user: T) => void logOut: () => void - refreshCookie: () => void + refreshCookie: (forceRefresh?: boolean) => void + refreshCookieAsync: () => Promise setToken: (token: string) => void token?: string refreshPermissions: () => Promise diff --git a/src/admin/components/views/Account/Default.tsx b/src/admin/components/views/Account/Default.tsx index 902d4b85a..1ea8c0df6 100644 --- a/src/admin/components/views/Account/Default.tsx +++ b/src/admin/components/views/Account/Default.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useCallback } from 'react'; import { Link } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { useConfig } from '../../utilities/Config'; @@ -22,6 +22,7 @@ import Label from '../../forms/Label'; import type { Translation } from '../../../../translations/type'; import { LoadingOverlayToggle } from '../../elements/Loading'; import { formatDate } from '../../../utilities/formatDate'; +import { useAuth } from '../../utilities/Auth'; import './index.scss'; @@ -37,7 +38,7 @@ const DefaultAccount: React.FC = (props) => { initialState, isLoading, action, - onSave, + onSave: onSaveFromProps, } = props; const { @@ -51,6 +52,7 @@ const DefaultAccount: React.FC = (props) => { auth, } = collection; + const { refreshCookieAsync } = useAuth(); const { admin: { dateFormat }, routes: { admin } } = useConfig(); const { t, i18n } = useTranslation('authentication'); @@ -58,6 +60,13 @@ const DefaultAccount: React.FC = (props) => { { label: (resource as Translation).general.thisLanguage, value: language } )); + const onSave = useCallback(async () => { + await refreshCookieAsync(); + if (typeof onSaveFromProps === 'function') { + onSaveFromProps(); + } + }, [onSaveFromProps, refreshCookieAsync]); + const classes = [ baseClass, ].filter(Boolean).join(' '); @@ -69,7 +78,6 @@ const DefaultAccount: React.FC = (props) => { show={isLoading} type="withoutNav" /> -
      {!isLoading && ( @@ -201,7 +209,6 @@ const DefaultAccount: React.FC = (props) => { )} )} -
    diff --git a/src/admin/components/views/Account/index.tsx b/src/admin/components/views/Account/index.tsx index 78f5a1eee..77c40746f 100644 --- a/src/admin/components/views/Account/index.tsx +++ b/src/admin/components/views/Account/index.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useRef } from 'react'; import { useLocation } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { useConfig } from '../../utilities/Config'; @@ -18,7 +18,8 @@ const AccountView: React.FC = () => { const locale = useLocale(); const { setStepNav } = useStepNav(); const { user } = useAuth(); - const [initialState, setInitialState] = useState(); + const userRef = useRef(user); + const [internalState, setInternalState] = useState(); const { id, preferencesKey, docPermissions, getDocPermissions, slug, getDocPreferences } = useDocumentInfo(); const { getPreference } = usePreferences(); @@ -36,6 +37,7 @@ const AccountView: React.FC = () => { } = {}, }, } = useConfig(); + const { t } = useTranslation('authentication'); const collection = collections.find((coll) => coll.slug === slug); @@ -63,7 +65,7 @@ const AccountView: React.FC = () => { getDocPermissions(); const preferences = await getDocPreferences(); const state = await buildStateFromSchema({ fieldSchema: collection.fields, preferences, data: json.doc, user, id, operation: 'update', locale, t }); - setInitialState(state); + setInternalState(state); }, [collection, user, id, t, locale, getDocPermissions, getDocPreferences]); useEffect(() => { @@ -75,26 +77,28 @@ const AccountView: React.FC = () => { }, [setStepNav, t]); useEffect(() => { - const awaitInitialState = async () => { + const awaitInternalState = async () => { const preferences = await getDocPreferences(); + const state = await buildStateFromSchema({ fieldSchema: fields, preferences, data: dataToRender, operation: 'update', id, - user, + user: userRef.current, locale, t, }); + await getPreference(preferencesKey); - setInitialState(state); + setInternalState(state); }; - if (dataToRender) awaitInitialState(); - }, [dataToRender, fields, id, user, locale, preferencesKey, getPreference, t, getDocPreferences]); + if (dataToRender) awaitInternalState(); + }, [dataToRender, fields, id, locale, preferencesKey, getPreference, t, getDocPreferences]); - const isLoading = !initialState || !docPermissions || isLoadingData; + const isLoading = !internalState || !docPermissions || isLoadingData; return ( { collection, permissions: docPermissions, hasSavePermission, - initialState, + initialState: internalState, apiURL, isLoading, onSave, diff --git a/src/admin/components/views/collections/Edit/Auth/index.tsx b/src/admin/components/views/collections/Edit/Auth/index.tsx index 8ffc1cc58..20fe3afc4 100644 --- a/src/admin/components/views/collections/Edit/Auth/index.tsx +++ b/src/admin/components/views/collections/Edit/Auth/index.tsx @@ -73,7 +73,7 @@ const Auth: React.FC = (props) => { return (
    - { !collection.auth.disableLocalStrategy && ( + {!collection.auth.disableLocalStrategy && ( = (props) => { const { admin: { dateFormat }, routes: { admin } } = useConfig(); const { publishedDoc } = useDocumentInfo(); const { t, i18n } = useTranslation('general'); + const { user, refreshCookieAsync } = useAuth(); const { collection, @@ -78,14 +80,18 @@ const DefaultEditView: React.FC = (props) => { isEditing && `${baseClass}--is-editing`, ].filter(Boolean).join(' '); - const onSave = useCallback((json) => { + const onSave = useCallback(async (json) => { + if (auth && id === user.id) { + await refreshCookieAsync(); + } + if (typeof onSaveFromProps === 'function') { onSaveFromProps({ ...json, operation: id ? 'update' : 'create', }); } - }, [id, onSaveFromProps]); + }, [id, onSaveFromProps, auth, user, refreshCookieAsync]); const operation = isEditing ? 'update' : 'create'; diff --git a/src/admin/components/views/collections/Edit/index.tsx b/src/admin/components/views/collections/Edit/index.tsx index 3cc42ac54..e51095d6e 100644 --- a/src/admin/components/views/collections/Edit/index.tsx +++ b/src/admin/components/views/collections/Edit/index.tsx @@ -1,5 +1,5 @@ -import React, { useState, useEffect, useCallback } from 'react'; -import { Redirect, useRouteMatch, useHistory, useLocation } from 'react-router-dom'; +import React, { useState, useEffect, useCallback, useRef } from 'react'; +import { Redirect, useRouteMatch, useHistory } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { useConfig } from '../../../utilities/Config'; import { useAuth } from '../../../utilities/Auth'; @@ -37,11 +37,11 @@ const EditView: React.FC = (props) => { const locale = useLocale(); const { serverURL, routes: { admin, api } } = useConfig(); const { params: { id } = {} } = useRouteMatch>(); - const { state: locationState } = useLocation(); const history = useHistory(); const [internalState, setInternalState] = useState(); const [updatedAt, setUpdatedAt] = useState(); const { user } = useAuth(); + const userRef = useRef(user); const { getVersions, getDocPermissions, docPermissions, getDocPreferences } = useDocumentInfo(); const { t } = useTranslation('general'); @@ -50,6 +50,24 @@ const EditView: React.FC = (props) => { { initialParams: { 'fallback-locale': 'null', depth: 0, draft: 'true' }, initialData: null }, ); + const buildState = useCallback(async (doc, overrides?: Partial[0]>) => { + const preferences = await getDocPreferences(); + + const state = await buildStateFromSchema({ + fieldSchema: overrides.fieldSchema, + preferences, + data: doc || {}, + user: userRef.current, + id, + operation: 'update', + locale, + t, + ...overrides, + }); + + setInternalState(state); + }, [getDocPreferences, id, locale, t]); + const onSave = useCallback(async (json: { doc }) => { @@ -59,24 +77,25 @@ const EditView: React.FC = (props) => { if (!isEditing) { setRedirect(`${admin}/collections/${collection.slug}/${json?.doc?.id}`); } else { - const preferences = await getDocPreferences(); - const state = await buildStateFromSchema({ fieldSchema: collection.fields, preferences, data: json.doc, user, id, operation: 'update', locale, t }); - setInternalState(state); + buildState(json.doc, { + fieldSchema: collection.fields, + }); } - }, [admin, collection.fields, collection.slug, getDocPreferences, getDocPermissions, getVersions, id, isEditing, locale, t, user]); - - const dataToRender = (locationState as Record)?.data || data; + }, [admin, getVersions, isEditing, buildState, getDocPermissions, collection]); useEffect(() => { - const awaitInternalState = async () => { - setUpdatedAt(dataToRender?.updatedAt); - const preferences = await getDocPreferences(); - const state = await buildStateFromSchema({ fieldSchema: fields, preferences, data: dataToRender || {}, user, operation: isEditing ? 'update' : 'create', id, locale, t }); - setInternalState(state); - }; + if (fields && (isEditing ? data : true)) { + const awaitInternalState = async () => { + setUpdatedAt(data?.updatedAt); + buildState(data, { + operation: isEditing ? 'update' : 'create', + fieldSchema: fields, + }); + }; - if (!isEditing || dataToRender) awaitInternalState(); - }, [dataToRender, fields, isEditing, id, user, locale, t, getDocPreferences]); + awaitInternalState(); + } + }, [isEditing, data, buildState, fields]); useEffect(() => { if (redirect) { @@ -103,7 +122,7 @@ const EditView: React.FC = (props) => { componentProps={{ id, isLoading, - data: dataToRender, + data, collection, permissions: docPermissions, isEditing, @@ -112,7 +131,7 @@ const EditView: React.FC = (props) => { hasSavePermission, apiURL, action, - updatedAt: updatedAt || dataToRender?.updatedAt, + updatedAt: updatedAt || data?.updatedAt, }} /> diff --git a/src/admin/hooks/useTitle.tsx b/src/admin/hooks/useTitle.tsx index 3cf1a35de..04abacdf1 100644 --- a/src/admin/hooks/useTitle.tsx +++ b/src/admin/hooks/useTitle.tsx @@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next'; import { SanitizedConfig } from '../../config/types'; import { SanitizedCollectionConfig } from '../../collections/config/types'; import { useFormFields } from '../components/forms/Form/context'; -import { Field } from '../components/forms/Form/types'; +import { FormField } from '../components/forms/Form/types'; import { useConfig } from '../components/utilities/Config'; import { formatDate } from '../utilities/formatDate'; import { getObjectDotNotation } from '../../utilities/getObjectDotNotation'; @@ -11,7 +11,7 @@ import { getObjectDotNotation } from '../../utilities/getObjectDotNotation'; // either send the `useAsTitle` field itself // or an object to dynamically extract the `useAsTitle` field from export const formatUseAsTitle = (args: { - field?: Field + field?: FormField doc?: Record collection: SanitizedCollectionConfig i18n: typeof i18next @@ -36,7 +36,7 @@ export const formatUseAsTitle = (args: { return ''; } - const field = fieldFromProps || getObjectDotNotation(doc, collection.admin.useAsTitle); + const field = fieldFromProps || getObjectDotNotation(doc, collection.admin.useAsTitle); let title = typeof field === 'string' ? field : field?.value as string; diff --git a/src/admin/scss/app.scss b/src/admin/scss/app.scss index 1d48f0b85..baf3014fd 100644 --- a/src/admin/scss/app.scss +++ b/src/admin/scss/app.scss @@ -20,6 +20,10 @@ --font-mono: monospace; --font-serif: 'Merriweather', serif; + --style-radius-s: #{$style-radius-s}; + --style-radius-m: #{$style-radius-m}; + --style-radius-l: #{$style-radius-l}; + --z-popup: 10; --z-nav: 20; --z-modal: 30; diff --git a/src/admin/scss/vars.scss b/src/admin/scss/vars.scss index 745747d5e..dc629e598 100644 --- a/src/admin/scss/vars.scss +++ b/src/admin/scss/vars.scss @@ -47,6 +47,7 @@ $color-purple : #F3DDF3 !default; $style-radius-s : 3px !default; $style-radius-m : 4px !default; +$style-radius-l: 9px !default; $style-stroke-width : 1px !default; $style-stroke-width-s : 1px !default; @@ -184,3 +185,17 @@ $focus-box-shadow: 0 0 0 $style-stroke-width-m var(--theme-success-500); } } } + +@mixin lightInputError { + background-color: var(--theme-error-50); + border: 1px solid var(--theme-error-500); +} + +@mixin darkInputError { + background-color: var(--theme-error-100); + border: 1px solid var(--theme-error-400); + + &:hover { + border-color: var(--theme-error-500); + } +} diff --git a/src/auth/operations/getFieldsToSign.ts b/src/auth/operations/getFieldsToSign.ts new file mode 100644 index 000000000..e5a86cf9e --- /dev/null +++ b/src/auth/operations/getFieldsToSign.ts @@ -0,0 +1,39 @@ +import { User } from '..'; +import { CollectionConfig } from '../../collections/config/types'; +import { Field, fieldAffectsData, fieldHasSubFields } from '../../fields/config/types'; + +export const getFieldsToSign = (args: { + collectionConfig: CollectionConfig, + user: User + email: string +}): Record => { + const { + collectionConfig, + user, + email, + } = args; + + return collectionConfig.fields.reduce((signedFields, field: Field) => { + const result = { + ...signedFields, + }; + + if (!fieldAffectsData(field) && fieldHasSubFields(field)) { + field.fields.forEach((subField) => { + if (fieldAffectsData(subField) && subField.saveToJWT) { + result[subField.name] = user[subField.name]; + } + }); + } + + if (fieldAffectsData(field) && field.saveToJWT) { + result[field.name] = user[field.name]; + } + + return result; + }, { + email, + id: user.id, + collection: collectionConfig.slug, + }); +}; diff --git a/src/auth/operations/local/forgotPassword.ts b/src/auth/operations/local/forgotPassword.ts index b2349cf20..ef75c57e7 100644 --- a/src/auth/operations/local/forgotPassword.ts +++ b/src/auth/operations/local/forgotPassword.ts @@ -31,7 +31,7 @@ async function localForgotPassword( const collection = payload.collections[collectionSlug]; if (!collection) { - throw new APIError(`The collection with slug ${String(collectionSlug)} can't be found.`); + throw new APIError(`The collection with slug ${String(collectionSlug)} can't be found. Login Operation.`); } req.payloadAPI = req.payloadAPI || 'local'; diff --git a/src/auth/operations/local/resetPassword.ts b/src/auth/operations/local/resetPassword.ts index 77be18c5c..2ad2bdbe3 100644 --- a/src/auth/operations/local/resetPassword.ts +++ b/src/auth/operations/local/resetPassword.ts @@ -30,7 +30,7 @@ async function localResetPassword const collection = payload.collections[collectionSlug]; if (!collection) { - throw new APIError(`The collection with slug ${String(collectionSlug)} can't be found.`); + throw new APIError(`The collection with slug ${String(collectionSlug)} can't be found. Reset Password Operation.`); } req.payload = payload; diff --git a/src/auth/operations/local/unlock.ts b/src/auth/operations/local/unlock.ts index 76a6f1a9c..586d16d3c 100644 --- a/src/auth/operations/local/unlock.ts +++ b/src/auth/operations/local/unlock.ts @@ -29,7 +29,7 @@ async function localUnlock( const collection = payload.collections[collectionSlug]; if (!collection) { - throw new APIError(`The collection with slug ${String(collectionSlug)} can't be found.`); + throw new APIError(`The collection with slug ${String(collectionSlug)} can't be found. Unlock Operation.`); } req.payload = payload; diff --git a/src/auth/operations/local/verifyEmail.ts b/src/auth/operations/local/verifyEmail.ts index 44d986962..dca0cb95e 100644 --- a/src/auth/operations/local/verifyEmail.ts +++ b/src/auth/operations/local/verifyEmail.ts @@ -25,7 +25,7 @@ async function localVerifyEmail( const collection = payload.collections[collectionSlug]; if (!collection) { - throw new APIError(`The collection with slug ${String(collectionSlug)} can't be found.`); + throw new APIError(`The collection with slug ${String(collectionSlug)} can't be found. Verify Email Operation.`); } return verifyEmail({ diff --git a/src/auth/operations/login.ts b/src/auth/operations/login.ts index 8b62637c1..7f54a8055 100644 --- a/src/auth/operations/login.ts +++ b/src/auth/operations/login.ts @@ -13,6 +13,9 @@ import { afterRead } from '../../fields/hooks/afterRead'; import unlock from './unlock'; import { incrementLoginAttempts } from '../strategies/local/incrementLoginAttempts'; import { authenticateLocalStrategy } from '../strategies/local/authenticate'; +import { getFieldsToSign } from './getFieldsToSign'; +import { initTransaction } from '../../utilities/initTransaction'; +import { killTransaction } from '../../utilities/killTransaction'; export type Result = { user?: User, @@ -37,20 +40,6 @@ async function login( incomingArgs: Arguments, ): Promise { let args = incomingArgs; - - // ///////////////////////////////////// - // beforeOperation - Collection - // ///////////////////////////////////// - - await args.collection.config.hooks.beforeOperation.reduce(async (priorHook, hook) => { - await priorHook; - - args = (await hook({ - args, - operation: 'login', - })) || args; - }, Promise.resolve()); - const { collection: { config: collectionConfig, @@ -69,163 +58,169 @@ async function login( showHiddenFields, } = args; - // ///////////////////////////////////// - // Login - // ///////////////////////////////////// + try { + const shouldCommit = await initTransaction(req); - const { email: unsanitizedEmail, password } = data; + // ///////////////////////////////////// + // beforeOperation - Collection + // ///////////////////////////////////// - const email = unsanitizedEmail ? (unsanitizedEmail as string).toLowerCase().trim() : null; + await args.collection.config.hooks.beforeOperation.reduce(async (priorHook, hook) => { + await priorHook; - let user = await payload.db.findOne({ - collection: collectionConfig.slug, - where: { email: { equals: email.toLowerCase() } }, - }); + args = (await hook({ + args, + operation: 'login', + })) || args; + }, Promise.resolve()); - if (!user || (args.collection.config.auth.verify && user._verified === false)) { - throw new AuthenticationError(req.t); - } + // ///////////////////////////////////// + // Login + // ///////////////////////////////////// - if (user && isLocked(user.lockUntil)) { - throw new LockedAuth(req.t); - } + const { email: unsanitizedEmail, password } = data; - const authResult = await authenticateLocalStrategy({ password, doc: user }); + const email = unsanitizedEmail ? (unsanitizedEmail as string).toLowerCase().trim() : null; - user = sanitizeInternalFields(user); - - const maxLoginAttemptsEnabled = args.collection.config.auth.maxLoginAttempts > 0; - - if (!authResult) { - if (maxLoginAttemptsEnabled) { - await incrementLoginAttempts({ - payload: req.payload, - doc: user, - collection: collectionConfig, - }); - } - - throw new AuthenticationError(req.t); - } - - if (maxLoginAttemptsEnabled) { - await unlock({ - collection: { - config: collectionConfig, - }, + let user = await payload.db.findOne({ + collection: collectionConfig.slug, + where: { email: { equals: email.toLowerCase() } }, req, - data, - overrideAccess: true, }); - } - const fieldsToSign = collectionConfig.fields.reduce((signedFields, field: Field) => { - const result = { - ...signedFields, - }; + if (!user || (args.collection.config.auth.verify && user._verified === false)) { + throw new AuthenticationError(req.t); + } - if (!fieldAffectsData(field) && fieldHasSubFields(field)) { - field.fields.forEach((subField) => { - if (fieldAffectsData(subField) && subField.saveToJWT) { - result[subField.name] = user[subField.name]; - } + if (user && isLocked(user.lockUntil)) { + throw new LockedAuth(req.t); + } + + const authResult = await authenticateLocalStrategy({ password, doc: user }); + + user = sanitizeInternalFields(user); + + const maxLoginAttemptsEnabled = args.collection.config.auth.maxLoginAttempts > 0; + + if (!authResult) { + if (maxLoginAttemptsEnabled) { + await incrementLoginAttempts({ + req, + payload: req.payload, + doc: user, + collection: collectionConfig, + }); + } + + throw new AuthenticationError(req.t); + } + + if (maxLoginAttemptsEnabled) { + await unlock({ + collection: { + config: collectionConfig, + }, + req, + data, + overrideAccess: true, }); } - if (fieldAffectsData(field) && field.saveToJWT) { - result[field.name] = user[field.name]; + const fieldsToSign = getFieldsToSign( { + collectionConfig, + user, + email, + + }); + + await collectionConfig.hooks.beforeLogin.reduce(async (priorHook, hook) => { + await priorHook; + + user = (await hook({ + user, + req: args.req, + })) || user; + }, Promise.resolve()); + + const token = jwt.sign( + fieldsToSign, + secret, + { + expiresIn: collectionConfig.auth.tokenExpiration, + }, + ); + + if (args.res) { + const cookieOptions: CookieOptions = { + path: '/', + httpOnly: true, + expires: getCookieExpiration(collectionConfig.auth.tokenExpiration), + secure: collectionConfig.auth.cookies.secure, + sameSite: collectionConfig.auth.cookies.sameSite, + domain: undefined, + }; + + if (collectionConfig.auth.cookies.domain) cookieOptions.domain = collectionConfig.auth.cookies.domain; + + args.res.cookie(`${config.cookiePrefix}-token`, token, cookieOptions); } - return result; - }, { - email, - id: user.id, - collection: collectionConfig.slug, - }); + req.user = user; - await collectionConfig.hooks.beforeLogin.reduce(async (priorHook, hook) => { - await priorHook; + // ///////////////////////////////////// + // afterLogin - Collection + // ///////////////////////////////////// - user = (await hook({ - user, - req: args.req, - })) || user; - }, Promise.resolve()); + await collectionConfig.hooks.afterLogin.reduce(async (priorHook, hook) => { + await priorHook; - const token = jwt.sign( - fieldsToSign, - secret, - { - expiresIn: collectionConfig.auth.tokenExpiration, - }, - ); + user = await hook({ + user, + req: args.req, + token, + }) || user; + }, Promise.resolve()); - if (args.res) { - const cookieOptions: CookieOptions = { - path: '/', - httpOnly: true, - expires: getCookieExpiration(collectionConfig.auth.tokenExpiration), - secure: collectionConfig.auth.cookies.secure, - sameSite: collectionConfig.auth.cookies.sameSite, - domain: undefined, - }; + // ///////////////////////////////////// + // afterRead - Fields + // ///////////////////////////////////// - if (collectionConfig.auth.cookies.domain) cookieOptions.domain = collectionConfig.auth.cookies.domain; - - args.res.cookie(`${config.cookiePrefix}-token`, token, cookieOptions); - } - - req.user = user; - - // ///////////////////////////////////// - // afterLogin - Collection - // ///////////////////////////////////// - - await collectionConfig.hooks.afterLogin.reduce(async (priorHook, hook) => { - await priorHook; - - user = await hook({ - user, - req: args.req, - token, - }) || user; - }, Promise.resolve()); - - // ///////////////////////////////////// - // afterRead - Fields - // ///////////////////////////////////// - - user = await afterRead({ - depth, - doc: user, - entityConfig: collectionConfig, - overrideAccess, - req, - showHiddenFields, - }); - - // ///////////////////////////////////// - // afterRead - Collection - // ///////////////////////////////////// - - await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => { - await priorHook; - - user = await hook({ - req, + user = await afterRead({ + depth, doc: user, - }) || user; - }, Promise.resolve()); + entityConfig: collectionConfig, + overrideAccess, + req, + showHiddenFields, + }); - // ///////////////////////////////////// - // Return results - // ///////////////////////////////////// + // ///////////////////////////////////// + // afterRead - Collection + // ///////////////////////////////////// - return { - token, - user, - exp: (jwt.decode(token) as jwt.JwtPayload).exp, - }; + await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => { + await priorHook; + + user = await hook({ + req, + doc: user, + }) || user; + }, Promise.resolve()); + + // ///////////////////////////////////// + // Return results + // ///////////////////////////////////// + if (shouldCommit) await payload.db.commitTransaction(req.transactionID); + + return { + token, + user, + exp: (jwt.decode(token) as jwt.JwtPayload).exp, + }; + } catch (error: unknown) { + await killTransaction(req); + throw error; + } } export default login; diff --git a/src/auth/operations/refresh.ts b/src/auth/operations/refresh.ts index ca85ef110..635a87ee1 100644 --- a/src/auth/operations/refresh.ts +++ b/src/auth/operations/refresh.ts @@ -1,10 +1,12 @@ import jwt from 'jsonwebtoken'; import { Response } from 'express'; +import url from 'url'; import { Collection, BeforeOperationHook } from '../../collections/config/types'; import { Forbidden } from '../../errors'; import getCookieExpiration from '../../utilities/getCookieExpiration'; import { Document } from '../../types'; import { PayloadRequest } from '../../express/types'; +import { getFieldsToSign } from './getFieldsToSign'; export type Result = { exp: number, @@ -51,16 +53,32 @@ async function refresh(incomingArgs: Arguments): Promise { }, } = args; - const opts = { - expiresIn: args.collection.config.auth.tokenExpiration, - }; - if (typeof args.token !== 'string') throw new Forbidden(args.req.t); - const payload = jwt.verify(args.token, secret, {}) as Record; - delete payload.iat; - delete payload.exp; - const refreshedToken = jwt.sign(payload, secret, opts); + const parsedURL = url.parse(args.req.url); + const isGraphQL = parsedURL.pathname === config.routes.graphQL; + + const user = await args.req.payload.findByID({ + id: args.req.user.id, + collection: args.req.user.collection, + req: args.req, + depth: isGraphQL ? 0 : args.collection.config.auth.depth, + }); + + const fieldsToSign = getFieldsToSign({ + collectionConfig, + user: args?.req?.user, + email: user?.email as string, + }); + + const refreshedToken = jwt.sign( + fieldsToSign, + secret, + { + expiresIn: collectionConfig.auth.tokenExpiration, + }, + ); + const exp = (jwt.decode(refreshedToken) as Record).exp as number; if (args.res) { @@ -78,6 +96,12 @@ async function refresh(incomingArgs: Arguments): Promise { args.res.cookie(`${config.cookiePrefix}-token`, refreshedToken, cookieOptions); } + let response: Result = { + user, + refreshedToken, + exp, + }; + // ///////////////////////////////////// // After Refresh - Collection // ///////////////////////////////////// @@ -85,23 +109,19 @@ async function refresh(incomingArgs: Arguments): Promise { await collectionConfig.hooks.afterRefresh.reduce(async (priorHook, hook) => { await priorHook; - args = (await hook({ + response = (await hook({ req: args.req, res: args.res, exp, token: refreshedToken, - })) || args; + })) || response; }, Promise.resolve()); // ///////////////////////////////////// // Return results // ///////////////////////////////////// - return { - refreshedToken, - exp, - user: payload, - }; + return response; } export default refresh; diff --git a/src/auth/operations/registerFirstUser.ts b/src/auth/operations/registerFirstUser.ts index 5001d5d7d..c4de1a849 100644 --- a/src/auth/operations/registerFirstUser.ts +++ b/src/auth/operations/registerFirstUser.ts @@ -4,6 +4,8 @@ import { MarkOptional } from 'ts-essentials'; import { Forbidden } from '../../errors'; import { PayloadRequest } from '../../express/types'; import { Collection } from '../../collections/config/types'; +import { initTransaction } from '../../utilities/initTransaction'; +import { killTransaction } from '../../utilities/killTransaction'; export type Arguments = { collection: Collection @@ -40,52 +42,62 @@ async function registerFirstUser({ - req, - collection: slug as TSlug, - data, - overrideAccess: true, - }); - - // auto-verify (if applicable) - if (verify) { - await payload.update({ - id: result.id, - collection: slug, - data: { - _verified: true, - }, + const doc = await payload.db.findOne({ + collection: config.slug, + req, }); + + if (doc) throw new Forbidden(req.t); + + // ///////////////////////////////////// + // Register first user + // ///////////////////////////////////// + + const result = await payload.create({ + req, + collection: slug as TSlug, + data, + overrideAccess: true, + }); + + // auto-verify (if applicable) + if (verify) { + await payload.update({ + id: result.id, + collection: slug, + data: { + _verified: true, + }, + }); + } + + // ///////////////////////////////////// + // Log in new user + // ///////////////////////////////////// + + const { token } = await payload.login({ + ...args, + collection: slug, + }); + + const resultToReturn = { + ...result, + token, + }; + + if (shouldCommit) await payload.db.commitTransaction(req.transactionID); + + return { + message: 'Registered and logged in successfully. Welcome!', + user: resultToReturn, + }; + } catch (error: unknown) { + await killTransaction(req); + throw error; } - - // ///////////////////////////////////// - // Log in new user - // ///////////////////////////////////// - - const { token } = await payload.login({ - ...args, - collection: slug, - }); - - const resultToReturn = { - ...result, - token, - }; - - return { - message: 'Registered and logged in successfully. Welcome!', - user: resultToReturn, - }; } export default registerFirstUser; diff --git a/src/auth/operations/resetPassword.ts b/src/auth/operations/resetPassword.ts index c3f5903e9..e418395e5 100644 --- a/src/auth/operations/resetPassword.ts +++ b/src/auth/operations/resetPassword.ts @@ -7,6 +7,8 @@ import { fieldAffectsData } from '../../fields/config/types'; import { PayloadRequest } from '../../express/types'; import { authenticateLocalStrategy } from '../strategies/local/authenticate'; import { generatePasswordSaltHash } from '../strategies/local/generatePasswordSaltHash'; +import { initTransaction } from '../../utilities/initTransaction'; +import { killTransaction } from '../../utilities/killTransaction'; export type Result = { token: string @@ -35,6 +37,7 @@ async function resetPassword(args: Arguments): Promise { collection: { config: collectionConfig, }, + req, req: { payload: { config, @@ -47,82 +50,92 @@ async function resetPassword(args: Arguments): Promise { depth, } = args; - // ///////////////////////////////////// - // Reset Password - // ///////////////////////////////////// + try { + const shouldCommit = await initTransaction(req); - const user = await payload.db.findOne({ - collection: collectionConfig.slug, - where: { - resetPasswordToken: { equals: data.token }, - resetPasswordExpiration: { greater_than: Date.now() }, - }, - }); + // ///////////////////////////////////// + // Reset Password + // ///////////////////////////////////// - if (!user) throw new APIError('Token is either invalid or has expired.'); + const user = await payload.db.findOne({ + collection: collectionConfig.slug, + where: { + resetPasswordToken: { equals: data.token }, + resetPasswordExpiration: { greater_than: Date.now() }, + }, + req, + }); - // TODO: replace this method - const { salt, hash } = await generatePasswordSaltHash({ password: data.password }); + if (!user) throw new APIError('Token is either invalid or has expired.'); - user.salt = salt; - user.hash = hash; + // TODO: replace this method + const { salt, hash } = await generatePasswordSaltHash({ password: data.password }); - user.resetPasswordExpiration = Date.now(); + user.salt = salt; + user.hash = hash; - if (collectionConfig.auth.verify) { - user._verified = true; - } + user.resetPasswordExpiration = Date.now(); - const doc = await payload.db.updateOne({ - collection: collectionConfig.slug, - where: { id: { equals: user.id } }, - data: user, - req: args.req, - }); - - - await authenticateLocalStrategy({ password: data.password, doc }); - - const fieldsToSign = collectionConfig.fields.reduce((signedFields, field) => { - if (fieldAffectsData(field) && field.saveToJWT) { - return { - ...signedFields, - [field.name]: user[field.name], - }; + if (collectionConfig.auth.verify) { + user._verified = true; } - return signedFields; - }, { - email: user.email, - id: user.id, - collection: collectionConfig.slug, - }); - const token = jwt.sign( - fieldsToSign, - secret, - { - expiresIn: collectionConfig.auth.tokenExpiration, - }, - ); - - if (args.res) { - const cookieOptions = { - path: '/', - httpOnly: true, - expires: getCookieExpiration(collectionConfig.auth.tokenExpiration), - secure: collectionConfig.auth.cookies.secure, - sameSite: collectionConfig.auth.cookies.sameSite, - domain: undefined, - }; + const doc = await payload.db.updateOne({ + collection: collectionConfig.slug, + where: { id: { equals: user.id } }, + data: user, + req, + }); - if (collectionConfig.auth.cookies.domain) cookieOptions.domain = collectionConfig.auth.cookies.domain; + await authenticateLocalStrategy({ password: data.password, doc }); - args.res.cookie(`${config.cookiePrefix}-token`, token, cookieOptions); + const fieldsToSign = collectionConfig.fields.reduce((signedFields, field) => { + if (fieldAffectsData(field) && field.saveToJWT) { + return { + ...signedFields, + [field.name]: user[field.name], + }; + } + return signedFields; + }, { + email: user.email, + id: user.id, + collection: collectionConfig.slug, + }); + + const token = jwt.sign( + fieldsToSign, + secret, + { + expiresIn: collectionConfig.auth.tokenExpiration, + }, + ); + + if (args.res) { + const cookieOptions = { + path: '/', + httpOnly: true, + expires: getCookieExpiration(collectionConfig.auth.tokenExpiration), + secure: collectionConfig.auth.cookies.secure, + sameSite: collectionConfig.auth.cookies.sameSite, + domain: undefined, + }; + + + if (collectionConfig.auth.cookies.domain) cookieOptions.domain = collectionConfig.auth.cookies.domain; + + args.res.cookie(`${config.cookiePrefix}-token`, token, cookieOptions); + } + + const fullUser = await payload.findByID({ collection: collectionConfig.slug, id: user.id, overrideAccess, depth, req }); + if (shouldCommit) await payload.db.commitTransaction(req.transactionID); + + return { token, user: fullUser }; + } catch (error: unknown) { + await killTransaction(req); + throw error; } - - const fullUser = await payload.findByID({ collection: collectionConfig.slug, id: user.id, overrideAccess, depth }); - return { token, user: fullUser }; } export default resetPassword; diff --git a/src/auth/operations/unlock.ts b/src/auth/operations/unlock.ts index 4428ad39e..427815e7f 100644 --- a/src/auth/operations/unlock.ts +++ b/src/auth/operations/unlock.ts @@ -3,6 +3,8 @@ import executeAccess from '../executeAccess'; import { Collection } from '../../collections/config/types'; import { PayloadRequest } from '../../express/types'; import { resetLoginAttempts } from '../strategies/local/resetLoginAttempts'; +import { initTransaction } from '../../utilities/initTransaction'; +import { killTransaction } from '../../utilities/killTransaction'; export type Args = { collection: Collection @@ -24,46 +26,63 @@ async function unlock(args: Args): Promise { }, req, req: { + payload, locale, }, overrideAccess, } = args; - // ///////////////////////////////////// - // Access - // ///////////////////////////////////// + try { + const shouldCommit = await initTransaction(req); - if (!overrideAccess) { - await executeAccess({ req }, collectionConfig.access.unlock); + // ///////////////////////////////////// + // Access + // ///////////////////////////////////// + + if (!overrideAccess) { + await executeAccess({ req }, collectionConfig.access.unlock); + } + + const options = { ...args }; + + const { data } = options; + + // ///////////////////////////////////// + // Unlock + // ///////////////////////////////////// + + if (!data.email) { + throw new APIError('Missing email.'); + } + + const user = await req.payload.db.findOne({ + collection: collectionConfig.slug, + where: { email: { equals: data.email.toLowerCase() } }, + locale, + req, + }); + + let result; + + if (user) { + await resetLoginAttempts({ + req, + payload: req.payload, + collection: collectionConfig, + doc: user, + }); + result = true; + } else { + result = null; + } + + if (shouldCommit) await payload.db.commitTransaction(req.transactionID); + + return result; + } catch (error: unknown) { + await killTransaction(req); + throw error; } - - const options = { ...args }; - - const { data } = options; - - // ///////////////////////////////////// - // Unlock - // ///////////////////////////////////// - - if (!data.email) { - throw new APIError('Missing email.'); - } - - const user = await req.payload.db.findOne({ - collection: collectionConfig.slug, - where: { email: { equals: data.email.toLowerCase() } }, - locale, - }); - - if (!user) return null; - - await resetLoginAttempts({ - payload: req.payload, - collection: collectionConfig, - doc: user, - }); - - return true; } export default unlock; diff --git a/src/auth/requestHandlers/forgotPassword.ts b/src/auth/requestHandlers/forgotPassword.ts index bfcee4fe4..c9e9d940d 100644 --- a/src/auth/requestHandlers/forgotPassword.ts +++ b/src/auth/requestHandlers/forgotPassword.ts @@ -1,4 +1,4 @@ -import { Response, NextFunction } from 'express'; +import { NextFunction, Response } from 'express'; import httpStatus from 'http-status'; import { PayloadRequest } from '../../express/types'; import forgotPassword from '../operations/forgotPassword'; diff --git a/src/auth/requestHandlers/login.ts b/src/auth/requestHandlers/login.ts index 30ce67c5e..42d1bc2b0 100644 --- a/src/auth/requestHandlers/login.ts +++ b/src/auth/requestHandlers/login.ts @@ -1,4 +1,4 @@ -import { Response, NextFunction } from 'express'; +import { NextFunction, Response } from 'express'; import httpStatus from 'http-status'; import { PayloadRequest } from '../../express/types'; import login, { Result } from '../operations/login'; @@ -13,7 +13,7 @@ export default async function loginHandler(req: PayloadRequest, res: Response, n depth: parseInt(String(req.query.depth), 10), }); - return res.status(httpStatus.OK) + res.status(httpStatus.OK) .json({ message: 'Auth Passed', user: result.user, @@ -21,6 +21,6 @@ export default async function loginHandler(req: PayloadRequest, res: Response, n exp: result.exp, }); } catch (error) { - return next(error); + next(error); } } diff --git a/src/auth/requestHandlers/registerFirstUser.ts b/src/auth/requestHandlers/registerFirstUser.ts index 915e4a763..d41ef6ce5 100644 --- a/src/auth/requestHandlers/registerFirstUser.ts +++ b/src/auth/requestHandlers/registerFirstUser.ts @@ -1,4 +1,4 @@ -import { Response, NextFunction } from 'express'; +import { NextFunction, Response } from 'express'; import { PayloadRequest } from '../../express/types'; import registerFirstUser from '../operations/registerFirstUser'; diff --git a/src/auth/requestHandlers/resetPassword.ts b/src/auth/requestHandlers/resetPassword.ts index 32c51202d..257b6d50b 100644 --- a/src/auth/requestHandlers/resetPassword.ts +++ b/src/auth/requestHandlers/resetPassword.ts @@ -1,4 +1,4 @@ -import { Response, NextFunction } from 'express'; +import { NextFunction, Response } from 'express'; import httpStatus from 'http-status'; import { PayloadRequest } from '../../express/types'; import resetPassword from '../operations/resetPassword'; diff --git a/src/auth/requestHandlers/unlock.ts b/src/auth/requestHandlers/unlock.ts index 9b49d2aeb..2b4421fe8 100644 --- a/src/auth/requestHandlers/unlock.ts +++ b/src/auth/requestHandlers/unlock.ts @@ -1,4 +1,4 @@ -import { Response, NextFunction } from 'express'; +import { NextFunction, Response } from 'express'; import httpStatus from 'http-status'; import { PayloadRequest } from '../../express/types'; import unlock from '../operations/unlock'; diff --git a/src/auth/strategies/local/incrementLoginAttempts.ts b/src/auth/strategies/local/incrementLoginAttempts.ts index 0e12fbff3..3c3f978dd 100644 --- a/src/auth/strategies/local/incrementLoginAttempts.ts +++ b/src/auth/strategies/local/incrementLoginAttempts.ts @@ -1,13 +1,16 @@ -import { Payload } from "../../.." -import { SanitizedCollectionConfig, TypeWithID } from "../../../collections/config/types" +import { Payload } from '../../..'; +import { SanitizedCollectionConfig, TypeWithID } from '../../../collections/config/types'; +import { PayloadRequest } from '../../../express/types'; type Args = { + req: PayloadRequest, payload: Payload doc: TypeWithID & Record collection: SanitizedCollectionConfig } export const incrementLoginAttempts = async ({ + req, payload, doc, collection, @@ -16,35 +19,36 @@ export const incrementLoginAttempts = async ({ auth: { maxLoginAttempts, lockTime, - } - } = collection + }, + } = collection; if ('lockUntil' in doc && typeof doc.lockUntil === 'string') { - const lockUntil = Math.floor(new Date(doc.lockUntil).getTime() / 1000) + const lockUntil = Math.floor(new Date(doc.lockUntil).getTime() / 1000); // Expired lock, restart count at 1 if (lockUntil < Date.now()) { await payload.update({ + req, collection: collection.slug, id: doc.id, data: { loginAttempts: 1, lockUntil: null, - } - }) + }, + }); } - return + return; } const data: Record = { loginAttempts: Number(doc.loginAttempts) + 1, - } + }; // Lock the account if at max attempts and not already locked if (typeof doc.loginAttempts === 'number' && doc.loginAttempts + 1 >= maxLoginAttempts) { - const lockUntil = new Date((Date.now() + lockTime)) - data.lockUntil = lockUntil + const lockUntil = new Date((Date.now() + lockTime)); + data.lockUntil = lockUntil; } @@ -52,5 +56,5 @@ export const incrementLoginAttempts = async ({ collection: collection.slug, id: doc.id, data, - }) -} \ No newline at end of file + }); +}; diff --git a/src/auth/strategies/local/resetLoginAttempts.ts b/src/auth/strategies/local/resetLoginAttempts.ts index f2d7045c5..59513b9ae 100644 --- a/src/auth/strategies/local/resetLoginAttempts.ts +++ b/src/auth/strategies/local/resetLoginAttempts.ts @@ -1,23 +1,27 @@ -import { Payload } from "../../.." -import { SanitizedCollectionConfig, TypeWithID } from "../../../collections/config/types" +import { Payload } from '../../..'; +import { SanitizedCollectionConfig, TypeWithID } from '../../../collections/config/types'; +import { PayloadRequest } from '../../../express/types'; type Args = { + req: PayloadRequest, payload: Payload doc: TypeWithID & Record collection: SanitizedCollectionConfig } export const resetLoginAttempts = async ({ + req, payload, doc, collection, }: Args): Promise => { await payload.update({ + req, collection: collection.slug, id: doc.id, data: { loginAttempts: 0, lockUntil: null, }, - }) -} \ No newline at end of file + }); +}; diff --git a/src/bin/generateGraphQLSchema.ts b/src/bin/generateGraphQLSchema.ts index 808b01a0a..35fbfc520 100644 --- a/src/bin/generateGraphQLSchema.ts +++ b/src/bin/generateGraphQLSchema.ts @@ -9,6 +9,8 @@ export async function generateGraphQLSchema(): Promise { const logger = Logger(); const config = await loadConfig(); + config.db = null; + await payload.init({ secret: '--unused--', mongoURL: false, diff --git a/src/bin/migrate.ts b/src/bin/migrate.ts old mode 100755 new mode 100644 diff --git a/src/collections/dataloader.ts b/src/collections/dataloader.ts index 67259e0fb..3d01c7a7b 100644 --- a/src/collections/dataloader.ts +++ b/src/collections/dataloader.ts @@ -28,7 +28,7 @@ const batchAndLoadDocs = (req: PayloadRequest): BatchLoadFn // { // // key is stringified set of find args - // '["pages",2,0,"es","en",false,false]': [ + // '[null,"pages",2,0,"es","en",false,false]': [ // // value is array of IDs to find with these args // 'q34tl23462346234524', // '435523540194324280', @@ -38,9 +38,10 @@ const batchAndLoadDocs = (req: PayloadRequest): BatchLoadFn // }; const batchByFindArgs = keys.reduce((batches, key) => { - const [collection, id, depth, currentDepth, locale, fallbackLocale, overrideAccess, showHiddenFields] = JSON.parse(key); + const [transactionID, collection, id, depth, currentDepth, locale, fallbackLocale, overrideAccess, showHiddenFields] = JSON.parse(key); const batchKeyArray = [ + transactionID, collection, depth, currentDepth, @@ -54,9 +55,9 @@ const batchAndLoadDocs = (req: PayloadRequest): BatchLoadFn const idField = payload.collections?.[collection].config.fields.find((field) => fieldAffectsData(field) && field.name === 'id'); - let sanitizedID: string | number = id + let sanitizedID: string | number = id; - if (idField?.type === 'number') sanitizedID = parseFloat(id) + if (idField?.type === 'number') sanitizedID = parseFloat(id); if (isValidID(sanitizedID, getIDType(idField))) { return { @@ -73,7 +74,7 @@ const batchAndLoadDocs = (req: PayloadRequest): BatchLoadFn // Run find requests in parallel const results = Object.entries(batchByFindArgs).map(async ([batchKey, ids]) => { - const [collection, depth, currentDepth, locale, fallbackLocale, overrideAccess, showHiddenFields] = JSON.parse(batchKey); + const [/* transactionID */, collection, depth, currentDepth, locale, fallbackLocale, overrideAccess, showHiddenFields] = JSON.parse(batchKey); const result = await payload.find({ collection, @@ -97,7 +98,7 @@ const batchAndLoadDocs = (req: PayloadRequest): BatchLoadFn // Inject doc within docs array if index exists result.docs.forEach((doc) => { - const docKey = JSON.stringify([collection, doc.id, depth, currentDepth, locale, fallbackLocale, overrideAccess, showHiddenFields]); + const docKey = JSON.stringify([req.transactionID, collection, doc.id, depth, currentDepth, locale, fallbackLocale, overrideAccess, showHiddenFields]); const docsIndex = keys.findIndex((key) => key === docKey); if (docsIndex > -1) { diff --git a/src/collections/initLocal.ts b/src/collections/initLocal.ts new file mode 100644 index 000000000..e69de29bb diff --git a/src/collections/operations/create.ts b/src/collections/operations/create.ts index 01400a59e..8ce7580b6 100644 --- a/src/collections/operations/create.ts +++ b/src/collections/operations/create.ts @@ -23,6 +23,8 @@ import { generateFileData } from '../../uploads/generateFileData'; import { saveVersion } from '../../versions/saveVersion'; import { mapAsync } from '../../utilities/mapAsync'; import { registerLocalStrategy } from '../../auth/strategies/local/register'; +import { initTransaction } from '../../utilities/initTransaction'; +import { killTransaction } from '../../utilities/killTransaction'; const unlinkFile = promisify(fs.unlink); @@ -43,20 +45,6 @@ async function create( incomingArgs: Arguments, ): Promise { let args = incomingArgs; - - // ///////////////////////////////////// - // beforeOperation - Collection - // ///////////////////////////////////// - - await args.collection.config.hooks.beforeOperation.reduce(async (priorHook: BeforeOperationHook | Promise, hook: BeforeOperationHook) => { - await priorHook; - - args = (await hook({ - args, - operation: 'create', - })) || args; - }, Promise.resolve()); - const { collection, collection: { @@ -79,252 +67,275 @@ async function create( autosave = false, } = args; - let { data } = args; + try { + const shouldCommit = await initTransaction(req); - const shouldSaveDraft = Boolean(draft && collectionConfig.versions.drafts); + // ///////////////////////////////////// + // beforeOperation - Collection + // ///////////////////////////////////// - // ///////////////////////////////////// - // Access - // ///////////////////////////////////// + await args.collection.config.hooks.beforeOperation.reduce(async (priorHook: BeforeOperationHook | Promise, hook: BeforeOperationHook) => { + await priorHook; - if (!overrideAccess) { - await executeAccess({ req, data }, collectionConfig.access.create); - } + args = (await hook({ + args, + operation: 'create', + })) || args; + }, Promise.resolve()); - // ///////////////////////////////////// - // Custom id - // ///////////////////////////////////// - const hasIdField = collectionConfig.fields.findIndex((field) => fieldAffectsData(field) && field.name === 'id') > -1; - if (hasIdField) { - data = { - _id: data.id, - ...data, - }; - } + let { data } = args; - // ///////////////////////////////////// - // Generate data for all files and sizes - // ///////////////////////////////////// + const shouldSaveDraft = Boolean(draft && collectionConfig.versions.drafts); - const { data: newFileData, files: filesToUpload } = await generateFileData({ - config, - collection, - req, - data, - throwOnMissingFile: !shouldSaveDraft, - overwriteExistingFiles, - }); + // ///////////////////////////////////// + // Access + // ///////////////////////////////////// - data = newFileData; - - // ///////////////////////////////////// - // beforeValidate - Fields - // ///////////////////////////////////// - - data = await beforeValidate({ - data, - doc: {}, - entityConfig: collectionConfig, - operation: 'create', - overrideAccess, - req, - }); - - // ///////////////////////////////////// - // beforeValidate - Collections - // ///////////////////////////////////// - - await collectionConfig.hooks.beforeValidate.reduce(async (priorHook: BeforeValidateHook | Promise, hook: BeforeValidateHook) => { - await priorHook; - - data = (await hook({ - data, - req, - operation: 'create', - })) || data; - }, Promise.resolve()); - - // ///////////////////////////////////// - // Write files to local storage - // ///////////////////////////////////// - - if (!collectionConfig.upload.disableLocalStorage) { - await uploadFiles(payload, filesToUpload, req.t); - } - - // ///////////////////////////////////// - // beforeChange - Collection - // ///////////////////////////////////// - - await collectionConfig.hooks.beforeChange.reduce(async (priorHook, hook) => { - await priorHook; - - data = (await hook({ - data, - req, - operation: 'create', - })) || data; - }, Promise.resolve()); - - // ///////////////////////////////////// - // beforeChange - Fields - // ///////////////////////////////////// - - const resultWithLocales = await beforeChange>({ - data, - doc: {}, - docWithLocales: {}, - entityConfig: collectionConfig, - operation: 'create', - req, - skipValidation: shouldSaveDraft, - }); - - // ///////////////////////////////////// - // Create - // ///////////////////////////////////// - - let doc; - - if (collectionConfig.auth && !collectionConfig.auth.disableLocalStrategy) { - if (data.email) { - resultWithLocales.email = (data.email as string).toLowerCase(); + if (!overrideAccess) { + await executeAccess({ req, data }, collectionConfig.access.create); } - if (collectionConfig.auth.verify) { - resultWithLocales._verified = Boolean(resultWithLocales._verified) || false; - resultWithLocales._verificationToken = crypto.randomBytes(20).toString('hex'); + // ///////////////////////////////////// + // Custom id + // ///////////////////////////////////// + + const hasIdField = collectionConfig.fields.findIndex((field) => fieldAffectsData(field) && field.name === 'id') > -1; + if (hasIdField) { + data = { + _id: data.id, + ...data, + }; } - doc = await registerLocalStrategy({ - collection: collectionConfig, - doc: resultWithLocales, - payload: req.payload, - password: data.password as string, + // ///////////////////////////////////// + // Generate data for all files and sizes + // ///////////////////////////////////// + + const { data: newFileData, files: filesToUpload } = await generateFileData({ + config, + collection, + req, + data, + throwOnMissingFile: !shouldSaveDraft, + overwriteExistingFiles, + }); + + data = newFileData; + + // ///////////////////////////////////// + // beforeValidate - Fields + // ///////////////////////////////////// + + data = await beforeValidate({ + data, + doc: {}, + entityConfig: collectionConfig, + operation: 'create', + overrideAccess, req, }); - } else { - try { - doc = await payload.db.create({ - collection: collectionConfig.slug, - data: resultWithLocales, + + // ///////////////////////////////////// + // beforeValidate - Collections + // ///////////////////////////////////// + + await collectionConfig.hooks.beforeValidate.reduce(async (priorHook: BeforeValidateHook | Promise, hook: BeforeValidateHook) => { + await priorHook; + + data = (await hook({ + data, + req, + operation: 'create', + })) || data; + }, Promise.resolve()); + + // ///////////////////////////////////// + // Write files to local storage + // ///////////////////////////////////// + + if (!collectionConfig.upload.disableLocalStorage) { + await uploadFiles(payload, filesToUpload, req.t); + } + + // ///////////////////////////////////// + // beforeChange - Collection + // ///////////////////////////////////// + + await collectionConfig.hooks.beforeChange.reduce(async (priorHook, hook) => { + await priorHook; + + data = (await hook({ + data, + req, + operation: 'create', + })) || data; + }, Promise.resolve()); + + // ///////////////////////////////////// + // beforeChange - Fields + // ///////////////////////////////////// + + const resultWithLocales = await beforeChange>({ + data, + doc: {}, + docWithLocales: {}, + entityConfig: collectionConfig, + operation: 'create', + req, + skipValidation: shouldSaveDraft, + }); + + // ///////////////////////////////////// + // Create + // ///////////////////////////////////// + + let doc; + + if (collectionConfig.auth && !collectionConfig.auth.disableLocalStrategy) { + if (data.email) { + resultWithLocales.email = (data.email as string).toLowerCase(); + } + + if (collectionConfig.auth.verify) { + resultWithLocales._verified = Boolean(resultWithLocales._verified) || false; + resultWithLocales._verificationToken = crypto.randomBytes(20).toString('hex'); + } + + doc = await registerLocalStrategy({ + collection: collectionConfig, + doc: resultWithLocales, + payload: req.payload, + password: data.password as string, req, }); - } catch (error) { + } else { + try { + doc = await payload.db.create({ + collection: collectionConfig.slug, + data: resultWithLocales, + req, + }); + } catch (error) { // Handle uniqueness error from MongoDB - throw error.code === 11000 && error.keyValue - ? new ValidationError([{ message: req.t('error:valueMustBeUnique'), field: Object.keys(error.keyValue)[0] }], req.t) - : error; + throw error.code === 11000 && error.keyValue + ? new ValidationError([{ message: req.t('error:valueMustBeUnique'), field: Object.keys(error.keyValue)[0] }], req.t) + : error; + } } - } - const verificationToken = doc._verificationToken; - let result: Document = sanitizeInternalFields(doc); + const verificationToken = doc._verificationToken; + let result: Document = sanitizeInternalFields(doc); - // ///////////////////////////////////// - // Create version - // ///////////////////////////////////// + // ///////////////////////////////////// + // Create version + // ///////////////////////////////////// - if (collectionConfig.versions) { - await saveVersion({ - payload, - collection: collectionConfig, - req, - id: result.id, - docWithLocales: result, - autosave, - }); - } + if (collectionConfig.versions) { + await saveVersion({ + payload, + collection: collectionConfig, + req, + id: result.id, + docWithLocales: result, + autosave, + }); + } - // ///////////////////////////////////// - // Send verification email if applicable - // ///////////////////////////////////// + // ///////////////////////////////////// + // Send verification email if applicable + // ///////////////////////////////////// - if (collectionConfig.auth && collectionConfig.auth.verify) { - sendVerificationEmail({ - emailOptions, - config: payload.config, - sendEmail: payload.sendEmail, - collection: { config: collectionConfig }, - user: result, - token: verificationToken, - req, - disableEmail: disableVerificationEmail, - }); - } + if (collectionConfig.auth && collectionConfig.auth.verify) { + sendVerificationEmail({ + emailOptions, + config: payload.config, + sendEmail: payload.sendEmail, + collection: { config: collectionConfig }, + user: result, + token: verificationToken, + req, + disableEmail: disableVerificationEmail, + }); + } - // ///////////////////////////////////// - // afterRead - Fields - // ///////////////////////////////////// + // ///////////////////////////////////// + // afterRead - Fields + // ///////////////////////////////////// - result = await afterRead({ - depth, - doc: result, - entityConfig: collectionConfig, - overrideAccess, - req, - showHiddenFields, - }); - - // ///////////////////////////////////// - // afterRead - Collection - // ///////////////////////////////////// - - await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => { - await priorHook; - - result = await hook({ - req, + result = await afterRead({ + depth, doc: result, - }) || result; - }, Promise.resolve()); + entityConfig: collectionConfig, + overrideAccess, + req, + showHiddenFields, + }); - // ///////////////////////////////////// - // afterChange - Fields - // ///////////////////////////////////// + // ///////////////////////////////////// + // afterRead - Collection + // ///////////////////////////////////// - result = await afterChange({ - data, - doc: result, - previousDoc: {}, - entityConfig: collectionConfig, - operation: 'create', - req, - }); + await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => { + await priorHook; - // ///////////////////////////////////// - // afterChange - Collection - // ///////////////////////////////////// + result = await hook({ + req, + doc: result, + }) || result; + }, Promise.resolve()); - await collectionConfig.hooks.afterChange.reduce(async (priorHook: AfterChangeHook | Promise, hook: AfterChangeHook) => { - await priorHook; + // ///////////////////////////////////// + // afterChange - Fields + // ///////////////////////////////////// - result = await hook({ + result = await afterChange({ + data, doc: result, previousDoc: {}, - req: args.req, + entityConfig: collectionConfig, operation: 'create', - }) || result; - }, Promise.resolve()); - - // Remove temp files if enabled, as express-fileupload does not do this automatically - if (config.upload?.useTempFiles && collectionConfig.upload) { - const { files } = req; - const fileArray = Array.isArray(files) ? files : [files]; - await mapAsync(fileArray, async ({ file }) => { - // Still need this check because this will not be populated if using local API - if (file.tempFilePath) { - await unlinkFile(file.tempFilePath); - } + req, }); + + // ///////////////////////////////////// + // afterChange - Collection + // ///////////////////////////////////// + + await collectionConfig.hooks.afterChange.reduce(async (priorHook: AfterChangeHook | Promise, hook: AfterChangeHook) => { + await priorHook; + + result = await hook({ + doc: result, + previousDoc: {}, + req: args.req, + operation: 'create', + }) || result; + }, Promise.resolve()); + + // Remove temp files if enabled, as express-fileupload does not do this automatically + if (config.upload?.useTempFiles && collectionConfig.upload) { + const { files } = req; + const fileArray = Array.isArray(files) ? files : [files]; + await mapAsync(fileArray, async ({ file }) => { + // Still need this check because this will not be populated if using local API + if (file.tempFilePath) { + await unlinkFile(file.tempFilePath); + } + }); + } + + // ///////////////////////////////////// + // Return results + // ///////////////////////////////////// + + if (shouldCommit) await payload.db.commitTransaction(req.transactionID); + + return result; + } catch (error: unknown) { + await killTransaction(req); + throw error; } - - // ///////////////////////////////////// - // Return results - // ///////////////////////////////////// - - return result; } export default create; diff --git a/src/collections/operations/delete.ts b/src/collections/operations/delete.ts index 424fc85fd..adc91ddaf 100644 --- a/src/collections/operations/delete.ts +++ b/src/collections/operations/delete.ts @@ -12,6 +12,8 @@ import { deleteAssociatedFiles } from '../../uploads/deleteAssociatedFiles'; import { deleteUserPreferences } from '../../preferences/deleteUserPreferences'; import { validateQueryPaths } from '../../database/queryValidation/validateQueryPaths'; import { combineQueries } from '../../database/combineQueries'; +import { initTransaction } from '../../utilities/initTransaction'; +import { killTransaction } from '../../utilities/killTransaction'; export type Arguments = { depth?: number @@ -32,20 +34,6 @@ async function deleteOperation { let args = incomingArgs; - - // ///////////////////////////////////// - // beforeOperation - Collection - // ///////////////////////////////////// - - await args.collection.config.hooks.beforeOperation.reduce(async (priorHook: BeforeOperationHook | Promise, hook: BeforeOperationHook) => { - await priorHook; - - args = (await hook({ - args, - operation: 'delete', - })) || args; - }, Promise.resolve()); - const { depth, collection: { @@ -65,166 +53,190 @@ async function deleteOperation, hook: BeforeOperationHook) => { + await priorHook; - if (!overrideAccess) { - accessResult = await executeAccess({ req }, collectionConfig.access.delete); - } + args = (await hook({ + args, + operation: 'delete', + })) || args; + }, Promise.resolve()); - await validateQueryPaths({ - collectionConfig, - where, - req, - overrideAccess, - }); + if (!where) { + throw new APIError('Missing \'where\' query of documents to delete.', httpStatus.BAD_REQUEST); + } - const fullWhere = combineQueries(where, accessResult); + // ///////////////////////////////////// + // Access + // ///////////////////////////////////// - // ///////////////////////////////////// - // Retrieve documents - // ///////////////////////////////////// + let accessResult: AccessResult; - const { docs } = await payload.db.find({ - locale, - where: fullWhere, - collection: collectionConfig.slug, - }); + if (!overrideAccess) { + accessResult = await executeAccess({ req }, collectionConfig.access.delete); + } - const errors = []; + await validateQueryPaths({ + collectionConfig, + where, + req, + overrideAccess, + }); - /* eslint-disable no-param-reassign */ - const promises = docs.map(async (doc) => { - let result; + const fullWhere = combineQueries(where, accessResult); - const { id } = doc; + // ///////////////////////////////////// + // Retrieve documents + // ///////////////////////////////////// - try { + const { docs } = await payload.db.find({ + locale, + where: fullWhere, + collection: collectionConfig.slug, + req, + }); + + const errors = []; + + /* eslint-disable no-param-reassign */ + const promises = docs.map(async (doc) => { + let result; + + const { id } = doc; + + try { // ///////////////////////////////////// // beforeDelete - Collection // ///////////////////////////////////// - await collectionConfig.hooks.beforeDelete.reduce(async (priorHook, hook) => { - await priorHook; + await collectionConfig.hooks.beforeDelete.reduce(async (priorHook, hook) => { + await priorHook; - return hook({ - req, - id, + return hook({ + req, + id, + }); + }, Promise.resolve()); + + await deleteAssociatedFiles({ + config, + collectionConfig, + doc, + t, + overrideDelete: true, }); - }, Promise.resolve()); - await deleteAssociatedFiles({ - config, - collectionConfig, - doc, - t, - overrideDelete: true, - }); + // ///////////////////////////////////// + // Delete document + // ///////////////////////////////////// - // ///////////////////////////////////// - // Delete document - // ///////////////////////////////////// - - await payload.db.deleteOne({ - collection: collectionConfig.slug, - where: { - id: { - equals: id, + await payload.db.deleteOne({ + collection: collectionConfig.slug, + where: { + id: { + equals: id, + }, }, - }, - req, - }); + req, + }); - // ///////////////////////////////////// - // Delete versions - // ///////////////////////////////////// + // ///////////////////////////////////// + // Delete versions + // ///////////////////////////////////// - if (collectionConfig.versions) { - deleteCollectionVersions({ - payload, - id, - slug: collectionConfig.slug, + if (collectionConfig.versions) { + deleteCollectionVersions({ + payload, + id, + slug: collectionConfig.slug, + req, + }); + } + + // ///////////////////////////////////// + // afterRead - Fields + // ///////////////////////////////////// + + result = await afterRead({ + depth, + doc: result || doc, + entityConfig: collectionConfig, + overrideAccess, + req, + showHiddenFields, + }); + + // ///////////////////////////////////// + // afterRead - Collection + // ///////////////////////////////////// + + await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => { + await priorHook; + + result = await hook({ + req, + doc: result || doc, + }) || result; + }, Promise.resolve()); + + // ///////////////////////////////////// + // afterDelete - Collection + // ///////////////////////////////////// + + await collectionConfig.hooks.afterDelete.reduce(async (priorHook, hook) => { + await priorHook; + + result = await hook({ + req, + id, + doc: result, + }) || result; + }, Promise.resolve()); + + // ///////////////////////////////////// + // 8. Return results + // ///////////////////////////////////// + + return result; + } catch (error) { + errors.push({ + message: error.message, + id: doc.id, }); } + return null; + }); - // ///////////////////////////////////// - // afterRead - Fields - // ///////////////////////////////////// + const awaitedDocs = await Promise.all(promises); - result = await afterRead({ - depth, - doc: result || doc, - entityConfig: collectionConfig, - overrideAccess, - req, - showHiddenFields, - }); + // ///////////////////////////////////// + // Delete Preferences + // ///////////////////////////////////// - // ///////////////////////////////////// - // afterRead - Collection - // ///////////////////////////////////// + deleteUserPreferences({ + payload, + collectionConfig, + ids: docs.map(({ id }) => id), + req, + }); - await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => { - await priorHook; + if (shouldCommit) await payload.db.commitTransaction(req.transactionID); - result = await hook({ - req, - doc: result || doc, - }) || result; - }, Promise.resolve()); - - // ///////////////////////////////////// - // afterDelete - Collection - // ///////////////////////////////////// - - await collectionConfig.hooks.afterDelete.reduce(async (priorHook, hook) => { - await priorHook; - - result = await hook({ - req, - id, - doc: result, - }) || result; - }, Promise.resolve()); - - // ///////////////////////////////////// - // 8. Return results - // ///////////////////////////////////// - - return result; - } catch (error) { - errors.push({ - message: error.message, - id: doc.id, - }); - } - return null; - }); - - const awaitedDocs = await Promise.all(promises); - - // ///////////////////////////////////// - // Delete Preferences - // ///////////////////////////////////// - - deleteUserPreferences({ - payload, - collectionConfig, - ids: docs.map(({ id }) => id), - req, - }); - - return { - docs: awaitedDocs.filter(Boolean), - errors, - }; + return { + docs: awaitedDocs.filter(Boolean), + errors, + }; + } catch (error: unknown) { + await killTransaction(req); + throw error; + } } export default deleteOperation; diff --git a/src/collections/operations/deleteByID.ts b/src/collections/operations/deleteByID.ts index a0443c111..24203fafa 100644 --- a/src/collections/operations/deleteByID.ts +++ b/src/collections/operations/deleteByID.ts @@ -10,6 +10,8 @@ import { deleteCollectionVersions } from '../../versions/deleteCollectionVersion import { deleteAssociatedFiles } from '../../uploads/deleteAssociatedFiles'; import { combineQueries } from '../../database/combineQueries'; import { deleteUserPreferences } from '../../preferences/deleteUserPreferences'; +import { killTransaction } from '../../utilities/killTransaction'; +import { initTransaction } from '../../utilities/initTransaction'; export type Arguments = { depth?: number @@ -22,20 +24,6 @@ export type Arguments = { async function deleteByID(incomingArgs: Arguments): Promise { let args = incomingArgs; - - // ///////////////////////////////////// - // beforeOperation - Collection - // ///////////////////////////////////// - - await args.collection.config.hooks.beforeOperation.reduce(async (priorHook: BeforeOperationHook | Promise, hook: BeforeOperationHook) => { - await priorHook; - - args = (await hook({ - args, - operation: 'delete', - })) || args; - }, Promise.resolve()); - const { depth, collection: { @@ -54,119 +42,143 @@ async function deleteByID(inc showHiddenFields, } = args; - // ///////////////////////////////////// - // Access - // ///////////////////////////////////// + try { + const shouldCommit = await initTransaction(req); - const accessResults = !overrideAccess ? await executeAccess({ req, id }, collectionConfig.access.delete) : true; - const hasWhereAccess = hasWhereAccessResult(accessResults); + // ///////////////////////////////////// + // beforeOperation - Collection + // ///////////////////////////////////// - // ///////////////////////////////////// - // beforeDelete - Collection - // ///////////////////////////////////// + await args.collection.config.hooks.beforeOperation.reduce(async (priorHook: BeforeOperationHook | Promise, hook: BeforeOperationHook) => { + await priorHook; - await collectionConfig.hooks.beforeDelete.reduce(async (priorHook, hook) => { - await priorHook; + args = (await hook({ + args, + operation: 'delete', + })) || args; + }, Promise.resolve()); - return hook({ + // ///////////////////////////////////// + // Access + // ///////////////////////////////////// + + const accessResults = !overrideAccess ? await executeAccess({ req, id }, collectionConfig.access.delete) : true; + const hasWhereAccess = hasWhereAccessResult(accessResults); + + // ///////////////////////////////////// + // beforeDelete - Collection + // ///////////////////////////////////// + + await collectionConfig.hooks.beforeDelete.reduce(async (priorHook, hook) => { + await priorHook; + + return hook({ + req, + id, + }); + }, Promise.resolve()); + + // ///////////////////////////////////// + // Retrieve document + // ///////////////////////////////////// + + const docToDelete = await req.payload.db.findOne({ + collection: collectionConfig.slug, + where: combineQueries({ id: { equals: id } }, accessResults), + locale: req.locale, req, - id, }); - }, Promise.resolve()); - - // ///////////////////////////////////// - // Retrieve document - // ///////////////////////////////////// - - const docToDelete = await req.payload.db.findOne({ - collection: collectionConfig.slug, - where: combineQueries({ id: { equals: id } }, accessResults), - locale: req.locale, - }); - if (!docToDelete && !hasWhereAccess) throw new NotFound(t); - if (!docToDelete && hasWhereAccess) throw new Forbidden(t); + if (!docToDelete && !hasWhereAccess) throw new NotFound(t); + if (!docToDelete && hasWhereAccess) throw new Forbidden(t); - await deleteAssociatedFiles({ config, collectionConfig, doc: docToDelete, t, overrideDelete: true }); + await deleteAssociatedFiles({ config, collectionConfig, doc: docToDelete, t, overrideDelete: true }); - // ///////////////////////////////////// - // Delete document - // ///////////////////////////////////// + // ///////////////////////////////////// + // Delete document + // ///////////////////////////////////// - let result = await req.payload.db.deleteOne({ - collection: collectionConfig.slug, - where: { id: { equals: id } }, - req, - }); + let result = await req.payload.db.deleteOne({ + collection: collectionConfig.slug, + where: { id: { equals: id } }, + req, + }); - // ///////////////////////////////////// - // Delete Preferences - // ///////////////////////////////////// + // ///////////////////////////////////// + // Delete Preferences + // ///////////////////////////////////// - deleteUserPreferences({ - payload, - collectionConfig, - ids: [id], - req, - }); - - // ///////////////////////////////////// - // Delete versions - // ///////////////////////////////////// - - if (collectionConfig.versions) { - deleteCollectionVersions({ + deleteUserPreferences({ payload, - id, - slug: collectionConfig.slug, - }); - } - - // ///////////////////////////////////// - // afterRead - Fields - // ///////////////////////////////////// - - result = await afterRead({ - depth, - doc: result, - entityConfig: collectionConfig, - overrideAccess, - req, - showHiddenFields, - }); - - // ///////////////////////////////////// - // afterRead - Collection - // ///////////////////////////////////// - - await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => { - await priorHook; - - result = await hook({ + collectionConfig, + ids: [id], req, + }); + + // ///////////////////////////////////// + // Delete versions + // ///////////////////////////////////// + + if (collectionConfig.versions) { + deleteCollectionVersions({ + payload, + id, + slug: collectionConfig.slug, + req, + }); + } + + // ///////////////////////////////////// + // afterRead - Fields + // ///////////////////////////////////// + + result = await afterRead({ + depth, doc: result, - }) || result; - }, Promise.resolve()); + entityConfig: collectionConfig, + overrideAccess, + req, + showHiddenFields, + }); - // ///////////////////////////////////// - // afterDelete - Collection - // ///////////////////////////////////// + // ///////////////////////////////////// + // afterRead - Collection + // ///////////////////////////////////// - await collectionConfig.hooks.afterDelete.reduce(async (priorHook, hook) => { - await priorHook; + await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => { + await priorHook; - result = await hook({ req, id, doc: result }) || result; - }, Promise.resolve()); + result = await hook({ + req, + doc: result, + }) || result; + }, Promise.resolve()); - // ///////////////////////////////////// - // 8. Return results - // ///////////////////////////////////// + // ///////////////////////////////////// + // afterDelete - Collection + // ///////////////////////////////////// - return result; + await collectionConfig.hooks.afterDelete.reduce(async (priorHook, hook) => { + await priorHook; + + result = await hook({ req, id, doc: result }) || result; + }, Promise.resolve()); + + // ///////////////////////////////////// + // 8. Return results + // ///////////////////////////////////// + + if (shouldCommit) await payload.db.commitTransaction(req.transactionID); + + return result; + } catch (error: unknown) { + await killTransaction(req); + throw error; + } } export default deleteByID; diff --git a/src/collections/operations/find.ts b/src/collections/operations/find.ts index d36caf7de..7cf03d031 100644 --- a/src/collections/operations/find.ts +++ b/src/collections/operations/find.ts @@ -9,6 +9,8 @@ import { validateQueryPaths } from '../../database/queryValidation/validateQuery import { appendVersionToQueryKey } from '../../versions/drafts/appendVersionToQueryKey'; import { buildVersionCollectionFields } from '../../versions/buildCollectionFields'; import { combineQueries } from '../../database/combineQueries'; +import { initTransaction } from '../../utilities/initTransaction'; +import { killTransaction } from '../../utilities/killTransaction'; export type Arguments = { collection: Collection @@ -30,20 +32,6 @@ async function find>( incomingArgs: Arguments, ): Promise> { let args = incomingArgs; - - // ///////////////////////////////////// - // beforeOperation - Collection - // ///////////////////////////////////// - - await args.collection.config.hooks.beforeOperation.reduce(async (priorHook, hook) => { - await priorHook; - - args = (await hook({ - args, - operation: 'read', - })) || args; - }, Promise.resolve()); - const { where, page, @@ -67,144 +55,168 @@ async function find>( pagination = true, } = args; - // ///////////////////////////////////// - // Access - // ///////////////////////////////////// + try { + const shouldCommit = await initTransaction(req); - let accessResult: AccessResult; + // ///////////////////////////////////// + // beforeOperation - Collection + // ///////////////////////////////////// - if (!overrideAccess) { - accessResult = await executeAccess({ req, disableErrors }, collectionConfig.access.read); + await args.collection.config.hooks.beforeOperation.reduce(async (priorHook, hook) => { + await priorHook; - // If errors are disabled, and access returns false, return empty results - if (accessResult === false) { - return { - docs: [], - totalDocs: 0, - totalPages: 1, - page: 1, - pagingCounter: 1, - hasPrevPage: false, - hasNextPage: false, - prevPage: null, - nextPage: null, - limit, - }; + args = (await hook({ + args, + operation: 'read', + })) || args; + }, Promise.resolve()); + + // ///////////////////////////////////// + // Access + // ///////////////////////////////////// + + let accessResult: AccessResult; + + if (!overrideAccess) { + accessResult = await executeAccess({ req, disableErrors }, collectionConfig.access.read); + + // If errors are disabled, and access returns false, return empty results + if (accessResult === false) { + return { + docs: [], + totalDocs: 0, + totalPages: 1, + page: 1, + pagingCounter: 1, + hasPrevPage: false, + hasNextPage: false, + prevPage: null, + nextPage: null, + limit, + }; + } } + + // ///////////////////////////////////// + // Find + // ///////////////////////////////////// + + const usePagination = pagination && limit !== 0; + const sanitizedLimit = limit ?? (usePagination ? 10 : 0); + const sanitizedPage = page || 1; + + let result: PaginatedDocs; + + let fullWhere = combineQueries(where, accessResult); + + if (collectionConfig.versions?.drafts && draftsEnabled) { + fullWhere = appendVersionToQueryKey(fullWhere); + + await validateQueryPaths({ + collectionConfig: collection.config, + where: fullWhere, + req, + overrideAccess, + versionFields: buildVersionCollectionFields(collection.config), + }); + + result = await payload.db.queryDrafts({ + collection: collectionConfig.slug, + where: fullWhere, + page: sanitizedPage, + limit: sanitizedLimit, + sort, + pagination: usePagination, + locale, + req, + }); + } else { + await validateQueryPaths({ + collectionConfig, + where, + req, + overrideAccess, + }); + + result = await payload.db.find({ + collection: collectionConfig.slug, + where: fullWhere, + page: sanitizedPage, + limit: sanitizedLimit, + sort, + locale, + pagination, + req, + }); + } + + // ///////////////////////////////////// + // beforeRead - Collection + // ///////////////////////////////////// + + result = { + ...result, + docs: await Promise.all(result.docs.map(async (doc) => { + let docRef = doc; + + await collectionConfig.hooks.beforeRead.reduce(async (priorHook, hook) => { + await priorHook; + + docRef = await hook({ req, query: fullWhere, doc: docRef }) || docRef; + }, Promise.resolve()); + + return docRef; + })), + }; + + // ///////////////////////////////////// + // afterRead - Fields + // ///////////////////////////////////// + + result = { + ...result, + docs: await Promise.all(result.docs.map(async (doc) => afterRead({ + depth, + currentDepth, + doc, + entityConfig: collectionConfig, + overrideAccess, + req, + showHiddenFields, + findMany: true, + }))), + }; + + // ///////////////////////////////////// + // afterRead - Collection + // ///////////////////////////////////// + + result = { + ...result, + docs: await Promise.all(result.docs.map(async (doc) => { + let docRef = doc; + + await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => { + await priorHook; + + docRef = await hook({ req, query: fullWhere, doc: docRef, findMany: true }) || doc; + }, Promise.resolve()); + + return docRef; + })), + }; + + // ///////////////////////////////////// + // Return results + // ///////////////////////////////////// + + if (shouldCommit) await payload.db.commitTransaction(req.transactionID); + + return result; + } catch (error: unknown) { + await killTransaction(req); + throw error; } - - // ///////////////////////////////////// - // Find - // ///////////////////////////////////// - - const usePagination = pagination && limit !== 0; - const sanitizedLimit = limit ?? (usePagination ? 10 : 0); - const sanitizedPage = page || 1; - - let result: PaginatedDocs; - - let fullWhere = combineQueries(where, accessResult); - - if (collectionConfig.versions?.drafts && draftsEnabled) { - fullWhere = appendVersionToQueryKey(fullWhere); - - await validateQueryPaths({ - collectionConfig: collection.config, - where: fullWhere, - req, - overrideAccess, - versionFields: buildVersionCollectionFields(collection.config), - }); - - result = await payload.db.queryDrafts({ - collection: collectionConfig.slug, - where: fullWhere, - page: sanitizedPage, - limit: sanitizedLimit, - sort, - pagination: usePagination, - locale, - }); - } else { - await validateQueryPaths({ - collectionConfig, - where, - req, - overrideAccess, - }); - - result = await payload.db.find({ - collection: collectionConfig.slug, - where: fullWhere, - page: sanitizedPage, - limit: sanitizedLimit, - sort, - locale, - pagination, - }); - } - - // ///////////////////////////////////// - // beforeRead - Collection - // ///////////////////////////////////// - - result = { - ...result, - docs: await Promise.all(result.docs.map(async (doc) => { - let docRef = doc; - - await collectionConfig.hooks.beforeRead.reduce(async (priorHook, hook) => { - await priorHook; - - docRef = await hook({ req, query: fullWhere, doc: docRef }) || docRef; - }, Promise.resolve()); - - return docRef; - })), - }; - - // ///////////////////////////////////// - // afterRead - Fields - // ///////////////////////////////////// - - result = { - ...result, - docs: await Promise.all(result.docs.map(async (doc) => afterRead({ - depth, - currentDepth, - doc, - entityConfig: collectionConfig, - overrideAccess, - req, - showHiddenFields, - findMany: true, - }))), - }; - - // ///////////////////////////////////// - // afterRead - Collection - // ///////////////////////////////////// - - result = { - ...result, - docs: await Promise.all(result.docs.map(async (doc) => { - let docRef = doc; - - await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => { - await priorHook; - - docRef = await hook({ req, query: fullWhere, doc: docRef, findMany: true }) || doc; - }, Promise.resolve()); - - return docRef; - })), - }; - - // ///////////////////////////////////// - // Return results - // ///////////////////////////////////// - - return result; } export default find; diff --git a/src/collections/operations/findByID.ts b/src/collections/operations/findByID.ts index 767cdef60..ce61523f3 100644 --- a/src/collections/operations/findByID.ts +++ b/src/collections/operations/findByID.ts @@ -8,6 +8,8 @@ import replaceWithDraftIfAvailable from '../../versions/drafts/replaceWithDraftI import { afterRead } from '../../fields/hooks/afterRead'; import { combineQueries } from '../../database/combineQueries'; import type { FindOneArgs } from '../../database/types'; +import { initTransaction } from '../../utilities/initTransaction'; +import { killTransaction } from '../../utilities/killTransaction'; export type Arguments = { collection: Collection @@ -26,19 +28,6 @@ async function findByID( ): Promise { let args = incomingArgs; - // ///////////////////////////////////// - // beforeOperation - Collection - // ///////////////////////////////////// - - await args.collection.config.hooks.beforeOperation.reduce(async (priorHook, hook) => { - await priorHook; - - args = (await hook({ - args, - operation: 'read', - })) || args; - }, Promise.resolve()); - const { depth, collection: { @@ -47,6 +36,7 @@ async function findByID( id, req, req: { + payload, t, locale, }, @@ -57,118 +47,144 @@ async function findByID( draft: draftEnabled = false, } = args; - // ///////////////////////////////////// - // Access - // ///////////////////////////////////// + try { + const shouldCommit = await initTransaction(req); + const { transactionID } = req; - const accessResult = !overrideAccess ? await executeAccess({ req, disableErrors, id }, collectionConfig.access.read) : true; + // ///////////////////////////////////// + // beforeOperation - Collection + // ///////////////////////////////////// - // If errors are disabled, and access returns false, return null - if (accessResult === false) return null; + await args.collection.config.hooks.beforeOperation.reduce(async (priorHook, hook) => { + await priorHook; + + args = (await hook({ + args, + operation: 'read', + })) || args; + }, Promise.resolve()); + + // ///////////////////////////////////// + // Access + // ///////////////////////////////////// + + const accessResult = !overrideAccess ? await executeAccess({ req, disableErrors, id }, collectionConfig.access.read) : true; + + // If errors are disabled, and access returns false, return null + if (accessResult === false) return null; - const findOneArgs: FindOneArgs = { - collection: collectionConfig.slug, - where: combineQueries({ id: { equals: id } }, accessResult), - locale, - }; + const findOneArgs: FindOneArgs = { + collection: collectionConfig.slug, + where: combineQueries({ id: { equals: id } }, accessResult), + locale, + req: { + transactionID: req.transactionID, + } as PayloadRequest, + }; - // ///////////////////////////////////// - // Find by ID - // ///////////////////////////////////// + // ///////////////////////////////////// + // Find by ID + // ///////////////////////////////////// - if (!findOneArgs.where.and[0].id) throw new NotFound(t); + if (!findOneArgs.where.and[0].id) throw new NotFound(t); - if (!req.findByID) req.findByID = {}; + if (!req.findByID) req.findByID = { [transactionID]: {} }; - if (!req.findByID[collectionConfig.slug]) { - const nonMemoizedFindByID = async (query: FindOneArgs) => req.payload.db.findOne(query); + if (!req.findByID[transactionID][collectionConfig.slug]) { + const nonMemoizedFindByID = async (query: FindOneArgs) => req.payload.db.findOne(query); - req.findByID[collectionConfig.slug] = memoize(nonMemoizedFindByID, { - isPromise: true, - maxSize: 100, - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore This is straight from their docs, bad typings - transformKey: JSON.stringify, - }); - } - - let result = await req.findByID[collectionConfig.slug](findOneArgs) as T; - - if (!result) { - if (!disableErrors) { - throw new NotFound(t); + req.findByID[transactionID][collectionConfig.slug] = memoize(nonMemoizedFindByID, { + isPromise: true, + maxSize: 100, + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore This is straight from their docs, bad typings + transformKey: JSON.stringify, + }); } - return null; - } + let result = await req.findByID[transactionID][collectionConfig.slug](findOneArgs) as T; - // Clone the result - it may have come back memoized - result = JSON.parse(JSON.stringify(result)); + if (!result) { + if (!disableErrors) { + throw new NotFound(t); + } + + return null; + } + + // Clone the result - it may have come back memoized + result = JSON.parse(JSON.stringify(result)); - // ///////////////////////////////////// - // Replace document with draft if available - // ///////////////////////////////////// + // ///////////////////////////////////// + // Replace document with draft if available + // ///////////////////////////////////// - if (collectionConfig.versions?.drafts && draftEnabled) { - result = await replaceWithDraftIfAvailable({ - entity: collectionConfig, - entityType: 'collection', + if (collectionConfig.versions?.drafts && draftEnabled) { + result = await replaceWithDraftIfAvailable({ + entity: collectionConfig, + entityType: 'collection', + doc: result, + accessResult, + req, + overrideAccess, + }); + } + + // ///////////////////////////////////// + // beforeRead - Collection + // ///////////////////////////////////// + + await collectionConfig.hooks.beforeRead.reduce(async (priorHook, hook) => { + await priorHook; + + result = await hook({ + req, + query: findOneArgs.where, + doc: result, + }) || result; + }, Promise.resolve()); + + // ///////////////////////////////////// + // afterRead - Fields + // ///////////////////////////////////// + + result = await afterRead({ + currentDepth, doc: result, - accessResult, - req, + depth, + entityConfig: collectionConfig, overrideAccess, + req, + showHiddenFields, }); + + // ///////////////////////////////////// + // afterRead - Collection + // ///////////////////////////////////// + + await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => { + await priorHook; + + result = await hook({ + req, + query: findOneArgs.where, + doc: result, + }) || result; + }, Promise.resolve()); + + // ///////////////////////////////////// + // Return results + // ///////////////////////////////////// + + if (shouldCommit) await payload.db.commitTransaction(req.transactionID); + + return result; + } catch (error: unknown) { + await killTransaction(req); + throw error; } - - // ///////////////////////////////////// - // beforeRead - Collection - // ///////////////////////////////////// - - await collectionConfig.hooks.beforeRead.reduce(async (priorHook, hook) => { - await priorHook; - - result = await hook({ - req, - query: findOneArgs.where, - doc: result, - }) || result; - }, Promise.resolve()); - - // ///////////////////////////////////// - // afterRead - Fields - // ///////////////////////////////////// - - result = await afterRead({ - currentDepth, - doc: result, - depth, - entityConfig: collectionConfig, - overrideAccess, - req, - showHiddenFields, - }); - - // ///////////////////////////////////// - // afterRead - Collection - // ///////////////////////////////////// - - await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => { - await priorHook; - - result = await hook({ - req, - query: findOneArgs.where, - doc: result, - }) || result; - }, Promise.resolve()); - - // ///////////////////////////////////// - // Return results - // ///////////////////////////////////// - - return result; } export default findByID; diff --git a/src/collections/operations/findVersionByID.ts b/src/collections/operations/findVersionByID.ts index aeefbb4e5..c357bf164 100644 --- a/src/collections/operations/findVersionByID.ts +++ b/src/collections/operations/findVersionByID.ts @@ -7,6 +7,8 @@ import executeAccess from '../../auth/executeAccess'; import { TypeWithVersion } from '../../versions/types'; import { afterRead } from '../../fields/hooks/afterRead'; import { combineQueries } from '../../database/combineQueries'; +import { initTransaction } from '../../utilities/initTransaction'; +import { killTransaction } from '../../utilities/killTransaction'; export type Arguments = { collection: Collection @@ -42,89 +44,99 @@ async function findVersionByID(args: Arguments): Pro throw new APIError('Missing ID of version.', httpStatus.BAD_REQUEST); } - // ///////////////////////////////////// - // Access - // ///////////////////////////////////// + try { + const shouldCommit = await initTransaction(req); - const accessResults = !overrideAccess ? await executeAccess({ req, disableErrors, id }, collectionConfig.access.readVersions) : true; + // ///////////////////////////////////// + // Access + // ///////////////////////////////////// - // If errors are disabled, and access returns false, return null - if (accessResults === false) return null; + const accessResults = !overrideAccess ? await executeAccess({ req, disableErrors, id }, collectionConfig.access.readVersions) : true; - const hasWhereAccess = typeof accessResults === 'object'; + // If errors are disabled, and access returns false, return null + if (accessResults === false) return null; - const fullWhere = combineQueries({ _id: { equals: id } }, accessResults); + const hasWhereAccess = typeof accessResults === 'object'; - // ///////////////////////////////////// - // Find by ID - // ///////////////////////////////////// + const fullWhere = combineQueries({ _id: { equals: id } }, accessResults); - const versionsQuery = await payload.db.findVersions({ - locale, - collection: collectionConfig.slug, - limit: 1, - pagination: false, - where: fullWhere, - }); + // ///////////////////////////////////// + // Find by ID + // ///////////////////////////////////// - const result = versionsQuery.docs[0]; + const versionsQuery = await payload.db.findVersions({ + locale, + collection: collectionConfig.slug, + limit: 1, + pagination: false, + where: fullWhere, + req, + }); - if (!result) { - if (!disableErrors) { - if (!hasWhereAccess) throw new NotFound(t); - if (hasWhereAccess) throw new Forbidden(t); + const result = versionsQuery.docs[0]; + + if (!result) { + if (!disableErrors) { + if (!hasWhereAccess) throw new NotFound(t); + if (hasWhereAccess) throw new Forbidden(t); + } + + return null; } - return null; + // ///////////////////////////////////// + // beforeRead - Collection + // ///////////////////////////////////// + + await collectionConfig.hooks.beforeRead.reduce(async (priorHook, hook) => { + await priorHook; + + result.version = await hook({ + req, + query: fullWhere, + doc: result.version, + }) || result.version; + }, Promise.resolve()); + + // ///////////////////////////////////// + // afterRead - Fields + // ///////////////////////////////////// + + result.version = await afterRead({ + currentDepth, + depth, + doc: result.version, + entityConfig: collectionConfig, + overrideAccess, + req, + showHiddenFields, + }); + + // ///////////////////////////////////// + // afterRead - Collection + // ///////////////////////////////////// + + await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => { + await priorHook; + + result.version = await hook({ + req, + query: fullWhere, + doc: result.version, + }) || result.version; + }, Promise.resolve()); + + // ///////////////////////////////////// + // Return results + // ///////////////////////////////////// + + if (shouldCommit) await payload.db.commitTransaction(req.transactionID); + + return result; + } catch (error: unknown) { + await killTransaction(req); + throw error; } - - // ///////////////////////////////////// - // beforeRead - Collection - // ///////////////////////////////////// - - await collectionConfig.hooks.beforeRead.reduce(async (priorHook, hook) => { - await priorHook; - - result.version = await hook({ - req, - query: fullWhere, - doc: result.version, - }) || result.version; - }, Promise.resolve()); - - // ///////////////////////////////////// - // afterRead - Fields - // ///////////////////////////////////// - - result.version = await afterRead({ - currentDepth, - depth, - doc: result.version, - entityConfig: collectionConfig, - overrideAccess, - req, - showHiddenFields, - }); - - // ///////////////////////////////////// - // afterRead - Collection - // ///////////////////////////////////// - - await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => { - await priorHook; - - result.version = await hook({ - req, - query: fullWhere, - doc: result.version, - }) || result.version; - }, Promise.resolve()); - - // ///////////////////////////////////// - // Return results - // ///////////////////////////////////// - - return result; } export default findVersionByID; diff --git a/src/collections/operations/findVersions.ts b/src/collections/operations/findVersions.ts index df99dfaba..4e12da49c 100644 --- a/src/collections/operations/findVersions.ts +++ b/src/collections/operations/findVersions.ts @@ -9,6 +9,8 @@ import { afterRead } from '../../fields/hooks/afterRead'; import { buildVersionCollectionFields } from '../../versions/buildCollectionFields'; import { validateQueryPaths } from '../../database/queryValidation/validateQueryPaths'; import { combineQueries } from '../../database/combineQueries'; +import { initTransaction } from '../../utilities/initTransaction'; +import { killTransaction } from '../../utilities/killTransaction'; export type Arguments = { collection: Collection @@ -43,108 +45,118 @@ async function findVersions>( showHiddenFields, } = args; - // ///////////////////////////////////// - // Access - // ///////////////////////////////////// + try { + const shouldCommit = await initTransaction(req); - let accessResults; + // ///////////////////////////////////// + // Access + // ///////////////////////////////////// - if (!overrideAccess) { - accessResults = await executeAccess({ req }, collectionConfig.access.readVersions); + let accessResults; + + if (!overrideAccess) { + accessResults = await executeAccess({ req }, collectionConfig.access.readVersions); + } + + const versionFields = buildVersionCollectionFields(collectionConfig); + + await validateQueryPaths({ + collectionConfig, + versionFields, + where, + req, + overrideAccess, + }); + + const fullWhere = combineQueries(where, accessResults); + + // ///////////////////////////////////// + // Find + // ///////////////////////////////////// + + const paginatedDocs = await payload.db.findVersions({ + where: fullWhere, + page: page || 1, + limit: limit ?? 10, + collection: collectionConfig.slug, + sort, + locale, + req, + }); + + // ///////////////////////////////////// + // beforeRead - Collection + // ///////////////////////////////////// + + let result = { + ...paginatedDocs, + docs: await Promise.all(paginatedDocs.docs.map(async (doc) => { + const docRef = doc; + await collectionConfig.hooks.beforeRead.reduce(async (priorHook, hook) => { + await priorHook; + + docRef.version = await hook({ req, query: fullWhere, doc: docRef.version }) || docRef.version; + }, Promise.resolve()); + + return docRef; + })), + } as PaginatedDocs; + + // ///////////////////////////////////// + // afterRead - Fields + // ///////////////////////////////////// + + result = { + ...result, + docs: await Promise.all(result.docs.map(async (data) => ({ + ...data, + version: await afterRead({ + depth, + doc: data.version, + entityConfig: collectionConfig, + overrideAccess, + req, + showHiddenFields, + findMany: true, + }), + }))), + }; + + // ///////////////////////////////////// + // afterRead - Collection + // ///////////////////////////////////// + + result = { + ...result, + docs: await Promise.all(result.docs.map(async (doc) => { + const docRef = doc; + + await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => { + await priorHook; + + docRef.version = await hook({ req, query: fullWhere, doc: doc.version, findMany: true }) || doc.version; + }, Promise.resolve()); + + return docRef; + })), + }; + + // ///////////////////////////////////// + // Return results + // ///////////////////////////////////// + + result = { + ...result, + docs: result.docs.map((doc) => sanitizeInternalFields(doc)), + }; + + if (shouldCommit) await payload.db.commitTransaction(req.transactionID); + + return result; + } catch (error: unknown) { + await killTransaction(req); + throw error; } - - const versionFields = buildVersionCollectionFields(collectionConfig); - - await validateQueryPaths({ - collectionConfig, - versionFields, - where, - req, - overrideAccess, - }); - - const fullWhere = combineQueries(where, accessResults); - - // ///////////////////////////////////// - // Find - // ///////////////////////////////////// - - const paginatedDocs = await payload.db.findVersions({ - where: fullWhere, - page: page || 1, - limit: limit ?? 10, - collection: collectionConfig.slug, - sort, - locale, - }); - - // ///////////////////////////////////// - // beforeRead - Collection - // ///////////////////////////////////// - - let result = { - ...paginatedDocs, - docs: await Promise.all(paginatedDocs.docs.map(async (doc) => { - const docRef = doc; - await collectionConfig.hooks.beforeRead.reduce(async (priorHook, hook) => { - await priorHook; - - docRef.version = await hook({ req, query: fullWhere, doc: docRef.version }) || docRef.version; - }, Promise.resolve()); - - return docRef; - })), - } as PaginatedDocs; - - // ///////////////////////////////////// - // afterRead - Fields - // ///////////////////////////////////// - - result = { - ...result, - docs: await Promise.all(result.docs.map(async (data) => ({ - ...data, - version: await afterRead({ - depth, - doc: data.version, - entityConfig: collectionConfig, - overrideAccess, - req, - showHiddenFields, - findMany: true, - }), - }))), - }; - - // ///////////////////////////////////// - // afterRead - Collection - // ///////////////////////////////////// - - result = { - ...result, - docs: await Promise.all(result.docs.map(async (doc) => { - const docRef = doc; - - await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => { - await priorHook; - - docRef.version = await hook({ req, query: fullWhere, doc: doc.version, findMany: true }) || doc.version; - }, Promise.resolve()); - - return docRef; - })), - }; - - // ///////////////////////////////////// - // Return results - // ///////////////////////////////////// - - result = { - ...result, - docs: result.docs.map((doc) => sanitizeInternalFields(doc)), - }; - - return result; } export default findVersions; diff --git a/src/collections/operations/local/create.ts b/src/collections/operations/local/create.ts index 4d7822905..22f8bd163 100644 --- a/src/collections/operations/local/create.ts +++ b/src/collections/operations/local/create.ts @@ -53,7 +53,7 @@ export default async function createLocal = { + req?: PayloadRequest, collection: T depth?: number locale?: string @@ -45,24 +46,23 @@ async function deleteLocal(pa user, overrideAccess = true, showHiddenFields, + req = {} as PayloadRequest, } = options; const collection = payload.collections[collectionSlug]; const defaultLocale = payload?.config?.localization ? payload?.config?.localization?.defaultLocale : null; - if (!collection) { - throw new APIError(`The collection with slug ${String(collectionSlug)} can't be found.`); + throw new APIError(`The collection with slug ${String(collectionSlug)} can't be found. Delete Operation.`); } - const req = { - user, - payloadAPI: 'local', - locale: locale ?? defaultLocale, - fallbackLocale: fallbackLocale ?? defaultLocale, - payload, - i18n: i18nInit(payload.config.i18n), - } as PayloadRequest; + req.payloadAPI = req.payloadAPI || 'local'; + req.locale = locale ?? req?.locale ?? defaultLocale; + req.fallbackLocale = fallbackLocale ?? req?.fallbackLocale ?? defaultLocale; + req.payload = payload; + req.i18n = i18nInit(payload.config.i18n); + + if (typeof user !== 'undefined') req.user = user; if (!req.t) req.t = req.i18n.t; if (!req.payloadDataLoader) req.payloadDataLoader = getDataLoader(req); diff --git a/src/collections/operations/local/find.ts b/src/collections/operations/local/find.ts index eccd1efd3..1f718dc94 100644 --- a/src/collections/operations/local/find.ts +++ b/src/collections/operations/local/find.ts @@ -54,7 +54,7 @@ export default async function findLocal = { + req?: PayloadRequest, collection: TSlug data: DeepPartial depth?: number @@ -60,28 +62,26 @@ async function updateLocal(pa autosave, id, where, + req = {} as PayloadRequest, } = options; const collection = payload.collections[collectionSlug]; - - if (!collection) { - throw new APIError(`The collection with slug ${String(collectionSlug)} can't be found.`); - } - const i18n = i18nInit(payload.config.i18n); const defaultLocale = payload.config.localization ? payload.config.localization?.defaultLocale : null; - const req = { - user, - payloadAPI: 'local', - locale: locale ?? defaultLocale, - fallbackLocale: fallbackLocale ?? defaultLocale, - payload, - i18n, - files: { - file: file ?? await getFileByPath(filePath), - }, - } as PayloadRequest; + if (!collection) { + throw new APIError(`The collection with slug ${String(collectionSlug)} can't be found. Update Operation.`); + } + + req.payloadAPI = req.payloadAPI || 'local'; + req.locale = locale ?? req?.locale ?? defaultLocale; + req.fallbackLocale = fallbackLocale ?? req?.fallbackLocale ?? defaultLocale; + req.payload = payload; + req.user = user; + req.i18n = i18n; + req.files = { + file: (file ?? (await getFileByPath(filePath))) as UploadedFile, + }; if (!req.t) req.t = req.i18n.t; if (!req.payloadDataLoader) req.payloadDataLoader = getDataLoader(req); diff --git a/src/collections/operations/restoreVersion.ts b/src/collections/operations/restoreVersion.ts index c4526423f..b97516fdd 100644 --- a/src/collections/operations/restoreVersion.ts +++ b/src/collections/operations/restoreVersion.ts @@ -10,6 +10,8 @@ import { afterRead } from '../../fields/hooks/afterRead'; import { getLatestCollectionVersion } from '../../versions/getLatestCollectionVersion'; import { combineQueries } from '../../database/combineQueries'; import type { FindOneArgs } from '../../database/types'; +import { initTransaction } from '../../utilities/initTransaction'; +import { killTransaction } from '../../utilities/killTransaction'; export type Arguments = { collection: Collection @@ -39,146 +41,159 @@ async function restoreVersion(args: Arguments): Prom req, } = args; - if (!id) { - throw new APIError('Missing ID of version to restore.', httpStatus.BAD_REQUEST); - } + try { + const shouldCommit = await initTransaction(req); - // ///////////////////////////////////// - // Retrieve original raw version - // ///////////////////////////////////// + if (!id) { + throw new APIError('Missing ID of version to restore.', httpStatus.BAD_REQUEST); + } - const { docs: versionDocs } = await req.payload.db.findVersions({ - collection: collectionConfig.slug, - where: { id: { equals: id } }, - locale, - limit: 1, - }); + // ///////////////////////////////////// + // Retrieve original raw version + // ///////////////////////////////////// - const [rawVersion] = versionDocs; - - if (!rawVersion) { - throw new NotFound(t); - } - - const parentDocID = rawVersion.parent; - - // ///////////////////////////////////// - // Access - // ///////////////////////////////////// - - const accessResults = !overrideAccess ? await executeAccess({ req, id: parentDocID }, collectionConfig.access.update) : true; - const hasWherePolicy = hasWhereAccessResult(accessResults); - - // ///////////////////////////////////// - // Retrieve document - // ///////////////////////////////////// - - const findOneArgs: FindOneArgs = { - collection: collectionConfig.slug, - where: combineQueries({ id: { equals: parentDocID } }, accessResults), - locale, - }; - - const doc = await req.payload.db.findOne(findOneArgs); - - - if (!doc && !hasWherePolicy) throw new NotFound(t); - if (!doc && hasWherePolicy) throw new Forbidden(t); - - // ///////////////////////////////////// - // fetch previousDoc - // ///////////////////////////////////// - - const prevDocWithLocales = await getLatestCollectionVersion({ - payload, - id: parentDocID, - query: findOneArgs, - config: collectionConfig, - }); - - // ///////////////////////////////////// - // Update - // ///////////////////////////////////// - - let result = await req.payload.db.updateOne({ - collection: collectionConfig.slug, - where: { id: { equals: parentDocID } }, - data: rawVersion.version, - req, - }); - - // ///////////////////////////////////// - // Save `previousDoc` as a version after restoring - // ///////////////////////////////////// - - const prevVersion = { ...prevDocWithLocales }; - - delete prevVersion.id; - - await payload.db.createVersion({ - collectionSlug: collectionConfig.slug, - parent: parentDocID, - versionData: rawVersion.version, - autosave: false, - createdAt: prevVersion.createdAt, - updatedAt: new Date().toISOString(), - }); - - // ///////////////////////////////////// - // afterRead - Fields - // ///////////////////////////////////// - - result = await afterRead({ - depth, - doc: result, - entityConfig: collectionConfig, - req, - overrideAccess, - showHiddenFields, - }); - - // ///////////////////////////////////// - // afterRead - Collection - // ///////////////////////////////////// - - await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => { - await priorHook; - - result = await hook({ + const { docs: versionDocs } = await req.payload.db.findVersions({ + collection: collectionConfig.slug, + where: { id: { equals: id } }, + locale, + limit: 1, req, - doc: result, - }) || result; - }, Promise.resolve()); + }); - // ///////////////////////////////////// - // afterChange - Fields - // ///////////////////////////////////// + const [rawVersion] = versionDocs; - result = await afterChange({ - data: result, - doc: result, - previousDoc: prevDocWithLocales, - entityConfig: collectionConfig, - operation: 'update', - req, - }); + if (!rawVersion) { + throw new NotFound(t); + } - // ///////////////////////////////////// - // afterChange - Collection - // ///////////////////////////////////// + const parentDocID = rawVersion.parent; - await collectionConfig.hooks.afterChange.reduce(async (priorHook, hook) => { - await priorHook; + // ///////////////////////////////////// + // Access + // ///////////////////////////////////// - result = await hook({ - doc: result, + const accessResults = !overrideAccess ? await executeAccess({ req, id: parentDocID }, collectionConfig.access.update) : true; + const hasWherePolicy = hasWhereAccessResult(accessResults); + + // ///////////////////////////////////// + // Retrieve document + // ///////////////////////////////////// + + const findOneArgs: FindOneArgs = { + collection: collectionConfig.slug, + where: combineQueries({ id: { equals: parentDocID } }, accessResults), + locale, req, + }; + + const doc = await req.payload.db.findOne(findOneArgs); + + + if (!doc && !hasWherePolicy) throw new NotFound(t); + if (!doc && hasWherePolicy) throw new Forbidden(t); + + // ///////////////////////////////////// + // fetch previousDoc + // ///////////////////////////////////// + + const prevDocWithLocales = await getLatestCollectionVersion({ + payload, + id: parentDocID, + query: findOneArgs, + config: collectionConfig, + req, + }); + + // ///////////////////////////////////// + // Update + // ///////////////////////////////////// + + let result = await req.payload.db.updateOne({ + collection: collectionConfig.slug, + where: { id: { equals: parentDocID } }, + data: rawVersion.version, + req, + }); + + // ///////////////////////////////////// + // Save `previousDoc` as a version after restoring + // ///////////////////////////////////// + + const prevVersion = { ...prevDocWithLocales }; + + delete prevVersion.id; + + await payload.db.createVersion({ + collectionSlug: collectionConfig.slug, + parent: parentDocID, + versionData: rawVersion.version, + autosave: false, + createdAt: prevVersion.createdAt, + updatedAt: new Date().toISOString(), + req, + }); + + // ///////////////////////////////////// + // afterRead - Fields + // ///////////////////////////////////// + + result = await afterRead({ + depth, + doc: result, + entityConfig: collectionConfig, + req, + overrideAccess, + showHiddenFields, + }); + + // ///////////////////////////////////// + // afterRead - Collection + // ///////////////////////////////////// + + await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => { + await priorHook; + + result = await hook({ + req, + doc: result, + }) || result; + }, Promise.resolve()); + + // ///////////////////////////////////// + // afterChange - Fields + // ///////////////////////////////////// + + result = await afterChange({ + data: result, + doc: result, previousDoc: prevDocWithLocales, + entityConfig: collectionConfig, operation: 'update', - }) || result; - }, Promise.resolve()); + req, + }); - return result; + // ///////////////////////////////////// + // afterChange - Collection + // ///////////////////////////////////// + + await collectionConfig.hooks.afterChange.reduce(async (priorHook, hook) => { + await priorHook; + + result = await hook({ + doc: result, + req, + previousDoc: prevDocWithLocales, + operation: 'update', + }) || result; + }, Promise.resolve()); + + if (shouldCommit) await payload.db.commitTransaction(req.transactionID); + + return result; + } catch (error: unknown) { + await killTransaction(req); + throw error; + } } export default restoreVersion; diff --git a/src/collections/operations/update.ts b/src/collections/operations/update.ts index baebe9b7e..8f008b857 100644 --- a/src/collections/operations/update.ts +++ b/src/collections/operations/update.ts @@ -20,6 +20,8 @@ import { validateQueryPaths } from '../../database/queryValidation/validateQuery import { combineQueries } from '../../database/combineQueries'; import { appendVersionToQueryKey } from '../../versions/drafts/appendVersionToQueryKey'; import { buildVersionCollectionFields } from '../../versions/buildCollectionFields'; +import { initTransaction } from '../../utilities/initTransaction'; +import { killTransaction } from '../../utilities/killTransaction'; export type Arguments = { collection: Collection @@ -37,20 +39,6 @@ async function update( incomingArgs: Arguments, ): Promise> { let args = incomingArgs; - - // ///////////////////////////////////// - // beforeOperation - Collection - // ///////////////////////////////////// - - await args.collection.config.hooks.beforeOperation.reduce(async (priorHook, hook) => { - await priorHook; - - args = (await hook({ - args, - operation: 'update', - })) || args; - }, Promise.resolve()); - const { depth, collection, @@ -73,283 +61,307 @@ async function update( draft: draftArg = false, } = args; - if (!where) { - throw new APIError('Missing \'where\' query of documents to update.', httpStatus.BAD_REQUEST); - } + try { + const shouldCommit = await initTransaction(req); - const { data: bulkUpdateData } = args; - const shouldSaveDraft = Boolean(draftArg && collectionConfig.versions.drafts); + // ///////////////////////////////////// + // beforeOperation - Collection + // ///////////////////////////////////// - // ///////////////////////////////////// - // Access - // ///////////////////////////////////// + await args.collection.config.hooks.beforeOperation.reduce(async (priorHook, hook) => { + await priorHook; - let accessResult: AccessResult; - if (!overrideAccess) { - accessResult = await executeAccess({ req }, collectionConfig.access.update); - } + args = (await hook({ + args, + operation: 'update', + })) || args; + }, Promise.resolve()); - await validateQueryPaths({ - collectionConfig, - where, - req, - overrideAccess, - }); + if (!where) { + throw new APIError('Missing \'where\' query of documents to update.', httpStatus.BAD_REQUEST); + } - // ///////////////////////////////////// - // Retrieve documents - // ///////////////////////////////////// + const { data: bulkUpdateData } = args; + const shouldSaveDraft = Boolean(draftArg && collectionConfig.versions.drafts); - const fullWhere = combineQueries(where, accessResult); + // ///////////////////////////////////// + // Access + // ///////////////////////////////////// - let docs; - - if (collectionConfig.versions?.drafts && shouldSaveDraft) { - const versionsWhere = appendVersionToQueryKey(fullWhere); + let accessResult: AccessResult; + if (!overrideAccess) { + accessResult = await executeAccess({ req }, collectionConfig.access.update); + } await validateQueryPaths({ - collectionConfig: collection.config, - where: versionsWhere, + collectionConfig, + where, req, overrideAccess, - versionFields: buildVersionCollectionFields(collection.config), }); - const query = await payload.db.queryDrafts({ - collection: collectionConfig.slug, - where: versionsWhere, - locale, - }); + // ///////////////////////////////////// + // Retrieve documents + // ///////////////////////////////////// - docs = query.docs; - } else { - const query = await payload.db.find({ - locale, - collection: collectionConfig.slug, - where: fullWhere, - pagination: false, - limit: 0, - }); + const fullWhere = combineQueries(where, accessResult); - docs = query.docs; - } + let docs; - // ///////////////////////////////////// - // Generate data for all files and sizes - // ///////////////////////////////////// + if (collectionConfig.versions?.drafts && shouldSaveDraft) { + const versionsWhere = appendVersionToQueryKey(fullWhere); - const { - data: newFileData, - files: filesToUpload, - } = await generateFileData({ - config, - collection, - req, - data: bulkUpdateData, - throwOnMissingFile: false, - overwriteExistingFiles, - }); - - const errors = []; - - const promises = docs.map(async (doc) => { - const { id } = doc; - let data = { - ...newFileData, - ...bulkUpdateData, - }; - - try { - const originalDoc = await afterRead({ - depth: 0, - doc, - entityConfig: collectionConfig, + await validateQueryPaths({ + collectionConfig: collection.config, + where: versionsWhere, req, - overrideAccess: true, - showHiddenFields: true, - }); - - await deleteAssociatedFiles({ config, collectionConfig, files: filesToUpload, doc, t, overrideDelete: false }); - - // ///////////////////////////////////// - // beforeValidate - Fields - // ///////////////////////////////////// - - data = await beforeValidate>({ - data, - doc: originalDoc, - entityConfig: collectionConfig, - id, - operation: 'update', overrideAccess, + versionFields: buildVersionCollectionFields(collection.config), + }); + + const query = await payload.db.queryDrafts({ + collection: collectionConfig.slug, + where: versionsWhere, + locale, req, }); - // ///////////////////////////////////// - // beforeValidate - Collection - // ///////////////////////////////////// - - await collectionConfig.hooks.beforeValidate.reduce(async (priorHook, hook) => { - await priorHook; - - data = (await hook({ - data, - req, - operation: 'update', - originalDoc, - })) || data; - }, Promise.resolve()); - - // ///////////////////////////////////// - // Write files to local storage - // ///////////////////////////////////// - - if (!collectionConfig.upload.disableLocalStorage) { - await uploadFiles(payload, filesToUpload, t); - } - - // ///////////////////////////////////// - // beforeChange - Collection - // ///////////////////////////////////// - - await collectionConfig.hooks.beforeChange.reduce(async (priorHook, hook) => { - await priorHook; - - data = (await hook({ - data, - req, - originalDoc, - operation: 'update', - })) || data; - }, Promise.resolve()); - - // ///////////////////////////////////// - // beforeChange - Fields - // ///////////////////////////////////// - - let result = await beforeChange({ - data, - doc: originalDoc, - docWithLocales: doc, - entityConfig: collectionConfig, - id, - operation: 'update', + docs = query.docs; + } else { + const query = await payload.db.find({ + locale, + collection: collectionConfig.slug, + where: fullWhere, + pagination: false, + limit: 0, req, - skipValidation: shouldSaveDraft || data._status === 'draft', }); - // ///////////////////////////////////// - // Update - // ///////////////////////////////////// + docs = query.docs; + } - if (!shouldSaveDraft) { - result = await req.payload.db.updateOne({ - collection: collectionConfig.slug, - locale, - where: { id: { equals: id } }, - data: result, + // ///////////////////////////////////// + // Generate data for all files and sizes + // ///////////////////////////////////// + + const { + data: newFileData, + files: filesToUpload, + } = await generateFileData({ + config, + collection, + req, + data: bulkUpdateData, + throwOnMissingFile: false, + overwriteExistingFiles, + }); + + const errors = []; + + const promises = docs.map(async (doc) => { + const { id } = doc; + let data = { + ...newFileData, + ...bulkUpdateData, + }; + + try { + const originalDoc = await afterRead({ + depth: 0, + doc, + entityConfig: collectionConfig, req, + overrideAccess: true, + showHiddenFields: true, }); - } - // ///////////////////////////////////// - // Create version - // ///////////////////////////////////// + await deleteAssociatedFiles({ config, collectionConfig, files: filesToUpload, doc, t, overrideDelete: false }); - if (collectionConfig.versions) { - result = await saveVersion({ - payload, - collection: collectionConfig, - req, - docWithLocales: { - ...result, - createdAt: doc.createdAt, - }, + // ///////////////////////////////////// + // beforeValidate - Fields + // ///////////////////////////////////// + + data = await beforeValidate>({ + data, + doc: originalDoc, + entityConfig: collectionConfig, id, - draft: shouldSaveDraft, - }); - } - - // ///////////////////////////////////// - // afterRead - Fields - // ///////////////////////////////////// - - result = await afterRead({ - depth, - doc: result, - entityConfig: collectionConfig, - req, - overrideAccess, - showHiddenFields, - }); - - // ///////////////////////////////////// - // afterRead - Collection - // ///////////////////////////////////// - - await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => { - await priorHook; - - result = await hook({ + operation: 'update', + overrideAccess, req, + }); + + // ///////////////////////////////////// + // beforeValidate - Collection + // ///////////////////////////////////// + + await collectionConfig.hooks.beforeValidate.reduce(async (priorHook, hook) => { + await priorHook; + + data = (await hook({ + data, + req, + operation: 'update', + originalDoc, + })) || data; + }, Promise.resolve()); + + // ///////////////////////////////////// + // Write files to local storage + // ///////////////////////////////////// + + if (!collectionConfig.upload.disableLocalStorage) { + await uploadFiles(payload, filesToUpload, t); + } + + // ///////////////////////////////////// + // beforeChange - Collection + // ///////////////////////////////////// + + await collectionConfig.hooks.beforeChange.reduce(async (priorHook, hook) => { + await priorHook; + + data = (await hook({ + data, + req, + originalDoc, + operation: 'update', + })) || data; + }, Promise.resolve()); + + // ///////////////////////////////////// + // beforeChange - Fields + // ///////////////////////////////////// + + let result = await beforeChange({ + data, + doc: originalDoc, + docWithLocales: doc, + entityConfig: collectionConfig, + id, + operation: 'update', + req, + skipValidation: shouldSaveDraft || data._status === 'draft', + }); + + // ///////////////////////////////////// + // Update + // ///////////////////////////////////// + + if (!shouldSaveDraft) { + result = await req.payload.db.updateOne({ + collection: collectionConfig.slug, + locale, + where: { id: { equals: id } }, + data: result, + req, + }); + } + + // ///////////////////////////////////// + // Create version + // ///////////////////////////////////// + + if (collectionConfig.versions) { + result = await saveVersion({ + payload, + collection: collectionConfig, + req, + docWithLocales: { + ...result, + createdAt: doc.createdAt, + }, + id, + draft: shouldSaveDraft, + }); + } + + // ///////////////////////////////////// + // afterRead - Fields + // ///////////////////////////////////// + + result = await afterRead({ + depth, doc: result, - }) || result; - }, Promise.resolve()); + entityConfig: collectionConfig, + req, + overrideAccess, + showHiddenFields, + }); - // ///////////////////////////////////// - // afterChange - Fields - // ///////////////////////////////////// + // ///////////////////////////////////// + // afterRead - Collection + // ///////////////////////////////////// - result = await afterChange({ - data, - doc: result, - previousDoc: originalDoc, - entityConfig: collectionConfig, - operation: 'update', - req, - }); + await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => { + await priorHook; - // ///////////////////////////////////// - // afterChange - Collection - // ///////////////////////////////////// + result = await hook({ + req, + doc: result, + }) || result; + }, Promise.resolve()); - await collectionConfig.hooks.afterChange.reduce(async (priorHook, hook) => { - await priorHook; + // ///////////////////////////////////// + // afterChange - Fields + // ///////////////////////////////////// - result = await hook({ + result = await afterChange({ + data, doc: result, previousDoc: originalDoc, - req, + entityConfig: collectionConfig, operation: 'update', - }) || result; - }, Promise.resolve()); + req, + }); - await unlinkTempFiles({ - req, - config, - collectionConfig, - }); + // ///////////////////////////////////// + // afterChange - Collection + // ///////////////////////////////////// - // ///////////////////////////////////// - // Return results - // ///////////////////////////////////// + await collectionConfig.hooks.afterChange.reduce(async (priorHook, hook) => { + await priorHook; - return result; - } catch (error) { - errors.push({ - message: error.message, - id, - }); - } - return null; - }); + result = await hook({ + doc: result, + previousDoc: originalDoc, + req, + operation: 'update', + }) || result; + }, Promise.resolve()); - const awaitedDocs = await Promise.all(promises); + await unlinkTempFiles({ + req, + config, + collectionConfig, + }); - return { - docs: awaitedDocs.filter(Boolean), - errors, - }; + // ///////////////////////////////////// + // Return results + // ///////////////////////////////////// + + return result; + } catch (error) { + errors.push({ + message: error.message, + id, + }); + } + return null; + }); + + const awaitedDocs = await Promise.all(promises); + + if (shouldCommit) await payload.db.commitTransaction(req.transactionID); + + return { + docs: awaitedDocs.filter(Boolean), + errors, + }; + } catch (error: unknown) { + await killTransaction(req); + throw error; + } } export default update; diff --git a/src/collections/operations/updateByID.ts b/src/collections/operations/updateByID.ts index f74c9aebf..ff4f7fd4d 100644 --- a/src/collections/operations/updateByID.ts +++ b/src/collections/operations/updateByID.ts @@ -19,6 +19,8 @@ import { unlinkTempFiles } from '../../uploads/unlinkTempFiles'; import { generatePasswordSaltHash } from '../../auth/strategies/local/generatePasswordSaltHash'; import { combineQueries } from '../../database/combineQueries'; import type { FindOneArgs } from '../../database/types'; +import { initTransaction } from '../../utilities/initTransaction'; +import { killTransaction } from '../../utilities/killTransaction'; export type Arguments = { collection: Collection @@ -38,20 +40,6 @@ async function updateByID( incomingArgs: Arguments, ): Promise { let args = incomingArgs; - - // ///////////////////////////////////// - // beforeOperation - Collection - // ///////////////////////////////////// - - await args.collection.config.hooks.beforeOperation.reduce(async (priorHook, hook) => { - await priorHook; - - args = (await hook({ - args, - operation: 'update', - })) || args; - }, Promise.resolve()); - const { depth, collection, @@ -75,253 +63,276 @@ async function updateByID( autosave = false, } = args; - if (!id) { - throw new APIError('Missing ID of document to update.', httpStatus.BAD_REQUEST); - } + try { + const shouldCommit = await initTransaction(req); - let { data } = args; - const { password } = data; - const shouldSaveDraft = Boolean(draftArg && collectionConfig.versions.drafts); - const shouldSavePassword = Boolean(password && collectionConfig.auth && !shouldSaveDraft); + // ///////////////////////////////////// + // beforeOperation - Collection + // ///////////////////////////////////// - // ///////////////////////////////////// - // Access - // ///////////////////////////////////// + await args.collection.config.hooks.beforeOperation.reduce(async (priorHook, hook) => { + await priorHook; - const accessResults = !overrideAccess ? await executeAccess({ req, id, data }, collectionConfig.access.update) : true; - const hasWherePolicy = hasWhereAccessResult(accessResults); + args = (await hook({ + args, + operation: 'update', + })) || args; + }, Promise.resolve()); - // ///////////////////////////////////// - // Retrieve document - // ///////////////////////////////////// + if (!id) { + throw new APIError('Missing ID of document to update.', httpStatus.BAD_REQUEST); + } + + let { data } = args; + const { password } = data; + const shouldSaveDraft = Boolean(draftArg && collectionConfig.versions.drafts); + const shouldSavePassword = Boolean(password && collectionConfig.auth && !shouldSaveDraft); + + // ///////////////////////////////////// + // Access + // ///////////////////////////////////// + + const accessResults = !overrideAccess ? await executeAccess({ req, id, data }, collectionConfig.access.update) : true; + const hasWherePolicy = hasWhereAccessResult(accessResults); + + // ///////////////////////////////////// + // Retrieve document + // ///////////////////////////////////// - const findOneArgs: FindOneArgs = { - collection: collectionConfig.slug, - where: combineQueries({ id: { equals: id } }, accessResults), - locale, - }; - - const docWithLocales = await getLatestCollectionVersion({ - payload, - config: collectionConfig, - id, - query: findOneArgs, - }); - - if (!docWithLocales && !hasWherePolicy) throw new NotFound(t); - if (!docWithLocales && hasWherePolicy) throw new Forbidden(t); - - - const originalDoc = await afterRead({ - depth: 0, - doc: docWithLocales, - entityConfig: collectionConfig, - req, - overrideAccess: true, - showHiddenFields: true, - }); - - // ///////////////////////////////////// - // Generate data for all files and sizes - // ///////////////////////////////////// - - const { data: newFileData, files: filesToUpload } = await generateFileData({ - config, - collection, - req, - data, - throwOnMissingFile: false, - overwriteExistingFiles, - }); - - data = newFileData; - - // ///////////////////////////////////// - // Delete any associated files - // ///////////////////////////////////// - - await deleteAssociatedFiles({ config, collectionConfig, files: filesToUpload, doc: docWithLocales, t, overrideDelete: false }); - - // ///////////////////////////////////// - // beforeValidate - Fields - // ///////////////////////////////////// - - data = await beforeValidate>({ - data, - doc: originalDoc, - entityConfig: collectionConfig, - id, - operation: 'update', - overrideAccess, - req, - }); - - // ///////////////////////////////////// - // beforeValidate - Collection - // ///////////////////////////////////// - - await collectionConfig.hooks.beforeValidate.reduce(async (priorHook, hook) => { - await priorHook; - - data = (await hook({ - data, - req, - operation: 'update', - originalDoc, - })) || data; - }, Promise.resolve()); - - // ///////////////////////////////////// - // Write files to local storage - // ///////////////////////////////////// - - if (!collectionConfig.upload.disableLocalStorage) { - await uploadFiles(payload, filesToUpload, t); - } - - // ///////////////////////////////////// - // beforeChange - Collection - // ///////////////////////////////////// - - await collectionConfig.hooks.beforeChange.reduce(async (priorHook, hook) => { - await priorHook; - - data = (await hook({ - data, - req, - originalDoc, - operation: 'update', - })) || data; - }, Promise.resolve()); - - // ///////////////////////////////////// - // beforeChange - Fields - // ///////////////////////////////////// - - let result = await beforeChange({ - data, - doc: originalDoc, - docWithLocales, - entityConfig: collectionConfig, - id, - operation: 'update', - req, - skipValidation: shouldSaveDraft || data._status === 'draft', - }); - - // ///////////////////////////////////// - // Handle potential password update - // ///////////////////////////////////// - - const dataToUpdate: Record = { ...result }; - - if (shouldSavePassword && typeof password === 'string') { - const { hash, salt } = await generatePasswordSaltHash({ password }); - dataToUpdate.salt = salt; - dataToUpdate.hash = hash; - delete data.password; - delete result.password; - } - - // ///////////////////////////////////// - // Update - // ///////////////////////////////////// - - if (!shouldSaveDraft) { - result = await req.payload.db.updateOne({ + const findOneArgs: FindOneArgs = { collection: collectionConfig.slug, + where: combineQueries({ id: { equals: id } }, accessResults), locale, - where: { id: { equals: id } }, - data: dataToUpdate, - req, - }); - } + }; - // ///////////////////////////////////// - // Create version - // ///////////////////////////////////// - - if (collectionConfig.versions) { - result = await saveVersion({ + const docWithLocales = await getLatestCollectionVersion({ payload, - collection: collectionConfig, - req, - docWithLocales: { - ...result, - createdAt: docWithLocales.createdAt, - }, + config: collectionConfig, id, - autosave, - draft: shouldSaveDraft, - }); - } - - // ///////////////////////////////////// - // afterRead - Fields - // ///////////////////////////////////// - - result = await afterRead({ - depth, - doc: result, - entityConfig: collectionConfig, - req, - overrideAccess, - showHiddenFields, - }); - - // ///////////////////////////////////// - // afterRead - Collection - // ///////////////////////////////////// - - await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => { - await priorHook; - - result = await hook({ + query: findOneArgs, req, + }); + + if (!docWithLocales && !hasWherePolicy) throw new NotFound(t); + if (!docWithLocales && hasWherePolicy) throw new Forbidden(t); + + + const originalDoc = await afterRead({ + depth: 0, + doc: docWithLocales, + entityConfig: collectionConfig, + req, + overrideAccess: true, + showHiddenFields: true, + }); + + // ///////////////////////////////////// + // Generate data for all files and sizes + // ///////////////////////////////////// + + const { data: newFileData, files: filesToUpload } = await generateFileData({ + config, + collection, + req, + data, + throwOnMissingFile: false, + overwriteExistingFiles, + }); + + data = newFileData; + + // ///////////////////////////////////// + // Delete any associated files + // ///////////////////////////////////// + + await deleteAssociatedFiles({ config, collectionConfig, files: filesToUpload, doc: docWithLocales, t, overrideDelete: false }); + + // ///////////////////////////////////// + // beforeValidate - Fields + // ///////////////////////////////////// + + data = await beforeValidate>({ + data, + doc: originalDoc, + entityConfig: collectionConfig, + id, + operation: 'update', + overrideAccess, + req, + }); + + // ///////////////////////////////////// + // beforeValidate - Collection + // ///////////////////////////////////// + + await collectionConfig.hooks.beforeValidate.reduce(async (priorHook, hook) => { + await priorHook; + + data = (await hook({ + data, + req, + operation: 'update', + originalDoc, + })) || data; + }, Promise.resolve()); + + // ///////////////////////////////////// + // Write files to local storage + // ///////////////////////////////////// + + if (!collectionConfig.upload.disableLocalStorage) { + await uploadFiles(payload, filesToUpload, t); + } + + // ///////////////////////////////////// + // beforeChange - Collection + // ///////////////////////////////////// + + await collectionConfig.hooks.beforeChange.reduce(async (priorHook, hook) => { + await priorHook; + + data = (await hook({ + data, + req, + originalDoc, + operation: 'update', + })) || data; + }, Promise.resolve()); + + // ///////////////////////////////////// + // beforeChange - Fields + // ///////////////////////////////////// + + let result = await beforeChange({ + data, + doc: originalDoc, + docWithLocales, + entityConfig: collectionConfig, + id, + operation: 'update', + req, + skipValidation: shouldSaveDraft || data._status === 'draft', + }); + + // ///////////////////////////////////// + // Handle potential password update + // ///////////////////////////////////// + + const dataToUpdate: Record = { ...result }; + + if (shouldSavePassword && typeof password === 'string') { + const { hash, salt } = await generatePasswordSaltHash({ password }); + dataToUpdate.salt = salt; + dataToUpdate.hash = hash; + delete data.password; + delete result.password; + } + + // ///////////////////////////////////// + // Update + // ///////////////////////////////////// + + if (!shouldSaveDraft) { + result = await req.payload.db.updateOne({ + collection: collectionConfig.slug, + locale, + where: { id: { equals: id } }, + data: dataToUpdate, + req, + }); + } + + // ///////////////////////////////////// + // Create version + // ///////////////////////////////////// + + if (collectionConfig.versions) { + result = await saveVersion({ + payload, + collection: collectionConfig, + req, + docWithLocales: { + ...result, + createdAt: docWithLocales.createdAt, + }, + id, + autosave, + draft: shouldSaveDraft, + }); + } + + // ///////////////////////////////////// + // afterRead - Fields + // ///////////////////////////////////// + + result = await afterRead({ + depth, doc: result, - }) || result; - }, Promise.resolve()); + entityConfig: collectionConfig, + req, + overrideAccess, + showHiddenFields, + }); - // ///////////////////////////////////// - // afterChange - Fields - // ///////////////////////////////////// + // ///////////////////////////////////// + // afterRead - Collection + // ///////////////////////////////////// - result = await afterChange({ - data, - doc: result, - previousDoc: originalDoc, - entityConfig: collectionConfig, - operation: 'update', - req, - }); + await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => { + await priorHook; - // ///////////////////////////////////// - // afterChange - Collection - // ///////////////////////////////////// + result = await hook({ + req, + doc: result, + }) || result; + }, Promise.resolve()); - await collectionConfig.hooks.afterChange.reduce(async (priorHook, hook) => { - await priorHook; + // ///////////////////////////////////// + // afterChange - Fields + // ///////////////////////////////////// - result = await hook({ + result = await afterChange({ + data, doc: result, previousDoc: originalDoc, - req, + entityConfig: collectionConfig, operation: 'update', - }) || result; - }, Promise.resolve()); + req, + }); - await unlinkTempFiles({ - req, - config, - collectionConfig, - }); + // ///////////////////////////////////// + // afterChange - Collection + // ///////////////////////////////////// - // ///////////////////////////////////// - // Return results - // ///////////////////////////////////// + await collectionConfig.hooks.afterChange.reduce(async (priorHook, hook) => { + await priorHook; - return result; + result = await hook({ + doc: result, + previousDoc: originalDoc, + req, + operation: 'update', + }) || result; + }, Promise.resolve()); + + await unlinkTempFiles({ + req, + config, + collectionConfig, + }); + + // ///////////////////////////////////// + // Return results + // ///////////////////////////////////// + + if (shouldCommit) await payload.db.commitTransaction(req.transactionID); + + return result; + } catch (error: unknown) { + await killTransaction(req); + throw error; + } } export default updateByID; diff --git a/src/collections/requestHandlers/create.ts b/src/collections/requestHandlers/create.ts index fc30fddc2..7a9ed3088 100644 --- a/src/collections/requestHandlers/create.ts +++ b/src/collections/requestHandlers/create.ts @@ -1,5 +1,5 @@ import httpStatus from 'http-status'; -import { Response, NextFunction } from 'express'; +import { NextFunction, Response } from 'express'; import { PayloadRequest } from '../../express/types'; import formatSuccessResponse from '../../express/responses/formatSuccess'; import { Document } from '../../types'; @@ -25,11 +25,11 @@ export default async function createHandler(req: PayloadRequest, res: Response, autosave, }); - return res.status(httpStatus.CREATED).json({ + res.status(httpStatus.CREATED).json({ ...formatSuccessResponse(req.t('general:successfullyCreated', { label: getTranslation(req.collection.config.labels.singular, req.i18n) }), 'message'), doc, }); } catch (error) { - return next(error); + next(error); } } diff --git a/src/collections/requestHandlers/delete.ts b/src/collections/requestHandlers/delete.ts index 99012a7b6..62dd945ee 100644 --- a/src/collections/requestHandlers/delete.ts +++ b/src/collections/requestHandlers/delete.ts @@ -1,4 +1,4 @@ -import { Response, NextFunction } from 'express'; +import { NextFunction, Response } from 'express'; import httpStatus from 'http-status'; import { PayloadRequest } from '../../express/types'; import { Document, Where } from '../../types'; @@ -26,10 +26,11 @@ export default async function deleteHandler(req: PayloadRequest, res: Response, label: getTranslation(req.collection.config.labels[result.docs.length > 1 ? 'plural' : 'singular'], req.i18n), }); - return res.status(httpStatus.OK).json({ + res.status(httpStatus.OK).json({ ...formatSuccessResponse(message, 'message'), ...result, }); + return; } const total = result.docs.length + result.errors.length; @@ -39,11 +40,11 @@ export default async function deleteHandler(req: PayloadRequest, res: Response, label: getTranslation(req.collection.config.labels[total > 1 ? 'plural' : 'singular'], req.i18n), }); - return res.status(httpStatus.BAD_REQUEST).json({ + res.status(httpStatus.BAD_REQUEST).json({ message, ...result, }); } catch (error) { - return next(error); + next(error); } } diff --git a/src/collections/requestHandlers/deleteByID.ts b/src/collections/requestHandlers/deleteByID.ts index c56523d36..c0468b796 100644 --- a/src/collections/requestHandlers/deleteByID.ts +++ b/src/collections/requestHandlers/deleteByID.ts @@ -1,4 +1,4 @@ -import { Response, NextFunction } from 'express'; +import { NextFunction, Response } from 'express'; import httpStatus from 'http-status'; import { PayloadRequest } from '../../express/types'; import { NotFound } from '../../errors'; @@ -20,11 +20,13 @@ export default async function deleteByIDHandler(req: PayloadRequest, res: Respon }); if (!doc) { - return res.status(httpStatus.NOT_FOUND).json(new NotFound(req.t)); + res.status(httpStatus.NOT_FOUND) + .json(new NotFound(req.t)); } - return res.status(httpStatus.OK).send(doc); + res.status(httpStatus.OK) + .send(doc); } catch (error) { - return next(error); + next(error); } } diff --git a/src/collections/requestHandlers/restoreVersion.ts b/src/collections/requestHandlers/restoreVersion.ts index 54fa60f96..c025b3408 100644 --- a/src/collections/requestHandlers/restoreVersion.ts +++ b/src/collections/requestHandlers/restoreVersion.ts @@ -1,4 +1,4 @@ -import { Response, NextFunction } from 'express'; +import { NextFunction, Response } from 'express'; import httpStatus from 'http-status'; import { PayloadRequest } from '../../express/types'; import { Document } from '../../types'; @@ -21,11 +21,12 @@ export default async function restoreVersionHandler(req: PayloadRequest, res: Re try { const doc = await restoreVersion(options); - return res.status(httpStatus.OK).json({ - ...formatSuccessResponse(req.t('version:restoredSuccessfully'), 'message'), - doc, - }); + res.status(httpStatus.OK) + .json({ + ...formatSuccessResponse(req.t('version:restoredSuccessfully'), 'message'), + doc, + }); } catch (error) { - return next(error); + next(error); } } diff --git a/src/collections/requestHandlers/update.ts b/src/collections/requestHandlers/update.ts index 4af136cc0..cb90be214 100644 --- a/src/collections/requestHandlers/update.ts +++ b/src/collections/requestHandlers/update.ts @@ -1,6 +1,6 @@ -import { Response, NextFunction } from 'express'; +import { NextFunction, Response } from 'express'; import httpStatus from 'http-status'; -import { Where, Document } from '../../types'; +import { Document, Where } from '../../types'; import { PayloadRequest } from '../../express/types'; import formatSuccessResponse from '../../express/responses/formatSuccess'; import update from '../operations/update'; @@ -30,10 +30,12 @@ export default async function updateHandler(req: PayloadRequest, res: Response, label: getTranslation(req.collection.config.labels[result.docs.length > 1 ? 'plural' : 'singular'], req.i18n), }); - return res.status(httpStatus.OK).json({ - ...formatSuccessResponse(message, 'message'), - ...result, - }); + res.status(httpStatus.OK) + .json({ + ...formatSuccessResponse(message, 'message'), + ...result, + }); + return; } const total = result.docs.length + result.errors.length; @@ -43,11 +45,13 @@ export default async function updateHandler(req: PayloadRequest, res: Response, label: getTranslation(req.collection.config.labels[total > 1 ? 'plural' : 'singular'], req.i18n), }); - return res.status(httpStatus.BAD_REQUEST).json({ - ...formatSuccessResponse(message, 'message'), - ...result, - }); + + res.status(httpStatus.BAD_REQUEST) + .json({ + ...formatSuccessResponse(message, 'message'), + ...result, + }); } catch (error) { - return next(error); + next(error); } } diff --git a/src/collections/requestHandlers/updateByID.ts b/src/collections/requestHandlers/updateByID.ts index e88ecb3e3..f9a0616b5 100644 --- a/src/collections/requestHandlers/updateByID.ts +++ b/src/collections/requestHandlers/updateByID.ts @@ -1,4 +1,4 @@ -import { Response, NextFunction } from 'express'; +import { NextFunction, Response } from 'express'; import httpStatus from 'http-status'; import { PayloadRequest } from '../../express/types'; import formatSuccessResponse from '../../express/responses/formatSuccess'; @@ -35,11 +35,11 @@ export default async function updateByIDHandler(req: PayloadRequest, res: Respon if (draft) message = req.t('version:draftSavedSuccessfully'); if (autosave) message = req.t('version:autosavedSuccessfully'); - return res.status(httpStatus.OK).json({ + res.status(httpStatus.OK).json({ ...formatSuccessResponse(message, 'message'), doc, }); } catch (error) { - return next(error); + next(error); } } diff --git a/src/config/schema.ts b/src/config/schema.ts index 6e6d68b54..b1d3b3b45 100644 --- a/src/config/schema.ts +++ b/src/config/schema.ts @@ -70,6 +70,14 @@ export default joi.object({ ), logoutRoute: joi.string(), inactivityRoute: joi.string(), + autoLogin: joi.alternatives() + .try( + joi.object().keys({ + email: joi.string(), + password: joi.string(), + }), + joi.boolean(), + ), components: joi.object() .keys({ routes: joi.array() diff --git a/src/config/types.ts b/src/config/types.ts index b63b79440..cead22b99 100644 --- a/src/config/types.ts +++ b/src/config/types.ts @@ -7,7 +7,7 @@ import SMTPConnection from 'nodemailer/lib/smtp-connection'; import GraphQL from 'graphql'; import { ConnectOptions } from 'mongoose'; import React from 'react'; -import { LoggerOptions } from 'pino'; +import { DestinationStream, LoggerOptions } from 'pino'; import type { InitOptions as i18nInitOptions } from 'i18next'; import { Payload } from '../payload'; import { @@ -117,7 +117,14 @@ export type InitOptions = { * See Pino Docs for options: https://getpino.io/#/docs/api?id=options */ loggerOptions?: LoggerOptions; - config?: Promise + loggerDestination?: DestinationStream; + + /** + * Sometimes, with the local API, you might need to pass a config file directly, for example, serverless on Vercel + * The passed config should match the config file, and if it doesn't, there could be mismatches between the admin UI + * and the backend functionality + */ + config?: Promise; }; /** @@ -276,6 +283,13 @@ export type Config = { logoutRoute?: string; /** The route the user will be redirected to after being inactive for too long. */ inactivityRoute?: string; + /** Automatically log in as a user when visiting the admin dashboard. */ + autoLogin?: false | { + /** The email address of the user to login as */ + email: string; + /** The password of the user to login as */ + password: string; + } /** * Add extra and/or replace built-in components with custom components * diff --git a/src/database/baseDatabaseAdapter.ts b/src/database/baseDatabaseAdapter.ts new file mode 100644 index 000000000..b112c754d --- /dev/null +++ b/src/database/baseDatabaseAdapter.ts @@ -0,0 +1,44 @@ +import { transaction } from './transaction'; +import { migrate } from './migrations/migrate'; +import { migrateStatus } from './migrations/migrateStatus'; +import { migrateDown } from './migrations/migrateDown'; +import { migrateRefresh } from './migrations/migrateRefresh'; +import { migrateReset } from './migrations/migrateReset'; +import { DatabaseAdapter } from './types'; +import type { Payload } from '../index'; +import { createMigration } from './migrations/createMigration'; + + +type BaseDatabaseAdapter = Pick + +type Args = { + payload: Payload, + migrationDir?: string, +} +export function baseDatabaseAdapter({ + payload, + migrationDir = '.migrations', +}: Args): BaseDatabaseAdapter { + return { + payload, + transaction, + migrate, + createMigration, + migrateStatus, + migrateDown, + migrateRefresh, + migrateReset, + migrateFresh: async () => null, + migrationDir, + }; +} diff --git a/src/database/migrations/createMigration.ts b/src/database/migrations/createMigration.ts index e9ad40cc8..4c3c638e2 100644 --- a/src/database/migrations/createMigration.ts +++ b/src/database/migrations/createMigration.ts @@ -1,15 +1,13 @@ /* eslint-disable no-restricted-syntax, no-await-in-loop */ import fs from 'fs'; import { migrationTemplate } from './migrationTemplate'; -import { Payload } from '../..'; +import { CreateMigration } from '../types'; -type CreateMigrationArgs = { - payload: Payload - migrationDir: string - migrationName: string -} - -export async function createMigration({ payload, migrationDir, migrationName }: CreateMigrationArgs) { +export const createMigration: CreateMigration = async function createMigration({ + payload, + migrationDir, + migrationName, +}) { const dir = migrationDir || '.migrations'; // TODO: Verify path after linking if (!fs.existsSync(dir)) { fs.mkdirSync(dir); @@ -24,9 +22,6 @@ export async function createMigration({ payload, migrationDir, migrationName }: const formattedName = migrationName.replace(/\W/g, '_'); const fileName = `${timestamp}_${formattedName}.ts`; const filePath = `${dir}/${fileName}`; - fs.writeFileSync( - filePath, - migrationTemplate, - ); + fs.writeFileSync(filePath, migrationTemplate); payload.logger.info({ msg: `Migration created at ${filePath}` }); -} +}; diff --git a/src/database/migrations/migrate.ts b/src/database/migrations/migrate.ts index 2b7e69b81..e4333960c 100644 --- a/src/database/migrations/migrate.ts +++ b/src/database/migrations/migrate.ts @@ -2,6 +2,7 @@ import { DatabaseAdapter } from '../types'; import { getMigrations } from './getMigrations'; import { readMigrationFiles } from './readMigrationFiles'; +import { PayloadRequest } from '../../express/types'; export async function migrate(this: DatabaseAdapter): Promise { const { payload } = this; @@ -19,22 +20,29 @@ export async function migrate(this: DatabaseAdapter): Promise { continue; // eslint-disable-line no-continue } - payload.logger.info({ msg: `Migrating: ${migration.name}` }); const start = Date.now(); + let transactionID; + try { + payload.logger.info({ msg: `Migrating: ${migration.name}` }); + transactionID = await this.beginTransaction(); await migration.up({ payload }); payload.logger.info({ msg: `Migrated: ${migration.name} (${Date.now() - start}ms)` }); + await payload.create({ + collection: 'payload-migrations', + data: { + name: migration.name, + batch: newBatch, + }, + req: { + transactionID, + } as PayloadRequest, + }); + await this.commitTransaction(transactionID); } catch (err: unknown) { + await this.rollbackTransaction(transactionID); payload.logger.error({ msg: `Error running migration ${migration.name}`, err }); throw err; } - - await payload.create({ - collection: 'payload-migrations', - data: { - name: migration.name, - batch: newBatch, - }, - }); } } diff --git a/src/database/migrations/migrateDown.ts b/src/database/migrations/migrateDown.ts index c39446a73..27ed2daca 100644 --- a/src/database/migrations/migrateDown.ts +++ b/src/database/migrations/migrateDown.ts @@ -2,12 +2,16 @@ import { DatabaseAdapter } from '../types'; import { getMigrations } from './getMigrations'; import { readMigrationFiles } from './readMigrationFiles'; +import { PayloadRequest } from '../../express/types'; export async function migrateDown(this: DatabaseAdapter): Promise { const { payload } = this; const migrationFiles = await readMigrationFiles({ payload }); - const { existingMigrations, latestBatch } = await getMigrations({ + const { + existingMigrations, + latestBatch, + } = await getMigrations({ payload, }); @@ -25,19 +29,28 @@ export async function migrateDown(this: DatabaseAdapter): Promise { throw new Error(`Migration ${migration.name} not found locally.`); } + const start = Date.now(); + let transactionID; + try { payload.logger.info({ msg: `Migrating: ${migrationFile.name}` }); - const start = Date.now(); + transactionID = await this.beginTransaction(); await migrationFile.down({ payload }); - payload.logger.info({ msg: `Migrated: ${migrationFile.name} (${Date.now() - start}ms)` }); - await payload.delete({ collection: 'payload-migrations', id: migration.id, + req: { + transactionID, + } as PayloadRequest, }); + await this.commitTransaction(transactionID); } catch (err: unknown) { - payload.logger.error({ msg: `Error running migration ${migrationFile.name}`, err }); + await this.rollbackTransaction(transactionID); + payload.logger.error({ + msg: `Error running migration ${migrationFile.name}`, + err, + }); throw err; } } diff --git a/src/database/migrations/migrateRefresh.ts b/src/database/migrations/migrateRefresh.ts index eb86f7b5b..dc350c3bf 100644 --- a/src/database/migrations/migrateRefresh.ts +++ b/src/database/migrations/migrateRefresh.ts @@ -1,6 +1,7 @@ /* eslint-disable no-restricted-syntax, no-await-in-loop */ import { DatabaseAdapter } from '../types'; import { readMigrationFiles } from './readMigrationFiles'; +import { PayloadRequest } from '../../express/types'; /** * Reset and re-run all migrations. @@ -14,25 +15,34 @@ export async function migrateRefresh(this: DatabaseAdapter) { collection: 'payload-migrations', where: {}, // All migrations }); - + let transactionID; // Run all migrations for (const migration of migrationFiles) { payload.logger.info({ msg: `Migrating: ${migration.name}` }); try { const start = Date.now(); + transactionID = await this.beginTransaction(); await migration.up({ payload }); + await payload.create({ + collection: 'payload-migrations', + data: { + name: migration.name, + executed: true, + }, + req: { + transactionID, + } as PayloadRequest, + }); + await this.commitTransaction(transactionID); + payload.logger.info({ msg: `Migrated: ${migration.name} (${Date.now() - start}ms)` }); } catch (err: unknown) { - payload.logger.error({ msg: `Error running migration ${migration.name}`, err }); + await this.rollbackTransaction(transactionID); + payload.logger.error({ + msg: `Error running migration ${migration.name}`, + err, + }); throw err; } - - await payload.create({ - collection: 'payload-migrations', - data: { - name: migration.name, - executed: true, - }, - }); } } diff --git a/src/database/migrations/migrateReset.ts b/src/database/migrations/migrateReset.ts index c00690dbb..c9ce3eb5e 100644 --- a/src/database/migrations/migrateReset.ts +++ b/src/database/migrations/migrateReset.ts @@ -2,6 +2,7 @@ import { DatabaseAdapter } from '../types'; import { getMigrations } from './getMigrations'; import { readMigrationFiles } from './readMigrationFiles'; +import { PayloadRequest } from '../../express/types'; export async function migrateReset(this: DatabaseAdapter): Promise { const { payload } = this; @@ -14,6 +15,8 @@ export async function migrateReset(this: DatabaseAdapter): Promise { return; } + let transactionID; + // Rollback all migrations in order for (const migration of migrationFiles) { // Create or update migration in database @@ -22,21 +25,24 @@ export async function migrateReset(this: DatabaseAdapter): Promise { payload.logger.info({ msg: `Migrating: ${migration.name}` }); try { const start = Date.now(); + transactionID = await this.beginTransaction(); await migration.down({ payload }); + await payload.delete({ + collection: 'payload-migrations', + where: { + id: { + equals: existingMigration.id, + }, + }, + req: { transactionID } as PayloadRequest, + }); + await this.commitTransaction(transactionID); payload.logger.info({ msg: `Migrated: ${migration.name} (${Date.now() - start}ms)` }); } catch (err: unknown) { + await this.rollbackTransaction(transactionID); payload.logger.error({ msg: `Error running migration ${migration.name}`, err }); throw err; } - - await payload.delete({ - collection: 'payload-migrations', - where: { - id: { - equals: existingMigration.id, - }, - }, - }); } } } diff --git a/src/database/transaction.ts b/src/database/transaction.ts new file mode 100644 index 000000000..8bb1bc778 --- /dev/null +++ b/src/database/transaction.ts @@ -0,0 +1,14 @@ +import { Transaction } from './types'; + +export const transaction: Transaction = async function transaction( + callback: () => Promise, + options, +) { + const id = await this.beginTransaction(options); + try { + await callback(); + await this.commitTransaction(id); + } catch (err: unknown) { + await this.rollbackTransaction(id); + } +}; diff --git a/src/database/types.ts b/src/database/types.ts index 87a714d17..98fb863fe 100644 --- a/src/database/types.ts +++ b/src/database/types.ts @@ -48,7 +48,7 @@ export interface DatabaseAdapter { /** * Terminate the connection with the database */ - destroy?: () => Promise; + destroy?: Destroy; /** * Used to alias server only modules or make other changes to webpack configuration @@ -59,12 +59,12 @@ export interface DatabaseAdapter { /** * Path to read and write migration files from */ - migrationDir: string; + migrationDir?: string; /** * Output a migration file */ - createMigration: (migrationName: string) => Promise; + createMigration: (CreateMigrationArgs) => Promise; /** * Run any migration up functions that have not yet been performed and update the status @@ -97,25 +97,31 @@ export interface DatabaseAdapter { migrateFresh: () => Promise; // transactions + /** + * assign the transaction to use when making queries, defaults to the last started transaction + */ + useTransaction?: (id: string | number) => void; + /** * Perform many database interactions in a single, all-or-nothing operation. */ - transaction?: () => Promise; + transaction?: Transaction; /** - * Start a transaction, requiring commit() to be called for any changes to be made. + * Start a transaction, requiring commitTransaction() to be called for any changes to be made. + * @returns an identifier for the transaction or null if one cannot be established */ - beginTransaction?: () => Promise; + beginTransaction?: BeginTransaction; /** - * Cancel any changes since the beginning of the transaction. + * Abort any changes since the start of the transaction. */ - rollbackTransaction?: () => Promise; + rollbackTransaction?: RollbackTransaction; /** - * Instruct the database to complete the changes made in the transaction. + * Persist the changes made since the start of the transaction. */ - commitTransaction?: () => Promise; + commitTransaction?: CommitTransaction; queryDrafts: QueryDrafts; @@ -142,12 +148,30 @@ export interface DatabaseAdapter { deleteVersions: DeleteVersions; } -export type Init = ({ config }: { config: SanitizedConfig }) => Promise; +export type Init = (payload: Payload) => Promise; -export type Connect = ({ config }: { config: SanitizedConfig }) => Promise +export type Connect = (payload: Payload) => Promise + +export type Destroy = (payload: Payload) => Promise export type Webpack = (config: Configuration) => Configuration; +export type CreateMigrationArgs = { + payload: Payload + migrationDir: string + migrationName: string +} + +export type CreateMigration = (args: CreateMigrationArgs) => Promise + +export type Transaction = (callback: () => Promise, options?: Record) => Promise + +export type BeginTransaction = (options?: Record) => Promise + +export type RollbackTransaction = (id: string | number) => Promise + +export type CommitTransaction = (id: string | number) => Promise + export type QueryDraftsArgs = { collection: string where?: Where @@ -156,6 +180,7 @@ export type QueryDraftsArgs = { pagination?: boolean sort?: string locale?: string + req?: PayloadRequest } export type QueryDrafts = (args: QueryDraftsArgs) => Promise>; @@ -164,6 +189,7 @@ export type FindOneArgs = { collection: string where?: Where locale?: string + req?: PayloadRequest } @@ -180,6 +206,7 @@ export type FindArgs = { pagination?: boolean sort?: string locale?: string + req?: PayloadRequest } export type Find = (args: FindArgs) => Promise>; @@ -194,6 +221,7 @@ export type FindVersionsArgs = { pagination?: boolean sort?: string locale?: string + req?: PayloadRequest } export type FindVersions = (args: FindVersionsArgs) => Promise>>; @@ -209,12 +237,14 @@ export type FindGlobalVersionsArgs = { pagination?: boolean sort?: string locale?: string + req?: PayloadRequest } export type FindGlobalArgs = { slug: string locale?: string where?: Where + req?: PayloadRequest } export type FindGlobal = (args: FindGlobalArgs) => Promise @@ -223,6 +253,7 @@ export type FindGlobal = (args: FindGlobalArg export type CreateGlobalArgs = { slug: string data: T + req?: PayloadRequest } export type CreateGlobal = (args: CreateGlobalArgs) => Promise @@ -230,9 +261,10 @@ export type CreateGlobal = (args: CreateGloba export type UpdateGlobalArgs = { slug: string data: T + req?: PayloadRequest } export type UpdateGlobal = (args: UpdateGlobalArgs) => Promise - +// export type UpdateOne = (args: UpdateOneArgs) => Promise export type FindGlobalVersions = (args: FindGlobalVersionsArgs) => Promise>>; @@ -243,6 +275,7 @@ export type DeleteVersionsArgs = { sort?: { [key: string]: string } + req?: PayloadRequest }; export type CreateVersionArgs = { @@ -253,6 +286,7 @@ export type CreateVersionArgs = { autosave: boolean createdAt: string updatedAt: string + req?: PayloadRequest } export type CreateVersion = (args: CreateVersionArgs) => Promise>; @@ -261,10 +295,11 @@ export type DeleteVersions = (args: DeleteVersionsArgs) => Promise; export type UpdateVersionArgs = { - collectionSlug: string, - where: Where, - locale?: string, + collectionSlug: string + where: Where + locale?: string versionData: T + req?: PayloadRequest } export type UpdateVersion = (args: UpdateVersionArgs) => Promise> @@ -275,7 +310,7 @@ export type CreateArgs = { data: Record draft?: boolean locale?: string - req: PayloadRequest + req?: PayloadRequest } export type Create = (args: CreateArgs) => Promise @@ -286,7 +321,7 @@ export type UpdateArgs = { where: Where draft?: boolean locale?: string - req: PayloadRequest + req?: PayloadRequest } export type Update = (args: UpdateArgs) => Promise @@ -297,7 +332,7 @@ export type UpdateOneArgs = { where: Where draft?: boolean locale?: string - req: PayloadRequest + req?: PayloadRequest } export type UpdateOne = (args: UpdateOneArgs) => Promise @@ -305,7 +340,7 @@ export type UpdateOne = (args: UpdateOneArgs) => Promise export type DeleteOneArgs = { collection: string where: Where - req: PayloadRequest + req?: PayloadRequest } export type DeleteOne = (args: DeleteOneArgs) => Promise @@ -313,7 +348,7 @@ export type DeleteOne = (args: DeleteOneArgs) => Promise export type DeleteManyArgs = { collection: string where: Where - req: PayloadRequest | null + req?: PayloadRequest } export type DeleteMany = (args: DeleteManyArgs) => Promise diff --git a/src/express/types.ts b/src/express/types.ts index 375e649f1..87f8065fa 100644 --- a/src/express/types.ts +++ b/src/express/types.ts @@ -28,6 +28,10 @@ export declare type PayloadRequest = Request & { collection?: Collection; /** What triggered this request */ payloadAPI?: 'REST' | 'local' | 'GraphQL'; + /** + * Identifier for the database transaction for interactions in a single, all-or-nothing operation. + */ + transactionID?: string | number; /** Uploaded files */ files?: { /** @@ -46,6 +50,8 @@ export declare type PayloadRequest = Request & { payloadUploadSizes?: Record; /** Cache of documents related to the current request */ findByID?: { - [slug: string]: (q: FindOneArgs) => Promise; + [transactionID: string]: { + [slug: string]: (q: FindOneArgs) => Promise; + } }; }; diff --git a/src/fields/hooks/afterRead/promise.ts b/src/fields/hooks/afterRead/promise.ts index 5aaa02e19..417cf1864 100644 --- a/src/fields/hooks/afterRead/promise.ts +++ b/src/fields/hooks/afterRead/promise.ts @@ -252,6 +252,27 @@ export const promise = async ({ showHiddenFields, }); }); + } else if (!shouldHoistLocalizedValue && typeof rows === 'object' && rows !== null) { + Object.values(rows).forEach((localeRows) => { + if (Array.isArray(localeRows)) { + localeRows.forEach((row) => { + traverseFields({ + currentDepth, + depth, + doc, + fields: field.fields, + fieldPromises, + findMany, + flattenLocales, + overrideAccess, + populationPromises, + req, + siblingDoc: row || {}, + showHiddenFields, + }); + }); + } + }); } break; } @@ -280,6 +301,31 @@ export const promise = async ({ }); } }); + } else if (!shouldHoistLocalizedValue && typeof rows === 'object' && rows !== null) { + Object.values(rows).forEach((localeRows) => { + if (Array.isArray(localeRows)) { + localeRows.forEach((row) => { + const block = field.blocks.find((blockType) => blockType.slug === row.blockType); + + if (block) { + traverseFields({ + currentDepth, + depth, + doc, + fields: block.fields, + fieldPromises, + findMany, + flattenLocales, + overrideAccess, + populationPromises, + req, + siblingDoc: row || {}, + showHiddenFields, + }); + } + }); + } + }); } break; diff --git a/src/fields/hooks/afterRead/relationshipPopulationPromise.ts b/src/fields/hooks/afterRead/relationshipPopulationPromise.ts index 28578189b..d1e4f23c0 100644 --- a/src/fields/hooks/afterRead/relationshipPopulationPromise.ts +++ b/src/fields/hooks/afterRead/relationshipPopulationPromise.ts @@ -1,5 +1,5 @@ import { PayloadRequest } from '../../../express/types'; -import { RelationshipField, fieldSupportsMany, fieldHasMaxDepth, UploadField } from '../../config/types'; +import { fieldHasMaxDepth, fieldSupportsMany, RelationshipField, UploadField } from '../../config/types'; type PopulateArgs = { depth: number @@ -41,6 +41,7 @@ const populate = async ({ if (shouldPopulate) { relationshipValue = await req.payloadDataLoader.load(JSON.stringify([ + req.transactionID, relatedCollection.config.slug, id, depth, diff --git a/src/fields/richText/populate.ts b/src/fields/richText/populate.ts index 9fd4f5c02..fdd0bf5d2 100644 --- a/src/fields/richText/populate.ts +++ b/src/fields/richText/populate.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ import { Collection } from '../../collections/config/types'; -import { RichTextField, Field } from '../config/types'; +import { Field, RichTextField } from '../config/types'; import { PayloadRequest } from '../../express/types'; type Arguments = { @@ -32,6 +32,7 @@ export const populate = async ({ const dataRef = data as Record; const doc = await req.payloadDataLoader.load(JSON.stringify([ + req.transactionID, collection.config.slug, id, depth, diff --git a/src/globals/initLocal.ts b/src/globals/initLocal.ts new file mode 100644 index 000000000..e69de29bb diff --git a/src/globals/operations/findOne.ts b/src/globals/operations/findOne.ts index 3e6569e76..00efa4df7 100644 --- a/src/globals/operations/findOne.ts +++ b/src/globals/operations/findOne.ts @@ -5,6 +5,8 @@ import replaceWithDraftIfAvailable from '../../versions/drafts/replaceWithDraftI import { afterRead } from '../../fields/hooks/afterRead'; import { SanitizedGlobalConfig } from '../config/types'; import { PayloadRequest } from '../../express/types'; +import { initTransaction } from '../../utilities/initTransaction'; +import { killTransaction } from '../../utilities/killTransaction'; type Args = { globalConfig: SanitizedGlobalConfig @@ -22,6 +24,7 @@ async function findOne>(args: Args): Promise>(args: Args): Promise { + await priorHook; + + doc = await hook({ + req, + doc, + }) || doc; + }, Promise.resolve()); + + // ///////////////////////////////////// + // Execute field-level hooks and access + // ///////////////////////////////////// + + doc = await afterRead({ + depth, doc, + entityConfig: globalConfig, req, overrideAccess, - accessResult, + showHiddenFields, }); + + // ///////////////////////////////////// + // Execute after global hook + // ///////////////////////////////////// + + await globalConfig.hooks.afterRead.reduce(async (priorHook, hook) => { + await priorHook; + + doc = await hook({ + req, + doc, + }) || doc; + }, Promise.resolve()); + + // ///////////////////////////////////// + // Return results + // ///////////////////////////////////// + + if (shouldCommit) await payload.db.commitTransaction(req.transactionID); + + return doc; + } catch (error: unknown) { + await killTransaction(req); + throw error; } - - // ///////////////////////////////////// - // Execute before global hook - // ///////////////////////////////////// - - await globalConfig.hooks.beforeRead.reduce(async (priorHook, hook) => { - await priorHook; - - doc = await hook({ - req, - doc, - }) || doc; - }, Promise.resolve()); - - // ///////////////////////////////////// - // Execute field-level hooks and access - // ///////////////////////////////////// - - doc = await afterRead({ - depth, - doc, - entityConfig: globalConfig, - req, - overrideAccess, - showHiddenFields, - }); - - // ///////////////////////////////////// - // Execute after global hook - // ///////////////////////////////////// - - await globalConfig.hooks.afterRead.reduce(async (priorHook, hook) => { - await priorHook; - - doc = await hook({ - req, - doc, - }) || doc; - }, Promise.resolve()); - - // ///////////////////////////////////// - // Return results - // ///////////////////////////////////// - - return doc; } export default findOne; diff --git a/src/globals/operations/findVersionByID.ts b/src/globals/operations/findVersionByID.ts index eec51729b..6d03c20cd 100644 --- a/src/globals/operations/findVersionByID.ts +++ b/src/globals/operations/findVersionByID.ts @@ -7,6 +7,8 @@ import { SanitizedGlobalConfig } from '../config/types'; import { afterRead } from '../../fields/hooks/afterRead'; import { combineQueries } from '../../database/combineQueries'; import { FindGlobalVersionsArgs } from '../../database/types'; +import { killTransaction } from '../../utilities/killTransaction'; +import { initTransaction } from '../../utilities/initTransaction'; export type Arguments = { globalConfig: SanitizedGlobalConfig @@ -36,91 +38,101 @@ async function findVersionByID = any>(args: Argumen showHiddenFields, } = args; - // ///////////////////////////////////// - // Access - // ///////////////////////////////////// + try { + const shouldCommit = await initTransaction(req); - const accessResults = !overrideAccess ? await executeAccess({ req, disableErrors, id }, globalConfig.access.readVersions) : true; + // ///////////////////////////////////// + // Access + // ///////////////////////////////////// - // If errors are disabled, and access returns false, return null - if (accessResults === false) return null; + const accessResults = !overrideAccess ? await executeAccess({ req, disableErrors, id }, globalConfig.access.readVersions) : true; - const hasWhereAccess = typeof accessResults === 'object'; + // If errors are disabled, and access returns false, return null + if (accessResults === false) return null; - const findGlobalVersionsArgs: FindGlobalVersionsArgs = { - global: globalConfig.slug, - where: combineQueries({ id: { equals: id } }, accessResults), - locale, - limit: 1, - }; + const hasWhereAccess = typeof accessResults === 'object'; - // ///////////////////////////////////// - // Find by ID - // ///////////////////////////////////// + const findGlobalVersionsArgs: FindGlobalVersionsArgs = { + global: globalConfig.slug, + where: combineQueries({ id: { equals: id } }, accessResults), + locale, + limit: 1, + req, + }; - if (!findGlobalVersionsArgs.where.and[0].id) throw new NotFound(t); + // ///////////////////////////////////// + // Find by ID + // ///////////////////////////////////// + + if (!findGlobalVersionsArgs.where.and[0].id) throw new NotFound(t); - const { docs: results } = await payload.db.findGlobalVersions(findGlobalVersionsArgs); - if (!results || results?.length === 0) { - if (!disableErrors) { - if (!hasWhereAccess) throw new NotFound(t); - if (hasWhereAccess) throw new Forbidden(t); + const { docs: results } = await payload.db.findGlobalVersions(findGlobalVersionsArgs); + if (!results || results?.length === 0) { + if (!disableErrors) { + if (!hasWhereAccess) throw new NotFound(t); + if (hasWhereAccess) throw new Forbidden(t); + } + + return null; } - return null; + + // Clone the result - it may have come back memoized + let result = JSON.parse(JSON.stringify(results[0])); + + // ///////////////////////////////////// + // beforeRead - Collection + // ///////////////////////////////////// + + await globalConfig.hooks.beforeRead.reduce(async (priorHook, hook) => { + await priorHook; + + result = await hook({ + req, + doc: result.version, + }) || result.version; + }, Promise.resolve()); + + // ///////////////////////////////////// + // afterRead - Fields + // ///////////////////////////////////// + + result.version = await afterRead({ + currentDepth, + depth, + doc: result.version, + entityConfig: globalConfig, + req, + overrideAccess, + showHiddenFields, + }); + + // ///////////////////////////////////// + // afterRead - Global + // ///////////////////////////////////// + + await globalConfig.hooks.afterRead.reduce(async (priorHook, hook) => { + await priorHook; + + result.version = await hook({ + req, + query: findGlobalVersionsArgs.where, + doc: result.version, + }) || result.version; + }, Promise.resolve()); + + // ///////////////////////////////////// + // Return results + // ///////////////////////////////////// + + if (shouldCommit) await payload.db.commitTransaction(req.transactionID); + + return result; + } catch (error: unknown) { + await killTransaction(req); + throw error; } - - - // Clone the result - it may have come back memoized - let result = JSON.parse(JSON.stringify(results[0])); - - // ///////////////////////////////////// - // beforeRead - Collection - // ///////////////////////////////////// - - await globalConfig.hooks.beforeRead.reduce(async (priorHook, hook) => { - await priorHook; - - result = await hook({ - req, - doc: result.version, - }) || result.version; - }, Promise.resolve()); - - // ///////////////////////////////////// - // afterRead - Fields - // ///////////////////////////////////// - - result.version = await afterRead({ - currentDepth, - depth, - doc: result.version, - entityConfig: globalConfig, - req, - overrideAccess, - showHiddenFields, - }); - - // ///////////////////////////////////// - // afterRead - Global - // ///////////////////////////////////// - - await globalConfig.hooks.afterRead.reduce(async (priorHook, hook) => { - await priorHook; - - result.version = await hook({ - req, - query: findGlobalVersionsArgs.where, - doc: result.version, - }) || result.version; - }, Promise.resolve()); - - // ///////////////////////////////////// - // Return results - // ///////////////////////////////////// - - return result; } export default findVersionByID; diff --git a/src/globals/operations/findVersions.ts b/src/globals/operations/findVersions.ts index 981c2b4b7..a03dd23db 100644 --- a/src/globals/operations/findVersions.ts +++ b/src/globals/operations/findVersions.ts @@ -9,6 +9,8 @@ import { buildVersionGlobalFields } from '../../versions/buildGlobalFields'; import { TypeWithVersion } from '../../versions/types'; import { validateQueryPaths } from '../../database/queryValidation/validateQueryPaths'; import { combineQueries } from '../../database/combineQueries'; +import { killTransaction } from '../../utilities/killTransaction'; +import { initTransaction } from '../../utilities/initTransaction'; export type Arguments = { globalConfig: SanitizedGlobalConfig @@ -43,84 +45,94 @@ async function findVersions>( const versionFields = buildVersionGlobalFields(globalConfig); - // ///////////////////////////////////// - // Access - // ///////////////////////////////////// + try { + const shouldCommit = await initTransaction(req); - const accessResults = !overrideAccess ? await executeAccess({ req }, globalConfig.access.readVersions) : true; + // ///////////////////////////////////// + // Access + // ///////////////////////////////////// - await validateQueryPaths({ - globalConfig, - versionFields, - where, - req, - overrideAccess, - }); + const accessResults = !overrideAccess ? await executeAccess({ req }, globalConfig.access.readVersions) : true; - const fullWhere = combineQueries(where, accessResults); + await validateQueryPaths({ + globalConfig, + versionFields, + where, + req, + overrideAccess, + }); - // ///////////////////////////////////// - // Find - // ///////////////////////////////////// + const fullWhere = combineQueries(where, accessResults); - const paginatedDocs = await payload.db.findGlobalVersions({ - where: fullWhere, - page: page || 1, - limit: limit ?? 10, - sort, - global: globalConfig.slug, - locale, - }); + // ///////////////////////////////////// + // Find + // ///////////////////////////////////// - // ///////////////////////////////////// - // afterRead - Fields - // ///////////////////////////////////// + const paginatedDocs = await payload.db.findGlobalVersions({ + where: fullWhere, + page: page || 1, + limit: limit ?? 10, + sort, + global: globalConfig.slug, + locale, + req, + }); - let result = { - ...paginatedDocs, - docs: await Promise.all(paginatedDocs.docs.map(async (data) => ({ - ...data, - version: await afterRead({ - depth, - doc: data.version, - entityConfig: globalConfig, - req, - overrideAccess, - showHiddenFields, - findMany: true, - }), - }))), - } as PaginatedDocs; + // ///////////////////////////////////// + // afterRead - Fields + // ///////////////////////////////////// - // ///////////////////////////////////// - // afterRead - Global - // ///////////////////////////////////// + let result = { + ...paginatedDocs, + docs: await Promise.all(paginatedDocs.docs.map(async (data) => ({ + ...data, + version: await afterRead({ + depth, + doc: data.version, + entityConfig: globalConfig, + req, + overrideAccess, + showHiddenFields, + findMany: true, + }), + }))), + } as PaginatedDocs; - result = { - ...result, - docs: await Promise.all(result.docs.map(async (doc) => { - const docRef = doc; + // ///////////////////////////////////// + // afterRead - Global + // ///////////////////////////////////// - await globalConfig.hooks.afterRead.reduce(async (priorHook, hook) => { - await priorHook; + result = { + ...result, + docs: await Promise.all(result.docs.map(async (doc) => { + const docRef = doc; - docRef.version = await hook({ req, query: fullWhere, doc: doc.version, findMany: true }) || doc.version; - }, Promise.resolve()); + await globalConfig.hooks.afterRead.reduce(async (priorHook, hook) => { + await priorHook; - return docRef; - })), - }; + docRef.version = await hook({ req, query: fullWhere, doc: doc.version, findMany: true }) || doc.version; + }, Promise.resolve()); - // ///////////////////////////////////// - // Return results - // ///////////////////////////////////// + return docRef; + })), + }; - result = { - ...result, - docs: result.docs.map((doc) => sanitizeInternalFields(doc)), - }; + // ///////////////////////////////////// + // Return results + // ///////////////////////////////////// - return result; + result = { + ...result, + docs: result.docs.map((doc) => sanitizeInternalFields(doc)), + }; + + if (shouldCommit) await payload.db.commitTransaction(req.transactionID); + + return result; + } catch (error: unknown) { + await killTransaction(req); + throw error; + } } export default findVersions; diff --git a/src/globals/operations/local/findOne.ts b/src/globals/operations/local/findOne.ts index 3b33c41f7..d5d271a8b 100644 --- a/src/globals/operations/local/findOne.ts +++ b/src/globals/operations/local/findOne.ts @@ -16,6 +16,7 @@ export type Options = { overrideAccess?: boolean showHiddenFields?: boolean draft?: boolean + req?: PayloadRequest } export default async function findOneLocal( @@ -31,25 +32,23 @@ export default async function findOneLocal config.slug === globalSlug); - const i18n = i18nInit(payload.config.i18n); - + const defaultLocale = payload?.config?.localization ? payload?.config?.localization?.defaultLocale : null; if (!globalConfig) { throw new APIError(`The global with slug ${String(globalSlug)} can't be found.`); } - const req = { - user, - payloadAPI: 'local', - locale, - fallbackLocale, - payload, - i18n, - t: i18n.t, - } as PayloadRequest; + req.payloadAPI = req.payloadAPI || 'local'; + req.locale = locale ?? req?.locale ?? defaultLocale; + req.fallbackLocale = fallbackLocale ?? req?.fallbackLocale ?? defaultLocale; + req.i18n = i18nInit(payload.config.i18n); + req.payload = payload; + + if (typeof user !== 'undefined') req.user = user; if (!req.payloadDataLoader) req.payloadDataLoader = getDataLoader(req); diff --git a/src/globals/operations/restoreVersion.ts b/src/globals/operations/restoreVersion.ts index 75012bf43..220a4be7d 100644 --- a/src/globals/operations/restoreVersion.ts +++ b/src/globals/operations/restoreVersion.ts @@ -5,6 +5,8 @@ import { SanitizedGlobalConfig } from '../config/types'; import { NotFound } from '../../errors'; import { afterChange } from '../../fields/hooks/afterChange'; import { afterRead } from '../../fields/hooks/afterRead'; +import { initTransaction } from '../../utilities/initTransaction'; +import { killTransaction } from '../../utilities/killTransaction'; export type Arguments = { globalConfig: SanitizedGlobalConfig @@ -29,116 +31,127 @@ async function restoreVersion = any>(args: Argument showHiddenFields, } = args; - // ///////////////////////////////////// - // Access - // ///////////////////////////////////// + try { + const shouldCommit = await initTransaction(req); - if (!overrideAccess) { - await executeAccess({ req }, globalConfig.access.update); - } + // ///////////////////////////////////// + // Access + // ///////////////////////////////////// - // ///////////////////////////////////// - // Retrieve original raw version - // ///////////////////////////////////// + if (!overrideAccess) { + await executeAccess({ req }, globalConfig.access.update); + } - const { docs: versionDocs } = await payload.db.findGlobalVersions({ - global: globalConfig.slug, - where: { id: { equals: id } }, - limit: 1, - }); + // ///////////////////////////////////// + // Retrieve original raw version + // ///////////////////////////////////// - - if (!versionDocs || versionDocs.length === 0) { - throw new NotFound(t); - } - - const rawVersion = versionDocs[0]; - - // ///////////////////////////////////// - // fetch previousDoc - // ///////////////////////////////////// - - const previousDoc = await payload.findGlobal({ - slug: globalConfig.slug, - depth, - }); - - // ///////////////////////////////////// - // Update global - // ///////////////////////////////////// - - const global = await payload.db.findGlobal({ - slug: globalConfig.slug, - }); - - let result = rawVersion.version; - - if (global) { - result = await payload.db.updateGlobal({ - slug: globalConfig.slug, - data: result, - }); - } else { - result = await payload.db.createGlobal({ - slug: globalConfig.slug, - data: result, - }); - } - - // ///////////////////////////////////// - // afterRead - Fields - // ///////////////////////////////////// - - result = await afterRead({ - depth, - doc: result, - entityConfig: globalConfig, - req, - overrideAccess, - showHiddenFields, - }); - - // ///////////////////////////////////// - // afterRead - Global - // ///////////////////////////////////// - - await globalConfig.hooks.afterRead.reduce(async (priorHook, hook) => { - await priorHook; - - result = await hook({ - doc: result, + const { docs: versionDocs } = await payload.db.findGlobalVersions({ + global: globalConfig.slug, + where: { id: { equals: id } }, + limit: 1, req, - }) || result; - }, Promise.resolve()); + }); - // ///////////////////////////////////// - // afterChange - Fields - // ///////////////////////////////////// - result = await afterChange({ - data: result, - doc: result, - previousDoc, - entityConfig: globalConfig, - operation: 'update', - req, - }); + if (!versionDocs || versionDocs.length === 0) { + throw new NotFound(t); + } - // ///////////////////////////////////// - // afterChange - Global - // ///////////////////////////////////// + const rawVersion = versionDocs[0]; - await globalConfig.hooks.afterChange.reduce(async (priorHook, hook) => { - await priorHook; + // ///////////////////////////////////// + // fetch previousDoc + // ///////////////////////////////////// - result = await hook({ + const previousDoc = await payload.findGlobal({ + slug: globalConfig.slug, + depth, + req, + }); + + // ///////////////////////////////////// + // Update global + // ///////////////////////////////////// + + const global = await payload.db.findGlobal({ + slug: globalConfig.slug, + }); + + let result = rawVersion.version; + + if (global) { + result = await payload.db.updateGlobal({ + slug: globalConfig.slug, + data: result, + }); + } else { + result = await payload.db.createGlobal({ + slug: globalConfig.slug, + data: result, + }); + } + + // ///////////////////////////////////// + // afterRead - Fields + // ///////////////////////////////////// + + result = await afterRead({ + depth, + doc: result, + entityConfig: globalConfig, + req, + overrideAccess, + showHiddenFields, + }); + + // ///////////////////////////////////// + // afterRead - Global + // ///////////////////////////////////// + + await globalConfig.hooks.afterRead.reduce(async (priorHook, hook) => { + await priorHook; + + result = await hook({ + doc: result, + req, + }) || result; + }, Promise.resolve()); + + // ///////////////////////////////////// + // afterChange - Fields + // ///////////////////////////////////// + + result = await afterChange({ + data: result, doc: result, previousDoc, + entityConfig: globalConfig, + operation: 'update', req, - }) || result; - }, Promise.resolve()); + }); - return result; + // ///////////////////////////////////// + // afterChange - Global + // ///////////////////////////////////// + + await globalConfig.hooks.afterChange.reduce(async (priorHook, hook) => { + await priorHook; + + result = await hook({ + doc: result, + previousDoc, + req, + }) || result; + }, Promise.resolve()); + + if (shouldCommit) await payload.db.commitTransaction(req.transactionID); + + return result; + } catch (error: unknown) { + await killTransaction(req); + throw error; + } } export default restoreVersion; diff --git a/src/globals/operations/update.ts b/src/globals/operations/update.ts index 8d21966aa..818e6b200 100644 --- a/src/globals/operations/update.ts +++ b/src/globals/operations/update.ts @@ -9,8 +9,9 @@ import { afterChange } from '../../fields/hooks/afterChange'; import { afterRead } from '../../fields/hooks/afterRead'; import { PayloadRequest } from '../../express/types'; import { saveVersion } from '../../versions/saveVersion'; -import sanitizeInternalFields from '../../utilities/sanitizeInternalFields'; import { getLatestGlobalVersion } from '../../versions/getLatestGlobalVersion'; +import { initTransaction } from '../../utilities/initTransaction'; +import { killTransaction } from '../../utilities/killTransaction'; type Args = { globalConfig: SanitizedGlobalConfig @@ -42,202 +43,220 @@ async function update( autosave, } = args; - let { data } = args; + try { + const shouldCommit = await initTransaction(req); - const shouldSaveDraft = Boolean(draftArg && globalConfig.versions?.drafts); + let { data } = args; - // ///////////////////////////////////// - // 1. Retrieve and execute access - // ///////////////////////////////////// + const shouldSaveDraft = Boolean(draftArg && globalConfig.versions?.drafts); - const accessResults = !overrideAccess ? await executeAccess({ req, data }, globalConfig.access.update) : true; + // ///////////////////////////////////// + // 1. Retrieve and execute access + // ///////////////////////////////////// - // ///////////////////////////////////// - // Retrieve document - // ///////////////////////////////////// - - const query: Where = overrideAccess ? undefined : accessResults as Where; - - // ///////////////////////////////////// - // 2. Retrieve document - // ///////////////////////////////////// - const { global, globalExists } = await getLatestGlobalVersion({ - payload, - config: globalConfig, - slug, - where: query, - locale, - }); - - let globalJSON: Record = {}; - - if (global) { - globalJSON = JSON.parse(JSON.stringify(global)); - - if (globalJSON._id) { - delete globalJSON._id; - } - } - - const originalDoc = await afterRead({ - depth: 0, - doc: globalJSON, - entityConfig: globalConfig, - req, - overrideAccess: true, - showHiddenFields, - }); - - // ///////////////////////////////////// - // beforeValidate - Fields - // ///////////////////////////////////// - - data = await beforeValidate({ - data, - doc: originalDoc, - entityConfig: globalConfig, - operation: 'update', - overrideAccess, - req, - }); - - // ///////////////////////////////////// - // beforeValidate - Global - // ///////////////////////////////////// - - await globalConfig.hooks.beforeValidate.reduce(async (priorHook, hook) => { - await priorHook; - - data = (await hook({ - data, + const accessResults = !overrideAccess ? await executeAccess({ req, - originalDoc, - })) || data; - }, Promise.resolve()); - - // ///////////////////////////////////// - // beforeChange - Global - // ///////////////////////////////////// - - await globalConfig.hooks.beforeChange.reduce(async (priorHook, hook) => { - await priorHook; - - data = (await hook({ data, - req, - originalDoc, - })) || data; - }, Promise.resolve()); + }, globalConfig.access.update) : true; - // ///////////////////////////////////// - // beforeChange - Fields - // ///////////////////////////////////// + // ///////////////////////////////////// + // Retrieve document + // ///////////////////////////////////// - let result = await beforeChange({ - data, - doc: originalDoc, - docWithLocales: globalJSON, - entityConfig: globalConfig, - operation: 'update', - req, - skipValidation: shouldSaveDraft, - }); + const query: Where = overrideAccess ? undefined : accessResults as Where; - // ///////////////////////////////////// - // Update - // ///////////////////////////////////// - - if (!shouldSaveDraft) { - if (globalExists) { - result = await payload.db.updateGlobal({ - slug, - data: result, - }); - } else { - result = await payload.db.createGlobal({ - slug, - data: result, - }); - } - } - - // ///////////////////////////////////// - // Create version - // ///////////////////////////////////// - - if (globalConfig.versions) { - result = await saveVersion({ + // ///////////////////////////////////// + // 2. Retrieve document + // ///////////////////////////////////// + const { + global, + globalExists, + } = await getLatestGlobalVersion({ payload, - global: globalConfig, + config: globalConfig, + slug, + where: query, + locale, req, - docWithLocales: { - ...result, - createdAt: result.createdAt, - updatedAt: result.updatedAt, - }, - autosave, - draft: shouldSaveDraft, }); - } - // ///////////////////////////////////// - // afterRead - Fields - // ///////////////////////////////////// + let globalJSON: Record = {}; - result = await afterRead({ - depth, - doc: result, - entityConfig: globalConfig, - req, - overrideAccess, - showHiddenFields, - }); + if (global) { + globalJSON = JSON.parse(JSON.stringify(global)); - // ///////////////////////////////////// - // afterRead - Global - // ///////////////////////////////////// + if (globalJSON._id) { + delete globalJSON._id; + } + } - await globalConfig.hooks.afterRead.reduce(async (priorHook, hook) => { - await priorHook; - - result = await hook({ - doc: result, + const originalDoc = await afterRead({ + depth: 0, + doc: globalJSON, + entityConfig: globalConfig, req, - }) || result; - }, Promise.resolve()); + overrideAccess: true, + showHiddenFields, + }); - // ///////////////////////////////////// - // afterChange - Fields - // ///////////////////////////////////// + // ///////////////////////////////////// + // beforeValidate - Fields + // ///////////////////////////////////// - result = await afterChange({ - data, - doc: result, - previousDoc: originalDoc, - entityConfig: globalConfig, - operation: 'update', - req, - }); + data = await beforeValidate({ + data, + doc: originalDoc, + entityConfig: globalConfig, + operation: 'update', + overrideAccess, + req, + }); - // ///////////////////////////////////// - // afterChange - Global - // ///////////////////////////////////// + // ///////////////////////////////////// + // beforeValidate - Global + // ///////////////////////////////////// - await globalConfig.hooks.afterChange.reduce(async (priorHook, hook) => { - await priorHook; + await globalConfig.hooks.beforeValidate.reduce(async (priorHook, hook) => { + await priorHook; - result = await hook({ + data = (await hook({ + data, + req, + originalDoc, + })) || data; + }, Promise.resolve()); + + // ///////////////////////////////////// + // beforeChange - Global + // ///////////////////////////////////// + + await globalConfig.hooks.beforeChange.reduce(async (priorHook, hook) => { + await priorHook; + + data = (await hook({ + data, + req, + originalDoc, + })) || data; + }, Promise.resolve()); + + // ///////////////////////////////////// + // beforeChange - Fields + // ///////////////////////////////////// + + let result = await beforeChange({ + data, + doc: originalDoc, + docWithLocales: globalJSON, + entityConfig: globalConfig, + operation: 'update', + req, + skipValidation: shouldSaveDraft, + }); + + // ///////////////////////////////////// + // Update + // ///////////////////////////////////// + + if (!shouldSaveDraft) { + if (globalExists) { + result = await payload.db.updateGlobal({ + slug, + data: result, + req, + }); + } else { + result = await payload.db.createGlobal({ + slug, + data: result, + req, + }); + } + } + + // ///////////////////////////////////// + // Create version + // ///////////////////////////////////// + + if (globalConfig.versions) { + result = await saveVersion({ + payload, + global: globalConfig, + req, + docWithLocales: { + ...result, + createdAt: result.createdAt, + updatedAt: result.updatedAt, + }, + autosave, + draft: shouldSaveDraft, + }); + } + + // ///////////////////////////////////// + // afterRead - Fields + // ///////////////////////////////////// + + result = await afterRead({ + depth, + doc: result, + entityConfig: globalConfig, + req, + overrideAccess, + showHiddenFields, + }); + + // ///////////////////////////////////// + // afterRead - Global + // ///////////////////////////////////// + + await globalConfig.hooks.afterRead.reduce(async (priorHook, hook) => { + await priorHook; + + result = await hook({ + doc: result, + req, + }) || result; + }, Promise.resolve()); + + // ///////////////////////////////////// + // afterChange - Fields + // ///////////////////////////////////// + + result = await afterChange({ + data, doc: result, previousDoc: originalDoc, + entityConfig: globalConfig, + operation: 'update', req, - }) || result; - }, Promise.resolve()); + }); - // ///////////////////////////////////// - // Return results - // ///////////////////////////////////// + // ///////////////////////////////////// + // afterChange - Global + // ///////////////////////////////////// - return result; + await globalConfig.hooks.afterChange.reduce(async (priorHook, hook) => { + await priorHook; + + result = await hook({ + doc: result, + previousDoc: originalDoc, + req, + }) || result; + }, Promise.resolve()); + + // ///////////////////////////////////// + // Return results + // ///////////////////////////////////// + + if (shouldCommit) await payload.db.commitTransaction(req.transactionID); + + return result; + } catch (error: unknown) { + await killTransaction(req); + throw error; + } } export default update; diff --git a/src/globals/requestHandlers/update.ts b/src/globals/requestHandlers/update.ts index fa1a20db6..9be2d8b25 100644 --- a/src/globals/requestHandlers/update.ts +++ b/src/globals/requestHandlers/update.ts @@ -1,4 +1,4 @@ -import { Response, NextFunction } from 'express'; +import { NextFunction, Response } from 'express'; import httpStatus from 'http-status'; import { PayloadRequest } from '../../express/types'; import { SanitizedGlobalConfig } from '../config/types'; @@ -30,9 +30,9 @@ export default function updateHandler(globalConfig: SanitizedGlobalConfig): Upda if (draft) message = req.t('version:draftSavedSuccessfully'); if (autosave) message = req.t('version:autosavedSuccessfully'); - return res.status(httpStatus.OK).json({ message, result }); + res.status(httpStatus.OK).json({ message, result }); } catch (error) { - return next(error); + next(error); } }; } diff --git a/src/graphql/schema/buildObjectType.ts b/src/graphql/schema/buildObjectType.ts index 892f3d0b9..2886a562c 100644 --- a/src/graphql/schema/buildObjectType.ts +++ b/src/graphql/schema/buildObjectType.ts @@ -4,7 +4,8 @@ /* eslint-disable no-use-before-define */ import { GraphQLJSON } from 'graphql-type-json'; import { - GraphQLBoolean, GraphQLEnumType, + GraphQLBoolean, + GraphQLEnumType, GraphQLFieldConfig, GraphQLFloat, GraphQLInt, @@ -17,28 +18,28 @@ import { } from 'graphql'; import { DateTimeResolver, EmailAddressResolver } from 'graphql-scalars'; import { + ArrayField, + BlockField, + CheckboxField, + CodeField, + CollapsibleField, + DateField, + EmailField, Field, + GroupField, + JSONField, + NumberField, + PointField, RadioField, RelationshipField, - SelectField, - UploadField, - ArrayField, - GroupField, RichTextField, - NumberField, - TextField, - EmailField, - TextareaField, - CodeField, - JSONField, - DateField, - PointField, - CheckboxField, - BlockField, RowField, - CollapsibleField, - TabsField, + SelectField, tabHasName, + TabsField, + TextareaField, + TextField, + UploadField, } from '../../fields/config/types'; import formatName from '../utilities/formatName'; import combineParentName from '../utilities/combineParentName'; @@ -188,6 +189,7 @@ function buildObjectType({ if (id) { const relatedDocument = await context.req.payloadDataLoader.load(JSON.stringify([ + context.req.transactionID, relatedCollectionSlug, id, 0, @@ -349,6 +351,7 @@ function buildObjectType({ } const result = await context.req.payloadDataLoader.load(JSON.stringify([ + context.req.transactionID, collectionSlug, id, 0, @@ -392,6 +395,7 @@ function buildObjectType({ if (id) { const relatedDocument = await context.req.payloadDataLoader.load(JSON.stringify([ + context.req.transactionID, relatedCollectionSlug, id, 0, diff --git a/src/mongoose/connect.ts b/src/mongoose/connect.ts index 47282f50f..ac284f0e9 100644 --- a/src/mongoose/connect.ts +++ b/src/mongoose/connect.ts @@ -5,8 +5,13 @@ import mongoose from 'mongoose'; import type { MongooseAdapter } from '.'; import type { Connect } from '../database/types'; -export const connect: Connect = async function connect(this: MongooseAdapter, - { config }) { +export const connect: Connect = async function connect( + this: MongooseAdapter, + payload, +) { + if (this.url === false) { + return; + } let urlToConnect = this.url; let successfulConnectionMessage = 'Connected to MongoDB server successfully!'; @@ -16,8 +21,6 @@ export const connect: Connect = async function connect(this: MongooseAdapter, useFacet: undefined, }; - let mongoMemoryServer; - if (process.env.NODE_ENV === 'test') { if (process.env.PAYLOAD_TEST_MONGO_URL) { urlToConnect = process.env.PAYLOAD_TEST_MONGO_URL; @@ -27,20 +30,22 @@ export const connect: Connect = async function connect(this: MongooseAdapter, const getPort = require('get-port'); const port = await getPort(); - mongoMemoryServer = await MongoMemoryServer.create({ + this.mongoMemoryServer = await MongoMemoryServer.create({ instance: { dbName: 'payloadmemory', port, }, }); - urlToConnect = mongoMemoryServer.getUri(); + urlToConnect = this.mongoMemoryServer.getUri(); successfulConnectionMessage = 'Connected to in-memory MongoDB server successfully!'; } } try { - await mongoose.connect(urlToConnect, connectionOptions); + this.connection = ( + await mongoose.connect(urlToConnect, connectionOptions) + ).connection; if (process.env.PAYLOAD_DROP_DATABASE === 'true') { this.payload.logger.info('---- DROPPING DATABASE ----'); @@ -55,8 +60,4 @@ export const connect: Connect = async function connect(this: MongooseAdapter, ); process.exit(1); } - - this.mongoMemoryServer = mongoMemoryServer; - - return mongoMemoryServer; }; diff --git a/src/mongoose/create.ts b/src/mongoose/create.ts index b3cc33223..07b0b8190 100644 --- a/src/mongoose/create.ts +++ b/src/mongoose/create.ts @@ -1,12 +1,17 @@ import type { MongooseAdapter } from '.'; import type { Create } from '../database/types'; import type { Document } from '../types'; +import { PayloadRequest } from '../types'; +import { withSession } from './withSession'; -export const create: Create = async function create(this: MongooseAdapter, - { collection, data }) { +export const create: Create = async function create( + this: MongooseAdapter, + { collection, data, req = {} as PayloadRequest }, +) { const Model = this.collections[collection]; + const options = withSession(this, req.transactionID); - const doc = await Model.create(data); + const [doc] = await Model.create([data], options); // doc.toJSON does not do stuff like converting ObjectIds to string, or date strings to date objects. That's why we use JSON.parse/stringify here const result: Document = JSON.parse(JSON.stringify(doc)); diff --git a/src/mongoose/createGlobal.ts b/src/mongoose/createGlobal.ts index 64c791074..fe766e954 100644 --- a/src/mongoose/createGlobal.ts +++ b/src/mongoose/createGlobal.ts @@ -1,16 +1,21 @@ import type { MongooseAdapter } from '.'; import type { CreateGlobal } from '../database/types'; import sanitizeInternalFields from '../utilities/sanitizeInternalFields'; +import { withSession } from './withSession'; +import { PayloadRequest } from '../express/types'; -export const createGlobal: CreateGlobal = async function createGlobal(this: MongooseAdapter, - { data, slug }) { +export const createGlobal: CreateGlobal = async function createGlobal( + this: MongooseAdapter, + { data, slug, req = {} as PayloadRequest }, +) { const Model = this.globals; - - - let result = await Model.create({ + const global = { globalType: slug, ...data, - }) as any; + }; + const options = withSession(this, req.transactionID); + + let [result] = (await Model.create([global], options)) as any; result = JSON.parse(JSON.stringify(result)); diff --git a/src/mongoose/createVersion.ts b/src/mongoose/createVersion.ts index c2e8e89ce..2e6bef772 100644 --- a/src/mongoose/createVersion.ts +++ b/src/mongoose/createVersion.ts @@ -1,19 +1,37 @@ import type { MongooseAdapter } from '.'; import type { CreateVersion } from '../database/types'; import type { Document } from '../types'; +import { PayloadRequest } from '../types'; +import { withSession } from './withSession'; -export const createVersion: CreateVersion = async function createVersion(this: MongooseAdapter, - { collectionSlug, parent, versionData, autosave, createdAt, updatedAt }) { - const VersionModel = this.versions[collectionSlug]; - - - const doc = await VersionModel.create({ +export const createVersion: CreateVersion = async function createVersion( + this: MongooseAdapter, + { + collectionSlug, parent, - version: versionData, + versionData, autosave, createdAt, updatedAt, - }); + req = {} as PayloadRequest, + }, +) { + const VersionModel = this.versions[collectionSlug]; + const options = withSession(this, req.transactionID); + + const [doc] = await VersionModel.create( + [ + { + parent, + version: versionData, + autosave, + createdAt, + updatedAt, + }, + ], + options, + req, + ); const result: Document = JSON.parse(JSON.stringify(doc)); const verificationToken = doc._verificationToken; diff --git a/src/mongoose/deleteMany.ts b/src/mongoose/deleteMany.ts index a9a2b0f5e..966b31e9e 100644 --- a/src/mongoose/deleteMany.ts +++ b/src/mongoose/deleteMany.ts @@ -1,14 +1,20 @@ import type { MongooseAdapter } from '.'; import type { DeleteMany } from '../database/types'; +import { withSession } from './withSession'; +import { PayloadRequest } from '../express/types'; export const deleteMany: DeleteMany = async function deleteMany(this: MongooseAdapter, - { collection, where }) { + { collection, where, req = {} as PayloadRequest }) { const Model = this.collections[collection]; + const options = { + ...withSession(this, req.transactionID), + lean: true, + }; const query = await Model.buildQuery({ payload: this.payload, where, }); - await Model.deleteMany(query).lean(); + await Model.deleteMany(query, options); }; diff --git a/src/mongoose/deleteOne.ts b/src/mongoose/deleteOne.ts index 62e18377f..4d901a86b 100644 --- a/src/mongoose/deleteOne.ts +++ b/src/mongoose/deleteOne.ts @@ -1,19 +1,23 @@ import type { MongooseAdapter } from '.'; import type { DeleteOne } from '../database/types'; import type { Document } from '../types'; +import { PayloadRequest } from '../types'; import sanitizeInternalFields from '../utilities/sanitizeInternalFields'; +import { withSession } from './withSession'; -export const deleteOne: DeleteOne = async function deleteOne(this: MongooseAdapter, - { collection, where }) { +export const deleteOne: DeleteOne = async function deleteOne( + this: MongooseAdapter, + { collection, where, req = {} as PayloadRequest }, +) { const Model = this.collections[collection]; + const options = withSession(this, req.transactionID); const query = await Model.buildQuery({ payload: this.payload, where, }); - - const doc = await Model.findOneAndDelete(query).lean(); + const doc = await Model.findOneAndDelete(query, options).lean(); let result: Document = JSON.parse(JSON.stringify(doc)); @@ -21,6 +25,5 @@ export const deleteOne: DeleteOne = async function deleteOne(this: MongooseAdapt result.id = result._id; result = sanitizeInternalFields(result); - return result; }; diff --git a/src/mongoose/deleteVersions.ts b/src/mongoose/deleteVersions.ts index 986f05801..3c4e0c07e 100644 --- a/src/mongoose/deleteVersions.ts +++ b/src/mongoose/deleteVersions.ts @@ -1,10 +1,15 @@ import type { MongooseAdapter } from '.'; import type { DeleteVersions } from '../database/types'; +import { withSession } from './withSession'; +import { PayloadRequest } from '../express/types'; export const deleteVersions: DeleteVersions = async function deleteVersions(this: MongooseAdapter, - { collection, where, locale }) { + { collection, where, locale, req = {} as PayloadRequest }) { const VersionsModel = this.versions[collection]; - + const options = { + ...withSession(this, req.transactionID), + lean: true, + }; const query = await VersionsModel.buildQuery({ payload: this.payload, @@ -12,5 +17,5 @@ export const deleteVersions: DeleteVersions = async function deleteVersions(this where, }); - await VersionsModel.deleteMany(query).lean(); + await VersionsModel.deleteMany(query, options); }; diff --git a/src/mongoose/destroy.ts b/src/mongoose/destroy.ts new file mode 100644 index 000000000..22d314e38 --- /dev/null +++ b/src/mongoose/destroy.ts @@ -0,0 +1,13 @@ +import mongoose from 'mongoose'; +import { Destroy } from '../database/types'; +import { MongooseAdapter } from './index'; + +export const destroy: Destroy = async function destroy( + this: MongooseAdapter, +) { + if (this.mongoMemoryServer) { + await mongoose.connection.dropDatabase(); + await mongoose.connection.close(); + await this.mongoMemoryServer.stop(); + } +}; diff --git a/src/mongoose/find.ts b/src/mongoose/find.ts index 36552da23..993c89a3a 100644 --- a/src/mongoose/find.ts +++ b/src/mongoose/find.ts @@ -4,13 +4,25 @@ import type { Find } from '../database/types'; import sanitizeInternalFields from '../utilities/sanitizeInternalFields'; import flattenWhereToOperators from '../database/flattenWhereToOperators'; import { buildSortParam } from './queries/buildSortParam'; +import { withSession } from './withSession'; +import { PayloadRequest } from '../express/types'; export const find: Find = async function find( this: MongooseAdapter, - { collection, where, page, limit, sort: sortArg, locale, pagination }, + { + collection, + where, + page, + limit, + sort: sortArg, + locale, + pagination, + req = {} as PayloadRequest, + }, ) { const Model = this.collections[collection]; const collectionConfig = this.payload.collections[collection].config; + const options = withSession(this, req.transactionID); let hasNearConstraint = false; @@ -44,8 +56,9 @@ export const find: Find = async function find( useEstimatedCount: hasNearConstraint, forceCountFn: hasNearConstraint, pagination, - options: {}, + options, }; + if (limit > 0) { paginationOptions.limit = limit; // limit must also be set here, it's ignored when pagination is false diff --git a/src/mongoose/findGlobal.ts b/src/mongoose/findGlobal.ts index 0dbd5424c..0f1fb28d1 100644 --- a/src/mongoose/findGlobal.ts +++ b/src/mongoose/findGlobal.ts @@ -2,10 +2,18 @@ import type { MongooseAdapter } from '.'; import { combineQueries } from '../database/combineQueries'; import type { FindGlobal } from '../database/types'; import sanitizeInternalFields from '../utilities/sanitizeInternalFields'; +import { withSession } from './withSession'; +import { PayloadRequest } from '../express/types'; -export const findGlobal: FindGlobal = async function findGlobal(this: MongooseAdapter, - { slug, locale, where }) { +export const findGlobal: FindGlobal = async function findGlobal( + this: MongooseAdapter, + { slug, locale, where, req = {} as PayloadRequest }, +) { const Model = this.globals; + const options = { + ...withSession(this, req.transactionID), + lean: true, + }; const query = await Model.buildQuery({ where: combineQueries({ globalType: { equals: slug } }, where), @@ -14,11 +22,12 @@ export const findGlobal: FindGlobal = async function findGlobal(this: MongooseAd globalSlug: slug, }); - let doc = await Model.findOne(query).lean() as any; + let doc = (await Model.findOne(query, {}, options)) as any; if (!doc) { return null; - } if (doc._id) { + } + if (doc._id) { doc.id = doc._id; delete doc._id; } @@ -26,6 +35,5 @@ export const findGlobal: FindGlobal = async function findGlobal(this: MongooseAd doc = JSON.parse(JSON.stringify(doc)); doc = sanitizeInternalFields(doc); - return doc; }; diff --git a/src/mongoose/findGlobalVersions.ts b/src/mongoose/findGlobalVersions.ts index 7435a850f..a1ace75ae 100644 --- a/src/mongoose/findGlobalVersions.ts +++ b/src/mongoose/findGlobalVersions.ts @@ -5,11 +5,32 @@ import sanitizeInternalFields from '../utilities/sanitizeInternalFields'; import flattenWhereToOperators from '../database/flattenWhereToOperators'; import { buildSortParam } from './queries/buildSortParam'; import { buildVersionGlobalFields } from '../versions/buildGlobalFields'; +import { withSession } from './withSession'; +import { PayloadRequest } from '../express/types'; -export const findGlobalVersions: FindGlobalVersions = async function findGlobalVersions(this: MongooseAdapter, - { global, where, page, limit, sort: sortArg, locale, pagination, skip }) { +export const findGlobalVersions: FindGlobalVersions = async function findGlobalVersions( + this: MongooseAdapter, + { + global, + where, + page, + limit, + sort: sortArg, + locale, + pagination, + skip, + req = {} as PayloadRequest, + }, +) { const Model = this.versions[global]; - const versionFields = buildVersionGlobalFields(this.payload.globals.config.find(({ slug }) => slug === global)); + const versionFields = buildVersionGlobalFields( + this.payload.globals.config.find(({ slug }) => slug === global), + ); + const options = { + ...withSession(this, req.transactionID), + skip, + limit, + }; let hasNearConstraint = false; @@ -45,10 +66,9 @@ export const findGlobalVersions: FindGlobalVersions = async function findGlobalV offset: skip, useEstimatedCount: hasNearConstraint, forceCountFn: hasNearConstraint, - options: { - skip, - }, + options, }; + if (limit > 0) { paginationOptions.limit = limit; // limit must also be set here, it's ignored when pagination is false diff --git a/src/mongoose/findOne.ts b/src/mongoose/findOne.ts index 8eaf7f993..a637d55f5 100644 --- a/src/mongoose/findOne.ts +++ b/src/mongoose/findOne.ts @@ -1,12 +1,20 @@ +import type { MongooseQueryOptions } from 'mongoose'; import type { MongooseAdapter } from '.'; import type { FindOne } from '../database/types'; import type { Document } from '../types'; +import { PayloadRequest } from '../types'; import sanitizeInternalFields from '../utilities/sanitizeInternalFields'; +import { withSession } from './withSession'; -export const findOne: FindOne = async function findOne(this: MongooseAdapter, - { collection, where, locale }) { +export const findOne: FindOne = async function findOne( + this: MongooseAdapter, + { collection, where, locale, req = {} as PayloadRequest }, +) { const Model = this.collections[collection]; - + const options: MongooseQueryOptions = { + ...withSession(this, req.transactionID), + lean: true, + }; const query = await Model.buildQuery({ payload: this.payload, @@ -14,13 +22,12 @@ export const findOne: FindOne = async function findOne(this: MongooseAdapter, where, }); - const doc = await Model.findOne(query).lean(); + const doc = await Model.findOne(query, {}, options); if (!doc) { return null; } - let result: Document = JSON.parse(JSON.stringify(doc)); // custom id type reset diff --git a/src/mongoose/findVersions.ts b/src/mongoose/findVersions.ts index 5dcfc1a86..c403124f8 100644 --- a/src/mongoose/findVersions.ts +++ b/src/mongoose/findVersions.ts @@ -4,11 +4,30 @@ import type { FindVersions } from '../database/types'; import sanitizeInternalFields from '../utilities/sanitizeInternalFields'; import flattenWhereToOperators from '../database/flattenWhereToOperators'; import { buildSortParam } from './queries/buildSortParam'; +import { withSession } from './withSession'; +import { PayloadRequest } from '../express/types'; -export const findVersions: FindVersions = async function findVersions(this: MongooseAdapter, - { collection, where, page, limit, sort: sortArg, locale, pagination, skip }) { +export const findVersions: FindVersions = async function findVersions( + this: MongooseAdapter, + { + collection, + where, + page, + limit, + sort: sortArg, + locale, + pagination, + skip, + req = {} as PayloadRequest, + }, +) { const Model = this.versions[collection]; const collectionConfig = this.payload.collections[collection].config; + const options = { + ...withSession(this, req.transactionID), + skip, + limit, + }; let hasNearConstraint = false; @@ -44,12 +63,9 @@ export const findVersions: FindVersions = async function findVersions(this: Mong offset: skip, useEstimatedCount: hasNearConstraint, forceCountFn: hasNearConstraint, - options: { - // limit must also be set here, it's ignored when pagination is false - limit, - skip, - }, + options, }; + if (limit > 0) { paginationOptions.limit = limit; // limit must also be set here, it's ignored when pagination is false diff --git a/src/mongoose/index.ts b/src/mongoose/index.ts index e70e9489d..419483de0 100644 --- a/src/mongoose/index.ts +++ b/src/mongoose/index.ts @@ -1,24 +1,21 @@ -import type { ConnectOptions } from 'mongoose'; +import type { ClientSession, Connection, ConnectOptions } from 'mongoose'; +import mongoose from 'mongoose'; import { createMigration } from '../database/migrations/createMigration'; -import { migrate } from '../database/migrations/migrate'; -import { migrateDown } from '../database/migrations/migrateDown'; -import { migrateRefresh } from '../database/migrations/migrateRefresh'; -import { migrateReset } from '../database/migrations/migrateReset'; -import { migrateStatus } from '../database/migrations/migrateStatus'; +import type { Payload } from '../index'; import type { DatabaseAdapter } from '../database/types'; -import { Payload } from '../index'; -import type { SanitizedConfig } from '../config/types'; import { connect } from './connect'; -import { create } from './create'; +import { init } from './init'; +import { webpack } from './webpack'; +import { createGlobal } from './createGlobal'; +import { createVersion } from './createVersion'; +import { beginTransaction } from './transactions/beginTransaction'; +import { rollbackTransaction } from './transactions/rollbackTransaction'; +import { commitTransaction } from './transactions/commitTransaction'; +import { queryDrafts } from './queryDrafts'; import { find } from './find'; import { findGlobalVersions } from './findGlobalVersions'; import { findVersions } from './findVersions'; -import { init } from './init'; -import { queryDrafts } from './queryDrafts'; -import { webpack } from './webpack'; - -import { createGlobal } from './createGlobal'; -import { createVersion } from './createVersion'; +import { create } from './create'; import { deleteOne } from './deleteOne'; import { deleteVersions } from './deleteVersions'; import { findGlobal } from './findGlobal'; @@ -26,14 +23,17 @@ import { findOne } from './findOne'; import { updateGlobal } from './updateGlobal'; import { updateOne } from './updateOne'; import { updateVersion } from './updateVersion'; -import type { CollectionModel, GlobalModel } from './types'; import { deleteMany } from './deleteMany'; +import { baseDatabaseAdapter } from '../database/baseDatabaseAdapter'; +import { destroy } from './destroy'; +import type { CollectionModel, GlobalModel } from './types'; export interface Args { payload: Payload; - /** The URL to connect to MongoDB */ - url: string; + /** The URL to connect to MongoDB or false to start payload and prevent connecting */ + url: string | false; migrationDir?: string; + /** Extra configuration options */ connectOptions?: ConnectOptions & { /** Set false to disable $facet aggregation in non-supporting databases, Defaults to true */ useFacet?: boolean; @@ -48,39 +48,42 @@ export type MongooseAdapter = DatabaseAdapter & }; globals: GlobalModel; versions: { - [slug: string]: CollectionModel; - }; - }; + [slug: string]: CollectionModel + } + sessions: Record + connection: Connection + } export function mongooseAdapter({ payload, url, connectOptions, - migrationDir = '.migrations', + migrationDir, }: Args): MongooseAdapter { + const adapter = baseDatabaseAdapter({ + payload, + migrationDir, + }); + mongoose.set('strictQuery', false); return { + ...adapter, + connection: undefined, + mongoMemoryServer: undefined, + sessions: {}, payload, url, connectOptions: connectOptions || {}, + globals: undefined, collections: {}, versions: {}, - globals: undefined, - mongoMemoryServer: undefined, connect, + destroy, init, webpack, - migrate, - migrateStatus, - migrateDown, - migrateRefresh, - migrateReset, - migrateFresh: async () => null, - migrationDir, createMigration: async (migrationName) => createMigration({ payload, migrationDir, migrationName }), - transaction: async () => true, - beginTransaction: async () => true, - rollbackTransaction: async () => true, - commitTransaction: async () => true, + beginTransaction, + rollbackTransaction, + commitTransaction, queryDrafts, findOne, find, diff --git a/src/mongoose/init.ts b/src/mongoose/init.ts index a84f647b8..846135aa3 100644 --- a/src/mongoose/init.ts +++ b/src/mongoose/init.ts @@ -1,5 +1,5 @@ /* eslint-disable no-param-reassign */ -import mongoose from 'mongoose'; +import mongoose, { PaginateOptions } from 'mongoose'; import paginate from 'mongoose-paginate-v2'; import mongooseAggregatePaginate from 'mongoose-aggregate-paginate-v2'; import { buildVersionCollectionFields } from '../versions/buildCollectionFields'; @@ -14,66 +14,74 @@ import { buildVersionGlobalFields } from '../versions/buildGlobalFields'; import type { Init } from '../database/types'; import { CollectionModel } from './types'; -export const init: Init = async function init(this: MongooseAdapter, - { config }) { - this.payload.config.collections.forEach((collection: SanitizedCollectionConfig) => { - const schema = buildCollectionSchema(collection, this.payload.config); +export const init: Init = async function init( + this: MongooseAdapter, +) { + this.payload.config.collections.forEach( + (collection: SanitizedCollectionConfig) => { + const schema = buildCollectionSchema(collection, this.payload.config); - if (collection.versions) { - const versionModelName = getVersionsModelName(collection); + if (collection.versions) { + const versionModelName = getVersionsModelName(collection); - const versionCollectionFields = buildVersionCollectionFields(collection); + const versionCollectionFields = buildVersionCollectionFields(collection); - const versionSchema = buildSchema( - this.payload.config, - versionCollectionFields, - { - disableUnique: true, - draftsEnabled: true, - options: { - timestamps: false, - minimize: false, + const versionSchema = buildSchema( + this.payload.config, + versionCollectionFields, + { + disableUnique: true, + draftsEnabled: true, + options: { + timestamps: false, + minimize: false, + }, }, - }, - ); + ); - if (collection.indexes) { - collection.indexes.forEach((index) => { - // prefix 'version.' to each field in the index - const versionIndex = { - fields: {}, - options: index.options, - }; - Object.entries(index.fields) - .forEach(([key, value]) => { - versionIndex.fields[`version.${key}`] = value; - }); - versionSchema.index(versionIndex.fields, versionIndex.options); - }); + if (collection.indexes) { + collection.indexes.forEach((index) => { + // prefix 'version.' to each field in the index + const versionIndex = { + fields: {}, + options: index.options, + }; + Object.entries(index.fields) + .forEach(([key, value]) => { + versionIndex.fields[`version.${key}`] = value; + }); + versionSchema.index(versionIndex.fields, versionIndex.options); + }); + } + + versionSchema.plugin(paginate, { useEstimatedCount: true }) + .plugin( + getBuildQueryPlugin({ + collectionSlug: collection.slug, + versionsFields: versionCollectionFields, + }), + ); + + if (collection.versions?.drafts) { + versionSchema.plugin(mongooseAggregatePaginate); + } + + const model = mongoose.model( + versionModelName, + versionSchema, + ) as CollectionModel; + this.payload.versions[collection.slug] = model; + this.versions[collection.slug] = model; } - versionSchema.plugin(paginate, { useEstimatedCount: true }) - .plugin(getBuildQueryPlugin({ - collectionSlug: collection.slug, - versionsFields: versionCollectionFields, - })); + const model = mongoose.model(collection.slug, schema) as CollectionModel; + this.collections[collection.slug] = model; - if (collection.versions?.drafts) { - versionSchema.plugin(mongooseAggregatePaginate); - } - - const model = mongoose.model(versionModelName, versionSchema) as CollectionModel; - this.payload.versions[collection.slug] = model; - this.versions[collection.slug] = model; - } - - const model = mongoose.model(collection.slug, schema) as CollectionModel; - this.collections[collection.slug] = model; - - this.payload.collections[collection.slug] = { - config: collection, - }; - }); + this.payload.collections[collection.slug] = { + config: collection, + }; + }, + ); const model = buildGlobalModel(this.payload.config); this.globals = model; @@ -98,10 +106,14 @@ export const init: Init = async function init(this: MongooseAdapter, }, ); - versionSchema.plugin(paginate, { useEstimatedCount: true }) + versionSchema + .plugin(paginate, { useEstimatedCount: true }) .plugin(getBuildQueryPlugin({ versionsFields: versionGlobalFields })); - const versionsModel = mongoose.model(versionModelName, versionSchema) as CollectionModel; + const versionsModel = mongoose.model( + versionModelName, + versionSchema, + ) as CollectionModel; this.versions[global.slug] = versionsModel; this.payload.versions[global.slug] = versionsModel; diff --git a/src/mongoose/models/buildCollectionSchema.ts b/src/mongoose/models/buildCollectionSchema.ts index 57e7526a0..aff26d46a 100644 --- a/src/mongoose/models/buildCollectionSchema.ts +++ b/src/mongoose/models/buildCollectionSchema.ts @@ -1,5 +1,5 @@ import paginate from 'mongoose-paginate-v2'; -import { Schema } from 'mongoose'; +import { PaginateOptions, Schema } from 'mongoose'; import { SanitizedConfig } from '../../config/types'; import getBuildQueryPlugin from '../queries/buildQuery'; import buildSchema from './buildSchema'; @@ -29,7 +29,7 @@ const buildCollectionSchema = (collection: SanitizedCollectionConfig, config: Sa schema.index(index.fields, index.options); }); } - schema.plugin(paginate, { useEstimatedCount: true }) + schema.plugin(paginate, { useEstimatedCount: true }) .plugin(getBuildQueryPlugin({ collectionSlug: collection.slug })); return schema; diff --git a/src/mongoose/queryDrafts.ts b/src/mongoose/queryDrafts.ts index 5e89a2748..7e33cdfb2 100644 --- a/src/mongoose/queryDrafts.ts +++ b/src/mongoose/queryDrafts.ts @@ -1,20 +1,35 @@ +import { PaginateOptions } from 'mongoose'; import type { MongooseAdapter } from '.'; import type { QueryDrafts } from '../database/types'; import flattenWhereToOperators from '../database/flattenWhereToOperators'; import sanitizeInternalFields from '../utilities/sanitizeInternalFields'; import { buildSortParam } from './queries/buildSortParam'; +import { withSession } from './withSession'; +import { PayloadRequest } from '../express/types'; type AggregateVersion = { - _id: string - version: T - updatedAt: string - createdAt: string -} + _id: string; + version: T; + updatedAt: string; + createdAt: string; +}; -export const queryDrafts: QueryDrafts = async function queryDrafts(this: MongooseAdapter, - { collection, where, page, limit, sort: sortArg, locale, pagination }) { +export const queryDrafts: QueryDrafts = async function queryDrafts( + this: MongooseAdapter, + { + collection, + where, + page, + limit, + sort: sortArg, + locale, + pagination, + req = {} as PayloadRequest, + }, +) { const VersionModel = this.versions[collection]; const collectionConfig = this.payload.collections[collection].config; + const options = withSession(this, req.transactionID); const versionQuery = await VersionModel.buildQuery({ where, @@ -40,23 +55,27 @@ export const queryDrafts: QueryDrafts = async function queryDrafts(this: Mong }); } - const aggregate = VersionModel.aggregate>([ - // Sort so that newest are first - { $sort: { updatedAt: -1 } }, - // Group by parent ID, and take the first of each - { - $group: { - _id: '$parent', - version: { $first: '$version' }, - updatedAt: { $first: '$updatedAt' }, - createdAt: { $first: '$createdAt' }, + const aggregate = VersionModel.aggregate>( + [ + // Sort so that newest are first + { $sort: { updatedAt: -1 } }, + // Group by parent ID, and take the first of each + { + $group: { + _id: '$parent', + version: { $first: '$version' }, + updatedAt: { $first: '$updatedAt' }, + createdAt: { $first: '$createdAt' }, + }, }, + // Filter based on incoming query + { $match: versionQuery }, + ], + { + ...options, + allowDiskUse: true, }, - // Filter based on incoming query - { $match: versionQuery }, - ], { - allowDiskUse: true, - }); + ); let result; @@ -68,8 +87,7 @@ export const queryDrafts: QueryDrafts = async function queryDrafts(this: Mong useEstimatedCount = constraints.some((prop) => Object.keys(prop).some((key) => key === 'near')); } - - const aggregatePaginateOptions = { + const aggregatePaginateOptions: PaginateOptions = { page, limit, lean: true, @@ -79,12 +97,16 @@ export const queryDrafts: QueryDrafts = async function queryDrafts(this: Mong useCustomCountFn: pagination ? undefined : () => Promise.resolve(1), useFacet: this.connectOptions.useFacet, options: { + ...options, limit, }, sort, }; - result = await VersionModel.aggregatePaginate(aggregate, aggregatePaginateOptions); + result = await VersionModel.aggregatePaginate( + aggregate, + aggregatePaginateOptions, + ); } else { result = aggregate.exec(); } diff --git a/src/mongoose/transactions/beginTransaction.ts b/src/mongoose/transactions/beginTransaction.ts new file mode 100644 index 000000000..918448652 --- /dev/null +++ b/src/mongoose/transactions/beginTransaction.ts @@ -0,0 +1,32 @@ +import type { TransactionOptions } from 'mongodb'; +import { v4 as uuid } from 'uuid'; +import { BeginTransaction } from '../../database/types'; +import { APIError } from '../../errors'; + +let transactionsNotAvailable; +export const beginTransaction: BeginTransaction = async function beginTransaction( + options: TransactionOptions = {}, +) { + let id = null; + if (!this.connection) { + throw new APIError('beginTransaction called while no connection to the database exists'); + } + + if (transactionsNotAvailable) return id; + + if (!this.connection.get('replicaSet')) { + transactionsNotAvailable = true; + this.payload.logger.warn('Database transactions for MongoDB are only available when connecting to a replica set. Operations will continue without using transactions.'); + } else { + id = uuid(); + if (!this.sessions[id]) { + this.sessions[id] = await this.connection.getClient().startSession(); + } + if (this.sessions[id].inTransaction()) { + this.payload.logger.warn('beginTransaction called while transaction already exists'); + } else { + await this.sessions[id].startTransaction(options); + } + } + return id; +}; diff --git a/src/mongoose/transactions/commitTransaction.ts b/src/mongoose/transactions/commitTransaction.ts new file mode 100644 index 000000000..f55c7f3fd --- /dev/null +++ b/src/mongoose/transactions/commitTransaction.ts @@ -0,0 +1,15 @@ +import { CommitTransaction } from '../../database/types'; + + +export const commitTransaction: CommitTransaction = async function commitTransaction(id) { + if (!this.connection.get('replicaSet')) { + return; + } + if (!this.session[id]?.inTransaction()) { + this.payload.logger.warn('commitTransaction called when no transaction exists'); + return; + } + await this.session[id].commitTransaction(); + await this.session[id].endSession(); + delete this.session[id]; +}; diff --git a/src/mongoose/transactions/rollbackTransaction.ts b/src/mongoose/transactions/rollbackTransaction.ts new file mode 100644 index 000000000..36d6acbc9 --- /dev/null +++ b/src/mongoose/transactions/rollbackTransaction.ts @@ -0,0 +1,12 @@ +import { RollbackTransaction } from '../../database/types'; + + +export const rollbackTransaction: RollbackTransaction = async function rollbackTransaction(id = '') { + if (!this.session[id]?.inTransaction()) { + this.payload.logger.warn('rollbackTransaction called when no transaction exists'); + return; + } + await this.session[id].abortTransaction(); + await this.session[id].endSession(); + delete this.session[id]; +}; diff --git a/src/mongoose/updateGlobal.ts b/src/mongoose/updateGlobal.ts index a7d95cb60..c06c02f02 100644 --- a/src/mongoose/updateGlobal.ts +++ b/src/mongoose/updateGlobal.ts @@ -1,17 +1,26 @@ import type { MongooseAdapter } from '.'; import type { UpdateGlobal } from '../database/types'; import sanitizeInternalFields from '../utilities/sanitizeInternalFields'; +import { withSession } from './withSession'; +import { PayloadRequest } from '../express/types'; -export const updateGlobal: UpdateGlobal = async function updateGlobal(this: MongooseAdapter, - { slug, data }) { +export const updateGlobal: UpdateGlobal = async function updateGlobal( + this: MongooseAdapter, + { slug, data, req = {} as PayloadRequest }, +) { const Model = this.globals; + const options = { + ...withSession(this, req.transactionID), + new: true, + lean: true, + }; let result; result = await Model.findOneAndUpdate( { globalType: slug }, data, - { new: true, lean: true }, - ).lean(); + options, + ); result = JSON.parse(JSON.stringify(result)); @@ -19,6 +28,5 @@ export const updateGlobal: UpdateGlobal = async function updateGlobal(this: Mong result.id = result._id; result = sanitizeInternalFields(result); - return result; }; diff --git a/src/mongoose/updateOne.ts b/src/mongoose/updateOne.ts index dc7ffed95..eb15e0670 100644 --- a/src/mongoose/updateOne.ts +++ b/src/mongoose/updateOne.ts @@ -3,10 +3,19 @@ import type { UpdateOne } from '../database/types'; import { ValidationError } from '../errors'; import sanitizeInternalFields from '../utilities/sanitizeInternalFields'; import { i18nInit } from '../translations/init'; +import { withSession } from './withSession'; +import { PayloadRequest } from '../express/types'; -export const updateOne: UpdateOne = async function updateOne(this: MongooseAdapter, - { collection, data, where, locale, req }) { +export const updateOne: UpdateOne = async function updateOne( + this: MongooseAdapter, + { collection, data, where, locale, req = {} as PayloadRequest }, +) { const Model = this.collections[collection]; + const options = { + ...withSession(this, req.transactionID), + new: true, + lean: true, + }; const query = await Model.buildQuery({ payload: this.payload, @@ -16,18 +25,19 @@ export const updateOne: UpdateOne = async function updateOne(this: MongooseAdapt let result; try { - result = await Model.findOneAndUpdate( - query, - data, - { new: true, lean: true }, - ).lean(); + result = await Model.findOneAndUpdate(query, data, options).lean(); } catch (error) { // Handle uniqueness error from MongoDB throw error.code === 11000 && error.keyValue - ? new ValidationError([{ - message: 'Value must be unique', - field: Object.keys(error.keyValue)[0], - }], req?.t ?? i18nInit(this.payload.config.i18n).t) + ? new ValidationError( + [ + { + message: 'Value must be unique', + field: Object.keys(error.keyValue)[0], + }, + ], + req?.t ?? i18nInit(this.payload.config.i18n).t, + ) : error; } @@ -35,6 +45,5 @@ export const updateOne: UpdateOne = async function updateOne(this: MongooseAdapt result.id = result._id; result = sanitizeInternalFields(result); - return result; }; diff --git a/src/mongoose/updateVersion.ts b/src/mongoose/updateVersion.ts index 5c0daf4fe..3d05f09f2 100644 --- a/src/mongoose/updateVersion.ts +++ b/src/mongoose/updateVersion.ts @@ -1,9 +1,18 @@ import type { MongooseAdapter } from '.'; import type { UpdateVersion } from '../database/types'; +import { withSession } from './withSession'; +import { PayloadRequest } from '../express/types'; -export const updateVersion: UpdateVersion = async function updateVersion(this: MongooseAdapter, - { collectionSlug, where, locale, versionData }) { +export const updateVersion: UpdateVersion = async function updateVersion( + this: MongooseAdapter, + { collectionSlug, where, locale, versionData, req = {} as PayloadRequest }, +) { const VersionModel = this.versions[collectionSlug]; + const options = { + ...withSession(this, req.transactionID), + new: true, + lean: true, + }; const query = await VersionModel.buildQuery({ payload: this.payload, @@ -11,12 +20,7 @@ export const updateVersion: UpdateVersion = async function updateVersion(this: M where, }); - - const doc = await VersionModel.findOneAndUpdate( - query, - versionData, - { new: true, lean: true }, - ).lean(); + const doc = await VersionModel.findOneAndUpdate(query, versionData, options); const result = JSON.parse(JSON.stringify(doc)); diff --git a/src/mongoose/withSession.ts b/src/mongoose/withSession.ts new file mode 100644 index 000000000..2c957961c --- /dev/null +++ b/src/mongoose/withSession.ts @@ -0,0 +1,10 @@ +import type { ClientSession } from 'mongoose'; +import { MongooseAdapter } from './index'; + +/** + * returns the session belonging to the transaction of the req.session if exists + * @returns ClientSession + */ +export function withSession(db: MongooseAdapter, transactionID?: string | number): { session: ClientSession } | object { + return db.sessions[transactionID] ? { session: db.sessions[transactionID] } : {}; +} diff --git a/src/payload.ts b/src/payload.ts index e8ae391c9..61f538ee2 100644 --- a/src/payload.ts +++ b/src/payload.ts @@ -3,7 +3,6 @@ import type { Express, Router } from 'express'; import { ExecutionResult, GraphQLSchema, ValidationRule } from 'graphql'; import crypto from 'crypto'; import path from 'path'; -import mongoose from 'mongoose'; import { Config as GeneratedTypes } from 'payload/generated-types'; import { OperationArgs, Request as graphQLRequest } from 'graphql-http/lib/handler'; import { SendMailOptions } from 'nodemailer'; @@ -149,7 +148,7 @@ export class BasePayload { * @param options */ async init(options: InitOptions): Promise { - this.logger = Logger('payload', options.loggerOptions); + this.logger = Logger('payload', options.loggerOptions, options.loggerDestination); this.mongoURL = options.mongoURL; this.mongoOptions = options.mongoOptions; @@ -205,7 +204,7 @@ export class BasePayload { if (!this.config.db) { this.config.db = mongooseAdapter({ payload: this, - url: this.mongoURL ? this.mongoURL : '', + url: this.mongoURL ? this.mongoURL : false, connectOptions: options.mongoOptions, }); } @@ -213,11 +212,8 @@ export class BasePayload { this.db = this.config.db; this.db.payload = this; - if (this.mongoURL || this.db.connect) { - mongoose.set('strictQuery', false); - if (this.db?.connect) { - this.mongoMemoryServer = await this.db.connect({ config: this.config }); - } + if (this.db?.connect) { + await this.db.connect(this); } // Configure email service @@ -237,7 +233,7 @@ export class BasePayload { } if (this.db?.init) { - await this.db?.init({ config: this.config }); + await this.db.init(this); } serverInitTelemetry(this); diff --git a/src/translations/en.json b/src/translations/en.json index 33b8f00ae..6e076186e 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -90,7 +90,9 @@ "unspecific": "An error has occurred.", "userLocked": "This user is locked due to having too many failed login attempts.", "valueMustBeUnique": "Value must be unique", - "verificationTokenInvalid": "Verification token is invalid." + "verificationTokenInvalid": "Verification token is invalid.", + "singular": "Error", + "plural": "Errors" }, "fields": { "addLabel": "Add {{label}}", diff --git a/src/translations/ua.json b/src/translations/ua.json index dbb8d48cd..45e09dac9 100644 --- a/src/translations/ua.json +++ b/src/translations/ua.json @@ -93,10 +93,10 @@ "verificationTokenInvalid": "Токен верифікації є недійсним." }, "fields": { - "addLabel": "Добавити {{label}}", - "addNew": "Добавити новий", + "addLabel": "Додати {{label}}", + "addNew": "Додати новий", "addNewLabel": "Створити {{label}}", - "addRelationship": "Добавити взаємозв'язок", + "addRelationship": "Додати взаємозв'язок", "block": "блок", "blockType": "Тип блока", "blocks": "блоки", @@ -138,8 +138,8 @@ "aboutToDeleteCount_many": "Ви збираєтеся видалити {{count}} {{label}}", "aboutToDeleteCount_one": "Ви збираєтеся видалити {{count}} {{label}}", "aboutToDeleteCount_other": "Ви збираєтеся видалити {{count}} {{label}}", - "addBelow": "Добавити нижче", - "addFilter": "Добавити фільтр", + "addBelow": "Додати нижче", + "addFilter": "Додати фільтр", "adminTheme": "Тема адмінки", "and": "і", "ascending": "В порядку зростання", diff --git a/src/utilities/deepCopyObject.ts b/src/utilities/deepCopyObject.ts index 1639fea4f..8b569a40f 100644 --- a/src/utilities/deepCopyObject.ts +++ b/src/utilities/deepCopyObject.ts @@ -1,6 +1,10 @@ const deepCopyObject = (inObject) => { if (inObject instanceof Date) return inObject; + if (inObject instanceof Set) return new Set(inObject); + + if (inObject instanceof Map) return new Map(inObject); + if (typeof inObject !== 'object' || inObject === null) { return inObject; // Return the value if inObject is not an object } diff --git a/src/utilities/initTransaction.ts b/src/utilities/initTransaction.ts new file mode 100644 index 000000000..0421b2252 --- /dev/null +++ b/src/utilities/initTransaction.ts @@ -0,0 +1,19 @@ +import { PayloadRequest } from '../express/types'; + +/** + * Starts a new transaction using the db adapter with a random id and then assigns it to the req.transaction + * @returns true if beginning a transaction and false when req already has a transaction to use + */ +export async function initTransaction(req: PayloadRequest): Promise { + const { + transactionID, + payload, + } = req; + if (!transactionID && typeof payload.db.beginTransaction === 'function') { + req.transactionID = await payload.db.beginTransaction(); + if (req.transactionID) { + return true; + } + } + return false; +} diff --git a/src/utilities/isNumber.ts b/src/utilities/isNumber.ts index 051e9251c..230ae0de9 100644 --- a/src/utilities/isNumber.ts +++ b/src/utilities/isNumber.ts @@ -1,7 +1,7 @@ -export function isNumber(value: unknown): boolean { - if (typeof value === 'string' && value.trim() === ''){ - return false +export function isNumber(value: unknown): value is number { + if (typeof value === 'string' && value.trim() === '') { + return false; } return !Number.isNaN(Number(value)); -} \ No newline at end of file +} diff --git a/src/utilities/killTransaction.ts b/src/utilities/killTransaction.ts new file mode 100644 index 000000000..6c035ff60 --- /dev/null +++ b/src/utilities/killTransaction.ts @@ -0,0 +1,15 @@ +import { PayloadRequest } from '../express/types'; + +/** + * Rollback the transaction from the req using the db adapter and removes it from the req + */ +export async function killTransaction(req: PayloadRequest): Promise { + const { + transactionID, + payload, + } = req; + if (transactionID) { + await payload.db.rollbackTransaction(req.transactionID); + delete req.transactionID; + } +} diff --git a/src/utilities/logger.ts b/src/utilities/logger.ts index 87effe4e9..911a6306d 100644 --- a/src/utilities/logger.ts +++ b/src/utilities/logger.ts @@ -9,10 +9,10 @@ const defaultLoggerOptions = { }, }; -const getLogger = (name = 'payload', options?: pino.LoggerOptions): PayloadLogger => pino({ +const getLogger = (name = 'payload', options?: pino.LoggerOptions, destination?: pino.DestinationStream): PayloadLogger => pino({ name: options?.name || name, enabled: process.env.DISABLE_LOGGING !== 'true', ...(options || defaultLoggerOptions), -}); +}, destination); export default getLogger; diff --git a/src/utilities/setsAreEqual.ts b/src/utilities/setsAreEqual.ts new file mode 100644 index 000000000..9fc064160 --- /dev/null +++ b/src/utilities/setsAreEqual.ts @@ -0,0 +1,2 @@ +export const setsAreEqual = (xs: Set, ys: Set) => xs.size === ys.size + && [...xs].every((x) => ys.has(x)); diff --git a/src/utilities/splitPathByArrayFields.ts b/src/utilities/splitPathByArrayFields.ts new file mode 100644 index 000000000..db9ec7778 --- /dev/null +++ b/src/utilities/splitPathByArrayFields.ts @@ -0,0 +1,9 @@ +/** + Turns: 'arrayField.0.group123field.arrayField.0.textField' + + Into: ['arrayField', '0', 'group123field.arrayField', '0', 'textField'] +*/ +export function splitPathByArrayFields(str: string): string[] { + const regex = /\.(\d+)\./g; + return str.split(regex).filter(Boolean); +} diff --git a/src/versions/deleteCollectionVersions.ts b/src/versions/deleteCollectionVersions.ts index bb1c14e2d..02ac17a1c 100644 --- a/src/versions/deleteCollectionVersions.ts +++ b/src/versions/deleteCollectionVersions.ts @@ -1,15 +1,18 @@ import { Payload } from '../payload'; +import { PayloadRequest } from '../express/types'; type Args = { payload: Payload slug: string id?: string | number + req?: PayloadRequest } export const deleteCollectionVersions = async ({ payload, slug, id, + req, }: Args): Promise => { try { await payload.db.deleteVersions({ @@ -19,6 +22,7 @@ export const deleteCollectionVersions = async ({ equals: id, }, }, + req, }); } catch (err) { payload.logger.error(`There was an error removing versions for the deleted ${slug} document with ID ${id}.`); diff --git a/src/versions/drafts/replaceWithDraftIfAvailable.ts b/src/versions/drafts/replaceWithDraftIfAvailable.ts index 184d2e313..1f2f47f97 100644 --- a/src/versions/drafts/replaceWithDraftIfAvailable.ts +++ b/src/versions/drafts/replaceWithDraftIfAvailable.ts @@ -24,6 +24,10 @@ const replaceWithDraftIfAvailable = async ({ req, accessResult, }: Arguments): Promise => { + const { + locale, + } = req; + const queryToBuild: Where = { and: [ { @@ -58,12 +62,13 @@ const replaceWithDraftIfAvailable = async ({ const findVersionsArgs: FindVersionsArgs & FindGlobalVersionsArgs = { - locale: req.locale, + locale, where: combineQueries(queryToBuild, versionAccessResult), collection: entity.slug, global: entity.slug, limit: 1, sort: '-updatedAt', + req, }; let versionDocs; diff --git a/src/versions/enforceMaxVersions.ts b/src/versions/enforceMaxVersions.ts index 4110c1eb8..6b317841a 100644 --- a/src/versions/enforceMaxVersions.ts +++ b/src/versions/enforceMaxVersions.ts @@ -2,6 +2,7 @@ import { Payload } from '../payload'; import type { SanitizedCollectionConfig } from '../collections/config/types'; import type { SanitizedGlobalConfig } from '../globals/config/types'; import type { Where } from '../types'; +import { PayloadRequest } from '../types'; type Args = { payload: Payload @@ -9,6 +10,7 @@ type Args = { collection?: SanitizedCollectionConfig global?: SanitizedGlobalConfig id?: string | number + req?: PayloadRequest } export const enforceMaxVersions = async ({ @@ -17,6 +19,7 @@ export const enforceMaxVersions = async ({ collection, global, id, + req, }: Args): Promise => { const entityType = collection ? 'collection' : 'global'; const slug = collection ? collection.slug : global?.slug; @@ -36,6 +39,7 @@ export const enforceMaxVersions = async ({ skip: max, sort: '-updatedAt', pagination: false, + req, }); [oldestAllowedDoc] = query.docs; @@ -45,6 +49,7 @@ export const enforceMaxVersions = async ({ global: global.slug, skip: max, sort: '-updatedAt', + req, }); [oldestAllowedDoc] = query.docs; @@ -66,6 +71,7 @@ export const enforceMaxVersions = async ({ await payload.db.deleteVersions({ collection: collection?.slug, where: deleteQuery, + req, }); } } catch (err) { diff --git a/src/versions/getLatestCollectionVersion.ts b/src/versions/getLatestCollectionVersion.ts index 6fcf17ce7..cecc6a717 100644 --- a/src/versions/getLatestCollectionVersion.ts +++ b/src/versions/getLatestCollectionVersion.ts @@ -1,21 +1,23 @@ -import { docHasTimestamps } from '../types'; +import { docHasTimestamps, PayloadRequest } from '../types'; import { Payload } from '../payload'; import { SanitizedCollectionConfig, TypeWithID } from '../collections/config/types'; import { TypeWithVersion } from './types'; import type { FindOneArgs } from '../database/types'; type Args = { - payload: Payload - query: FindOneArgs - id: string | number - config: SanitizedCollectionConfig -} + payload: Payload; + query: FindOneArgs; + id: string | number; + config: SanitizedCollectionConfig; + req?: PayloadRequest +}; export const getLatestCollectionVersion = async ({ payload, config, query, id, + req, }: Args): Promise => { let latestVersion: TypeWithVersion; @@ -24,14 +26,17 @@ export const getLatestCollectionVersion = async ({ collection: config.slug, where: { parent: { equals: id } }, sort: '-updatedAt', + req, }); [latestVersion] = docs; } - const doc = await payload.db.findOne(query); + const doc = await payload.db.findOne({ ...query, req }); - - if (!latestVersion || (docHasTimestamps(doc) && latestVersion.updatedAt < doc.updatedAt)) { + if ( + !latestVersion + || (docHasTimestamps(doc) && latestVersion.updatedAt < doc.updatedAt) + ) { return doc; } diff --git a/src/versions/getLatestGlobalVersion.ts b/src/versions/getLatestGlobalVersion.ts index 642a76409..042902664 100644 --- a/src/versions/getLatestGlobalVersion.ts +++ b/src/versions/getLatestGlobalVersion.ts @@ -1,5 +1,5 @@ import { Payload } from '../payload'; -import { docHasTimestamps, Document, Where } from '../types'; +import { docHasTimestamps, Document, PayloadRequest, Where } from '../types'; import { SanitizedGlobalConfig } from '../globals/config/types'; type Args = { @@ -8,6 +8,7 @@ type Args = { slug: string config: SanitizedGlobalConfig locale?: string + req?: PayloadRequest } export const getLatestGlobalVersion = async ({ @@ -16,6 +17,7 @@ export const getLatestGlobalVersion = async ({ slug, where, locale, + req, }: Args): Promise<{global: Document, globalExists: boolean}> => { let latestVersion; @@ -26,6 +28,7 @@ export const getLatestGlobalVersion = async ({ limit: 1, sort: '-updatedAt', locale, + req, })).docs[0]; } @@ -33,6 +36,7 @@ export const getLatestGlobalVersion = async ({ slug, where, locale, + req, }); const globalExists = Boolean(global); diff --git a/src/versions/saveVersion.ts b/src/versions/saveVersion.ts index cb7d0b0cd..83591217a 100644 --- a/src/versions/saveVersion.ts +++ b/src/versions/saveVersion.ts @@ -9,11 +9,11 @@ type Args = { payload: Payload global?: SanitizedGlobalConfig collection?: SanitizedCollectionConfig - req: PayloadRequest docWithLocales: any id?: string | number autosave?: boolean draft?: boolean + req?: PayloadRequest } export const saveVersion = async ({ @@ -24,6 +24,7 @@ export const saveVersion = async ({ docWithLocales: doc, autosave, draft, + req, }: Args): Promise => { let result; let entityConfig; @@ -53,6 +54,7 @@ export const saveVersion = async ({ }, }, sort: '-updatedAt', + req, }); const [latestVersion] = docs; @@ -75,6 +77,7 @@ export const saveVersion = async ({ equals: latestVersion.id, }, }, + req, }); } } @@ -87,6 +90,7 @@ export const saveVersion = async ({ createdAt: doc?.createdAt ? new Date(doc.createdAt).toISOString() : now, updatedAt: draft ? now : new Date(doc.updatedAt).toISOString(), versionData, + req, }); } } catch (err) { @@ -110,6 +114,7 @@ export const saveVersion = async ({ collection, global, max, + req, }); } diff --git a/templates/ecommerce/.env.example b/templates/ecommerce/.env.example index d208fd3cf..885b1efba 100644 --- a/templates/ecommerce/.env.example +++ b/templates/ecommerce/.env.example @@ -1,8 +1,7 @@ # Payload vars -PORT=8000 +PORT=3000 MONGODB_URI=mongodb://localhost/payload-template-ecommerce PAYLOAD_SECRET=712kjbkuh87234sflj98713b -PAYLOAD_PUBLIC_SERVER_URL=http://localhost:8000 PAYLOAD_PUBLIC_SERVER_URL=http://localhost:3000 STRIPE_SECRET_KEY= PAYLOAD_PUBLIC_STRIPE_IS_TEST_KEY=true @@ -10,6 +9,5 @@ STRIPE_WEBHOOKS_ENDPOINT_SECRET= # Next.js vars NEXT_PUBLIC_SERVER_URL=http://localhost:3000 -NEXT_PUBLIC_SERVER_URL=http://localhost:8000 NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY= NEXT_PUBLIC_IS_LIVE= diff --git a/test/_community/e2e.spec.ts b/test/_community/e2e.spec.ts index d2795ca2c..9330374b6 100644 --- a/test/_community/e2e.spec.ts +++ b/test/_community/e2e.spec.ts @@ -2,7 +2,6 @@ import type { Page } from '@playwright/test'; import { expect, test } from '@playwright/test'; import { AdminUrlUtil } from '../helpers/adminUrlUtil'; import { initPayloadE2E } from '../helpers/configHelpers'; -import { login } from '../helpers'; const { beforeAll, describe } = test; let url: AdminUrlUtil; @@ -16,11 +15,6 @@ describe('Admin Panel', () => { const context = await browser.newContext(); page = await context.newPage(); - - await login({ - page, - serverURL, - }); }); test('example test', async () => { diff --git a/test/_community/int.spec.ts b/test/_community/int.spec.ts index 02d4de240..f7d9ee689 100644 --- a/test/_community/int.spec.ts +++ b/test/_community/int.spec.ts @@ -1,4 +1,3 @@ -import mongoose from 'mongoose'; import payload from '../../src'; import { initPayloadTest } from '../helpers/configHelpers'; import { devUser } from '../credentials'; @@ -35,9 +34,7 @@ describe('_Community Tests', () => { }); afterAll(async () => { - await mongoose.connection.dropDatabase(); - await mongoose.connection.close(); - await payload.mongoMemoryServer.stop(); + await payload.db.destroy(payload); }); // --__--__--__--__--__--__--__--__--__ diff --git a/test/access-control/e2e.spec.ts b/test/access-control/e2e.spec.ts index 69543bdec..7017cc170 100644 --- a/test/access-control/e2e.spec.ts +++ b/test/access-control/e2e.spec.ts @@ -3,7 +3,6 @@ import { expect, test } from '@playwright/test'; import payload from '../../src'; import { AdminUrlUtil } from '../helpers/adminUrlUtil'; import { initPayloadE2E } from '../helpers/configHelpers'; -import { login } from '../helpers'; import { restrictedVersionsSlug, readOnlySlug, restrictedSlug, slug, docLevelAccessSlug, unrestrictedSlug } from './config'; import type { ReadOnlyCollection, RestrictedVersion } from './payload-types'; import wait from '../../src/utilities/wait'; @@ -37,8 +36,6 @@ describe('access control', () => { const context = await browser.newContext(); page = await context.newPage(); - - await login({ page, serverURL }); }); test('field without read access should not show', async () => { diff --git a/test/access-control/int.spec.ts b/test/access-control/int.spec.ts index cb6abe05b..6a6f7cbcb 100644 --- a/test/access-control/int.spec.ts +++ b/test/access-control/int.spec.ts @@ -1,4 +1,3 @@ -import mongoose from 'mongoose'; import payload from '../../src'; import { Forbidden } from '../../src/errors'; import type { PayloadRequest } from '../../src/types'; @@ -37,9 +36,7 @@ describe('Access Control', () => { }); afterAll(async () => { - await mongoose.connection.dropDatabase(); - await mongoose.connection.close(); - await payload.mongoMemoryServer.stop(); + await payload.db.destroy(payload); }); it('should not affect hidden fields when patching data', async () => { diff --git a/test/admin/e2e.spec.ts b/test/admin/e2e.spec.ts index 031f44671..2888142dc 100644 --- a/test/admin/e2e.spec.ts +++ b/test/admin/e2e.spec.ts @@ -3,7 +3,7 @@ import { expect, test } from '@playwright/test'; import payload from '../../src'; import { AdminUrlUtil } from '../helpers/adminUrlUtil'; import { initPayloadE2E } from '../helpers/configHelpers'; -import { login, saveDocAndAssert } from '../helpers'; +import { saveDocAndAssert } from '../helpers'; import type { Post } from './config'; import { globalSlug, slug } from './shared'; import { mapAsync } from '../../src/utilities/mapAsync'; @@ -26,8 +26,6 @@ describe('admin', () => { const context = await browser.newContext(); page = await context.newPage(); - - await login({ page, serverURL }); }); afterEach(async () => { diff --git a/test/array-update/int.spec.ts b/test/array-update/int.spec.ts index bde66c091..72c181843 100644 --- a/test/array-update/int.spec.ts +++ b/test/array-update/int.spec.ts @@ -1,4 +1,3 @@ -import mongoose from 'mongoose'; import { initPayloadTest } from '../helpers/configHelpers'; import payload from '../../src'; import configPromise from './config'; @@ -13,9 +12,7 @@ describe('array-update', () => { }); afterAll(async () => { - await mongoose.connection.dropDatabase(); - await mongoose.connection.close(); - await payload.mongoMemoryServer.stop(); + await payload.db.destroy(payload); }); it('should persist existing array-based data while updating and passing row ID', async () => { diff --git a/test/auth/AuthDebug.tsx b/test/auth/AuthDebug.tsx new file mode 100644 index 000000000..d0de538b2 --- /dev/null +++ b/test/auth/AuthDebug.tsx @@ -0,0 +1,29 @@ +import React, { useEffect, useState } from 'react'; +import { useAuth } from '../../src/admin/components/utilities/Auth'; +import { User } from '../../src/auth'; +import { UIField } from '../../src/fields/config/types'; + +export const AuthDebug: React.FC = () => { + const [state, setState] = useState(); + const { user } = useAuth(); + + useEffect(() => { + const fetchUser = async () => { + const userRes = await fetch(`/api/users/${user?.id}`)?.then((res) => res.json()); + setState(userRes); + }; + + fetchUser(); + }, [user]); + + return ( +
    +
    + {user?.custom as string} +
    +
    + {state?.custom as string} +
    +
    + ); +}; diff --git a/test/auth/config.ts b/test/auth/config.ts index 19810289a..b98f9cf30 100644 --- a/test/auth/config.ts +++ b/test/auth/config.ts @@ -2,12 +2,14 @@ import { v4 as uuid } from 'uuid'; import { mapAsync } from '../../src/utilities/mapAsync'; import { buildConfig } from '../buildConfig'; import { devUser } from '../credentials'; +import { AuthDebug } from './AuthDebug'; export const slug = 'users'; export default buildConfig({ admin: { user: 'users', + autoLogin: false, }, collections: [ { @@ -36,6 +38,21 @@ export default buildConfig({ saveToJWT: true, hasMany: true, }, + { + name: 'custom', + label: 'Custom', + type: 'text', + }, + { + name: 'authDebug', + label: 'Auth Debug', + type: 'ui', + admin: { + components: { + Field: AuthDebug, + }, + }, + }, ], }, { @@ -65,6 +82,7 @@ export default buildConfig({ data: { email: devUser.email, password: devUser.password, + custom: 'Hello, world!', }, }); diff --git a/test/auth/custom-strategy/int.spec.ts b/test/auth/custom-strategy/int.spec.ts index 0c3a8a782..0a7fcb7ae 100644 --- a/test/auth/custom-strategy/int.spec.ts +++ b/test/auth/custom-strategy/int.spec.ts @@ -1,4 +1,3 @@ -import mongoose from 'mongoose'; import payload from '../../../src'; import { initPayloadTest } from '../../helpers/configHelpers'; import { slug } from './config'; @@ -20,9 +19,7 @@ describe('AuthStrategies', () => { }); afterAll(async () => { - await mongoose.connection.dropDatabase(); - await mongoose.connection.close(); - await payload.mongoMemoryServer.stop(); + await payload.db.destroy(payload); }); describe('create user', () => { diff --git a/test/auth/e2e.spec.ts b/test/auth/e2e.spec.ts index f05a65558..a567a6619 100644 --- a/test/auth/e2e.spec.ts +++ b/test/auth/e2e.spec.ts @@ -1,5 +1,5 @@ import type { Page } from '@playwright/test'; -import { expect, test } from '@playwright/test'; +import { test, expect } from '@playwright/test'; import { AdminUrlUtil } from '../helpers/adminUrlUtil'; import { initPayloadE2E } from '../helpers/configHelpers'; import { login, saveDocAndAssert } from '../helpers'; @@ -42,5 +42,19 @@ describe('auth', () => { await saveDocAndAssert(page); }); + + test('should have up-to-date user in `useAuth` hook', async () => { + await page.goto(url.account); + + await expect(await page.locator('#users-api-result')).toHaveText('Hello, world!'); + await expect(await page.locator('#use-auth-result')).toHaveText('Hello, world!'); + + const field = await page.locator('#field-custom'); + await field.fill('Goodbye, world!'); + await saveDocAndAssert(page); + + await expect(await page.locator('#users-api-result')).toHaveText('Goodbye, world!'); + await expect(await page.locator('#use-auth-result')).toHaveText('Goodbye, world!'); + }); }); }); diff --git a/test/auth/int.spec.ts b/test/auth/int.spec.ts index 1bbf3ca94..97986669f 100644 --- a/test/auth/int.spec.ts +++ b/test/auth/int.spec.ts @@ -3,6 +3,7 @@ import payload from '../../src'; import { initPayloadTest } from '../helpers/configHelpers'; import { slug } from './config'; import { devUser } from '../credentials'; +import type { User } from '../../src/auth'; require('isomorphic-fetch'); @@ -11,6 +12,7 @@ let apiUrl; const headers = { 'Content-Type': 'application/json', }; + const { email, password } = devUser; describe('Auth', () => { @@ -20,9 +22,7 @@ describe('Auth', () => { }); afterAll(async () => { - await mongoose.connection.dropDatabase(); - await mongoose.connection.close(); - await payload.mongoMemoryServer.stop(); + await payload.db.destroy(payload); }); describe('admin user', () => { @@ -68,6 +68,8 @@ describe('Auth', () => { describe('logged in', () => { let token: string | undefined; + let loggedInUser: User | undefined; + beforeAll(async () => { const response = await fetch(`${apiUrl}/${slug}/login`, { body: JSON.stringify({ @@ -80,6 +82,7 @@ describe('Auth', () => { const data = await response.json(); token = data.token; + loggedInUser = data.user; }); it('should return a logged in user from /me', async () => { @@ -99,6 +102,7 @@ describe('Auth', () => { it('should allow authentication with an API key with useAPIKey', async () => { const apiKey = '0123456789ABCDEFGH'; + const user = await payload.create({ collection: slug, data: { @@ -107,10 +111,11 @@ describe('Auth', () => { apiKey, }, }); + const response = await fetch(`${apiUrl}/${slug}/me`, { headers: { ...headers, - Authorization: `${slug} API-Key ${user.apiKey}`, + Authorization: `${slug} API-Key ${user?.apiKey}`, }, }); @@ -135,6 +140,30 @@ describe('Auth', () => { expect(data.refreshedToken).toBeDefined(); }); + it('should refresh a token and receive an up-to-date user', async () => { + expect(loggedInUser?.custom).toBe('Hello, world!'); + + await payload.update({ + collection: slug, + id: loggedInUser?.id || '', + data: { + custom: 'Goodbye, world!', + }, + }); + + const response = await fetch(`${apiUrl}/${slug}/refresh-token`, { + method: 'post', + headers: { + Authorization: `JWT ${token}`, + }, + }); + + const data = await response.json(); + + expect(response.status).toBe(200); + expect(data.user.custom).toBe('Goodbye, world!'); + }); + it('should allow a user to be created', async () => { const response = await fetch(`${apiUrl}/${slug}`, { body: JSON.stringify({ @@ -200,6 +229,7 @@ describe('Auth', () => { expect(verificationResponse.status).toBe(200); const afterVerifyResult = await db.collection('public-users').findOne({ email: emailToVerify }); + // @ts-expect-error trust const { _verified: afterVerified, _verificationToken: afterToken } = afterVerifyResult; expect(afterVerified).toBe(true); expect(afterToken).toBeUndefined(); diff --git a/test/auth/ui/AuthDebug.tsx b/test/auth/ui/AuthDebug.tsx new file mode 100644 index 000000000..2c52ba9b5 --- /dev/null +++ b/test/auth/ui/AuthDebug.tsx @@ -0,0 +1,28 @@ +import React, { useEffect, useState } from 'react'; +import { useAuth } from '../../../src/admin/components/utilities/Auth'; +import { UIField } from '../../../src/fields/config/types'; +import { User } from '../../../src/auth'; + +export const AuthDebug: React.FC = () => { + const [state, setState] = useState(); + const { user } = useAuth(); + + useEffect(() => { + if (user) { + fetch(`/api/users/${user.id}`).then((r) => r.json()).then((newUser) => { + setState(newUser); + }); + } + }, [user]); + + return ( +
    +
    + {state?.custom as string} +
    +
    + {user?.custom as string} +
    +
    + ); +}; diff --git a/test/buildConfig.ts b/test/buildConfig.ts index bd5693216..4ee56812c 100644 --- a/test/buildConfig.ts +++ b/test/buildConfig.ts @@ -11,8 +11,11 @@ export function buildConfig(config?: Partial): Promise }, ...config, }; - baseConfig.admin = { + autoLogin: process.env.PAYLOAD_PUBLIC_DISABLE_AUTO_LOGIN === 'true' ? false : { + email: 'dev@payloadcms.com', + password: 'test', + }, ...(baseConfig.admin || {}), webpack: (webpackConfig) => { const existingConfig = typeof config?.admin?.webpack === 'function' diff --git a/test/collections-graphql/int.spec.ts b/test/collections-graphql/int.spec.ts index 0230f64e9..66aff81d0 100644 --- a/test/collections-graphql/int.spec.ts +++ b/test/collections-graphql/int.spec.ts @@ -1,4 +1,3 @@ -import mongoose from 'mongoose'; import { GraphQLClient } from 'graphql-request'; import { initPayloadTest } from '../helpers/configHelpers'; import configPromise, { slug } from './config'; @@ -18,9 +17,7 @@ describe('collections-graphql', () => { }); afterAll(async () => { - await mongoose.connection.dropDatabase(); - await mongoose.connection.close(); - await payload.mongoMemoryServer.stop(); + await payload.db.destroy(payload); }); describe('CRUD', () => { @@ -97,7 +94,7 @@ describe('collections-graphql', () => { } } } - } + } `; const response = await client.request(query); diff --git a/test/collections-rest/int.spec.ts b/test/collections-rest/int.spec.ts index 30304c7f3..9b0d8c34a 100644 --- a/test/collections-rest/int.spec.ts +++ b/test/collections-rest/int.spec.ts @@ -1,4 +1,3 @@ -import mongoose from 'mongoose'; import { randomBytes } from 'crypto'; import { initPayloadTest } from '../helpers/configHelpers'; import type { Relation } from './config'; @@ -17,9 +16,7 @@ describe('collections-rest', () => { }); afterAll(async () => { - await mongoose.connection.dropDatabase(); - await mongoose.connection.close(); - await payload.mongoMemoryServer.stop(); + await payload.db.destroy(payload); }); beforeEach(async () => { diff --git a/test/dev.ts b/test/dev.ts index b474f0b99..9b00b952e 100644 --- a/test/dev.ts +++ b/test/dev.ts @@ -25,6 +25,10 @@ process.env.PAYLOAD_CONFIG_PATH = configPath; process.env.PAYLOAD_DROP_DATABASE = 'true'; +if (process.argv.includes('--no-auto-login') && process.env.NODE_ENV !== 'production') { + process.env.PAYLOAD_PUBLIC_DISABLE_AUTO_LOGIN = 'true'; +} + const expressApp = express(); const startDev = async () => { diff --git a/test/field-error-states/collections/ErrorFields/index.ts b/test/field-error-states/collections/ErrorFields/index.ts new file mode 100644 index 000000000..cbbae49e1 --- /dev/null +++ b/test/field-error-states/collections/ErrorFields/index.ts @@ -0,0 +1,219 @@ +import type { CollectionConfig } from '../../../../src/collections/config/types'; +import { Field } from '../../../../src/fields/config/types'; + +export const errorFieldsSlug = 'error-fields'; + +const errorFields: Field[] = [ + { + type: 'text', + name: 'tabText', + required: true, + }, + { + type: 'collapsible', + label: 'Collapse me', + fields: [ + { + type: 'text', + name: 'text', + required: true, + }, + ], + }, + { + type: 'array', + name: 'array', + fields: [ + { + name: 'requiredArrayText', + type: 'text', + required: true, + }, + { + name: 'arrayText', + type: 'text', + }, + { + type: 'collapsible', + label: 'Collapse me', + fields: [ + { + type: 'group', + name: 'group', + fields: [ + { + type: 'text', + name: 'text', + required: true, + }, + { + type: 'number', + name: 'number', + required: true, + }, + { + type: 'date', + name: 'date', + required: true, + }, + { + type: 'checkbox', + name: 'checkbox', + required: true, + validate: (value) => { + if (!value) { + return 'This field is required'; + } + return true; + }, + }, + ], + }, + { + type: 'row', + fields: [ + { + type: 'code', + name: 'code', + required: true, + }, + { + type: 'json', + name: 'json', + required: true, + }, + ], + }, + { + type: 'email', + name: 'email', + required: true, + }, + { + type: 'point', + name: 'point', + required: true, + }, + { + type: 'radio', + name: 'radio', + required: true, + options: [ + { + label: 'Mint', + value: 'mint', + }, + { + label: 'Dark Gray', + value: 'dark_gray', + }, + ], + }, + { + type: 'relationship', + name: 'relationship', + relationTo: 'users', + required: true, + }, + { + type: 'richText', + name: 'richtext', + required: true, + }, + { + type: 'select', + name: 'select', + required: true, + options: [ + { + label: 'Mint', + value: 'mint', + }, + { + label: 'Dark Gray', + value: 'dark_gray', + }, + ], + }, + { + type: 'upload', + name: 'upload', + required: true, + relationTo: 'uploads', + }, + { + type: 'text', + name: 'text', + required: true, + }, + { + type: 'textarea', + name: 'textarea', + required: true, + }, + ], + }, + ], + }, +]; + +export const ErrorFieldsCollection: CollectionConfig = { + slug: errorFieldsSlug, + fields: [ + { + type: 'array', + name: 'parentArray', + fields: [ + { + type: 'array', + name: 'childArray', + required: true, + minRows: 2, + fields: [ + { + type: 'text', + name: 'childArrayText', + required: true, + }, + ], + }, + ], + }, + { + type: 'tabs', + tabs: [ + { + label: 'Home', + name: 'home', + fields: errorFields, + }, + { + label: 'Hero', + fields: errorFields, + }, + ], + }, + { + type: 'blocks', + name: 'layout', + blocks: [ + { + slug: 'block1', + fields: errorFields, + }, + ], + }, + { + type: 'group', + name: 'group', + label: 'Group Field', + fields: [ + { + type: 'text', + name: 'text', + required: true, + }, + ], + }, + ], +}; diff --git a/test/field-error-states/collections/Upload/.gitignore b/test/field-error-states/collections/Upload/.gitignore new file mode 100644 index 000000000..3f549faf9 --- /dev/null +++ b/test/field-error-states/collections/Upload/.gitignore @@ -0,0 +1 @@ +uploads diff --git a/test/field-error-states/collections/Upload/index.ts b/test/field-error-states/collections/Upload/index.ts new file mode 100644 index 000000000..8f84cfaca --- /dev/null +++ b/test/field-error-states/collections/Upload/index.ts @@ -0,0 +1,35 @@ +import path from 'path'; +import { CollectionConfig } from '../../../../src/collections/config/types'; + +const Uploads: CollectionConfig = { + slug: 'uploads', + upload: { + staticDir: path.resolve(__dirname, './uploads'), + }, + fields: [ + { + type: 'text', + name: 'text', + }, + { + type: 'upload', + name: 'media', + relationTo: 'uploads', + filterOptions: { + mimeType: { + equals: 'image/png', + }, + }, + }, + { + type: 'richText', + name: 'richText', + }, + ], +}; + +export const uploadsDoc = { + text: 'An upload here', +}; + +export default Uploads; diff --git a/test/field-error-states/config.ts b/test/field-error-states/config.ts new file mode 100644 index 000000000..a79122bbd --- /dev/null +++ b/test/field-error-states/config.ts @@ -0,0 +1,24 @@ +import { buildConfig } from '../buildConfig'; +import { ErrorFieldsCollection } from './collections/ErrorFields'; +import { devUser } from '../credentials'; +import Uploads from './collections/Upload'; + +export default buildConfig({ + collections: [ + ErrorFieldsCollection, + Uploads, + ], + graphQL: { + schemaOutputFile: './test/field-error-states/schema.graphql', + }, + + onInit: async (payload) => { + await payload.create({ + collection: 'users', + data: { + email: devUser.email, + password: devUser.password, + }, + }); + }, +}); diff --git a/test/field-error-states/e2e.spec.ts b/test/field-error-states/e2e.spec.ts new file mode 100644 index 000000000..b177dbdb2 --- /dev/null +++ b/test/field-error-states/e2e.spec.ts @@ -0,0 +1,42 @@ +import { expect, Page, test } from '@playwright/test'; +import { initPayloadE2E } from '../helpers/configHelpers'; + +const { beforeAll, describe } = test; + +describe('field error states', () => { + let serverURL: string; + let page: Page; + + beforeAll(async ({ browser }) => { + ({ serverURL } = await initPayloadE2E(__dirname)); + const context = await browser.newContext(); + page = await context.newPage(); + }); + + test('Remove row should remove error states from parent fields', async () => { + await page.goto(`${serverURL}/admin/collections/error-fields/create`); + + // add parent array + await page.locator('#field-parentArray > .array-field__add-button-wrap > button').click(); + + // add first child array + await page.locator('#parentArray-row-0 .collapsible__content .array-field__add-button-wrap > button').click(); + await page.locator('#field-parentArray__0__childArray__0__childArrayText').focus(); + await page.keyboard.type('T1'); + + // add second child array + await page.locator('#parentArray-row-0 .collapsible__content .array-field__add-button-wrap > button').click(); + await page.locator('#field-parentArray__0__childArray__1__childArrayText').focus(); + await page.keyboard.type('T2'); + + // add third child array + await page.locator('#parentArray-row-0 .collapsible__content .array-field__add-button-wrap > button').click(); + await page.locator('#parentArray-0-childArray-row-2 .array-actions__button').click(); + await page.locator('#parentArray-0-childArray-row-2 .array-actions__action.array-actions__remove').click(); + + await page.locator('#action-save').click(); + + const errorPill = await page.waitForSelector('#parentArray-row-0 > .collapsible > .collapsible__toggle-wrap .array-field__row-error-pill', { state: 'hidden', timeout: 500 }); + expect(errorPill).toBeNull(); + }); +}); diff --git a/test/field-error-states/payload-types.ts b/test/field-error-states/payload-types.ts new file mode 100644 index 000000000..e5223510b --- /dev/null +++ b/test/field-error-states/payload-types.ts @@ -0,0 +1,46 @@ +/* tslint:disable */ +/** + * This file was automatically generated by Payload CMS. + * DO NOT MODIFY IT BY HAND. Instead, modify your source Payload config, + * and re-run `payload generate:types` to regenerate this file. + */ + +export interface Config { + collections: { + posts: Post; + users: User; + }; + globals: {}; +} +export interface Post { + id: string; + arrayField?: { + group23field: { + arrayField: { + group23field: { + arrayField: { + textField: string; + id?: string; + }[]; + }; + id?: string; + }[]; + }; + id?: string; + }[]; + updatedAt: string; + createdAt: string; +} +export interface User { + id: string; + updatedAt: string; + createdAt: string; + email?: string; + resetPasswordToken?: string; + resetPasswordExpiration?: string; + salt?: string; + hash?: string; + loginAttempts?: number; + lockUntil?: string; + password?: string; +} diff --git a/test/field-error-states/schema.graphql b/test/field-error-states/schema.graphql new file mode 100644 index 000000000..499274fd1 --- /dev/null +++ b/test/field-error-states/schema.graphql @@ -0,0 +1,1319 @@ +type Query { + Post(id: String!, draft: Boolean): Post + Posts(where: Post_where, draft: Boolean, page: Int, limit: Int, sort: String): Posts + docAccessPost(id: String!): postsDocAccess + User(id: String!, draft: Boolean): User + Users(where: User_where, draft: Boolean, page: Int, limit: Int, sort: String): Users + docAccessUser(id: String!): usersDocAccess + meUser: usersMe + initializedUser: Boolean + Preference(key: String): Preference + Access: Access +} + +type Post { + id: String + arrayField: [Post_ArrayField!] + updatedAt: DateTime + createdAt: DateTime +} + +type Post_ArrayField { + group23field: Post_ArrayField_Group23field + id: String +} + +type Post_ArrayField_Group23field { + arrayField: [Post_ArrayField_Group23field_ArrayField!]! +} + +type Post_ArrayField_Group23field_ArrayField { + group23field: Post_ArrayField_Group23field_ArrayField_Group23field + id: String +} + +type Post_ArrayField_Group23field_ArrayField_Group23field { + arrayField: [Post_ArrayField_Group23field_ArrayField_Group23field_ArrayField!]! +} + +type Post_ArrayField_Group23field_ArrayField_Group23field_ArrayField { + textField: String! + id: String +} + +""" +A date-time string at UTC, such as 2007-12-03T10:15:30Z, compliant with the `date-time` format outlined in section 5.6 of the RFC 3339 profile of the ISO 8601 standard for representation of dates and times using the Gregorian calendar. +""" +scalar DateTime + +type Posts { + docs: [Post] + totalDocs: Int + offset: Int + limit: Int + totalPages: Int + page: Int + pagingCounter: Int + hasPrevPage: Boolean + hasNextPage: Boolean + prevPage: Int + nextPage: Int +} + +input Post_where { + arrayField__group23field__arrayField__group23field__arrayField__textField: Post_arrayField__group23field__arrayField__group23field__arrayField__textField_operator + arrayField__group23field__arrayField__group23field__arrayField__id: Post_arrayField__group23field__arrayField__group23field__arrayField__id_operator + arrayField__group23field__arrayField__id: Post_arrayField__group23field__arrayField__id_operator + arrayField__id: Post_arrayField__id_operator + updatedAt: Post_updatedAt_operator + createdAt: Post_createdAt_operator + id: Post_id_operator + OR: [Post_where_or] + AND: [Post_where_and] +} + +input Post_arrayField__group23field__arrayField__group23field__arrayField__textField_operator { + equals: String + not_equals: String + like: String + contains: String + in: [String] + not_in: [String] + all: [String] +} + +input Post_arrayField__group23field__arrayField__group23field__arrayField__id_operator { + equals: String + not_equals: String + like: String + contains: String + in: [String] + not_in: [String] + all: [String] + exists: Boolean +} + +input Post_arrayField__group23field__arrayField__id_operator { + equals: String + not_equals: String + like: String + contains: String + in: [String] + not_in: [String] + all: [String] + exists: Boolean +} + +input Post_arrayField__id_operator { + equals: String + not_equals: String + like: String + contains: String + in: [String] + not_in: [String] + all: [String] + exists: Boolean +} + +input Post_updatedAt_operator { + equals: DateTime + not_equals: DateTime + greater_than_equal: DateTime + greater_than: DateTime + less_than_equal: DateTime + less_than: DateTime + like: DateTime + exists: Boolean +} + +input Post_createdAt_operator { + equals: DateTime + not_equals: DateTime + greater_than_equal: DateTime + greater_than: DateTime + less_than_equal: DateTime + less_than: DateTime + like: DateTime + exists: Boolean +} + +input Post_id_operator { + equals: String + not_equals: String + like: String + contains: String + in: [String] + not_in: [String] + all: [String] + exists: Boolean +} + +input Post_where_or { + arrayField__group23field__arrayField__group23field__arrayField__textField: Post_arrayField__group23field__arrayField__group23field__arrayField__textField_operator + arrayField__group23field__arrayField__group23field__arrayField__id: Post_arrayField__group23field__arrayField__group23field__arrayField__id_operator + arrayField__group23field__arrayField__id: Post_arrayField__group23field__arrayField__id_operator + arrayField__id: Post_arrayField__id_operator + updatedAt: Post_updatedAt_operator + createdAt: Post_createdAt_operator + id: Post_id_operator +} + +input Post_where_and { + arrayField__group23field__arrayField__group23field__arrayField__textField: Post_arrayField__group23field__arrayField__group23field__arrayField__textField_operator + arrayField__group23field__arrayField__group23field__arrayField__id: Post_arrayField__group23field__arrayField__group23field__arrayField__id_operator + arrayField__group23field__arrayField__id: Post_arrayField__group23field__arrayField__id_operator + arrayField__id: Post_arrayField__id_operator + updatedAt: Post_updatedAt_operator + createdAt: Post_createdAt_operator + id: Post_id_operator +} + +type postsDocAccess { + fields: PostsDocAccessFields + create: PostsCreateDocAccess + read: PostsReadDocAccess + update: PostsUpdateDocAccess + delete: PostsDeleteDocAccess +} + +type PostsDocAccessFields { + arrayField: PostsDocAccessFields_arrayField + updatedAt: PostsDocAccessFields_updatedAt + createdAt: PostsDocAccessFields_createdAt +} + +type PostsDocAccessFields_arrayField { + create: PostsDocAccessFields_arrayField_Create + read: PostsDocAccessFields_arrayField_Read + update: PostsDocAccessFields_arrayField_Update + delete: PostsDocAccessFields_arrayField_Delete + fields: PostsDocAccessFields_arrayField_Fields +} + +type PostsDocAccessFields_arrayField_Create { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_Read { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_Update { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_Delete { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_Fields { + group23field: PostsDocAccessFields_arrayField_group23field + id: PostsDocAccessFields_arrayField_id +} + +type PostsDocAccessFields_arrayField_group23field { + create: PostsDocAccessFields_arrayField_group23field_Create + read: PostsDocAccessFields_arrayField_group23field_Read + update: PostsDocAccessFields_arrayField_group23field_Update + delete: PostsDocAccessFields_arrayField_group23field_Delete + fields: PostsDocAccessFields_arrayField_group23field_Fields +} + +type PostsDocAccessFields_arrayField_group23field_Create { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_group23field_Read { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_group23field_Update { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_group23field_Delete { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_group23field_Fields { + arrayField: PostsDocAccessFields_arrayField_group23field_arrayField +} + +type PostsDocAccessFields_arrayField_group23field_arrayField { + create: PostsDocAccessFields_arrayField_group23field_arrayField_Create + read: PostsDocAccessFields_arrayField_group23field_arrayField_Read + update: PostsDocAccessFields_arrayField_group23field_arrayField_Update + delete: PostsDocAccessFields_arrayField_group23field_arrayField_Delete + fields: PostsDocAccessFields_arrayField_group23field_arrayField_Fields +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_Create { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_Read { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_Update { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_Delete { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_Fields { + group23field: PostsDocAccessFields_arrayField_group23field_arrayField_group23field + id: PostsDocAccessFields_arrayField_group23field_arrayField_id +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_group23field { + create: PostsDocAccessFields_arrayField_group23field_arrayField_group23field_Create + read: PostsDocAccessFields_arrayField_group23field_arrayField_group23field_Read + update: PostsDocAccessFields_arrayField_group23field_arrayField_group23field_Update + delete: PostsDocAccessFields_arrayField_group23field_arrayField_group23field_Delete + fields: PostsDocAccessFields_arrayField_group23field_arrayField_group23field_Fields +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_group23field_Create { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_group23field_Read { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_group23field_Update { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_group23field_Delete { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_group23field_Fields { + arrayField: PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField { + create: PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField_Create + read: PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField_Read + update: PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField_Update + delete: PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField_Delete + fields: PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField_Fields +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField_Create { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField_Read { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField_Update { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField_Delete { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField_Fields { + textField: PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField_textField + id: PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField_id +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField_textField { + create: PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField_textField_Create + read: PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField_textField_Read + update: PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField_textField_Update + delete: PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField_textField_Delete +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField_textField_Create { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField_textField_Read { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField_textField_Update { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField_textField_Delete { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField_id { + create: PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField_id_Create + read: PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField_id_Read + update: PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField_id_Update + delete: PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField_id_Delete +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField_id_Create { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField_id_Read { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField_id_Update { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_group23field_arrayField_id_Delete { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_id { + create: PostsDocAccessFields_arrayField_group23field_arrayField_id_Create + read: PostsDocAccessFields_arrayField_group23field_arrayField_id_Read + update: PostsDocAccessFields_arrayField_group23field_arrayField_id_Update + delete: PostsDocAccessFields_arrayField_group23field_arrayField_id_Delete +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_id_Create { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_id_Read { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_id_Update { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_group23field_arrayField_id_Delete { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_id { + create: PostsDocAccessFields_arrayField_id_Create + read: PostsDocAccessFields_arrayField_id_Read + update: PostsDocAccessFields_arrayField_id_Update + delete: PostsDocAccessFields_arrayField_id_Delete +} + +type PostsDocAccessFields_arrayField_id_Create { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_id_Read { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_id_Update { + permission: Boolean! +} + +type PostsDocAccessFields_arrayField_id_Delete { + permission: Boolean! +} + +type PostsDocAccessFields_updatedAt { + create: PostsDocAccessFields_updatedAt_Create + read: PostsDocAccessFields_updatedAt_Read + update: PostsDocAccessFields_updatedAt_Update + delete: PostsDocAccessFields_updatedAt_Delete +} + +type PostsDocAccessFields_updatedAt_Create { + permission: Boolean! +} + +type PostsDocAccessFields_updatedAt_Read { + permission: Boolean! +} + +type PostsDocAccessFields_updatedAt_Update { + permission: Boolean! +} + +type PostsDocAccessFields_updatedAt_Delete { + permission: Boolean! +} + +type PostsDocAccessFields_createdAt { + create: PostsDocAccessFields_createdAt_Create + read: PostsDocAccessFields_createdAt_Read + update: PostsDocAccessFields_createdAt_Update + delete: PostsDocAccessFields_createdAt_Delete +} + +type PostsDocAccessFields_createdAt_Create { + permission: Boolean! +} + +type PostsDocAccessFields_createdAt_Read { + permission: Boolean! +} + +type PostsDocAccessFields_createdAt_Update { + permission: Boolean! +} + +type PostsDocAccessFields_createdAt_Delete { + permission: Boolean! +} + +type PostsCreateDocAccess { + permission: Boolean! + where: JSONObject +} + +""" +The `JSONObject` scalar type represents JSON objects as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). +""" +scalar JSONObject + +type PostsReadDocAccess { + permission: Boolean! + where: JSONObject +} + +type PostsUpdateDocAccess { + permission: Boolean! + where: JSONObject +} + +type PostsDeleteDocAccess { + permission: Boolean! + where: JSONObject +} + +type User { + id: String + updatedAt: DateTime + createdAt: DateTime + email: EmailAddress + resetPasswordToken: String + resetPasswordExpiration: DateTime + salt: String + hash: String + loginAttempts: Float + lockUntil: DateTime + password: String! +} + +""" +A field whose value conforms to the standard internet email address format as specified in HTML Spec: https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address. +""" +scalar EmailAddress @specifiedBy(url: "https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address") + +type Users { + docs: [User] + totalDocs: Int + offset: Int + limit: Int + totalPages: Int + page: Int + pagingCounter: Int + hasPrevPage: Boolean + hasNextPage: Boolean + prevPage: Int + nextPage: Int +} + +input User_where { + updatedAt: User_updatedAt_operator + createdAt: User_createdAt_operator + email: User_email_operator + id: User_id_operator + OR: [User_where_or] + AND: [User_where_and] +} + +input User_updatedAt_operator { + equals: DateTime + not_equals: DateTime + greater_than_equal: DateTime + greater_than: DateTime + less_than_equal: DateTime + less_than: DateTime + like: DateTime + exists: Boolean +} + +input User_createdAt_operator { + equals: DateTime + not_equals: DateTime + greater_than_equal: DateTime + greater_than: DateTime + less_than_equal: DateTime + less_than: DateTime + like: DateTime + exists: Boolean +} + +input User_email_operator { + equals: EmailAddress + not_equals: EmailAddress + like: EmailAddress + contains: EmailAddress + in: [EmailAddress] + not_in: [EmailAddress] + all: [EmailAddress] + exists: Boolean +} + +input User_id_operator { + equals: String + not_equals: String + like: String + contains: String + in: [String] + not_in: [String] + all: [String] + exists: Boolean +} + +input User_where_or { + updatedAt: User_updatedAt_operator + createdAt: User_createdAt_operator + email: User_email_operator + id: User_id_operator +} + +input User_where_and { + updatedAt: User_updatedAt_operator + createdAt: User_createdAt_operator + email: User_email_operator + id: User_id_operator +} + +type usersDocAccess { + fields: UsersDocAccessFields + create: UsersCreateDocAccess + read: UsersReadDocAccess + update: UsersUpdateDocAccess + delete: UsersDeleteDocAccess + unlock: UsersUnlockDocAccess +} + +type UsersDocAccessFields { + updatedAt: UsersDocAccessFields_updatedAt + createdAt: UsersDocAccessFields_createdAt + email: UsersDocAccessFields_email + password: UsersDocAccessFields_password +} + +type UsersDocAccessFields_updatedAt { + create: UsersDocAccessFields_updatedAt_Create + read: UsersDocAccessFields_updatedAt_Read + update: UsersDocAccessFields_updatedAt_Update + delete: UsersDocAccessFields_updatedAt_Delete +} + +type UsersDocAccessFields_updatedAt_Create { + permission: Boolean! +} + +type UsersDocAccessFields_updatedAt_Read { + permission: Boolean! +} + +type UsersDocAccessFields_updatedAt_Update { + permission: Boolean! +} + +type UsersDocAccessFields_updatedAt_Delete { + permission: Boolean! +} + +type UsersDocAccessFields_createdAt { + create: UsersDocAccessFields_createdAt_Create + read: UsersDocAccessFields_createdAt_Read + update: UsersDocAccessFields_createdAt_Update + delete: UsersDocAccessFields_createdAt_Delete +} + +type UsersDocAccessFields_createdAt_Create { + permission: Boolean! +} + +type UsersDocAccessFields_createdAt_Read { + permission: Boolean! +} + +type UsersDocAccessFields_createdAt_Update { + permission: Boolean! +} + +type UsersDocAccessFields_createdAt_Delete { + permission: Boolean! +} + +type UsersDocAccessFields_email { + create: UsersDocAccessFields_email_Create + read: UsersDocAccessFields_email_Read + update: UsersDocAccessFields_email_Update + delete: UsersDocAccessFields_email_Delete +} + +type UsersDocAccessFields_email_Create { + permission: Boolean! +} + +type UsersDocAccessFields_email_Read { + permission: Boolean! +} + +type UsersDocAccessFields_email_Update { + permission: Boolean! +} + +type UsersDocAccessFields_email_Delete { + permission: Boolean! +} + +type UsersDocAccessFields_password { + create: UsersDocAccessFields_password_Create + read: UsersDocAccessFields_password_Read + update: UsersDocAccessFields_password_Update + delete: UsersDocAccessFields_password_Delete +} + +type UsersDocAccessFields_password_Create { + permission: Boolean! +} + +type UsersDocAccessFields_password_Read { + permission: Boolean! +} + +type UsersDocAccessFields_password_Update { + permission: Boolean! +} + +type UsersDocAccessFields_password_Delete { + permission: Boolean! +} + +type UsersCreateDocAccess { + permission: Boolean! + where: JSONObject +} + +type UsersReadDocAccess { + permission: Boolean! + where: JSONObject +} + +type UsersUpdateDocAccess { + permission: Boolean! + where: JSONObject +} + +type UsersDeleteDocAccess { + permission: Boolean! + where: JSONObject +} + +type UsersUnlockDocAccess { + permission: Boolean! + where: JSONObject +} + +type usersMe { + token: String + user: User + exp: Int + collection: String +} + +type Preference { + key: String! + value: JSON + createdAt: DateTime! + updatedAt: DateTime! +} + +""" +The `JSON` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). +""" +scalar JSON + +type Access { + canAccessAdmin: Boolean! + posts: postsAccess + users: usersAccess +} + +type postsAccess { + fields: PostsFields + create: PostsCreateAccess + read: PostsReadAccess + update: PostsUpdateAccess + delete: PostsDeleteAccess +} + +type PostsFields { + arrayField: PostsFields_arrayField + updatedAt: PostsFields_updatedAt + createdAt: PostsFields_createdAt +} + +type PostsFields_arrayField { + create: PostsFields_arrayField_Create + read: PostsFields_arrayField_Read + update: PostsFields_arrayField_Update + delete: PostsFields_arrayField_Delete + fields: PostsFields_arrayField_Fields +} + +type PostsFields_arrayField_Create { + permission: Boolean! +} + +type PostsFields_arrayField_Read { + permission: Boolean! +} + +type PostsFields_arrayField_Update { + permission: Boolean! +} + +type PostsFields_arrayField_Delete { + permission: Boolean! +} + +type PostsFields_arrayField_Fields { + group23field: PostsFields_arrayField_group23field + id: PostsFields_arrayField_id +} + +type PostsFields_arrayField_group23field { + create: PostsFields_arrayField_group23field_Create + read: PostsFields_arrayField_group23field_Read + update: PostsFields_arrayField_group23field_Update + delete: PostsFields_arrayField_group23field_Delete + fields: PostsFields_arrayField_group23field_Fields +} + +type PostsFields_arrayField_group23field_Create { + permission: Boolean! +} + +type PostsFields_arrayField_group23field_Read { + permission: Boolean! +} + +type PostsFields_arrayField_group23field_Update { + permission: Boolean! +} + +type PostsFields_arrayField_group23field_Delete { + permission: Boolean! +} + +type PostsFields_arrayField_group23field_Fields { + arrayField: PostsFields_arrayField_group23field_arrayField +} + +type PostsFields_arrayField_group23field_arrayField { + create: PostsFields_arrayField_group23field_arrayField_Create + read: PostsFields_arrayField_group23field_arrayField_Read + update: PostsFields_arrayField_group23field_arrayField_Update + delete: PostsFields_arrayField_group23field_arrayField_Delete + fields: PostsFields_arrayField_group23field_arrayField_Fields +} + +type PostsFields_arrayField_group23field_arrayField_Create { + permission: Boolean! +} + +type PostsFields_arrayField_group23field_arrayField_Read { + permission: Boolean! +} + +type PostsFields_arrayField_group23field_arrayField_Update { + permission: Boolean! +} + +type PostsFields_arrayField_group23field_arrayField_Delete { + permission: Boolean! +} + +type PostsFields_arrayField_group23field_arrayField_Fields { + group23field: PostsFields_arrayField_group23field_arrayField_group23field + id: PostsFields_arrayField_group23field_arrayField_id +} + +type PostsFields_arrayField_group23field_arrayField_group23field { + create: PostsFields_arrayField_group23field_arrayField_group23field_Create + read: PostsFields_arrayField_group23field_arrayField_group23field_Read + update: PostsFields_arrayField_group23field_arrayField_group23field_Update + delete: PostsFields_arrayField_group23field_arrayField_group23field_Delete + fields: PostsFields_arrayField_group23field_arrayField_group23field_Fields +} + +type PostsFields_arrayField_group23field_arrayField_group23field_Create { + permission: Boolean! +} + +type PostsFields_arrayField_group23field_arrayField_group23field_Read { + permission: Boolean! +} + +type PostsFields_arrayField_group23field_arrayField_group23field_Update { + permission: Boolean! +} + +type PostsFields_arrayField_group23field_arrayField_group23field_Delete { + permission: Boolean! +} + +type PostsFields_arrayField_group23field_arrayField_group23field_Fields { + arrayField: PostsFields_arrayField_group23field_arrayField_group23field_arrayField +} + +type PostsFields_arrayField_group23field_arrayField_group23field_arrayField { + create: PostsFields_arrayField_group23field_arrayField_group23field_arrayField_Create + read: PostsFields_arrayField_group23field_arrayField_group23field_arrayField_Read + update: PostsFields_arrayField_group23field_arrayField_group23field_arrayField_Update + delete: PostsFields_arrayField_group23field_arrayField_group23field_arrayField_Delete + fields: PostsFields_arrayField_group23field_arrayField_group23field_arrayField_Fields +} + +type PostsFields_arrayField_group23field_arrayField_group23field_arrayField_Create { + permission: Boolean! +} + +type PostsFields_arrayField_group23field_arrayField_group23field_arrayField_Read { + permission: Boolean! +} + +type PostsFields_arrayField_group23field_arrayField_group23field_arrayField_Update { + permission: Boolean! +} + +type PostsFields_arrayField_group23field_arrayField_group23field_arrayField_Delete { + permission: Boolean! +} + +type PostsFields_arrayField_group23field_arrayField_group23field_arrayField_Fields { + textField: PostsFields_arrayField_group23field_arrayField_group23field_arrayField_textField + id: PostsFields_arrayField_group23field_arrayField_group23field_arrayField_id +} + +type PostsFields_arrayField_group23field_arrayField_group23field_arrayField_textField { + create: PostsFields_arrayField_group23field_arrayField_group23field_arrayField_textField_Create + read: PostsFields_arrayField_group23field_arrayField_group23field_arrayField_textField_Read + update: PostsFields_arrayField_group23field_arrayField_group23field_arrayField_textField_Update + delete: PostsFields_arrayField_group23field_arrayField_group23field_arrayField_textField_Delete +} + +type PostsFields_arrayField_group23field_arrayField_group23field_arrayField_textField_Create { + permission: Boolean! +} + +type PostsFields_arrayField_group23field_arrayField_group23field_arrayField_textField_Read { + permission: Boolean! +} + +type PostsFields_arrayField_group23field_arrayField_group23field_arrayField_textField_Update { + permission: Boolean! +} + +type PostsFields_arrayField_group23field_arrayField_group23field_arrayField_textField_Delete { + permission: Boolean! +} + +type PostsFields_arrayField_group23field_arrayField_group23field_arrayField_id { + create: PostsFields_arrayField_group23field_arrayField_group23field_arrayField_id_Create + read: PostsFields_arrayField_group23field_arrayField_group23field_arrayField_id_Read + update: PostsFields_arrayField_group23field_arrayField_group23field_arrayField_id_Update + delete: PostsFields_arrayField_group23field_arrayField_group23field_arrayField_id_Delete +} + +type PostsFields_arrayField_group23field_arrayField_group23field_arrayField_id_Create { + permission: Boolean! +} + +type PostsFields_arrayField_group23field_arrayField_group23field_arrayField_id_Read { + permission: Boolean! +} + +type PostsFields_arrayField_group23field_arrayField_group23field_arrayField_id_Update { + permission: Boolean! +} + +type PostsFields_arrayField_group23field_arrayField_group23field_arrayField_id_Delete { + permission: Boolean! +} + +type PostsFields_arrayField_group23field_arrayField_id { + create: PostsFields_arrayField_group23field_arrayField_id_Create + read: PostsFields_arrayField_group23field_arrayField_id_Read + update: PostsFields_arrayField_group23field_arrayField_id_Update + delete: PostsFields_arrayField_group23field_arrayField_id_Delete +} + +type PostsFields_arrayField_group23field_arrayField_id_Create { + permission: Boolean! +} + +type PostsFields_arrayField_group23field_arrayField_id_Read { + permission: Boolean! +} + +type PostsFields_arrayField_group23field_arrayField_id_Update { + permission: Boolean! +} + +type PostsFields_arrayField_group23field_arrayField_id_Delete { + permission: Boolean! +} + +type PostsFields_arrayField_id { + create: PostsFields_arrayField_id_Create + read: PostsFields_arrayField_id_Read + update: PostsFields_arrayField_id_Update + delete: PostsFields_arrayField_id_Delete +} + +type PostsFields_arrayField_id_Create { + permission: Boolean! +} + +type PostsFields_arrayField_id_Read { + permission: Boolean! +} + +type PostsFields_arrayField_id_Update { + permission: Boolean! +} + +type PostsFields_arrayField_id_Delete { + permission: Boolean! +} + +type PostsFields_updatedAt { + create: PostsFields_updatedAt_Create + read: PostsFields_updatedAt_Read + update: PostsFields_updatedAt_Update + delete: PostsFields_updatedAt_Delete +} + +type PostsFields_updatedAt_Create { + permission: Boolean! +} + +type PostsFields_updatedAt_Read { + permission: Boolean! +} + +type PostsFields_updatedAt_Update { + permission: Boolean! +} + +type PostsFields_updatedAt_Delete { + permission: Boolean! +} + +type PostsFields_createdAt { + create: PostsFields_createdAt_Create + read: PostsFields_createdAt_Read + update: PostsFields_createdAt_Update + delete: PostsFields_createdAt_Delete +} + +type PostsFields_createdAt_Create { + permission: Boolean! +} + +type PostsFields_createdAt_Read { + permission: Boolean! +} + +type PostsFields_createdAt_Update { + permission: Boolean! +} + +type PostsFields_createdAt_Delete { + permission: Boolean! +} + +type PostsCreateAccess { + permission: Boolean! + where: JSONObject +} + +type PostsReadAccess { + permission: Boolean! + where: JSONObject +} + +type PostsUpdateAccess { + permission: Boolean! + where: JSONObject +} + +type PostsDeleteAccess { + permission: Boolean! + where: JSONObject +} + +type usersAccess { + fields: UsersFields + create: UsersCreateAccess + read: UsersReadAccess + update: UsersUpdateAccess + delete: UsersDeleteAccess + unlock: UsersUnlockAccess +} + +type UsersFields { + updatedAt: UsersFields_updatedAt + createdAt: UsersFields_createdAt + email: UsersFields_email + password: UsersFields_password +} + +type UsersFields_updatedAt { + create: UsersFields_updatedAt_Create + read: UsersFields_updatedAt_Read + update: UsersFields_updatedAt_Update + delete: UsersFields_updatedAt_Delete +} + +type UsersFields_updatedAt_Create { + permission: Boolean! +} + +type UsersFields_updatedAt_Read { + permission: Boolean! +} + +type UsersFields_updatedAt_Update { + permission: Boolean! +} + +type UsersFields_updatedAt_Delete { + permission: Boolean! +} + +type UsersFields_createdAt { + create: UsersFields_createdAt_Create + read: UsersFields_createdAt_Read + update: UsersFields_createdAt_Update + delete: UsersFields_createdAt_Delete +} + +type UsersFields_createdAt_Create { + permission: Boolean! +} + +type UsersFields_createdAt_Read { + permission: Boolean! +} + +type UsersFields_createdAt_Update { + permission: Boolean! +} + +type UsersFields_createdAt_Delete { + permission: Boolean! +} + +type UsersFields_email { + create: UsersFields_email_Create + read: UsersFields_email_Read + update: UsersFields_email_Update + delete: UsersFields_email_Delete +} + +type UsersFields_email_Create { + permission: Boolean! +} + +type UsersFields_email_Read { + permission: Boolean! +} + +type UsersFields_email_Update { + permission: Boolean! +} + +type UsersFields_email_Delete { + permission: Boolean! +} + +type UsersFields_password { + create: UsersFields_password_Create + read: UsersFields_password_Read + update: UsersFields_password_Update + delete: UsersFields_password_Delete +} + +type UsersFields_password_Create { + permission: Boolean! +} + +type UsersFields_password_Read { + permission: Boolean! +} + +type UsersFields_password_Update { + permission: Boolean! +} + +type UsersFields_password_Delete { + permission: Boolean! +} + +type UsersCreateAccess { + permission: Boolean! + where: JSONObject +} + +type UsersReadAccess { + permission: Boolean! + where: JSONObject +} + +type UsersUpdateAccess { + permission: Boolean! + where: JSONObject +} + +type UsersDeleteAccess { + permission: Boolean! + where: JSONObject +} + +type UsersUnlockAccess { + permission: Boolean! + where: JSONObject +} + +type Mutation { + createPost(data: mutationPostInput!, draft: Boolean): Post + updatePost(id: String!, data: mutationPostUpdateInput!, draft: Boolean, autosave: Boolean): Post + deletePost(id: String!): Post + createUser(data: mutationUserInput!, draft: Boolean): User + updateUser(id: String!, data: mutationUserUpdateInput!, draft: Boolean, autosave: Boolean): User + deleteUser(id: String!): User + refreshTokenUser(token: String): usersRefreshedUser + logoutUser: String + unlockUser(email: String!): Boolean! + loginUser(email: String, password: String): usersLoginResult + forgotPasswordUser(email: String!, disableEmail: Boolean, expiration: Int): Boolean! + resetPasswordUser(token: String, password: String): usersResetPassword + verifyEmailUser(token: String): Boolean + updatePreference(key: String!, value: JSON): Preference + deletePreference(key: String!): Preference +} + +input mutationPostInput { + arrayField: [mutationPost_ArrayFieldInput] + updatedAt: String + createdAt: String +} + +input mutationPost_ArrayFieldInput { + group23field: mutationPost_ArrayField_Group23fieldInput! + id: String +} + +input mutationPost_ArrayField_Group23fieldInput { + arrayField: [mutationPost_ArrayField_Group23field_ArrayFieldInput!] +} + +input mutationPost_ArrayField_Group23field_ArrayFieldInput { + group23field: mutationPost_ArrayField_Group23field_ArrayField_Group23fieldInput! + id: String +} + +input mutationPost_ArrayField_Group23field_ArrayField_Group23fieldInput { + arrayField: [mutationPost_ArrayField_Group23field_ArrayField_Group23field_ArrayFieldInput!] +} + +input mutationPost_ArrayField_Group23field_ArrayField_Group23field_ArrayFieldInput { + textField: String! + id: String +} + +input mutationPostUpdateInput { + arrayField: [mutationPostUpdate_ArrayFieldInput] + updatedAt: String + createdAt: String +} + +input mutationPostUpdate_ArrayFieldInput { + group23field: mutationPostUpdate_ArrayField_Group23fieldInput! + id: String +} + +input mutationPostUpdate_ArrayField_Group23fieldInput { + arrayField: [mutationPostUpdate_ArrayField_Group23field_ArrayFieldInput!] +} + +input mutationPostUpdate_ArrayField_Group23field_ArrayFieldInput { + group23field: mutationPostUpdate_ArrayField_Group23field_ArrayField_Group23fieldInput! + id: String +} + +input mutationPostUpdate_ArrayField_Group23field_ArrayField_Group23fieldInput { + arrayField: [mutationPostUpdate_ArrayField_Group23field_ArrayField_Group23field_ArrayFieldInput!] +} + +input mutationPostUpdate_ArrayField_Group23field_ArrayField_Group23field_ArrayFieldInput { + textField: String! + id: String +} + +input mutationUserInput { + updatedAt: String + createdAt: String + email: String + resetPasswordToken: String + resetPasswordExpiration: String + salt: String + hash: String + loginAttempts: Float + lockUntil: String + password: String! +} + +input mutationUserUpdateInput { + updatedAt: String + createdAt: String + email: String + resetPasswordToken: String + resetPasswordExpiration: String + salt: String + hash: String + loginAttempts: Float + lockUntil: String + password: String +} + +type usersRefreshedUser { + user: usersJWT + refreshedToken: String + exp: Int +} + +type usersJWT { + email: EmailAddress! + collection: String! +} + +type usersLoginResult { + token: String + user: User + exp: Int +} + +type usersResetPassword { + token: String + user: User +} \ No newline at end of file diff --git a/test/field-error-states/tsconfig.json b/test/field-error-states/tsconfig.json new file mode 100644 index 000000000..f920e99ec --- /dev/null +++ b/test/field-error-states/tsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "paths": { + "payload/generated-types": [ + "./payload-types.ts" + ] + } + } +} \ No newline at end of file diff --git a/test/fields-relationship/e2e.spec.ts b/test/fields-relationship/e2e.spec.ts index 12ac494bc..81cdcc5ca 100644 --- a/test/fields-relationship/e2e.spec.ts +++ b/test/fields-relationship/e2e.spec.ts @@ -4,7 +4,7 @@ import payload from '../../src'; import { mapAsync } from '../../src/utilities/mapAsync'; import { AdminUrlUtil } from '../helpers/adminUrlUtil'; import { initPayloadE2E } from '../helpers/configHelpers'; -import { login, saveDocAndAssert } from '../helpers'; +import { saveDocAndAssert } from '../helpers'; import type { FieldsRelationship as CollectionWithRelationships, RelationOne, @@ -37,8 +37,6 @@ describe('fields - relationship', () => { const context = await browser.newContext(); page = await context.newPage(); - - await login({ page, serverURL }); }); beforeEach(async () => { diff --git a/test/fields/collections/Date/index.ts b/test/fields/collections/Date/index.ts index 578a94e54..bb1decc4d 100644 --- a/test/fields/collections/Date/index.ts +++ b/test/fields/collections/Date/index.ts @@ -16,6 +16,15 @@ const DateFields: CollectionConfig = { { name: 'timeOnly', type: 'date', + admin: { + date: { + pickerAppearance: 'timeOnly', + }, + }, + }, + { + name: 'timeOnlyWithCustomFormat', + type: 'date', admin: { date: { pickerAppearance: 'timeOnly', @@ -56,6 +65,7 @@ const DateFields: CollectionConfig = { export const dateDoc = { default: '2022-08-12T10:00:00.000+00:00', timeOnly: '2022-08-12T10:00:00.157+00:00', + timeOnlyWithCustomFormat: '2022-08-12T10:00:00.157+00:00', dayOnly: '2022-08-11T22:00:00.000+00:00', dayAndTime: '2022-08-12T10:00:00.052+00:00', monthOnly: '2022-07-31T22:00:00.000+00:00', diff --git a/test/fields/config.ts b/test/fields/config.ts index c72069da4..85aea7101 100644 --- a/test/fields/config.ts +++ b/test/fields/config.ts @@ -51,7 +51,6 @@ export default buildConfig({ name: 'canViewConditionalField', type: 'checkbox', defaultValue: true, - saveToJWT: true, }, ], }, diff --git a/test/fields/e2e.spec.ts b/test/fields/e2e.spec.ts index b4bea5af4..0183e92e2 100644 --- a/test/fields/e2e.spec.ts +++ b/test/fields/e2e.spec.ts @@ -4,7 +4,7 @@ import path from 'path'; import payload from '../../src'; import { AdminUrlUtil } from '../helpers/adminUrlUtil'; import { initPayloadE2E } from '../helpers/configHelpers'; -import { login, saveDocAndAssert } from '../helpers'; +import { saveDocAndAssert } from '../helpers'; import { textDoc } from './collections/Text'; import { arrayFieldsSlug } from './collections/Array'; import { pointFieldsSlug } from './collections/Point'; @@ -26,8 +26,6 @@ describe('fields', () => { const context = await browser.newContext(); page = await context.newPage(); - - await login({ page, serverURL }); }); describe('text', () => { @@ -319,7 +317,7 @@ describe('fields', () => { await firstBlockSelector.click(); // ensure the block was appended to the rows - const addedRow = await page.locator('#field-blocks #blocks-row-3'); + const addedRow = await page.locator('#field-blocks .blocks-field__row').last(); await expect(addedRow).toBeVisible(); await expect(addedRow.locator('.blocks-field__block-pill-text')).toContainText('Text'); }); @@ -366,7 +364,7 @@ describe('fields', () => { await firstBlockSelector.click(); // ensure the block was appended to the rows - const firstRow = page.locator('#i18nBlocks-row-0'); + const firstRow = page.locator('#field-i18nBlocks .blocks-field__row').first(); await expect(firstRow).toBeVisible(); await expect(firstRow.locator('.blocks-field__block-pill-text')).toContainText('Text en'); }); @@ -479,6 +477,27 @@ describe('fields', () => { } describe('toolbar', () => { + test('should run url validation', async () => { + await navigateToRichTextFields(); + + // Open link drawer + await page.locator('.rich-text__toolbar button:not([disabled]) .link').first().click(); + + // find the drawer + const editLinkModal = await page.locator('[id^=drawer_1_rich-text-link-]'); + await expect(editLinkModal).toBeVisible(); + + // Fill values and click Confirm + await editLinkModal.locator('#field-text').fill('link text'); + await editLinkModal.locator('label[for="field-linkType-custom"]').click(); + await editLinkModal.locator('#field-url').fill(''); + await wait(200); + await editLinkModal.locator('button[type="submit"]').click(); + const errorField = await page.locator('[id^=drawer_1_rich-text-link-] .render-fields > :nth-child(3)'); + const hasErrorClass = await errorField.evaluate(el => el.classList.contains('error')); + expect(hasErrorClass).toBe(true); + }); + test('should create new url custom link', async () => { await navigateToRichTextFields(); diff --git a/test/hooks/int.spec.ts b/test/hooks/int.spec.ts index 01db8ab10..905bb212c 100644 --- a/test/hooks/int.spec.ts +++ b/test/hooks/int.spec.ts @@ -1,4 +1,3 @@ -import mongoose from 'mongoose'; import { initPayloadTest } from '../helpers/configHelpers'; import config from './config'; import payload from '../../src'; @@ -22,9 +21,7 @@ describe('Hooks', () => { }); afterAll(async () => { - await mongoose.connection.dropDatabase(); - await mongoose.connection.close(); - await payload.mongoMemoryServer.stop(); + await payload.db.destroy(payload); }); describe('transform actions', () => { diff --git a/test/localization/config.ts b/test/localization/config.ts index fda878d83..c2502e46d 100644 --- a/test/localization/config.ts +++ b/test/localization/config.ts @@ -168,6 +168,20 @@ export default buildConfig({ hasMany: true, localized: true, }, + { + name: 'arrayField', + label: 'Array Field', + type: 'array', + localized: true, + fields: [ + { + type: 'relationship', + name: 'nestedRelation', + label: 'Nested Relation', + relationTo: localizedPostsSlug, + }, + ], + }, ], }, { @@ -288,6 +302,11 @@ export default buildConfig({ { relationTo: localizedPostsSlug, value: localizedRelation.id }, { relationTo: localizedPostsSlug, value: localizedRelation2.id }, ], + arrayField: [ + { + nestedRelation: localizedRelation.id, + }, + ], }, }); diff --git a/test/localization/e2e.spec.ts b/test/localization/e2e.spec.ts index 27d2da713..e8913863b 100644 --- a/test/localization/e2e.spec.ts +++ b/test/localization/e2e.spec.ts @@ -3,7 +3,7 @@ import { expect, test } from '@playwright/test'; import payload from '../../src'; import { AdminUrlUtil } from '../helpers/adminUrlUtil'; import { initPayloadTest } from '../helpers/configHelpers'; -import { login, saveDocAndAssert } from '../helpers'; +import { saveDocAndAssert } from '../helpers'; import type { LocalizedPost } from './payload-types'; import { localizedPostsSlug } from './config'; import { englishTitle, spanishLocale } from './shared'; @@ -39,8 +39,6 @@ describe('Localization', () => { const context = await browser.newContext(); page = await context.newPage(); - - await login({ page, serverURL }); }); describe('localized text', () => { diff --git a/test/localization/int.spec.ts b/test/localization/int.spec.ts index 76a762a51..7bee62dfc 100644 --- a/test/localization/int.spec.ts +++ b/test/localization/int.spec.ts @@ -1,12 +1,13 @@ -import mongoose from 'mongoose'; import { GraphQLClient } from 'graphql-request'; import { initPayloadTest } from '../helpers/configHelpers'; import payload from '../../src'; -import type { - LocalizedPost, - WithLocalizedRelationship, -} from './payload-types'; -import configPromise, { relationshipLocalizedSlug, localizedPostsSlug, withLocalizedRelSlug, withRequiredLocalizedFields } from './config'; +import type { LocalizedPost, WithLocalizedRelationship } from './payload-types'; +import configPromise, { + localizedPostsSlug, + relationshipLocalizedSlug, + withLocalizedRelSlug, + withRequiredLocalizedFields, +} from './config'; import { defaultLocale, englishTitle, @@ -59,9 +60,7 @@ describe('Localization', () => { }); afterAll(async () => { - await mongoose.connection.dropDatabase(); - await mongoose.connection.close(); - await payload.mongoMemoryServer.stop(); + await payload.db.destroy(payload); }); describe('localized text', () => { @@ -308,6 +307,7 @@ describe('Localization', () => { expect((result.docs[0].relationshipHasMany as any).en[0].id).toBeDefined(); expect((result.docs[0].relationMultiRelationTo as any).en.value.id).toBeDefined(); expect((result.docs[0].relationMultiRelationToHasMany as any).en[0].value.id).toBeDefined(); + expect(result.docs[0].arrayField.en[0].nestedRelation.id).toBeDefined(); }); }); diff --git a/test/migrations-cli/config.ts b/test/migrations-cli/config.ts index d7a0aacb5..90d82be74 100644 --- a/test/migrations-cli/config.ts +++ b/test/migrations-cli/config.ts @@ -48,5 +48,5 @@ export default buildConfig({ typescript: { outputFile: path.resolve(__dirname, 'payload-types.ts'), }, - db: mongooseAdapter({ payload, url: 'mongodb://localhost:27017/migrations-cli-test' }), + db: mongooseAdapter({ payload, url: 'mongodb://127.0.0.1:27017/migrations-cli-test' }), }); diff --git a/test/refresh-permissions/e2e.spec.ts b/test/refresh-permissions/e2e.spec.ts index c61cd1a05..aa52f99c6 100644 --- a/test/refresh-permissions/e2e.spec.ts +++ b/test/refresh-permissions/e2e.spec.ts @@ -1,5 +1,4 @@ import { expect, Page, test } from '@playwright/test'; -import { login } from '../helpers'; import { initPayloadE2E } from '../helpers/configHelpers'; const { beforeAll, describe } = test; @@ -12,7 +11,6 @@ describe('refresh-permissions', () => { ({ serverURL } = await initPayloadE2E(__dirname)); const context = await browser.newContext(); page = await context.newPage(); - await login({ page, serverURL }); }); test('should show test global immediately after allowing access', async () => { diff --git a/test/relationships/int.spec.ts b/test/relationships/int.spec.ts index 20302a295..7f509d1a3 100644 --- a/test/relationships/int.spec.ts +++ b/test/relationships/int.spec.ts @@ -1,10 +1,23 @@ -import mongoose from 'mongoose'; import { randomBytes } from 'crypto'; import { initPayloadTest } from '../helpers/configHelpers'; -import config, { customIdSlug, chainedRelSlug, defaultAccessRelSlug, slug, relationSlug, customIdNumberSlug } from './config'; +import config, { + chainedRelSlug, + customIdNumberSlug, + customIdSlug, + defaultAccessRelSlug, + relationSlug, + slug, +} from './config'; import payload from '../../src'; import { RESTClient } from '../helpers/rest'; -import type { ChainedRelation, CustomIdNumberRelation, CustomIdRelation, Director, Post, Relation } from './payload-types'; +import type { + ChainedRelation, + CustomIdNumberRelation, + CustomIdRelation, + Director, + Post, + Relation, +} from './payload-types'; import { mapAsync } from '../../src/utilities/mapAsync'; let client: RESTClient; @@ -19,9 +32,7 @@ describe('Relationships', () => { }); afterAll(async () => { - await mongoose.connection.dropDatabase(); - await mongoose.connection.close(); - await payload.mongoMemoryServer.stop(); + await payload.db.destroy(payload); }); beforeEach(async () => { diff --git a/test/uploads/e2e.spec.ts b/test/uploads/e2e.spec.ts index d710b2e23..417faa981 100644 --- a/test/uploads/e2e.spec.ts +++ b/test/uploads/e2e.spec.ts @@ -6,7 +6,7 @@ import type { Media } from './payload-types'; import payload from '../../src'; import { AdminUrlUtil } from '../helpers/adminUrlUtil'; import { initPayloadE2E } from '../helpers/configHelpers'; -import { login, saveDocAndAssert } from '../helpers'; +import { saveDocAndAssert } from '../helpers'; import wait from '../../src/utilities/wait'; const { beforeAll, describe } = test; @@ -50,8 +50,6 @@ describe('uploads', () => { }); audioDoc = findAudio.docs[0] as Media; - - await login({ page, serverURL }); }); test('should see upload filename in relation list', async () => { diff --git a/test/versions/e2e.spec.ts b/test/versions/e2e.spec.ts index 6ca33fe2b..787fa065f 100644 --- a/test/versions/e2e.spec.ts +++ b/test/versions/e2e.spec.ts @@ -28,7 +28,6 @@ import type { Page } from '@playwright/test'; import { expect, test } from '@playwright/test'; import { initPayloadE2E } from '../helpers/configHelpers'; import { AdminUrlUtil } from '../helpers/adminUrlUtil'; -import { login } from '../helpers'; import { draftSlug, autosaveSlug } from './shared'; import wait from '../../src/utilities/wait'; @@ -44,8 +43,6 @@ describe('versions', () => { const context = await browser.newContext(); page = await context.newPage(); - - await login({ page, serverURL }); }); describe('draft collections', () => { diff --git a/yarn.lock b/yarn.lock index 9070013ad..4120ea3b5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3680,7 +3680,7 @@ bson-objectid@^2.0.4: resolved "https://registry.yarnpkg.com/bson-objectid/-/bson-objectid-2.0.4.tgz#339211572ef97dc98f2d68eaee7b99b7be59a089" integrity sha512-vgnKAUzcDoa+AeyYwXCoHyF2q6u/8H46dxu5JN+4/TZeq/Dlinn0K6GvxsCLb3LHUJl0m/TLiEK31kUwtgocMQ== -bson@^4.6.5, bson@^4.7.2: +bson@^4.7.2: version "4.7.2" resolved "https://registry.yarnpkg.com/bson/-/bson-4.7.2.tgz#320f4ad0eaf5312dd9b45dc369cc48945e2a5f2e" integrity sha512-Ry9wCtIZ5kGqkJoi6aD8KjxFZEx78guTQDnpXWiNthsxzrxAK/i8E6pCHAIZTbaEFWcOCvbecMukfK7XUvyLpQ== @@ -4861,11 +4861,6 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== -denque@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/denque/-/denque-2.1.0.tgz#e93e1a6569fb5e66f16a3c2a2964617d349d6ab1" - integrity sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw== - depd@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" @@ -7813,11 +7808,6 @@ jwt-decode@^3.1.2: resolved "https://registry.yarnpkg.com/jwt-decode/-/jwt-decode-3.1.2.tgz#3fb319f3675a2df0c2895c8f5e9fa4b67b04ed59" integrity sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A== -kareem@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/kareem/-/kareem-2.4.1.tgz#7d81ec518204a48c1cb16554af126806c3cd82b0" - integrity sha512-aJ9opVoXroQUPfovYP5kaj2lM7Jn02Gw13bL0lg9v0V7SaUc0qavPs0Eue7d2DcC3NjqI6QAUElXNsuZSeM+EA== - kareem@2.5.1: version "2.5.1" resolved "https://registry.yarnpkg.com/kareem/-/kareem-2.5.1.tgz#7b8203e11819a8e77a34b3517d3ead206764d15d" @@ -8320,7 +8310,7 @@ monaco-editor@^0.38.0: resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.38.0.tgz#7b3cd16f89b1b8867fcd3c96e67fccee791ff05c" integrity sha512-11Fkh6yzEmwx7O0YoLxeae0qEGFwmyPRlVxpg7oF9czOOCB/iCjdJrG5I67da5WiXK3YJCxoz9TJFE8Tfq/v9A== -mongodb-connection-string-url@^2.5.2, mongodb-connection-string-url@^2.5.4, mongodb-connection-string-url@^2.6.0: +mongodb-connection-string-url@^2.5.4, mongodb-connection-string-url@^2.6.0: version "2.6.0" resolved "https://registry.yarnpkg.com/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz#57901bf352372abdde812c81be47b75c6b2ec5cf" integrity sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ== @@ -8356,16 +8346,16 @@ mongodb-memory-server@^8.12.2: mongodb-memory-server-core "8.12.2" tslib "^2.5.0" -mongodb@4.8.1: - version "4.8.1" - resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-4.8.1.tgz#596de88ff4519128266d9254dbe5b781c4005796" - integrity sha512-/NyiM3Ox9AwP5zrfT9TXjRKDJbXlLaUDQ9Rg//2lbg8D2A8GXV0VidYYnA/gfdK6uwbnL4FnAflH7FbGw3TS7w== +mongodb@4.16.0, mongodb@^4.13.0: + version "4.16.0" + resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-4.16.0.tgz#8b0043de7b577c6a7e0ce44a2ca7315b9c0a7927" + integrity sha512-0EB113Fsucaq1wsY0dOhi1fmZOwFtLOtteQkiqOXGklvWMnSH3g2QS53f0KTP+/6qOkuoXE2JksubSZNmxeI+g== dependencies: - bson "^4.6.5" - denque "^2.0.1" - mongodb-connection-string-url "^2.5.2" - socks "^2.6.2" + bson "^4.7.2" + mongodb-connection-string-url "^2.5.4" + socks "^2.7.1" optionalDependencies: + "@aws-sdk/credential-providers" "^3.186.0" saslprep "^1.0.3" mongodb@5.3.0: @@ -8379,40 +8369,28 @@ mongodb@5.3.0: optionalDependencies: saslprep "^1.0.3" -mongodb@^4.13.0: - version "4.16.0" - resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-4.16.0.tgz#8b0043de7b577c6a7e0ce44a2ca7315b9c0a7927" - integrity sha512-0EB113Fsucaq1wsY0dOhi1fmZOwFtLOtteQkiqOXGklvWMnSH3g2QS53f0KTP+/6qOkuoXE2JksubSZNmxeI+g== - dependencies: - bson "^4.7.2" - mongodb-connection-string-url "^2.5.4" - socks "^2.7.1" - optionalDependencies: - "@aws-sdk/credential-providers" "^3.186.0" - saslprep "^1.0.3" - mongoose-aggregate-paginate-v2@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/mongoose-aggregate-paginate-v2/-/mongoose-aggregate-paginate-v2-1.0.6.tgz#fd2f2564d1bbf52f49a196f0b7b03675913dacca" integrity sha512-UuALu+mjhQa1K9lMQvjLL3vm3iALvNw8PQNIh2gp1b+tO5hUa0NC0Wf6/8QrT9PSJVTihXaD8hQVy3J4e0jO0Q== -mongoose-paginate-v2@^1.6.1: - version "1.7.1" - resolved "https://registry.yarnpkg.com/mongoose-paginate-v2/-/mongoose-paginate-v2-1.7.1.tgz#0b390f5eb8e5dca55ffcb1fd7b4d8078636cb8f1" - integrity sha512-J8DJw3zRXcXOKoZv+RvO9tt5HotRnbo2iCR3lke+TtsQsYwQvbY3EgUkPqZXw6qCX2IByvXrW5SGNdAB0od/Cw== +mongoose-paginate-v2@1.7.22: + version "1.7.22" + resolved "https://registry.yarnpkg.com/mongoose-paginate-v2/-/mongoose-paginate-v2-1.7.22.tgz#9f178fe5fb71597e231639adac84d3ab9a96c62a" + integrity sha512-xW5GugkE21DJiu9e13EOxKt4ejEKQkRP/S1PkkXRjnk2rRZVKBcld1nPV+VJ/YCPfm8hb3sz9OvI7O38RmixkA== -mongoose@6.5.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-6.5.0.tgz#5c71aa8d4027e50bfe8d29d6e955e378e010d174" - integrity sha512-swOX8ZEbmCeJaEs29B1j67StBIhuOccNNkipbVhsnLYYCDpNE7heM9W54MFGwN5es9tGGoxINHSzOhJ9kTOZGg== +mongoose@6.11.4: + version "6.11.4" + resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-6.11.4.tgz#7bab3a32eca8a43715057ae5f78d5515ecf94d7d" + integrity sha512-q9NaW9/BBYZofx80SqlR7uoSR09CS3g02y+KMj1lNLUxcFFsPshupY3WWisNFauYG9gyuDF4L/RgyIK3obSghg== dependencies: - bson "^4.6.5" - kareem "2.4.1" - mongodb "4.8.1" + bson "^4.7.2" + kareem "2.5.1" + mongodb "4.16.0" mpath "0.9.0" mquery "4.0.3" ms "2.1.3" - sift "16.0.0" + sift "16.0.1" mongoose@>=6.3.0: version "7.1.1" @@ -10793,11 +10771,6 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" -sift@16.0.0: - version "16.0.0" - resolved "https://registry.yarnpkg.com/sift/-/sift-16.0.0.tgz#447991577db61f1a8fab727a8a98a6db57a23eb8" - integrity sha512-ILTjdP2Mv9V1kIxWMXeMTIRbOBrqKc4JAXmFMnFq3fKeyQ2Qwa3Dw1ubcye3vR+Y6ofA0b9gNDr/y2t6eUeIzQ== - sift@16.0.1: version "16.0.1" resolved "https://registry.yarnpkg.com/sift/-/sift-16.0.1.tgz#e9c2ccc72191585008cf3e36fc447b2d2633a053" @@ -10917,7 +10890,7 @@ socks-proxy-agent@5, socks-proxy-agent@^5.0.0: debug "4" socks "^2.3.3" -socks@^2.3.3, socks@^2.6.2, socks@^2.7.1: +socks@^2.3.3, socks@^2.7.1: version "2.7.1" resolved "https://registry.yarnpkg.com/socks/-/socks-2.7.1.tgz#d8e651247178fde79c0663043e07240196857d55" integrity sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==