diff --git a/docs/admin/bundlers.mdx b/docs/admin/bundlers.mdx
index c6d7d088cc..5aaacbc6d2 100644
--- a/docs/admin/bundlers.mdx
+++ b/docs/admin/bundlers.mdx
@@ -33,7 +33,7 @@ import { webpackBundler } from '@payloadcms/bundler-webpack'
export default buildConfig({
// highlight-start
admin: {
- bundler: webpackBundler() // or viteBundler()
+ bundler: webpackBundler(), // or viteBundler()
},
// highlight-end
})
@@ -48,7 +48,7 @@ Since the bundled file is sent to the browser, it can't include any server-only
Using environment variables in the admin UI
- Bundles should not contain sensitive information. By default, Payload
- excludes env variables from the bundle. If you need to use env variables in your payload config,
- you need to prefix them with `PAYLOAD_PUBLIC_` to make them available to the client-side code.
+ Bundles should not contain sensitive information. By default, Payload excludes env variables from
+ the bundle. If you need to use env variables in your payload config, you need to prefix them with
+ `PAYLOAD_PUBLIC_` to make them available to the client-side code.
diff --git a/docs/admin/components.mdx b/docs/admin/components.mdx
index 00d810f263..d4ca134b81 100644
--- a/docs/admin/components.mdx
+++ b/docs/admin/components.mdx
@@ -13,29 +13,29 @@ To swap in your own React component, first, consult the list of available compon
Tip:
- Custom components will automatically be provided with all props that the default component normally
- accepts.
+ Custom components will automatically be provided with all props that the default component
+ normally accepts.
### Base Component Overrides
You can override a set of admin panel-wide components by providing a component to your base Payload config's `admin.components` property. The following options are available:
-| Path | Description |
-| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`Nav`** | Contains the sidebar / mobile menu in its entirety. |
-| **`BeforeNavLinks`** | Array of components to inject into the built-in Nav, _before_ the links themselves. |
-| **`AfterNavLinks`** | Array of components to inject into the built-in Nav, _after_ the links. |
-| **`BeforeDashboard`** | Array of components to inject into the built-in Dashboard, _before_ the default dashboard contents. |
-| **`AfterDashboard`** | Array of components to inject into the built-in Dashboard, _after_ the default dashboard contents. [Demo](https://github.com/payloadcms/payload/tree/main/test/admin/components/AfterDashboard/index.tsx) |
-| **`BeforeLogin`** | Array of components to inject into the built-in Login, _before_ the default login form. |
-| **`AfterLogin`** | Array of components to inject into the built-in Login, _after_ the default login form. |
-| **`logout.Button`** | A custom React component. |
-| **`graphics.Icon`** | Used as a graphic within the `Nav` component. Often represents a condensed version of a full logo. |
-| **`graphics.Logo`** | The full logo to be used in contexts like the `Login` view. |
-| **`providers`** | Define your own provider components that will wrap the Payload Admin UI. [More](#custom-providers) |
-| **`actions`** | Array of custom components to be rendered in the Payload Admin UI header, providing additional interactivity and functionality. |
-| **`views`** | Override or create new views within the Payload Admin UI. [More](#views) |
+| Path | Description |
+| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`Nav`** | Contains the sidebar / mobile menu in its entirety. |
+| **`BeforeNavLinks`** | Array of components to inject into the built-in Nav, _before_ the links themselves. |
+| **`AfterNavLinks`** | Array of components to inject into the built-in Nav, _after_ the links. |
+| **`BeforeDashboard`** | Array of components to inject into the built-in Dashboard, _before_ the default dashboard contents. |
+| **`AfterDashboard`** | Array of components to inject into the built-in Dashboard, _after_ the default dashboard contents. [Demo](https://github.com/payloadcms/payload/tree/main/test/admin/components/AfterDashboard/index.tsx) |
+| **`BeforeLogin`** | Array of components to inject into the built-in Login, _before_ the default login form. |
+| **`AfterLogin`** | Array of components to inject into the built-in Login, _after_ the default login form. |
+| **`logout.Button`** | A custom React component. |
+| **`graphics.Icon`** | Used as a graphic within the `Nav` component. Often represents a condensed version of a full logo. |
+| **`graphics.Logo`** | The full logo to be used in contexts like the `Login` view. |
+| **`providers`** | Define your own provider components that will wrap the Payload Admin UI. [More](#custom-providers) |
+| **`actions`** | Array of custom components to be rendered in the Payload Admin UI header, providing additional interactivity and functionality. |
+| **`views`** | Override or create new views within the Payload Admin UI. [More](#views) |
Here is a full example showing how to swap some of these components for your own.
@@ -77,10 +77,10 @@ export default buildConfig({
You can easily swap entire views with your own by using the `admin.components.views` property. At the root level, Payload renders the following views by default, all of which can be overridden:
-| Property | Description |
-| ------------------ | ---------------------------------------------------------------------------------------------------------------------------- |
-| **`Account`** | The Account view is used to show the currently logged in user's Account page. |
-| **`Dashboard`** | The main landing page of the Admin panel. |
+| Property | Description |
+| --------------- | ----------------------------------------------------------------------------- |
+| **`Account`** | The Account view is used to show the currently logged in user's Account page. |
+| **`Dashboard`** | The main landing page of the Admin panel. |
To swap out any of these views, simply pass in your custom component to the `admin.components.views` property of your Payload config. For example:
@@ -135,7 +135,10 @@ To add a _new_ view to the Admin Panel, simply add another key to the `views` ob
Note:
- Routes are cascading. This means that unless explicitly given the `exact` property, they will match on URLs that simply _start_ with the route's path. This is helpful when creating catch-all routes in your application. Alternatively, you could define your nested route _before_ your parent route.
+ Routes are cascading. This means that unless explicitly given the `exact` property, they will
+ match on URLs that simply _start_ with the route's path. This is helpful when creating catch-all
+ routes in your application. Alternatively, you could define your nested route _before_ your parent
+ route.
_For more examples regarding how to customize components, look at the following [examples](https://github.com/payloadcms/payload/tree/main/test/admin/components)._
@@ -214,7 +217,7 @@ export const MyCollection: SanitizedCollectionConfig = {
PreviewButton: CustomPreviewButton,
},
},
- }
+ },
}
```
@@ -222,10 +225,10 @@ export const MyCollection: SanitizedCollectionConfig = {
To swap out entire views on collections, you can use the `admin.components.views` property on the collection's config. Payload renders the following views by default, all of which can be overridden:
-| Property | Description |
-| ------------------ | ---------------------------------------------------------------------------------------------------------------------------- |
-| **`Edit`** | The Edit view is used to edit a single document for a given collection. |
-| **`List`** | The List view is used to show a list of documents for a given collection. |
+| Property | Description |
+| ---------- | ------------------------------------------------------------------------- |
+| **`Edit`** | The Edit view is used to edit a single document for a given collection. |
+| **`List`** | The List view is used to show a list of documents for a given collection. |
To swap out any of these views, simply pass in your custom component to the `admin.components.views` property of your Payload config. This will replace the entire view, including the page breadcrumbs, title, tabs, etc, _as well as all nested routes_.
@@ -310,9 +313,9 @@ As with Collections, you can override components on a global-by-global basis via
To swap out views for globals, you can use the `admin.components.views` property on the global's config. Payload renders the following views by default, all of which can be overridden:
-| Property | Description |
-| ------------------ | ---------------------------------------------------------------------------------------------------------------------------- |
-| **`Edit`** | The Edit view is used to edit a single document for a given Global. |
+| Property | Description |
+| ---------- | ------------------------------------------------------------------- |
+| **`Edit`** | The Edit view is used to edit a single document for a given Global. |
To swap out any of these views, simply pass in your custom component to the `admin.components.views` property of your Payload config. This will replace the entire view, including the page breadcrumbs, title, and tabs, _as well as all nested views_.
@@ -379,13 +382,13 @@ You can also add _new_ tabs to the `Edit` view by adding another key to the `com
You can easily swap individual collection or global edit views. To do this, pass an _object_ to the `admin.components.views.Edit` property of the config. Payload renders the following views by default, all of which can be overridden:
-| Property | Description |
-| ------------------ | ---------------------------------------------------------------------------------------------------------------------------- |
-| **`Default`** | The Default view is the primary view in which your document is edited. |
-| **`Versions`** | The Versions view is used to view the version history of a single document. [More details](../versions) |
-| **`Version`** | The Version view is used to view a single version of a single document for a given collection. [More details](../versions). |
-| **`API`** | The API view is used to display the REST API JSON response for a given document. |
-| **`LivePreview`** | The LivePreview view is used to display the Live Preview interface. [More details](../live-preview) |
+| Property | Description |
+| ----------------- | --------------------------------------------------------------------------------------------------------------------------- |
+| **`Default`** | The Default view is the primary view in which your document is edited. |
+| **`Versions`** | The Versions view is used to view the version history of a single document. [More details](../versions) |
+| **`Version`** | The Version view is used to view a single version of a single document for a given collection. [More details](../versions). |
+| **`API`** | The API view is used to display the REST API JSON response for a given document. |
+| **`LivePreview`** | The LivePreview view is used to display the Live Preview interface. [More details](../live-preview) |
Here is an example:
@@ -396,7 +399,8 @@ export const MyCollection: SanitizedCollectionConfig = {
admin: {
components: {
views: {
- Edit: { // You can also define `components.views.Edit` as a component, this will override _all_ nested views
+ Edit: {
+ // You can also define `components.views.Edit` as a component, this will override _all_ nested views
Default: MyCustomDefaultTab,
Versions: MyCustomVersionsTab,
Version: MyCustomVersionTab,
@@ -423,7 +427,7 @@ export const MyCollection: SanitizedCollectionConfig = {
Component: MyCustomTab,
path: '/my-custom-tab',
// You an swap the entire tab component out for your own
- Tab: MyCustomTab
+ Tab: MyCustomTab,
},
AnotherCustomView: {
Component: AnotherCustomView,
@@ -432,7 +436,7 @@ export const MyCollection: SanitizedCollectionConfig = {
Tab: {
label: 'Another Custom View',
href: '/another-custom-view',
- }
+ },
},
},
},
@@ -539,7 +543,6 @@ const CustomTextField: React.FC<{ path: string }> = ({ path }) => {
const { value, setValue } = useField({ path })
// highlight-end
-
return setValue(e.target.value)} value={value} />
}
```
@@ -553,11 +556,11 @@ const CustomTextField: React.FC<{ path: string }> = ({ path }) => {
These are the props that will be passed to your custom Label.
-| Property | Description |
-| ---------------- | ---------------------------------------------------------------- |
-| **`htmlFor`** | Property used to set `for` attribute for label. |
-| **`label`** | Label value provided in field, it can be used with i18n. |
-| **`required`** | A boolean value that represents if the field is required or not. |
+| Property | Description |
+| -------------- | ---------------------------------------------------------------- |
+| **`htmlFor`** | Property used to set `for` attribute for label. |
+| **`label`** | Label value provided in field, it can be used with i18n. |
+| **`required`** | A boolean value that represents if the field is required or not. |
#### Example
@@ -579,10 +582,12 @@ const CustomLabel: React.FC = (props) => {
const { i18n } = useTranslation()
if (label) {
- return (
- {getTranslation(label, i18n)}
- {required && * }
- );
+ return (
+
+ {getTranslation(label, i18n)}
+ {required && * }
+
+ )
}
return null
@@ -593,10 +598,10 @@ const CustomLabel: React.FC = (props) => {
These are the props that will be passed to your custom Error.
-| Property | Description |
-| ---------------- | ------------------------------------------------------------- |
-| **`message`** | The error message. |
-| **`showError`** | A boolean value that represents if the error should be shown. |
+| Property | Description |
+| --------------- | ------------------------------------------------------------- |
+| **`message`** | The error message. |
+| **`showError`** | A boolean value that represents if the error should be shown. |
#### Example
@@ -612,8 +617,8 @@ const CustomError: React.FC = (props) => {
const { message, showError } = props
if (showError) {
- return {message}
- } else return null;
+ return {message}
+ } else return null
}
```
@@ -630,7 +635,15 @@ import { Field } from 'payload/types'
import './style.scss'
const ClearButton: React.FC = () => {
- return {/* ... */}}>X
+ return (
+ {
+ /* ... */
+ }}
+ >
+ X
+
+ )
}
const titleField: Field = {
@@ -638,12 +651,12 @@ const titleField: Field = {
type: 'text',
admin: {
components: {
- afterInput: [ClearButton]
- }
- }
+ afterInput: [ClearButton],
+ },
+ },
}
-export default titleField;
+export default titleField
```
## Custom providers
diff --git a/docs/admin/excluding-server-code.mdx b/docs/admin/excluding-server-code.mdx
index f3abbf91b5..c87cd5b664 100644
--- a/docs/admin/excluding-server-code.mdx
+++ b/docs/admin/excluding-server-code.mdx
@@ -104,6 +104,7 @@ By default the browser bundle will now include all the code from that file and a
To fix this, we need to alias the `createStripeSubscription` file to a different file that can safely be included in the browser bundle.
First, we will create a mock file to replace the server-only file when bundling:
+
```js
// mocks/modules.js
@@ -131,7 +132,7 @@ import { Subscriptions } from './collections/Subscriptions'
const mockModulePath = path.resolve(__dirname, 'mocks/emptyObject.js')
const fullFilePath = path.resolve(
__dirname,
- 'collections/Subscriptions/hooks/createStripeSubscription'
+ 'collections/Subscriptions/hooks/createStripeSubscription',
)
export default buildConfig({
@@ -173,24 +174,23 @@ export default buildConfig({
admin: {
bundler: viteBundler(),
vite: (incomingViteConfig) => {
- const existingAliases = incomingViteConfig?.resolve?.alias || {};
- let aliasArray: { find: string | RegExp; replacement: string; }[] = [];
+ const existingAliases = incomingViteConfig?.resolve?.alias || {}
+ let aliasArray: { find: string | RegExp; replacement: string }[] = []
// Pass the existing Vite aliases
if (Array.isArray(existingAliases)) {
- aliasArray = existingAliases;
+ aliasArray = existingAliases
} else {
- aliasArray = Object.values(existingAliases);
+ aliasArray = Object.values(existingAliases)
}
-
// highlight-start
// Add your own aliases using the find and replacement keys
// remember, vite aliases are exact-match only
aliasArray.push({
find: '../server-only-module',
- replacement: path.resolve(__dirname, './path/to/browser-safe-module.js')
- });
+ replacement: path.resolve(__dirname, './path/to/browser-safe-module.js'),
+ })
// highlight-end
return {
@@ -198,8 +198,8 @@ export default buildConfig({
resolve: {
...(incomingViteConfig?.resolve || {}),
alias: aliasArray,
- }
- };
+ },
+ }
},
},
})
diff --git a/docs/admin/hooks.mdx b/docs/admin/hooks.mdx
index 4da4bd7e0d..4560bed0a6 100644
--- a/docs/admin/hooks.mdx
+++ b/docs/admin/hooks.mdx
@@ -639,12 +639,12 @@ export const CustomArrayManager = () => {
The `useCollapsible` hook allows you to control parent collapsibles:
-| Property | Description |
-|---------------------------|--------------------------------------------------------------------------------------------------------------------|
-| **`collapsed`** | State of the collapsible. `true` if open, `false` if collapsed |
-| **`isVisible`** | If nested, determine if the nearest collapsible is visible. `true` if no parent is closed, `false` otherwise |
-| **`toggle`** | Toggles the state of the nearest collapsible |
-| **`withinCollapsible`** | Determine when you are within another collaspible | |
+| Property | Description |
+| ----------------------- | ------------------------------------------------------------------------------------------------------------ | --- |
+| **`collapsed`** | State of the collapsible. `true` if open, `false` if collapsed |
+| **`isVisible`** | If nested, determine if the nearest collapsible is visible. `true` if no parent is closed, `false` otherwise |
+| **`toggle`** | Toggles the state of the nearest collapsible |
+| **`withinCollapsible`** | Determine when you are within another collaspible | |
**Example:**
@@ -671,7 +671,7 @@ const CustomComponent: React.FC = () => {
The `useDocumentInfo` hook provides lots of information about the document currently being edited, including the following:
| Property | Description |
-|---------------------------|--------------------------------------------------------------------------------------------------------------------|
+| ------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| **`collection`** | If the doc is a collection, its collection config will be returned |
| **`global`** | If the doc is a global, its global config will be returned |
| **`id`** | If the doc is a collection, its ID will be returned |
@@ -804,15 +804,17 @@ const MyComponent: React.FC = () => {
return (
<>
- The current theme is {theme} and autoMode is {autoMode}
+
+ The current theme is {theme} and autoMode is {autoMode}
+
setTheme(prev => prev === "light" ? "dark" : "light")}
+ onClick={() => setTheme((prev) => (prev === 'light' ? 'dark' : 'light'))}
>
Toggle theme
>
- )
+ )
}
```
@@ -833,10 +835,7 @@ const MyComponent: React.FC = () => {
// highlight-end
return (
-
+
Reset columns
)
@@ -847,10 +846,10 @@ const MyComponent: React.FC = () => {
The `useDocumentEvents` hook provides a way of subscribing to cross-document events, such as updates made to nested documents within a drawer. This hook will report document events that are outside the scope of the document currently being edited. This hook provides the following:
-| Property | Description |
-|---------------------------|-------------------------------------------------------------------------------------------------------------------------------------------|
-| **`mostRecentUpdate`** | An object containing the most recently updated document. It contains the `entitySlug`, `id` (if collection), and `updatedAt` properties |
-| **`reportUpdate`** | A method used to report updates to documents. It accepts the same arguments as the `mostRecentUpdate` property. |
+| Property | Description |
+| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
+| **`mostRecentUpdate`** | An object containing the most recently updated document. It contains the `entitySlug`, `id` (if collection), and `updatedAt` properties |
+| **`reportUpdate`** | A method used to report updates to documents. It accepts the same arguments as the `mostRecentUpdate` property. |
**Example:**
@@ -860,14 +859,11 @@ import { useDocumentEvents } from 'payload/components/hooks'
const ListenForUpdates: React.FC = () => {
const { mostRecentUpdate } = useDocumentEvents()
- return (
-
- {JSON.stringify(mostRecentUpdate)}
-
- )
+ return {JSON.stringify(mostRecentUpdate)}
}
```
- Right now the `useDocumentEvents` hook only tracks recently updated documents, but in the future it will track more document-related events as needed, such as document creation, deletion, etc.
+ Right now the `useDocumentEvents` hook only tracks recently updated documents, but in the future
+ it will track more document-related events as needed, such as document creation, deletion, etc.
diff --git a/docs/admin/vite.mdx b/docs/admin/vite.mdx
index 763d45b6b8..e8247097ae 100644
--- a/docs/admin/vite.mdx
+++ b/docs/admin/vite.mdx
@@ -6,7 +6,8 @@ desc: NEEDS TO BE WRITTEN
---
- The Vite bundler is currently in beta. If you would like to help us test this package, we'd love to hear from you if you find any [bugs or issues](https://github.com/payloadcms/payload/issues/)!
+ The Vite bundler is currently in beta. If you would like to help us test this package, we'd love
+ to hear from you if you find any [bugs or issues](https://github.com/payloadcms/payload/issues/)!
Payload has a Vite bundler that you can install and bundle the Admin Panel with. This is an alternative to the [Webpack](/docs/admin/webpack) bundler and might give some performance boosts to your development workflow.
@@ -27,7 +28,7 @@ export default buildConfig({
collections: [],
admin: {
bundler: viteBundler(),
- }
+ },
})
```
@@ -36,7 +37,8 @@ Vite works fundamentally differently than Webpack. In development mode, it will
It then uses Rollup to create production builds of your admin UI. With Vite, you should see a decent performance boost—especially after your first cold start. However, that first cold start might take a few more seconds.
- In most cases, Vite should work out of the box. But existing Payload plugins may need to make compatibility changes to support Vite.
+ In most cases, Vite should work out of the box. But existing Payload plugins may need to make
+ compatibility changes to support Vite.
This is because Vite aliases work fundamentally differently than Webpack aliases, and Payload relies on aliasing server-only code out of the Payload config to ensure that the bundled admin JS works within your browser.
diff --git a/docs/admin/webpack.mdx b/docs/admin/webpack.mdx
index 5e808259c7..cf7e7be2b7 100644
--- a/docs/admin/webpack.mdx
+++ b/docs/admin/webpack.mdx
@@ -27,7 +27,7 @@ import { webpackBundler } from '@payloadcms/bundler-webpack'
export default buildConfig({
// highlight-start
admin: {
- bundler: webpackBundler()
+ bundler: webpackBundler(),
},
// highlight-end
})
diff --git a/docs/authentication/config.mdx b/docs/authentication/config.mdx
index 8fdf5d1f8e..8aceb21632 100644
--- a/docs/authentication/config.mdx
+++ b/docs/authentication/config.mdx
@@ -49,7 +49,8 @@ To enable API keys on a collection, set the `useAPIKey` auth option to `true`. F
Important:
If you change your `PAYLOAD_SECRET`, you will need to regenerate your API keys.
- The secret key is used to encrypt the API keys, so if you change the secret, existing API keys will no longer be valid.
+ The secret key is used to encrypt the API keys, so if you change the secret, existing API keys will
+ no longer be valid.
#### Authenticating via API Key
diff --git a/docs/authentication/overview.mdx b/docs/authentication/overview.mdx
index 0732a036d4..aa27dc7189 100644
--- a/docs/authentication/overview.mdx
+++ b/docs/authentication/overview.mdx
@@ -57,12 +57,7 @@ export const Admins: CollectionConfig = {
name: 'role',
type: 'select',
required: true,
- options: [
- 'user',
- 'admin',
- 'editor',
- 'developer',
- ],
+ options: ['user', 'admin', 'editor', 'developer'],
},
],
}
diff --git a/docs/configuration/collections.mdx b/docs/configuration/collections.mdx
index 6ad9b746d1..63446b5857 100644
--- a/docs/configuration/collections.mdx
+++ b/docs/configuration/collections.mdx
@@ -14,7 +14,7 @@ It's often best practice to write your Collections in separate files and then im
## Options
| Option | Description |
-|-------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **`slug`** \* | Unique, URL-friendly string that will act as an identifier for this Collection. |
| **`fields`** \* | Array of field types that will determine the structure and functionality of the data stored within this Collection. [Click here](/docs/fields/overview) for a full list of field types as well as how to configure them. |
| **`labels`** | Singular and plural labels for use in identifying this Collection throughout Payload. Auto-generated from slug if not defined. |
@@ -68,7 +68,7 @@ You can customize the way that the Admin panel behaves on a collection-by-collec
property on a collection's config.
| Option | Description |
-|------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `group` | Text used as a label for grouping collection and global links together in the navigation. |
| `hidden` | Set to true or a function, called with the current user, returning true to exclude this collection from navigation and admin routing. |
| `hooks` | Admin-specific hooks for this collection. [More](#admin-hooks) |
@@ -129,7 +129,7 @@ export const Posts: CollectionConfig = {
Here are a few options that you can specify options for pagination on a collection-by-collection basis:
| Option | Description |
-|----------------|-----------------------------------------------------------------------------------------------------|
+| -------------- | --------------------------------------------------------------------------------------------------- |
| `defaultLimit` | Integer that specifies the default per-page limit that should be used. Defaults to 10. |
| `limits` | Provide an array of integers to use as per-page options for admins to choose from in the List view. |
diff --git a/docs/configuration/globals.mdx b/docs/configuration/globals.mdx
index 394068146d..4c7fd59beb 100644
--- a/docs/configuration/globals.mdx
+++ b/docs/configuration/globals.mdx
@@ -65,14 +65,14 @@ You can find a few [example Global configs](https://github.com/payloadcms/public
You can customize the way that the Admin panel behaves on a Global-by-Global basis by defining the `admin` property on a Global's config.
-| Option | Description |
-| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
-| `group` | Text used as a label for grouping collection and global links together in the navigation. |
-| `hidden` | Set to true or a function, called with the current user, returning true to exclude this global from navigation and admin routing. |
-| `components` | Swap in your own React components to be used within this Global. [More](/docs/admin/components#globals) |
-| `preview` | Function to generate a preview URL within the Admin panel for this global that can point to your app. [More](#preview). |
-| `livePreview`| Enable real-time editing for instant visual feedback of your front-end application. [More](/docs/live-preview/overview). |
-| `hideAPIURL` | Hides the "API URL" meta field while editing documents within this collection. |
+| Option | Description |
+| ------------- | --------------------------------------------------------------------------------------------------------------------------------- |
+| `group` | Text used as a label for grouping collection and global links together in the navigation. |
+| `hidden` | Set to true or a function, called with the current user, returning true to exclude this global from navigation and admin routing. |
+| `components` | Swap in your own React components to be used within this Global. [More](/docs/admin/components#globals) |
+| `preview` | Function to generate a preview URL within the Admin panel for this global that can point to your app. [More](#preview). |
+| `livePreview` | Enable real-time editing for instant visual feedback of your front-end application. [More](/docs/live-preview/overview). |
+| `hideAPIURL` | Hides the "API URL" meta field while editing documents within this collection. |
### Preview
diff --git a/docs/configuration/localization.mdx b/docs/configuration/localization.mdx
index f8e5d9d616..c4a4379a4b 100644
--- a/docs/configuration/localization.mdx
+++ b/docs/configuration/localization.mdx
@@ -105,7 +105,7 @@ language and country codes (ISO 3166‑1) such as `en-US`, `en-UK`, `es-MX`, etc
### Locale Properties:
| Option | Description |
-|----------------------|--------------------------------------------------------------------------------------------------------------------------------|
+| -------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| **`code`** \* | Unique code to identify the language throughout the APIs for `locale` and `fallbackLocale` |
| **`label`** | A string to use for the selector when choosing a language, or an object keyed on the i18n keys for different languages in use. |
| **`rtl`** | A boolean that when true will make the admin UI display in Right-To-Left. |
@@ -207,11 +207,11 @@ The `fallbackLocale` arg will accept valid locales as well as `none` to disable
```graphql
query {
- Posts(locale: de, fallbackLocale: none) {
- docs {
- title
- }
+ Posts(locale: de, fallbackLocale: none) {
+ docs {
+ title
}
+ }
}
```
diff --git a/docs/configuration/overview.mdx b/docs/configuration/overview.mdx
index a9784a7906..101570f02a 100644
--- a/docs/configuration/overview.mdx
+++ b/docs/configuration/overview.mdx
@@ -19,33 +19,33 @@ Payload is a _config-based_, code-first CMS and application framework. The Paylo
## Options
-| Option | Description |
-| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `admin` \* | Base Payload admin configuration. Specify bundler*, custom components, control metadata, set the Admin user collection, and [more](/docs/admin/overview#admin-options). Required. |
-| `editor` \* | Rich Text Editor which will be used by richText fields. Required. |
-| `db` \* | Database Adapter which will be used by Payload. Read more [here](/docs/database/overview). Required. |
-| `serverURL` | A string used to define the absolute URL of your app including the protocol, for example `https://example.com`. No paths allowed, only protocol, domain and (optionally) port |
-| `collections` | An array of all Collections that Payload will manage. To read more about how to define your collection configs, [click here](/docs/configuration/collections). |
-| `globals` | An array of all Globals that Payload will manage. For more on Globals and their configs, [click here](/docs/configuration/globals). |
-| `cors` | Either a whitelist array of URLS to allow CORS requests from, or a wildcard string (`'*'`) to accept incoming requests from any domain. |
-| `localization` | Opt-in and control how Payload handles the translation of your content into multiple locales. [More](/docs/configuration/localization) |
-| `graphQL` | Manage GraphQL-specific functionality here. Define your own queries and mutations, manage query complexity limits, and [more](/docs/graphql/overview#graphql-options). |
-| `cookiePrefix` | A string that will be prefixed to all cookies that Payload sets. |
-| `csrf` | A whitelist array of URLs to allow Payload cookies to be accepted from as a form of CSRF protection. [More](/docs/authentication/overview#csrf-protection) |
-| `defaultDepth` | If a user does not specify `depth` while requesting a resource, this depth will be used. [More](/docs/getting-started/concepts#depth) |
-| `maxDepth` | The maximum allowed depth to be permitted application-wide. This setting helps prevent against malicious queries. Defaults to `10`. |
-| `indexSortableFields` | Automatically index all sortable top-level fields in the database to improve sort performance and add database compatibility for Azure Cosmos and similar. |
-| `upload` | Base Payload upload configuration. [More](/docs/upload/overview#payload-wide-upload-options). |
-| `routes` | Control the routing structure that Payload binds itself to. Specify `admin`, `api`, `graphQL`, and `graphQLPlayground`. |
-| `email` | Base email settings to allow Payload to generate email such as Forgot Password requests and other requirements. [More](/docs/email/overview#configuration) |
-| `express` | Express-specific middleware options such as compression and JSON parsing. [More](/docs/configuration/express) |
-| `debug` | Enable to expose more detailed error information. |
-| `telemetry` | Disable Payload telemetry by passing `false`. [More](/docs/configuration/overview#telemetry) |
-| `rateLimit` | Control IP-based rate limiting for all Payload resources. Used to prevent DDoS attacks and [more](/docs/production/preventing-abuse#rate-limiting-requests). |
-| `hooks` | Tap into Payload-wide hooks. [More](/docs/hooks/overview) |
-| `plugins` | An array of Payload plugins. [More](/docs/plugins/overview) |
-| `endpoints` | An array of custom API endpoints added to the Payload router. [More](/docs/rest-api/overview#custom-endpoints) |
-| `custom` | Extension point for adding custom data (e.g. for plugins) |
+| Option | Description |
+| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `admin` \* | Base Payload admin configuration. Specify bundler\*, custom components, control metadata, set the Admin user collection, and [more](/docs/admin/overview#admin-options). Required. |
+| `editor` \* | Rich Text Editor which will be used by richText fields. Required. |
+| `db` \* | Database Adapter which will be used by Payload. Read more [here](/docs/database/overview). Required. |
+| `serverURL` | A string used to define the absolute URL of your app including the protocol, for example `https://example.com`. No paths allowed, only protocol, domain and (optionally) port |
+| `collections` | An array of all Collections that Payload will manage. To read more about how to define your collection configs, [click here](/docs/configuration/collections). |
+| `globals` | An array of all Globals that Payload will manage. For more on Globals and their configs, [click here](/docs/configuration/globals). |
+| `cors` | Either a whitelist array of URLS to allow CORS requests from, or a wildcard string (`'*'`) to accept incoming requests from any domain. |
+| `localization` | Opt-in and control how Payload handles the translation of your content into multiple locales. [More](/docs/configuration/localization) |
+| `graphQL` | Manage GraphQL-specific functionality here. Define your own queries and mutations, manage query complexity limits, and [more](/docs/graphql/overview#graphql-options). |
+| `cookiePrefix` | A string that will be prefixed to all cookies that Payload sets. |
+| `csrf` | A whitelist array of URLs to allow Payload cookies to be accepted from as a form of CSRF protection. [More](/docs/authentication/overview#csrf-protection) |
+| `defaultDepth` | If a user does not specify `depth` while requesting a resource, this depth will be used. [More](/docs/getting-started/concepts#depth) |
+| `maxDepth` | The maximum allowed depth to be permitted application-wide. This setting helps prevent against malicious queries. Defaults to `10`. |
+| `indexSortableFields` | Automatically index all sortable top-level fields in the database to improve sort performance and add database compatibility for Azure Cosmos and similar. |
+| `upload` | Base Payload upload configuration. [More](/docs/upload/overview#payload-wide-upload-options). |
+| `routes` | Control the routing structure that Payload binds itself to. Specify `admin`, `api`, `graphQL`, and `graphQLPlayground`. |
+| `email` | Base email settings to allow Payload to generate email such as Forgot Password requests and other requirements. [More](/docs/email/overview#configuration) |
+| `express` | Express-specific middleware options such as compression and JSON parsing. [More](/docs/configuration/express) |
+| `debug` | Enable to expose more detailed error information. |
+| `telemetry` | Disable Payload telemetry by passing `false`. [More](/docs/configuration/overview#telemetry) |
+| `rateLimit` | Control IP-based rate limiting for all Payload resources. Used to prevent DDoS attacks and [more](/docs/production/preventing-abuse#rate-limiting-requests). |
+| `hooks` | Tap into Payload-wide hooks. [More](/docs/hooks/overview) |
+| `plugins` | An array of Payload plugins. [More](/docs/plugins/overview) |
+| `endpoints` | An array of custom API endpoints added to the Payload router. [More](/docs/rest-api/overview#custom-endpoints) |
+| `custom` | Extension point for adding custom data (e.g. for plugins) |
_\* An asterisk denotes that a property is required._
diff --git a/docs/database/migrations.mdx b/docs/database/migrations.mdx
index 5f8f2a904d..95cdfa489d 100644
--- a/docs/database/migrations.mdx
+++ b/docs/database/migrations.mdx
@@ -20,7 +20,8 @@ Ensure you have an npm script called "payload" in your `package.json` file.
```
- Note that you need to run Payload migrations through the package manager that you are using, because Payload should not be globally installed on your system.
+ Note that you need to run Payload migrations through the package manager that you are using,
+ because Payload should not be globally installed on your system.
### Migration file contents
@@ -41,15 +42,15 @@ Here is an example migration file:
```ts
import { MigrateUpArgs, MigrateDownArgs } from '@payloadcms/your-db-adapter'
-export async function up ({ payload, req }: MigrateUpArgs): Promise {
+export async function up({ payload, req }: MigrateUpArgs): Promise {
// Perform changes to your database here.
// You have access to `payload` as an argument, and
// everything is done in TypeScript.
-};
+}
-export async function down ({ payload, req }: MigrateDownArgs): Promise {
+export async function down({ payload, req }: MigrateDownArgs): Promise {
// Do whatever you need to revert changes if the `up` function fails
-};
+}
```
### Migrations Directory
diff --git a/docs/database/mongodb.mdx b/docs/database/mongodb.mdx
index 4682b99b50..9da41eadc0 100644
--- a/docs/database/mongodb.mdx
+++ b/docs/database/mongodb.mdx
@@ -31,12 +31,12 @@ export default buildConfig({
### Options
| Option | Description |
-|----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --- |
| `autoPluralization` | Tell Mongoose to auto-pluralize any collection names if it encounters any singular words used as collection `slug`s. |
| `connectOptions` | Customize MongoDB connection options. Payload will connect to your MongoDB database using default options which you can override and extend to include all the [options](https://mongoosejs.com/docs/connections.html#options) available to mongoose. |
| `disableIndexHints` | Set to true to disable hinting to MongoDB to use 'id' as index. This is currently done when counting documents for pagination, as it increases the speed of the count function used in that query. Disabling this optimization might fix some problems with AWS DocumentDB. Defaults to false |
| `migrationDir` | Customize the directory that migrations are stored. |
-| `transactionOptions` | An object with configuration properties used in [transactions](https://www.mongodb.com/docs/manual/core/transactions/) or `false` which will disable the use of transactions. | |
+| `transactionOptions` | An object with configuration properties used in [transactions](https://www.mongodb.com/docs/manual/core/transactions/) or `false` which will disable the use of transactions. | |
### Access to Mongoose models
diff --git a/docs/database/overview.mdx b/docs/database/overview.mdx
index 7f20e8df65..fd2c3d0765 100644
--- a/docs/database/overview.mdx
+++ b/docs/database/overview.mdx
@@ -42,15 +42,15 @@ You should prefer a relational DB like Postgres if:
#### Differences in Payload features
-It's important to note that almost everything Payload does is available in all of our officially supported database adapters, including localization, arrays, blocks, etc.
+It's important to note that almost everything Payload does is available in all of our officially supported database adapters, including localization, arrays, blocks, etc.
-The only thing that is not supported in Postgres yet is the [Point field](/docs/fields/point), but that should be added soon.
+The only thing that is not supported in Postgres yet is the [Point field](/docs/fields/point), but that should be added soon.
It's up to you to choose which database you would like to use.
## Configuration
-To configure the database for your Payload application, an adapter can be assigned to `config.db`. This property is required within your Payload config.
+To configure the database for your Payload application, an adapter can be assigned to `config.db`. This property is required within your Payload config.
Here's an example:
@@ -67,7 +67,7 @@ export default buildConfig({
db: postgresAdapter({
pool: {
connectionString: process.env.DATABASE_URI,
- }
+ },
}),
})
-```
\ No newline at end of file
+```
diff --git a/docs/database/postgres.mdx b/docs/database/postgres.mdx
index b641fdd83a..6d36506dd9 100644
--- a/docs/database/postgres.mdx
+++ b/docs/database/postgres.mdx
@@ -9,7 +9,8 @@ keywords: Postgres, documentation, typescript, Content Management System, cms, h
To use Payload with Postgres, install the package `@payloadcms/db-postgres`. It leverages Drizzle ORM and `node-postgres` to interact with a Postgres database that you provide.
- The Postgres database adapter is currently in beta. If you would like to help us test this package, we'd love to hear if you find any bugs or issues!
+ The Postgres database adapter is currently in beta. If you would like to help us test this
+ package, we'd love to hear if you find any bugs or issues!
It automatically manages changes to your database for you in development mode, and exposes a full suite of migration controls for you to leverage in order to keep other database environments in sync with your schema. DDL transformations are automatically generated.
@@ -30,7 +31,7 @@ export default buildConfig({
// `pool` is required.
pool: {
connectionString: process.env.DATABASE_URI,
- }
+ },
}),
})
```
@@ -38,7 +39,7 @@ export default buildConfig({
### Options
| Option | Description |
-|----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `pool` | [Pool connection options](https://orm.drizzle.team/docs/quick-postgresql/node-postgres) that will be passed to Drizzle and `node-postgres`. |
| `push` | Disable Drizzle's [`db push`](https://orm.drizzle.team/kit-docs/overview#prototyping-with-db-push) in development mode. By default, `push` is enabled for development mode only. |
| `migrationDir` | Customize the directory that migrations are stored. |
@@ -84,5 +85,7 @@ Migrations are extremely powerful thanks to the seamless way that Payload and Dr
1. Now your production database is in sync with your Payload config!
- Warning: do not mix "push" and migrations with your local development database. If you use "push" locally, and then try to migrate, Payload will throw a warning, telling you that these two methods are not meant to be used interchangeably.
+ Warning: do not mix "push" and migrations with your local development database. If you use "push"
+ locally, and then try to migrate, Payload will throw a warning, telling you that these two methods
+ are not meant to be used interchangeably.
diff --git a/docs/database/transactions.mdx b/docs/database/transactions.mdx
index 0a3784accc..e93729822e 100644
--- a/docs/database/transactions.mdx
+++ b/docs/database/transactions.mdx
@@ -66,4 +66,4 @@ The following functions can be used for managing transactions:
`payload.db.beginTransaction` - Starts a new session and returns a transaction ID for use in other Payload Local API calls.
`payload.db.commitTransaction` - Takes the identifier for the transaction, finalizes any changes.
-`payload.db.rollbackTransaction` - Takes the identifier for the transaction, discards any changes.
\ No newline at end of file
+`payload.db.rollbackTransaction` - Takes the identifier for the transaction, discards any changes.
diff --git a/docs/email/overview.mdx b/docs/email/overview.mdx
index 82f1c8d920..49c457bd4a 100644
--- a/docs/email/overview.mdx
+++ b/docs/email/overview.mdx
@@ -25,13 +25,13 @@ in the `email` property object of your payload init call. Payload will make use
The following options are configurable in the `email` property object as part of the options object when calling payload.init().
-| Option | Description |
-| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`fromName`** \* | The name part of the From field that will be seen on the delivered email |
-| **`fromAddress`** \* | The email address part of the From field that will be used when delivering email |
-| **`transport`** | The NodeMailer transport object for when you want to do it yourself, not needed when transportOptions is set |
+| Option | Description |
+| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`fromName`** \* | The name part of the From field that will be seen on the delivered email |
+| **`fromAddress`** \* | The email address part of the From field that will be used when delivering email |
+| **`transport`** | The NodeMailer transport object for when you want to do it yourself, not needed when transportOptions is set |
| **`transportOptions`** | An object that configures the transporter that Payload will create. For all the available options see the [NodeMailer documentation](https://nodemailer.com) or see the examples below |
-| **`logMockCredentials`** | If set to true and no transport/transportOptions, ethereal credentials will be logged to console on startup |
+| **`logMockCredentials`** | If set to true and no transport/transportOptions, ethereal credentials will be logged to console on startup |
_\* An asterisk denotes that a property is required._
diff --git a/docs/fields/blocks.mdx b/docs/fields/blocks.mdx
index ac5540ace1..a6333403a2 100644
--- a/docs/fields/blocks.mdx
+++ b/docs/fields/blocks.mdx
@@ -80,7 +80,7 @@ Blocks are defined as separate configs of their own.
| **`imageAltText`** | Customize this block's image thumbnail alt text. |
| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). |
| **`graphQL.singularName`** | Text to use for the GraphQL schema name. Auto-generated from slug if not defined. NOTE: this is set for deprecation, prefer `interfaceName`. |
-| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
+| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
#### Auto-generated data per block
diff --git a/docs/fields/checkbox.mdx b/docs/fields/checkbox.mdx
index fdb3fb41da..0d8644db32 100644
--- a/docs/fields/checkbox.mdx
+++ b/docs/fields/checkbox.mdx
@@ -17,21 +17,21 @@ keywords: checkbox, fields, config, configuration, documentation, Content Manage
### Config
-| Option | Description |
-| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
-| **`label`** | Text used as a field label in the Admin panel or an object with keys for each language. |
-| **`validate`** | Provide a custom validation function that will be executed on both the Admin panel and the backend. [More](/docs/fields/overview#validation) |
+| Option | Description |
+| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
+| **`label`** | Text used as a field label in the Admin panel or an object with keys for each language. |
+| **`validate`** | Provide a custom validation function that will be executed on both the Admin panel and the backend. [More](/docs/fields/overview#validation) |
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
-| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/config), include its data in the user JWT. |
-| **`hooks`** | Provide field-based hooks to control logic for this field. [More](/docs/fields/overview#field-level-hooks) |
-| **`access`** | Provide field-based access control to denote what users can see and do with this field's data. [More](/docs/fields/overview#field-level-access-control) |
-| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin panel. |
-| **`defaultValue`** | Provide data to be used for this field's default value, will default to false if field is also `required`. [More](/docs/fields/overview#default-values) |
-| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
-| **`required`** | Require this field to have a value. |
-| **`admin`** | Admin-specific configuration. See the [default field admin config](/docs/fields/overview#admin-config) for more details. |
-| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
+| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/config), include its data in the user JWT. |
+| **`hooks`** | Provide field-based hooks to control logic for this field. [More](/docs/fields/overview#field-level-hooks) |
+| **`access`** | Provide field-based access control to denote what users can see and do with this field's data. [More](/docs/fields/overview#field-level-access-control) |
+| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin panel. |
+| **`defaultValue`** | Provide data to be used for this field's default value, will default to false if field is also `required`. [More](/docs/fields/overview#default-values) |
+| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
+| **`required`** | Require this field to have a value. |
+| **`admin`** | Admin-specific configuration. See the [default field admin config](/docs/fields/overview#admin-config) for more details. |
+| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
_\* An asterisk denotes that a property is required._
diff --git a/docs/fields/code.mdx b/docs/fields/code.mdx
index 5dc2ce8bc9..45d91d8502 100644
--- a/docs/fields/code.mdx
+++ b/docs/fields/code.mdx
@@ -23,24 +23,24 @@ This field uses the `monaco-react` editor syntax highlighting.
### Config
-| Option | Description |
-| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
-| **`label`** | Text used as a field label in the Admin panel or an object with keys for each language. |
-| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
+| Option | Description |
+| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
+| **`label`** | Text used as a field label in the Admin panel or an object with keys for each language. |
+| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
| **`index`** | Build an [index](/docs/database#overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
-| **`minLength`** | Used by the default validation function to ensure values are of a minimum character length. |
-| **`maxLength`** | Used by the default validation function to ensure values are of a maximum character length. |
-| **`validate`** | Provide a custom validation function that will be executed on both the Admin panel and the backend. [More](/docs/fields/overview#validation) |
-| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/config), include its data in the user JWT. |
-| **`hooks`** | Provide field-based hooks to control logic for this field. [More](/docs/fields/overview#field-level-hooks) |
-| **`access`** | Provide field-based access control to denote what users can see and do with this field's data. [More](/docs/fields/overview#field-level-access-control) |
-| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin panel. |
-| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
-| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
-| **`required`** | Require this field to have a value. |
-| **`admin`** | Admin-specific configuration. See below for [more detail](#admin-config). |
-| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
+| **`minLength`** | Used by the default validation function to ensure values are of a minimum character length. |
+| **`maxLength`** | Used by the default validation function to ensure values are of a maximum character length. |
+| **`validate`** | Provide a custom validation function that will be executed on both the Admin panel and the backend. [More](/docs/fields/overview#validation) |
+| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/config), include its data in the user JWT. |
+| **`hooks`** | Provide field-based hooks to control logic for this field. [More](/docs/fields/overview#field-level-hooks) |
+| **`access`** | Provide field-based access control to denote what users can see and do with this field's data. [More](/docs/fields/overview#field-level-access-control) |
+| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin panel. |
+| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
+| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
+| **`required`** | Require this field to have a value. |
+| **`admin`** | Admin-specific configuration. See below for [more detail](#admin-config). |
+| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
_\* An asterisk denotes that a property is required._
diff --git a/docs/fields/date.mdx b/docs/fields/date.mdx
index 6137fa359a..1af59c6050 100644
--- a/docs/fields/date.mdx
+++ b/docs/fields/date.mdx
@@ -22,21 +22,21 @@ This field uses [`react-datepicker`](https://www.npmjs.com/package/react-datepic
### Config
-| Option | Description |
-| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
-| **`label`** | Text used as a field label in the Admin panel or an object with keys for each language. |
+| Option | Description |
+| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
+| **`label`** | Text used as a field label in the Admin panel or an object with keys for each language. |
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
-| **`validate`** | Provide a custom validation function that will be executed on both the Admin panel and the backend. [More](/docs/fields/overview#validation) |
-| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/config), include its data in the user JWT. |
-| **`hooks`** | Provide field-based hooks to control logic for this field. [More](/docs/fields/overview#field-level-hooks) |
-| **`access`** | Provide field-based access control to denote what users can see and do with this field's data. [More](/docs/fields/overview#field-level-access-control) |
-| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin panel. |
-| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
-| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
-| **`required`** | Require this field to have a value. |
-| **`admin`** | Admin-specific configuration. See below for [more detail](#admin-config). |
-| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
+| **`validate`** | Provide a custom validation function that will be executed on both the Admin panel and the backend. [More](/docs/fields/overview#validation) |
+| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/config), include its data in the user JWT. |
+| **`hooks`** | Provide field-based hooks to control logic for this field. [More](/docs/fields/overview#field-level-hooks) |
+| **`access`** | Provide field-based access control to denote what users can see and do with this field's data. [More](/docs/fields/overview#field-level-access-control) |
+| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin panel. |
+| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
+| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
+| **`required`** | Require this field to have a value. |
+| **`admin`** | Admin-specific configuration. See below for [more detail](#admin-config). |
+| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
_\* An asterisk denotes that a property is required._
@@ -44,20 +44,20 @@ _\* An asterisk denotes that a property is required._
In addition to the default [field admin config](/docs/fields/overview#admin-config), you can customize the following fields that will adjust how the component displays in the admin panel via the `date` property.
-| Property | Description |
-| ------------------------------ | ------------------------------------------------------------------------------------------- |
-| **`placeholder`** | Placeholder text for the field. |
-| **`date`** | Pass options to customize date field appearance. |
-| **`date.displayFormat`** | Format date to be shown in field **cell**. |
-| **`date.pickerAppearance`** \* | Determines the appearance of the datepicker: `dayAndTime` `timeOnly` `dayOnly` `monthOnly`. |
-| **`date.monthsToShow`** \* | Number of months to display max is 2. Defaults to 1. |
-| **`date.minDate`** \* | Min date value to allow. |
-| **`date.maxDate`** \* | Max date value to allow. |
-| **`date.minTime`** \* | Min time value to allow. |
-| **`date.maxTime`** \* | Max date value to allow. |
-| **`date.overrides`** \* | Pass any valid props directly to the [react-datepicker](https://github.com/Hacker0x01/react-datepicker/blob/master/docs/datepicker.md) |
-| **`date.timeIntervals`** \* | Time intervals to display. Defaults to 30 minutes. |
-| **`date.timeFormat`** \* | Determines time format. Defaults to `'h:mm aa'`. |
+| Property | Description |
+| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
+| **`placeholder`** | Placeholder text for the field. |
+| **`date`** | Pass options to customize date field appearance. |
+| **`date.displayFormat`** | Format date to be shown in field **cell**. |
+| **`date.pickerAppearance`** \* | Determines the appearance of the datepicker: `dayAndTime` `timeOnly` `dayOnly` `monthOnly`. |
+| **`date.monthsToShow`** \* | Number of months to display max is 2. Defaults to 1. |
+| **`date.minDate`** \* | Min date value to allow. |
+| **`date.maxDate`** \* | Max date value to allow. |
+| **`date.minTime`** \* | Min time value to allow. |
+| **`date.maxTime`** \* | Max date value to allow. |
+| **`date.overrides`** \* | Pass any valid props directly to the [react-datepicker](https://github.com/Hacker0x01/react-datepicker/blob/master/docs/datepicker.md) |
+| **`date.timeIntervals`** \* | Time intervals to display. Defaults to 30 minutes. |
+| **`date.timeFormat`** \* | Determines time format. Defaults to `'h:mm aa'`. |
_\* This property is passed directly to [react-datepicker](https://github.com/Hacker0x01/react-datepicker/blob/master/docs/datepicker.md). ._
diff --git a/docs/fields/email.mdx b/docs/fields/email.mdx
index 4eff51daca..d07000f6d1 100644
--- a/docs/fields/email.mdx
+++ b/docs/fields/email.mdx
@@ -17,22 +17,22 @@ keywords: email, fields, config, configuration, documentation, Content Managemen
### Config
-| Option | Description |
-| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
-| **`label`** | Text used as a field label in the Admin panel or an object with keys for each language. |
-| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
+| Option | Description |
+| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
+| **`label`** | Text used as a field label in the Admin panel or an object with keys for each language. |
+| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
-| **`validate`** | Provide a custom validation function that will be executed on both the Admin panel and the backend. [More](/docs/fields/overview#validation) |
-| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/config), include its data in the user JWT. |
-| **`hooks`** | Provide field-based hooks to control logic for this field. [More](/docs/fields/overview#field-level-hooks) |
-| **`access`** | Provide field-based access control to denote what users can see and do with this field's data. [More](/docs/fields/overview#field-level-access-control) |
-| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin panel. |
-| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
-| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
-| **`required`** | Require this field to have a value. |
-| **`admin`** | Admin-specific configuration. See below for [more detail](#admin-config). |
-| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
+| **`validate`** | Provide a custom validation function that will be executed on both the Admin panel and the backend. [More](/docs/fields/overview#validation) |
+| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/config), include its data in the user JWT. |
+| **`hooks`** | Provide field-based hooks to control logic for this field. [More](/docs/fields/overview#field-level-hooks) |
+| **`access`** | Provide field-based access control to denote what users can see and do with this field's data. [More](/docs/fields/overview#field-level-access-control) |
+| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin panel. |
+| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
+| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
+| **`required`** | Require this field to have a value. |
+| **`admin`** | Admin-specific configuration. See below for [more detail](#admin-config). |
+| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
_\* An asterisk denotes that a property is required._
diff --git a/docs/fields/json.mdx b/docs/fields/json.mdx
index 123b7b197a..31f079d7af 100644
--- a/docs/fields/json.mdx
+++ b/docs/fields/json.mdx
@@ -23,22 +23,22 @@ This field uses the `monaco-react` editor syntax highlighting.
### Config
-| Option | Description |
-| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
-| **`label`** | Text used as a field label in the Admin panel or an object with keys for each language. |
-| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
+| Option | Description |
+| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
+| **`label`** | Text used as a field label in the Admin panel or an object with keys for each language. |
+| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
-| **`validate`** | Provide a custom validation function that will be executed on both the Admin panel and the backend. [More](/docs/fields/overview#validation) |
-| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/config), include its data in the user JWT. |
-| **`hooks`** | Provide field-based hooks to control logic for this field. [More](/docs/fields/overview#field-level-hooks) |
-| **`access`** | Provide field-based access control to denote what users can see and do with this field's data. [More](/docs/fields/overview#field-level-access-control) |
-| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin panel. |
-| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
-| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
-| **`required`** | Require this field to have a value. |
-| **`admin`** | Admin-specific configuration. See below for [more detail](#admin-config). |
-| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
+| **`validate`** | Provide a custom validation function that will be executed on both the Admin panel and the backend. [More](/docs/fields/overview#validation) |
+| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/config), include its data in the user JWT. |
+| **`hooks`** | Provide field-based hooks to control logic for this field. [More](/docs/fields/overview#field-level-hooks) |
+| **`access`** | Provide field-based access control to denote what users can see and do with this field's data. [More](/docs/fields/overview#field-level-access-control) |
+| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin panel. |
+| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
+| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
+| **`required`** | Require this field to have a value. |
+| **`admin`** | Admin-specific configuration. See below for [more detail](#admin-config). |
+| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
_\* An asterisk denotes that a property is required._
@@ -46,8 +46,8 @@ _\* An asterisk denotes that a property is required._
In addition to the default [field admin config](/docs/fields/overview#admin-config), you can adjust the following properties:
-| Option | Description |
-| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Option | Description |
+| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`editorOptions`** | Options that can be passed to the monaco editor, [view the full list](https://microsoft.github.io/monaco-editor/typedoc/variables/editor.EditorOptions.html). |
### Example
diff --git a/docs/fields/number.mdx b/docs/fields/number.mdx
index bdeed4bbbd..ac42b246a7 100644
--- a/docs/fields/number.mdx
+++ b/docs/fields/number.mdx
@@ -20,27 +20,27 @@ keywords: number, fields, config, configuration, documentation, Content Manageme
### Config
-| Option | Description |
-| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
-| **`label`** | Text used as a field label in the Admin panel or an object with keys for each language. |
-| **`min`** | Minimum value accepted. Used in the default `validation` function. |
-| **`max`** | Maximum value accepted. Used in the default `validation` function. |
-| **`hasMany`** | Makes this field an ordered array of numbers instead of just a single number. |
-| **`minRows`** | Minimum number of numbers in the numbers array, if `hasMany` is set to true. |
-| **`maxRows`** | Maximum number of numbers in the numbers array, if `hasMany` is set to true. |
-| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
+| Option | Description |
+| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
+| **`label`** | Text used as a field label in the Admin panel or an object with keys for each language. |
+| **`min`** | Minimum value accepted. Used in the default `validation` function. |
+| **`max`** | Maximum value accepted. Used in the default `validation` function. |
+| **`hasMany`** | Makes this field an ordered array of numbers instead of just a single number. |
+| **`minRows`** | Minimum number of numbers in the numbers array, if `hasMany` is set to true. |
+| **`maxRows`** | Maximum number of numbers in the numbers array, if `hasMany` is set to true. |
+| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
-| **`validate`** | Provide a custom validation function that will be executed on both the Admin panel and the backend. [More](/docs/fields/overview#validation) |
-| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/config), include its data in the user JWT. |
-| **`hooks`** | Provide field-based hooks to control logic for this field. [More](/docs/fields/overview#field-level-hooks) |
-| **`access`** | Provide field-based access control to denote what users can see and do with this field's data. [More](/docs/fields/overview#field-level-access-control) |
-| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin panel. |
-| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
-| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
-| **`required`** | Require this field to have a value. |
-| **`admin`** | Admin-specific configuration. See below for [more detail](#admin-config). |
-| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
+| **`validate`** | Provide a custom validation function that will be executed on both the Admin panel and the backend. [More](/docs/fields/overview#validation) |
+| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/config), include its data in the user JWT. |
+| **`hooks`** | Provide field-based hooks to control logic for this field. [More](/docs/fields/overview#field-level-hooks) |
+| **`access`** | Provide field-based access control to denote what users can see and do with this field's data. [More](/docs/fields/overview#field-level-access-control) |
+| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin panel. |
+| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
+| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
+| **`required`** | Require this field to have a value. |
+| **`admin`** | Admin-specific configuration. See below for [more detail](#admin-config). |
+| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
_\* An asterisk denotes that a property is required._
diff --git a/docs/fields/point.mdx b/docs/fields/point.mdx
index 60219ab7c9..a7350d46d2 100644
--- a/docs/fields/point.mdx
+++ b/docs/fields/point.mdx
@@ -27,22 +27,22 @@ The data structure in the database matches the GeoJSON structure to represent po
### Config
-| Option | Description |
-| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
-| **`label`** | Used as a field label in the Admin panel and to name the generated GraphQL type. |
-| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
+| Option | Description |
+| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
+| **`label`** | Used as a field label in the Admin panel and to name the generated GraphQL type. |
+| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. To support location queries, point index defaults to `2dsphere`, to disable the index set to `false`. |
-| **`validate`** | Provide a custom validation function that will be executed on both the Admin panel and the backend. [More](/docs/fields/overview#validation) |
-| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/config), include its data in the user JWT. |
-| **`hooks`** | Provide field-based hooks to control logic for this field. [More](/docs/fields/overview#field-level-hooks) |
-| **`access`** | Provide field-based access control to denote what users can see and do with this field's data. [More](/docs/fields/overview#field-level-access-control) |
-| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin panel. |
-| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
-| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
-| **`required`** | Require this field to have a value. |
-| **`admin`** | Admin-specific configuration. See below for [more detail](#admin-config). |
-| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
+| **`validate`** | Provide a custom validation function that will be executed on both the Admin panel and the backend. [More](/docs/fields/overview#validation) |
+| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/config), include its data in the user JWT. |
+| **`hooks`** | Provide field-based hooks to control logic for this field. [More](/docs/fields/overview#field-level-hooks) |
+| **`access`** | Provide field-based access control to denote what users can see and do with this field's data. [More](/docs/fields/overview#field-level-access-control) |
+| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin panel. |
+| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
+| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
+| **`required`** | Require this field to have a value. |
+| **`admin`** | Admin-specific configuration. See below for [more detail](#admin-config). |
+| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
_\* An asterisk denotes that a property is required._
diff --git a/docs/fields/radio.mdx b/docs/fields/radio.mdx
index b22ab2d3fc..f77ed81ab9 100644
--- a/docs/fields/radio.mdx
+++ b/docs/fields/radio.mdx
@@ -20,22 +20,22 @@ keywords: radio, fields, config, configuration, documentation, Content Managemen
### Config
-| Option | Description |
-| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
-| **`options`** \* | Array of options to allow the field to store. Can either be an array of strings, or an array of objects containing an `label` string and a `value` string. |
-| **`label`** | Text used as a field label in the Admin panel or an object with keys for each language. |
-| **`validate`** | Provide a custom validation function that will be executed on both the Admin panel and the backend. [More](/docs/fields/overview#validation) |
+| Option | Description |
+| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
+| **`options`** \* | Array of options to allow the field to store. Can either be an array of strings, or an array of objects containing an `label` string and a `value` string. |
+| **`label`** | Text used as a field label in the Admin panel or an object with keys for each language. |
+| **`validate`** | Provide a custom validation function that will be executed on both the Admin panel and the backend. [More](/docs/fields/overview#validation) |
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
-| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/config), include its data in the user JWT. |
-| **`hooks`** | Provide field-based hooks to control logic for this field. [More](/docs/fields/overview#field-level-hooks) |
-| **`access`** | Provide field-based access control to denote what users can see and do with this field's data. [More](/docs/fields/overview#field-level-access-control) |
-| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin panel. |
-| **`defaultValue`** | Provide data to be used for this field's default value. The default value must exist within provided values in `options`. [More](/docs/fields/overview#default-values) |
-| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
-| **`required`** | Require this field to have a value. |
-| **`admin`** | Admin-specific configuration. See below for [more detail](#admin-config). |
-| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
+| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/config), include its data in the user JWT. |
+| **`hooks`** | Provide field-based hooks to control logic for this field. [More](/docs/fields/overview#field-level-hooks) |
+| **`access`** | Provide field-based access control to denote what users can see and do with this field's data. [More](/docs/fields/overview#field-level-access-control) |
+| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin panel. |
+| **`defaultValue`** | Provide data to be used for this field's default value. The default value must exist within provided values in `options`. [More](/docs/fields/overview#default-values) |
+| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
+| **`required`** | Require this field to have a value. |
+| **`admin`** | Admin-specific configuration. See below for [more detail](#admin-config). |
+| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
_\* An asterisk denotes that a property is required._
diff --git a/docs/fields/relationship.mdx b/docs/fields/relationship.mdx
index 0a07fe0c14..3d567bc790 100644
--- a/docs/fields/relationship.mdx
+++ b/docs/fields/relationship.mdx
@@ -12,10 +12,10 @@ keywords: relationship, fields, config, configuration, documentation, Content Ma
**Example uses:**
@@ -26,28 +26,28 @@ caption="Admin panel screenshot of a Relationship field"
### Config
-| Option | Description |
-|---------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
-| **`relationTo`** \* | Provide one or many collection `slug`s to be able to assign relationships to. |
-| **`filterOptions`** | A query to filter which options appear in the UI and validate against. [More](#filtering-relationship-options). |
-| **`hasMany`** | Boolean when, if set to `true`, allows this field to have many relations instead of only one. |
-| **`minRows`** | A number for the fewest allowed items during validation when a value is present. Used with `hasMany`. |
-| **`maxRows`** | A number for the most allowed items during validation when a value is present. Used with `hasMany`. |
-| **`maxDepth`** | Sets a number limit on iterations of related documents to populate when queried. [Depth](/docs/getting-started/concepts#depth) |
-| **`label`** | Text used as a field label in the Admin panel or an object with keys for each language. |
-| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
-| **`validate`** | Provide a custom validation function that will be executed on both the Admin panel and the backend. [More](/docs/fields/overview#validation) |
+| Option | Description |
+| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
+| **`relationTo`** \* | Provide one or many collection `slug`s to be able to assign relationships to. |
+| **`filterOptions`** | A query to filter which options appear in the UI and validate against. [More](#filtering-relationship-options). |
+| **`hasMany`** | Boolean when, if set to `true`, allows this field to have many relations instead of only one. |
+| **`minRows`** | A number for the fewest allowed items during validation when a value is present. Used with `hasMany`. |
+| **`maxRows`** | A number for the most allowed items during validation when a value is present. Used with `hasMany`. |
+| **`maxDepth`** | Sets a number limit on iterations of related documents to populate when queried. [Depth](/docs/getting-started/concepts#depth) |
+| **`label`** | Text used as a field label in the Admin panel or an object with keys for each language. |
+| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
+| **`validate`** | Provide a custom validation function that will be executed on both the Admin panel and the backend. [More](/docs/fields/overview#validation) |
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
-| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/config), include its data in the user JWT. |
-| **`hooks`** | Provide field-based hooks to control logic for this field. [More](/docs/fields/overview#field-level-hooks) |
-| **`access`** | Provide field-based access control to denote what users can see and do with this field's data. [More](/docs/fields/overview#field-level-access-control) |
-| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin panel. |
-| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
-| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
-| **`required`** | Require this field to have a value. |
-| **`admin`** | Admin-specific configuration. See the [default field admin config](/docs/fields/overview#admin-config) for more details. |
-| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
+| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/config), include its data in the user JWT. |
+| **`hooks`** | Provide field-based hooks to control logic for this field. [More](/docs/fields/overview#field-level-hooks) |
+| **`access`** | Provide field-based access control to denote what users can see and do with this field's data. [More](/docs/fields/overview#field-level-access-control) |
+| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin panel. |
+| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
+| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
+| **`required`** | Require this field to have a value. |
+| **`admin`** | Admin-specific configuration. See the [default field admin config](/docs/fields/overview#admin-config) for more details. |
+| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
_\* An asterisk denotes that a property is required._
@@ -131,13 +131,13 @@ The `filterOptions` property can either be a `Where` query, or a function return
prevent all, or a `Where` query. When using a function, it will be
called with an argument object with the following properties:
-| Property | Description |
-|---------------|--------------------------------------------------------------------------------------------------------------|
-| `relationTo` | The collection `slug` to filter against, limited to this field's `relationTo` property |
-| `data` | An object containing the full collection or global document currently being edited |
-| `siblingData` | An object containing document data that is scoped to only fields within the same parent of this field |
-| `id` | The `id` of the current document being edited. `id` is `undefined` during the `create` operation |
-| `user` | An object containing the currently authenticated user |
+| Property | Description |
+| ------------- | ----------------------------------------------------------------------------------------------------- |
+| `relationTo` | The collection `slug` to filter against, limited to this field's `relationTo` property |
+| `data` | An object containing the full collection or global document currently being edited |
+| `siblingData` | An object containing document data that is scoped to only fields within the same parent of this field |
+| `id` | The `id` of the current document being edited. `id` is `undefined` during the `create` operation |
+| `user` | An object containing the currently authenticated user |
### Example
@@ -287,10 +287,7 @@ To save the to `hasMany` relationship field we need to send an array of IDs:
```json
{
- "owners": [
- "6031ac9e1289176380734024",
- "602c3c327b811235943ee12b"
- ]
+ "owners": ["6031ac9e1289176380734024", "602c3c327b811235943ee12b"]
}
```
@@ -362,5 +359,6 @@ Since we are referencing multiple collections, the field you are querying on may
Note:
- You cannot query on a field within a polymorphic relationship as you would with a non-polymorphic relationship.
+ You cannot query on a field within a polymorphic relationship as you would with a
+ non-polymorphic relationship.
diff --git a/docs/fields/rich-text.mdx b/docs/fields/rich-text.mdx
index 6c2f0fafdc..f57cf9f0e4 100644
--- a/docs/fields/rich-text.mdx
+++ b/docs/fields/rich-text.mdx
@@ -18,7 +18,7 @@ keywords: rich text, fields, config, configuration, documentation, Content Manag
caption="Admin panel screenshot of a Rich Text field"
/>
-Payload's rich text field is built on an "adapter pattern" which lets you specify which rich text editor you'd like to use.
+Payload's rich text field is built on an "adapter pattern" which lets you specify which rich text editor you'd like to use.
Right now, Payload is officially supporting two rich text editors:
@@ -26,7 +26,13 @@ Right now, Payload is officially supporting two rich text editors:
2. [Lexical](/docs/rich-text/lexical) - beta, where things will be moving
- Consistent with Payload's goal of making you learn as little of Payload as possible, customizing and using the Rich Text Editor does not involve learning how to develop for a Payload rich text editor. Instead, you can invest your time and effort into learning the underlying open-source tools that will allow you to apply your learnings elsewhere as well.
+
+ Consistent with Payload's goal of making you learn as little of Payload as possible, customizing
+ and using the Rich Text Editor does not involve learning how to develop for a Payload {' '}
+ rich text editor.
+ {' '}
+ Instead, you can invest your time and effort into learning the underlying open-source tools that
+ will allow you to apply your learnings elsewhere as well.
### Config
@@ -67,4 +73,4 @@ Override the default text direction of the Admin panel for this field. Set to `t
### Editor-specific options
-For a ton more editor-specific options, including how to build custom rich text elements directly into your editor, take a look at either the [Slate docs](/docs/rich-text/slate) or the [Lexical docs](/docs/rich-text/lexical) depending on which editor you're using.
\ No newline at end of file
+For a ton more editor-specific options, including how to build custom rich text elements directly into your editor, take a look at either the [Slate docs](/docs/rich-text/slate) or the [Lexical docs](/docs/rich-text/lexical) depending on which editor you're using.
diff --git a/docs/fields/select.mdx b/docs/fields/select.mdx
index bc0d7c0a78..9244116267 100644
--- a/docs/fields/select.mdx
+++ b/docs/fields/select.mdx
@@ -20,24 +20,24 @@ keywords: select, multi-select, fields, config, configuration, documentation, Co
### Config
-| Option | Description |
-| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
-| **`options`** \* | Array of options to allow the field to store. Can either be an array of strings, or an array of objects containing a `label` string and a `value` string. |
-| **`hasMany`** | Boolean when, if set to `true`, allows this field to have many selections instead of only one. |
-| **`label`** | Text used as a field label in the Admin panel or an object with keys for each language. |
-| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
-| **`validate`** | Provide a custom validation function that will be executed on both the Admin panel and the backend. [More](/docs/fields/overview#validation) |
+| Option | Description |
+| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
+| **`options`** \* | Array of options to allow the field to store. Can either be an array of strings, or an array of objects containing a `label` string and a `value` string. |
+| **`hasMany`** | Boolean when, if set to `true`, allows this field to have many selections instead of only one. |
+| **`label`** | Text used as a field label in the Admin panel or an object with keys for each language. |
+| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
+| **`validate`** | Provide a custom validation function that will be executed on both the Admin panel and the backend. [More](/docs/fields/overview#validation) |
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
-| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/config), include its data in the user JWT. |
-| **`hooks`** | Provide field-based hooks to control logic for this field. [More](/docs/fields/overview#field-level-hooks) |
-| **`access`** | Provide field-based access control to denote what users can see and do with this field's data. [More](/docs/fields/overview#field-level-access-control) |
-| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin panel. |
-| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
-| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
-| **`required`** | Require this field to have a value. |
-| **`admin`** | Admin-specific configuration. See the [default field admin config](/docs/fields/overview#admin-config) for more details. |
-| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
+| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/config), include its data in the user JWT. |
+| **`hooks`** | Provide field-based hooks to control logic for this field. [More](/docs/fields/overview#field-level-hooks) |
+| **`access`** | Provide field-based access control to denote what users can see and do with this field's data. [More](/docs/fields/overview#field-level-access-control) |
+| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin panel. |
+| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
+| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
+| **`required`** | Require this field to have a value. |
+| **`admin`** | Admin-specific configuration. See the [default field admin config](/docs/fields/overview#admin-config) for more details. |
+| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
_\* An asterisk denotes that a property is required._
@@ -122,7 +122,7 @@ export const CustomSelectField: Field = {
],
}),
},
- }
+ },
}
```
@@ -174,9 +174,9 @@ export const CustomSelectComponent: React.FC = ({ path, optio
If you are looking to create a dynamic select field, the following tutorial will walk you through the process of creating a custom select field that fetches its options from an external API.
If you want to learn more about custom components check out the [Admin > Custom Component](/docs/admin/components#field-component) docs.
diff --git a/docs/fields/text.mdx b/docs/fields/text.mdx
index 82b0bfd20d..89d3966d99 100644
--- a/docs/fields/text.mdx
+++ b/docs/fields/text.mdx
@@ -20,27 +20,28 @@ keywords: text, fields, config, configuration, documentation, Content Management
### Config
-| Option | Description |
-| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
-| **`label`** | Text used as a field label in the Admin panel or an object with keys for each language. |
-| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
-| **`minLength`** | Used by the default validation function to ensure values are of a minimum character length. |
-| **`maxLength`** | Used by the default validation function to ensure values are of a maximum character length. |
-| **`validate`** | Provide a custom validation function that will be executed on both the Admin panel and the backend. [More](/docs/fields/overview#validation) |
+| Option | Description |
+| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
+| **`label`** | Text used as a field label in the Admin panel or an object with keys for each language. |
+| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
+| **`minLength`** | Used by the default validation function to ensure values are of a minimum character length. |
+| **`maxLength`** | Used by the default validation function to ensure values are of a maximum character length. |
+| **`validate`** | Provide a custom validation function that will be executed on both the Admin panel and the backend. [More](/docs/fields/overview#validation) |
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
-| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/config), include its data in the user JWT. |
-| **`hooks`** | Provide field-based hooks to control logic for this field. [More](/docs/fields/overview#field-level-hooks) |
-| **`access`** | Provide field-based access control to denote what users can see and do with this field's data. [More](/docs/fields/overview#field-level-access-control) |
-| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin panel. |
-| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
-| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
-| **`required`** | Require this field to have a value. |
-| **`admin`** | Admin-specific configuration. See below for [more detail](#admin-config). |
-| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
-| **`hasMany`** | Makes this field an ordered array of text instead of just a single text. |
-| **`minRows`** | Minimum number of texts in the array, if `hasMany` is set to true. |
-| **`maxRows`** | Maximum number of texts in the array, if `hasMany` is set to true. |
+| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/config), include its data in the user JWT. |
+| **`hooks`** | Provide field-based hooks to control logic for this field. [More](/docs/fields/overview#field-level-hooks) |
+| **`access`** | Provide field-based access control to denote what users can see and do with this field's data. [More](/docs/fields/overview#field-level-access-control) |
+| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin panel. |
+| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
+| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
+| **`required`** | Require this field to have a value. |
+| **`admin`** | Admin-specific configuration. See below for [more detail](#admin-config). |
+| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
+| **`hasMany`** | Makes this field an ordered array of text instead of just a single text. |
+| **`minRows`** | Minimum number of texts in the array, if `hasMany` is set to true. |
+| **`maxRows`** | Maximum number of texts in the array, if `hasMany` is set to true. |
+
_\* An asterisk denotes that a property is required._
### Admin config
diff --git a/docs/fields/textarea.mdx b/docs/fields/textarea.mdx
index c3684e543f..be2528c8a2 100644
--- a/docs/fields/textarea.mdx
+++ b/docs/fields/textarea.mdx
@@ -20,24 +20,24 @@ keywords: textarea, fields, config, configuration, documentation, Content Manage
### Config
-| Option | Description |
-| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
-| **`label`** | Text used as a field label in the Admin panel or an object with keys for each language. |
-| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
-| **`minLength`** | Used by the default validation function to ensure values are of a minimum character length. |
-| **`maxLength`** | Used by the default validation function to ensure values are of a maximum character length. |
-| **`validate`** | Provide a custom validation function that will be executed on both the Admin panel and the backend. [More](/docs/fields/overview#validation) |
+| Option | Description |
+| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
+| **`label`** | Text used as a field label in the Admin panel or an object with keys for each language. |
+| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
+| **`minLength`** | Used by the default validation function to ensure values are of a minimum character length. |
+| **`maxLength`** | Used by the default validation function to ensure values are of a maximum character length. |
+| **`validate`** | Provide a custom validation function that will be executed on both the Admin panel and the backend. [More](/docs/fields/overview#validation) |
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
-| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/config), include its data in the user JWT. |
-| **`hooks`** | Provide field-based hooks to control logic for this field. [More](/docs/fields/overview#field-level-hooks) |
-| **`access`** | Provide field-based access control to denote what users can see and do with this field's data. [More](/docs/fields/overview#field-level-access-control) |
-| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin panel. |
-| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
-| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
-| **`required`** | Require this field to have a value. |
-| **`admin`** | Admin-specific configuration. See below for [more detail](#admin-config). |
-| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
+| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/config), include its data in the user JWT. |
+| **`hooks`** | Provide field-based hooks to control logic for this field. [More](/docs/fields/overview#field-level-hooks) |
+| **`access`** | Provide field-based access control to denote what users can see and do with this field's data. [More](/docs/fields/overview#field-level-access-control) |
+| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin panel. |
+| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
+| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
+| **`required`** | Require this field to have a value. |
+| **`admin`** | Admin-specific configuration. See below for [more detail](#admin-config). |
+| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
_\* An asterisk denotes that a property is required._
diff --git a/docs/fields/upload.mdx b/docs/fields/upload.mdx
index 7db96525a5..6247a8b4d5 100644
--- a/docs/fields/upload.mdx
+++ b/docs/fields/upload.mdx
@@ -20,10 +20,10 @@ keywords: upload, images media, fields, config, configuration, documentation, Co
**Example uses:**
@@ -35,7 +35,7 @@ caption="Admin panel screenshot of an Upload field"
### Config
| Option | Description |
-|----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
| **`*relationTo`** \* | Provide a single collection `slug` to allow this field to accept a relation to. Note: the related collection must be configured to support Uploads. |
| **`filterOptions`** | A query to filter which options appear in the UI and validate against. [More](#filtering-upload-options). |
@@ -85,13 +85,13 @@ The `filterOptions` property can either be a `Where` query, or a function return
prevent all, or a `Where` query. When using a function, it will be
called with an argument object with the following properties:
-| Property | Description |
-|---------------|--------------------------------------------------------------------------------------------------------------|
-| `relationTo` | The collection `slug` to filter against, limited to this field's `relationTo` property |
-| `data` | An object containing the full collection or global document currently being edited |
-| `siblingData` | An object containing document data that is scoped to only fields within the same parent of this field |
-| `id` | The `id` of the current document being edited. `id` is `undefined` during the `create` operation |
-| `user` | An object containing the currently authenticated user |
+| Property | Description |
+| ------------- | ----------------------------------------------------------------------------------------------------- |
+| `relationTo` | The collection `slug` to filter against, limited to this field's `relationTo` property |
+| `data` | An object containing the full collection or global document currently being edited |
+| `siblingData` | An object containing document data that is scoped to only fields within the same parent of this field |
+| `id` | The `id` of the current document being edited. `id` is `undefined` during the `create` operation |
+| `user` | An object containing the currently authenticated user |
### Example
diff --git a/docs/getting-started/installation.mdx b/docs/getting-started/installation.mdx
index b55a6ef7db..c7793b82ac 100644
--- a/docs/getting-started/installation.mdx
+++ b/docs/getting-started/installation.mdx
@@ -62,9 +62,7 @@ import express from 'express'
const app = express()
app.listen(3000, async () => {
- console.log(
- "Express is now listening for incoming connections on port 3000."
- )
+ console.log('Express is now listening for incoming connections on port 3000.')
})
```
@@ -86,9 +84,7 @@ const start = async () => {
})
app.listen(3000, async () => {
- console.log(
- "Express is now listening for incoming connections on port 3000."
- )
+ console.log('Express is now listening for incoming connections on port 3000.')
})
}
@@ -105,6 +101,7 @@ PAYLOAD_SECRET=your-payload-secret
Here is a list of all properties available to pass through `payload.init`:
##### secret
+
**Required**. This is a secure string that will be used to authenticate with Payload. It can be random but should be at least 14 characters and be very difficult to guess.
Payload uses this secret key to generate secure user tokens (JWT). Behind the scenes, we do not use your secret key to encrypt directly - instead, we first take the secret key and create an encrypted string using the SHA-256 hash function. Then, we reduce the encrypted string to its first 32 characters. This final value is what Payload uses for encryption.
@@ -126,6 +123,7 @@ A boolean that disables the database connection when Payload starts up.
An object used to configure SMTP. [Read more](/docs/email/overview).
##### express
+
This is your Express app as shown above. Payload will tie into your existing `app` and scope all of its functionalities to sub-routers. By default, Payload will add an `/admin` router and an `/api` router, but you can customize these paths.
##### local
diff --git a/docs/getting-started/what-is-payload.mdx b/docs/getting-started/what-is-payload.mdx
index 3b8ba8ab3b..067bd9dd80 100644
--- a/docs/getting-started/what-is-payload.mdx
+++ b/docs/getting-started/what-is-payload.mdx
@@ -17,7 +17,8 @@ development process, but importantly, stay out of your way as your apps get more
Payload 2.0 has been released!
- Includes Postgres support, Live Preview, Lexical Editor, and more. Read the announcement .
+ Includes Postgres support, Live Preview, Lexical Editor, and more.{' '}
+ Read the announcement .
Out of the box, Payload gives you a lot of the things that you often need when developing a new website, web app, or native app:
diff --git a/docs/graphql/overview.mdx b/docs/graphql/overview.mdx
index 1ef6561302..5ec19ff40f 100644
--- a/docs/graphql/overview.mdx
+++ b/docs/graphql/overview.mdx
@@ -16,13 +16,13 @@ The labels you provide for your Collections and Globals are used to name the Gra
At the top of your Payload config you can define all the options to manage GraphQL.
-| Option | Description |
-| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `mutations` | Any custom Mutations to be added in addition to what Payload provides. [More](/docs/graphql/extending) |
-| `queries` | Any custom Queries to be added in addition to what Payload provides. [More](/docs/graphql/extending) |
-| `maxComplexity` | A number used to set the maximum allowed complexity allowed by requests [More](/docs/graphql/overview#query-complexity-limits) |
-| `disablePlaygroundInProduction` | A boolean that if false will enable the GraphQL playground, defaults to true. [More](/docs/graphql/overview#graphql-playground) |
-| `disable` | A boolean that if true will disable the GraphQL entirely, defaults to false. |
+| Option | Description |
+| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
+| `mutations` | Any custom Mutations to be added in addition to what Payload provides. [More](/docs/graphql/extending) |
+| `queries` | Any custom Queries to be added in addition to what Payload provides. [More](/docs/graphql/extending) |
+| `maxComplexity` | A number used to set the maximum allowed complexity allowed by requests [More](/docs/graphql/overview#query-complexity-limits) |
+| `disablePlaygroundInProduction` | A boolean that if false will enable the GraphQL playground, defaults to true. [More](/docs/graphql/overview#graphql-playground) |
+| `disable` | A boolean that if true will disable the GraphQL entirely, defaults to false. |
## Collections
diff --git a/docs/hooks/collections.mdx b/docs/hooks/collections.mdx
index f895a76efc..1444016e42 100644
--- a/docs/hooks/collections.mdx
+++ b/docs/hooks/collections.mdx
@@ -294,7 +294,7 @@ import { CollectionAfterForgotPasswordHook } from 'payload/types'
const afterForgotPasswordHook: CollectionAfterForgotPasswordHook = async ({
args, // arguments passed into the operation
- context,
+ context,
collection, // The collection which this hook is being run on
}) => {...}
```
diff --git a/docs/hooks/fields.mdx b/docs/hooks/fields.mdx
index fd3c8860e4..c9772083fc 100644
--- a/docs/hooks/fields.mdx
+++ b/docs/hooks/fields.mdx
@@ -64,7 +64,7 @@ which field hook you are utilizing.
Field Hooks receive one `args` argument that contains the following properties:
| Option | Description |
-|--------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`data`** | The data passed to update the document within `create` and `update` operations, and the full document itself in the `afterRead` hook. |
| **`siblingData`** | The sibling data passed to a field that the hook is running against. |
| **`findMany`** | Boolean to denote if this hook is running against finding one, or finding many within the `afterRead` hook. |
@@ -111,11 +111,13 @@ const usernameField: Field = {
name: 'username',
type: 'text',
hooks: {
- beforeValidate: [({ value }) => {
- // Trim whitespace and convert to lowercase
- return value.trim().toLowerCase()
- }],
- }
+ beforeValidate: [
+ ({ value }) => {
+ // Trim whitespace and convert to lowercase
+ return value.trim().toLowerCase()
+ },
+ ],
+ },
}
```
@@ -136,13 +138,15 @@ const emailField: Field = {
name: 'email',
type: 'email',
hooks: {
- beforeChange: [({ value, operation }) => {
- if (operation === 'create') {
- // Perform additional validation or transformation for 'create' operation
- }
- return value
- }],
- }
+ beforeChange: [
+ ({ value, operation }) => {
+ if (operation === 'create') {
+ // Perform additional validation or transformation for 'create' operation
+ }
+ return value
+ },
+ ],
+ },
}
```
@@ -164,17 +168,21 @@ const membershipStatusField: Field = {
options: [
{ label: 'Standard', value: 'standard' },
{ label: 'Premium', value: 'premium' },
- { label: 'VIP', value: 'vip' }
+ { label: 'VIP', value: 'vip' },
],
hooks: {
- afterChange: [({ value, previousValue, req }) => {
- if (value !== previousValue) {
- // Log or perform an action when the membership status changes
- console.log(`User ID ${req.user.id} changed their membership status from ${previousValue} to ${value}.`)
- // Here, you can implement actions that could track conversions from one tier to another
- }
- }],
- }
+ afterChange: [
+ ({ value, previousValue, req }) => {
+ if (value !== previousValue) {
+ // Log or perform an action when the membership status changes
+ console.log(
+ `User ID ${req.user.id} changed their membership status from ${previousValue} to ${value}.`,
+ )
+ // Here, you can implement actions that could track conversions from one tier to another
+ }
+ },
+ ],
+ },
}
```
@@ -195,11 +203,13 @@ const dateField: Field = {
name: 'createdAt',
type: 'date',
hooks: {
- afterRead: [({ value }) => {
- // Format date for display
- return new Date(value).toLocaleDateString()
- }],
- }
+ afterRead: [
+ ({ value }) => {
+ // Format date for display
+ return new Date(value).toLocaleDateString()
+ },
+ ],
+ },
}
```
diff --git a/docs/live-preview/frontend.mdx b/docs/live-preview/frontend.mdx
index f9e82499ee..32475822ea 100644
--- a/docs/live-preview/frontend.mdx
+++ b/docs/live-preview/frontend.mdx
@@ -12,24 +12,28 @@ Wiring your front-end into Live Preview is easy. If your front-end application i
By default, all hooks accept the following args:
-| Path | Description |
-| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`serverURL`** \* | The URL of your Payload server. |
-| **`initialData`** | The initial data of the document. The live data will be merged in as changes are made. |
-| **`depth`** | The depth of the relationships to fetch. Defaults to `0`. |
-| **`apiRoute`** | The path of your API route as defined in `routes.api`. Defaults to `/api`. |
+| Path | Description |
+| ------------------ | -------------------------------------------------------------------------------------- |
+| **`serverURL`** \* | The URL of your Payload server. |
+| **`initialData`** | The initial data of the document. The live data will be merged in as changes are made. |
+| **`depth`** | The depth of the relationships to fetch. Defaults to `0`. |
+| **`apiRoute`** | The path of your API route as defined in `routes.api`. Defaults to `/api`. |
_\* An asterisk denotes that a property is required._
And return the following values:
-| Path | Description |
-| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`data`** | The live data of the document, merged with the initial data. |
-| **`isLoading`** | A boolean that indicates whether or not the document is loading. |
+| Path | Description |
+| --------------- | ---------------------------------------------------------------- |
+| **`data`** | The live data of the document, merged with the initial data. |
+| **`isLoading`** | A boolean that indicates whether or not the document is loading. |
- If your front-end is tightly coupled to required fields, you should ensure that your UI does not break when these fields are removed. For example, if you are rendering something like `data.relatedPosts[0].title`, your page will break once you remove the first related post. To get around this, use conditional logic, optional chaining, or default values in your UI where needed. For example, `data?.relatedPosts?.[0]?.title`.
+ If your front-end is tightly coupled to required fields, you should ensure that your UI does not
+ break when these fields are removed. For example, if you are rendering something like
+ `data.relatedPosts[0].title`, your page will break once you remove the first related post. To get
+ around this, use conditional logic, optional chaining, or default values in your UI where needed.
+ For example, `data?.relatedPosts?.[0]?.title`.
### React
@@ -45,8 +49,8 @@ npm install @payloadcms/live-preview-react
Then, use the `useLivePreview` hook in your React component:
```tsx
-'use client';
-import { useLivePreview } from '@payloadcms/live-preview-react';
+'use client'
+import { useLivePreview } from '@payloadcms/live-preview-react'
import { Page as PageType } from '@/payload-types'
// Fetch the page in a server component, pass it to the client component, then thread it through the hook
@@ -63,14 +67,14 @@ export const PageClient: React.FC<{
depth: 2,
})
- return (
- {data.title}
- )
+ return {data.title}
}
```
- If is important that the `depth` argument matches exactly with the depth of your initial page request. The depth property is used to populated relationships and uploads beyond their IDs. See [Depth](../getting-started/concepts#depth) for more information.
+ If is important that the `depth` argument matches exactly with the depth of your initial page
+ request. The depth property is used to populated relationships and uploads beyond their IDs. See
+ [Depth](../getting-started/concepts#depth) for more information.
## Building your own hook
@@ -85,25 +89,25 @@ npm install @payloadcms/live-preview
This package provides the following functions:
-| Path | Description |
-| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`subscribe`** | Subscribes to the Admin panel's `window.postMessage` events and calls the provided callback function. |
-| **`unsubscribe`** | Unsubscribes from the Admin panel's `window.postMessage` events. |
-| **`ready`** | Sends a `window.postMessage` event to the Admin panel to indicate that the front-end is ready to receive messages. |
+| Path | Description |
+| ----------------- | ------------------------------------------------------------------------------------------------------------------ |
+| **`subscribe`** | Subscribes to the Admin panel's `window.postMessage` events and calls the provided callback function. |
+| **`unsubscribe`** | Unsubscribes from the Admin panel's `window.postMessage` events. |
+| **`ready`** | Sends a `window.postMessage` event to the Admin panel to indicate that the front-end is ready to receive messages. |
The `subscribe` function takes the following args:
-| Path | Description |
-| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`callback`** \* | A callback function that is called with `data` every time a change is made to the document. |
-| **`serverURL`** \* | The URL of your Payload server. |
-| **`initialData`** | The initial data of the document. The live data will be merged in as changes are made. |
-| **`depth`** | The depth of the relationships to fetch. Defaults to `0`. |
+| Path | Description |
+| ------------------ | ------------------------------------------------------------------------------------------- |
+| **`callback`** \* | A callback function that is called with `data` every time a change is made to the document. |
+| **`serverURL`** \* | The URL of your Payload server. |
+| **`initialData`** | The initial data of the document. The live data will be merged in as changes are made. |
+| **`depth`** | The depth of the relationships to fetch. Defaults to `0`. |
With these functions, you can build your own hook using your front-end framework of choice:
```tsx
-import { subscribe, unsubscribe } from '@payloadcms/live-preview';
+import { subscribe, unsubscribe } from '@payloadcms/live-preview'
// To build your own hook, subscribe to Live Preview events using the`subscribe` function
// It handles everything from:
@@ -159,7 +163,7 @@ export const useLivePreview = (props: {
hasSentReadyMessage.current = true
ready({
- serverURL
+ serverURL,
})
}
@@ -177,7 +181,8 @@ export const useLivePreview = (props: {
```
- When building your own hook, ensure that the args and return values are consistent with the ones listed at the top of this document. This will ensure that all hooks follow the same API.
+ When building your own hook, ensure that the args and return values are consistent with the ones
+ listed at the top of this document. This will ensure that all hooks follow the same API.
## Example
@@ -226,8 +231,8 @@ const { docs } = await payload.find({
where: {
slug: {
equals: 'home',
- }
- }
+ },
+ },
})
```
diff --git a/docs/live-preview/overview.mdx b/docs/live-preview/overview.mdx
index 292ec5053c..1fcc75f793 100644
--- a/docs/live-preview/overview.mdx
+++ b/docs/live-preview/overview.mdx
@@ -13,19 +13,23 @@ Live Preview works by rendering an iframe on the page that loads your front-end
{/* IMAGE OF LIVE PREVIEW HERE */}
- Live Preview is currently in beta. You may use this feature in production, but please be aware that it is subject to change and may not be fully stable for all use cases. If you encounter any issues, please [report them](https://github.com/payloadcms/payload/issues/new?assignees=jacobsfletch&labels=possible-bug&projects=&title=Live%20Preview&template=1.bug_report.yml) with as much detail as possible.
+ Live Preview is currently in beta. You may use this feature in production, but please be aware
+ that it is subject to change and may not be fully stable for all use cases. If you encounter any
+ issues, please [report
+ them](https://github.com/payloadcms/payload/issues/new?assignees=jacobsfletch&labels=possible-bug&projects=&title=Live%20Preview&template=1.bug_report.yml)
+ with as much detail as possible.
## Setup
Setting up Live Preview is easy. You first need to enable it through the `admin.livePreview` property of your Payload config. It takes the following options:
-| Path | Description |
-| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`url`** \* | String, or function that returns a string, pointing to your front-end application. This value is used as the iframe `src`. [More details](#url). |
-| **`breakpoints`** | Array of breakpoints to be used as “device sizes” in the preview window. Each item appears as an option in the toolbar. [More details](#breakpoints). |
-| **`collections`** | Array of collection slugs to enable Live Preview on. |
-| **`globals`** | Array of global slugs to enable Live Preview on. |
+| Path | Description |
+| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`url`** \* | String, or function that returns a string, pointing to your front-end application. This value is used as the iframe `src`. [More details](#url). |
+| **`breakpoints`** | Array of breakpoints to be used as “device sizes” in the preview window. Each item appears as an option in the toolbar. [More details](#breakpoints). |
+| **`collections`** | Array of collection slugs to enable Live Preview on. |
+| **`globals`** | Array of global slugs to enable Live Preview on. |
_\* An asterisk denotes that a property is required._
@@ -68,11 +72,11 @@ The `url` property is a string that points to your front-end application. This v
You can also pass a function in order to dynamically format URLs. This function is called with the following arguments:
-| Path | Description |
-| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`data`** | The data of the document being edited. This includes changes that have not yet been saved. |
-| **`documentInfo`** | Information about the document being edited like collection slug. [More details](../admin/hooks#usedocumentinfo). |
-| **`locale`** | The locale currently being edited (if applicable). [More details](../configuration/localization). |
+| Path | Description |
+| ------------------ | ----------------------------------------------------------------------------------------------------------------- |
+| **`data`** | The data of the document being edited. This includes changes that have not yet been saved. |
+| **`documentInfo`** | Information about the document being edited like collection slug. [More details](../admin/hooks#usedocumentinfo). |
+| **`locale`** | The locale currently being edited (if applicable). [More details](../configuration/localization). |
Here is an example of using a function that returns a dynamic URL:
@@ -100,12 +104,12 @@ Here is an example of using a function that returns a dynamic URL:
The breakpoints property is an array of objects which are used as “device sizes” in the preview window. Each item will render as an option in the toolbar. When selected, the preview window will resize to the exact dimensions specified in that breakpoint. Each breakpoint takes the following properties:
-| Path | Description |
-| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`label`** \* | The label to display in the drop-down. This is what the user will see. |
-| **`name`** \* | The name of the breakpoint. |
-| **`width`** \* | The width of the breakpoint. This is used to set the width of the iframe. |
-| **`height`** \* | The height of the breakpoint. This is used to set the height of the iframe. |
+| Path | Description |
+| --------------- | --------------------------------------------------------------------------- |
+| **`label`** \* | The label to display in the drop-down. This is what the user will see. |
+| **`name`** \* | The name of the breakpoint. |
+| **`width`** \* | The width of the breakpoint. This is used to set the width of the iframe. |
+| **`height`** \* | The height of the breakpoint. This is used to set the height of the iframe. |
_\* An asterisk denotes that a property is required._
diff --git a/docs/local-api/overview.mdx b/docs/local-api/overview.mdx
index aef4c71e21..ce17b99885 100644
--- a/docs/local-api/overview.mdx
+++ b/docs/local-api/overview.mdx
@@ -70,7 +70,7 @@ You can specify more options within the Local API vs. REST or GraphQL due to the
executed in.
| Local Option | Description |
-|--------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `collection` | Required for Collection operations. Specifies the Collection slug to operate against. |
| `data` | The data to use within the operation. Required for `create`, `update`. |
| `depth` | [Control auto-population](/docs/getting-started/concepts#depth) of nested relationship and upload fields. |
diff --git a/docs/plugins/build-your-own.mdx b/docs/plugins/build-your-own.mdx
index 0b6970112c..49991d2524 100644
--- a/docs/plugins/build-your-own.mdx
+++ b/docs/plugins/build-your-own.mdx
@@ -9,14 +9,16 @@ keywords: plugins, template, config, configuration, extensions, custom, document
Building your own plugin is easy, and if you're already familiar with Payload then you'll have everything you need to get started. You can either start from scratch or use the Payload plugin template to get up and running quickly.
- To use the template, run `npx create-payload-app@latest -t plugin -n my-new-plugin` directly in your terminal or [clone the template directly from GitHub](https://github.com/payloadcms/payload-plugin-template).
+ To use the template, run `npx create-payload-app@latest -t plugin -n my-new-plugin` directly in
+ your terminal or [clone the template directly from
+ GitHub](https://github.com/payloadcms/payload-plugin-template).
Our plugin template includes everything you need to build a full life-cycle plugin:
-* Example files and functions for extending the payload config
-* A local dev environment to develop the plugin
-* Test suite with integrated GitHub workflow
+- Example files and functions for extending the payload config
+- A local dev environment to develop the plugin
+- Test suite with integrated GitHub workflow
By abstracting your code into a plugin, you'll be able to reuse your feature across multiple projects and make it available for other developers to use.
@@ -24,7 +26,6 @@ By abstracting your code into a plugin, you'll be able to reuse your featur
Here is a brief recap of how to integrate plugins with Payload, to learn more head back to the [plugin overview page](https://payloadcms.com/docs/plugins/overview).
-
#### How to install a plugin
To install any plugin, simply add it to your Payload config in the plugins array.
@@ -44,7 +45,6 @@ const config = buildConfig({
export default config;
```
-
#### Initialization
The initialization process goes in the following order:
@@ -55,7 +55,6 @@ The initialization process goes in the following order:
4. Sanitization cleans and validates data
5. Final config gets initialized
-
### Plugin Template
In the [Payload plugin template](https://github.com/payloadcms/payload-plugin-template), you will see a common file structure that is used across plugins:
@@ -64,14 +63,12 @@ In the [Payload plugin template](https://github.com/payloadcms/payload-plugin-te
2. /src folder - everything related to the plugin
3. /dev folder - sanitized test project for development
-
#### Root
In the root folder, you will see various files related to the configuration of the plugin. We set up our environment in a similar manner in Payload core and across other projects. The only two files you need to modify are:
-* **README**.md - This contains instructions on how to use the template. When you are ready, update this to contain instructions on how to use your Plugin.
-* **package**.json - Contains necessary scripts and dependencies. Overwrite the metadata in this file to describe your Plugin.
-
+- **README**.md - This contains instructions on how to use the template. When you are ready, update this to contain instructions on how to use your Plugin.
+- **package**.json - Contains necessary scripts and dependencies. Overwrite the metadata in this file to describe your Plugin.
#### Dev
@@ -104,7 +101,6 @@ When you're ready to start development, navigate into this folder with `cd
And then start the project with `yarn dev` and pull up `http://localhost:3000` in your browser.
-
### Testing
Another benefit of the dev folder is that you have the perfect environment established for testing.
@@ -133,7 +129,6 @@ describe('Plugin tests', () => {
})
```
-
### Seeding data
For development and testing, you will likely need some data to work with. You can streamline this process by seeding and dropping your database - instead of manually entering data.
@@ -164,17 +159,14 @@ export const seed = async (payload: Payload): Promise => {
```
-
#### Src
Now that we have our environment setup and dev project ready to go - it's time to build the plugin!
-
**index.ts**
First up, the `src/index.ts` file - this is where the plugin should be imported from. It is best practice not to build the plugin directly in this file, instead we use this to export the plugin and types from their respective files.
-
**Plugin.ts**
To reiterate, the essence of a payload plugin is simply to extend the Payload config - and that is exactly what we are doing in this file.
@@ -196,7 +188,6 @@ export const samplePlugin =
3. From here, you can extend the config however you like!
4. Finally, return the config and you're all set.
-
### Spread Syntax
[Spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) (or the spread operator) is a feature in JavaScript that uses the dot notation **(...)** to spread elements from arrays, strings, or objects into various contexts.
@@ -244,7 +235,6 @@ If you wish to add to the `onInit`, you must include the async/await. We don&apo
In the template, we have stubbed out a basic `onInitExtension` file that you can use, if not needed feel free to delete it.
-
### Webpack
If any of your files use server only packages such as fs, stripe, nodemailer, etc, they will need to be removed from the browser bundle. To do that, you can [alias the file imports with webpack](https://payloadcms.com/docs/admin/webpack#aliasing-server-only-modules).
@@ -283,12 +273,21 @@ If possible, include [JSDoc comments](https://www.typescriptlang.org/docs/handbo
In addition to the setup covered above, here are other best practices to follow:
##### Providing an enable / disable option:
+
For a better user experience, provide a way to disable the plugin without uninstalling it. This is especially important if your plugin adds additional webpack aliases, this will allow you to still let the webpack run to prevent errors.
+
##### Include tests in your GitHub CI workflow:
+
If you've configured tests for your package, integrate them into your workflow to run the tests each time you commit to the plugin repository. Learn more about [how to configure tests into your GitHub CI workflow.](https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs)
+
##### Publish your finished plugin to NPM:
+
The best way to share and allow others to use your plugin once it is complete is to publish an NPM package. This process is straightforward and well documented, find out more about [creating and publishing a NPM package here](https://docs.npmjs.com/creating-and-publishing-scoped-public-packages/).
+
##### Add payload-plugin topic tag:
+
Apply the tag **payload-plugin** to your GitHub repository. This will boost the visibility of your plugin and ensure it gets listed with [existing payload plugins](https://github.com/topics/payload-plugin).
+
##### Use [Semantic Versioning](https://semver.org/) (SemVer):
+
With the SemVer system you release version numbers that reflect the nature of changes (major, minor, patch). Ensure all major versions reference their Payload compatibility.
diff --git a/docs/plugins/form-builder.mdx b/docs/plugins/form-builder.mdx
index f77a0cd23c..a34ea060b6 100644
--- a/docs/plugins/form-builder.mdx
+++ b/docs/plugins/form-builder.mdx
@@ -15,7 +15,12 @@ All form submissions are stored directly in your database and are managed direct
Forms can be as simple or complex as you need, from a basic contact form, to a multi-step lead generation engine, or even a donation form that processes payment. You may not need to reach for third-party services like HubSpot or Mailchimp for this, but instead use your own first-party tooling, built directly into your own application.
- This plugin is completely open-source and the [source code can be found here](https://github.com/payloadcms/payload/tree/main/packages/plugin-form-builder). If you need help, check out our [Community Help](https://payloadcms.com/community-help). If you think you've found a bug, please [open a new issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%20form-builder&template=bug_report.md&title=plugin-form-builder%3A) with as much detail as possible.
+ This plugin is completely open-source and the [source code can be found
+ here](https://github.com/payloadcms/payload/tree/main/packages/plugin-form-builder). If you need
+ help, check out our [Community Help](https://payloadcms.com/community-help). If you think you've
+ found a bug, please [open a new
+ issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%20form-builder&template=bug_report.md&title=plugin-form-builder%3A)
+ with as much detail as possible.
##### Core Features
@@ -52,7 +57,7 @@ const config = buildConfig({
plugins: [
formBuilder({
// see below for a list of available options
- })
+ }),
],
})
@@ -79,8 +84,8 @@ formBuilder({
checkbox: true,
number: true,
message: true,
- payment: false
- }
+ payment: false,
+ },
})
```
@@ -92,7 +97,7 @@ The `redirectRelationships` property is an array of collection slugs that, when
// payload.config.ts
formBuilder({
// ...
- redirectRelationships: ['pages']
+ redirectRelationships: ['pages'],
})
```
@@ -110,7 +115,7 @@ formBuilder({
...email,
html: email.html, // transform the html in any way you'd like (maybe wrap it in an html template?)
}))
- }
+ },
})
```
@@ -123,18 +128,18 @@ Override anything on the `forms` collection by sending a [Payload Collection Con
formBuilder({
// ...
formOverrides: {
- slug: "contact-forms",
+ slug: 'contact-forms',
access: {
read: () => true,
update: () => false,
},
fields: [
{
- name: "custom-field",
- type: "text"
- }
- ]
- }
+ name: 'custom-field',
+ type: 'text',
+ },
+ ],
+ },
})
```
@@ -143,7 +148,12 @@ formBuilder({
Override anything on the `form-submissions` collection by sending a [Payload Collection Config](https://payloadcms.com/docs/configuration/collections) to the `formSubmissionOverrides` property.
- By default, this plugin relies on [Payload access control](https://payloadcms.com/docs/access-control/collections) to restrict the `update` and `read` operations on the `form-submissions` collection. This is because _anyone_ should be able to create a form submission, even from a public-facing website, but _no one_ should be able to update a submission one it has been created, or read a submission unless they have permission. You can override this behavior or any other property as needed.
+ By default, this plugin relies on [Payload access
+ control](https://payloadcms.com/docs/access-control/collections) to restrict the `update` and
+ `read` operations on the `form-submissions` collection. This is because _anyone_ should be able to
+ create a form submission, even from a public-facing website, but _no one_ should be able to update
+ a submission one it has been created, or read a submission unless they have permission. You can
+ override this behavior or any other property as needed.
```ts
@@ -151,8 +161,8 @@ Override anything on the `form-submissions` collection by sending a [Payload Col
formBuilder({
// ...
formSubmissionOverrides: {
- slug: "leads",
- }
+ slug: 'leads',
+ },
})
```
@@ -164,7 +174,7 @@ First import the utility function. This will execute all of the price conditions
```ts
// payload.config.ts
-import { getPaymentTotal } from '@payloadcms/plugin-form-builder';
+import { getPaymentTotal } from '@payloadcms/plugin-form-builder'
```
Then in your plugin's config:
@@ -175,14 +185,14 @@ formBuilder({
// ...
handlePayment: async ({ form, submissionData }) => {
// first calculate the price
- const paymentField = form.fields?.find((field) => field.blockType === 'payment');
+ const paymentField = form.fields?.find((field) => field.blockType === 'payment')
const price = getPaymentTotal({
basePrice: paymentField.basePrice,
priceConditions: paymentField.priceConditions,
fieldValues: submissionData,
- });
+ })
// then asynchronously process the payment here
- }
+ },
})
```
@@ -192,139 +202,140 @@ Each field represents a form input. To override default settings pass either a b
Note:
- "Fields" here is in reference to the _fields to build forms with_, not to be confused with the _fields of a collection_ which are set via `formOverrides.fields`.
+ "Fields" here is in reference to the _fields to build forms with_, not to be confused with the _fields
+ of a collection_ which are set via `formOverrides.fields`.
#### Text
Maps to a `text` input in your front-end. Used to collect a simple string.
-| Property | Type | Description |
-| --- | --- | --- |
-| `name` | string | The name of the field. |
-| `label` | string | The label of the field. |
-| `defaultValue` | string | The default value of the field. |
-| `width` | string | The width of the field on the front-end. |
-| `required` | checkbox | Whether or not the field is required when submitted. |
+| Property | Type | Description |
+| -------------- | -------- | ---------------------------------------------------- |
+| `name` | string | The name of the field. |
+| `label` | string | The label of the field. |
+| `defaultValue` | string | The default value of the field. |
+| `width` | string | The width of the field on the front-end. |
+| `required` | checkbox | Whether or not the field is required when submitted. |
#### Textarea
Maps to a `textarea` input on your front-end. Used to collect a multi-line string.
-| Property | Type | Description |
-| --- | --- | --- |
-| `name` | string | The name of the field. |
-| `label` | string | The label of the field. |
-| `defaultValue` | string | The default value of the field. |
-| `width` | string | The width of the field on the front-end. |
-| `required` | checkbox | Whether or not the field is required when submitted. |
+| Property | Type | Description |
+| -------------- | -------- | ---------------------------------------------------- |
+| `name` | string | The name of the field. |
+| `label` | string | The label of the field. |
+| `defaultValue` | string | The default value of the field. |
+| `width` | string | The width of the field on the front-end. |
+| `required` | checkbox | Whether or not the field is required when submitted. |
#### Select
Maps to a `select` input on your front-end. Used to display a list of options.
-| Property | Type | Description |
-| --- | --- | --- |
-| `name` | string | The name of the field. |
-| `label` | string | The label of the field. |
-| `defaultValue` | string | The default value of the field. |
-| `width` | string | The width of the field on the front-end. |
-| `required` | checkbox | Whether or not the field is required when submitted. |
-| `options` | array | An array of objects with `label` and `value` properties. |
+| Property | Type | Description |
+| -------------- | -------- | -------------------------------------------------------- |
+| `name` | string | The name of the field. |
+| `label` | string | The label of the field. |
+| `defaultValue` | string | The default value of the field. |
+| `width` | string | The width of the field on the front-end. |
+| `required` | checkbox | Whether or not the field is required when submitted. |
+| `options` | array | An array of objects with `label` and `value` properties. |
#### Email (field)
Maps to a `text` input with type `email` on your front-end. Used to collect an email address.
-| Property | Type | Description |
-| --- | --- | --- |
-| `name` | string | The name of the field. |
-| `label` | string | The label of the field. |
-| `defaultValue` | string | The default value of the field. |
-| `width` | string | The width of the field on the front-end. |
-| `required` | checkbox | Whether or not the field is required when submitted. |
+| Property | Type | Description |
+| -------------- | -------- | ---------------------------------------------------- |
+| `name` | string | The name of the field. |
+| `label` | string | The label of the field. |
+| `defaultValue` | string | The default value of the field. |
+| `width` | string | The width of the field on the front-end. |
+| `required` | checkbox | Whether or not the field is required when submitted. |
#### State
Maps to a `select` input on your front-end. Used to collect a US state.
-| Property | Type | Description |
-| --- | --- | --- |
-| `name` | string | The name of the field. |
-| `label` | string | The label of the field. |
-| `defaultValue` | string | The default value of the field. |
-| `width` | string | The width of the field on the front-end. |
-| `required` | checkbox | Whether or not the field is required when submitted. |
+| Property | Type | Description |
+| -------------- | -------- | ---------------------------------------------------- |
+| `name` | string | The name of the field. |
+| `label` | string | The label of the field. |
+| `defaultValue` | string | The default value of the field. |
+| `width` | string | The width of the field on the front-end. |
+| `required` | checkbox | Whether or not the field is required when submitted. |
#### Country
Maps to a `select` input on your front-end. Used to collect a country.
-| Property | Type | Description |
-| --- | --- | --- |
-| `name` | string | The name of the field. |
-| `label` | string | The label of the field. |
-| `defaultValue` | string | The default value of the field. |
-| `width` | string | The width of the field on the front-end. |
-| `required` | checkbox | Whether or not the field is required when submitted. |
+| Property | Type | Description |
+| -------------- | -------- | ---------------------------------------------------- |
+| `name` | string | The name of the field. |
+| `label` | string | The label of the field. |
+| `defaultValue` | string | The default value of the field. |
+| `width` | string | The width of the field on the front-end. |
+| `required` | checkbox | Whether or not the field is required when submitted. |
#### Checkbox
Maps to a `checkbox` input on your front-end. Used to collect a boolean value.
-| Property | Type | Description |
-| --- | --- | --- |
-| `name` | string | The name of the field. |
-| `label` | string | The label of the field. |
-| `defaultValue` | checkbox | The default value of the field. |
-| `width` | string | The width of the field on the front-end. |
-| `required` | checkbox | Whether or not the field is required when submitted. |
+| Property | Type | Description |
+| -------------- | -------- | ---------------------------------------------------- |
+| `name` | string | The name of the field. |
+| `label` | string | The label of the field. |
+| `defaultValue` | checkbox | The default value of the field. |
+| `width` | string | The width of the field on the front-end. |
+| `required` | checkbox | Whether or not the field is required when submitted. |
#### Number
Maps to a `number` input on your front-end. Used to collect a number.
-| Property | Type | Description |
-| --- | --- | --- |
-| `name` | string | The name of the field. |
-| `label` | string | The label of the field. |
-| `defaultValue` | string | The default value of the field. |
-| `width` | string | The width of the field on the front-end. |
-| `required` | checkbox | Whether or not the field is required when submitted. || `defaultValue` | number | The default value of the field. |
+| Property | Type | Description |
+| -------------- | -------- | ---------------------------------------------------- | --- | -------------- | ------ | ------------------------------- |
+| `name` | string | The name of the field. |
+| `label` | string | The label of the field. |
+| `defaultValue` | string | The default value of the field. |
+| `width` | string | The width of the field on the front-end. |
+| `required` | checkbox | Whether or not the field is required when submitted. | | `defaultValue` | number | The default value of the field. |
#### Message
Maps to a `RichText` component on your front-end. Used to display an arbitrary message to the user anywhere in the form.
-| property | type | description |
-| --- | --- | --- |
+| property | type | description |
+| --------- | -------- | ----------------------------------- |
| `message` | richText | The message to display on the form. |
#### Payment
Add this field to your form if it should collect payment. Upon submission, the `handlePayment` callback is executed with the form and submission data. You can use this to integrate with any third-party payment processing API.
-| property | type | description |
-| --- | --- | --- |
-| `name` | string | The name of the field. |
-| `label` | string | The label of the field. |
-| `defaultValue` | number | The default value of the field. |
-| `width` | string | The width of the field on the front-end. |
-| `required` | checkbox | Whether or not the field is required when submitted. |
-| `priceConditions` | array | An array of objects that define the price conditions. See below for more details. |
+| property | type | description |
+| ----------------- | -------- | --------------------------------------------------------------------------------- |
+| `name` | string | The name of the field. |
+| `label` | string | The label of the field. |
+| `defaultValue` | number | The default value of the field. |
+| `width` | string | The width of the field on the front-end. |
+| `required` | checkbox | Whether or not the field is required when submitted. |
+| `priceConditions` | array | An array of objects that define the price conditions. See below for more details. |
##### Price Conditions
Each of the `priceConditions` are executed by the `getPaymentTotal` utility that this plugin provides. You can call this function in your `handlePayment` callback to dynamically calculate the total price of a form upon submission based on the user's input. For example, you could create a price condition that says "if the user selects 'yes' for this checkbox, add $10 to the total price".
-| property | type | description |
-| --- | --- | --- |
-| `fieldToUse` | relationship | The field to use to determine the price. |
-| `condition` | string | The condition to use to determine the price. |
-| `valueForOperator` | string | The value to use for the operator. |
-| `operator` | string | The operator to use to determine the price. |
-| `valueType` | string | The type of value to use to determine the price. |
-| `value` | string | The value to use to determine the price. |
+| property | type | description |
+| ------------------ | ------------ | ------------------------------------------------ |
+| `fieldToUse` | relationship | The field to use to determine the price. |
+| `condition` | string | The condition to use to determine the price. |
+| `valueForOperator` | string | The value to use for the operator. |
+| `operator` | string | The operator to use to determine the price. |
+| `valueType` | string | The type of value to use to determine the price. |
+| `value` | string | The value to use to determine the price. |
#### Field Overrides
@@ -344,11 +355,11 @@ formBuilder({
text: {
...fields.text,
labels: {
- singular: "Custom Text Field",
- plural: "Custom Text Fields",
- }
- }
- }
+ singular: 'Custom Text Field',
+ plural: 'Custom Text Fields',
+ },
+ },
+ },
})
```
@@ -388,6 +399,7 @@ Below are some common troubleshooting tips. To help other developers, please con
## Screenshots

+

diff --git a/docs/plugins/nested-docs.mdx b/docs/plugins/nested-docs.mdx
index 27d52fa77c..0687fa4127 100644
--- a/docs/plugins/nested-docs.mdx
+++ b/docs/plugins/nested-docs.mdx
@@ -25,7 +25,12 @@ field instead of the original title. This is especially useful if you happen to
but different parents.
- This plugin is completely open-source and the [source code can be found here](https://github.com/payloadcms/payload/tree/main/packages/plugin-nested-docs). If you need help, check out our [Community Help](https://payloadcms.com/community-help). If you think you've found a bug, please [open a new issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%20nested-docs&template=bug_report.md&title=plugin-nested-docs%3A) with as much detail as possible.
+ This plugin is completely open-source and the [source code can be found
+ here](https://github.com/payloadcms/payload/tree/main/packages/plugin-nested-docs). If you need
+ help, check out our [Community Help](https://payloadcms.com/community-help). If you think you've
+ found a bug, please [open a new
+ issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%20nested-docs&template=bug_report.md&title=plugin-nested-docs%3A)
+ with as much detail as possible.
##### Core features
@@ -96,7 +101,7 @@ The `breadcrumbs` field is an array which dynamically populates all parent relat
level and stores the following fields.
| Field | Description |
-|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `label` | The label of the breadcrumb. This field is automatically set to either the `collection.admin.useAsTitle` (if defined) or is set to the `ID` of the document. You can also dynamically define the `label` by passing a function to the options property of [`generateLabel`](#generateLabel). |
| `url` | The URL of the breadcrumb. By default, this field is undefined. You can manually define this field by passing a property called function to the plugin options property of [`generateURL`](#generateURL). |
@@ -117,14 +122,14 @@ You can also pass a function to dynamically set the `label` of your breadcrumb.
// payload.config.ts
nestedDocs({
//...
- generateLabel: (_, doc) => doc.title // NOTE: 'title' is a hypothetical field
+ generateLabel: (_, doc) => doc.title, // NOTE: 'title' is a hypothetical field
})
```
The function takes two arguments and returns a string:
| Argument | Type | Description |
-|----------|----------|----------------------------------------------|
+| -------- | -------- | -------------------------------------------- |
| `docs` | `Array` | An array of the breadcrumbs up to that point |
| `doc` | `Object` | The current document being edited |
@@ -143,7 +148,7 @@ nestedDocs({
```
| Argument | Type | Description |
-|----------|----------|----------------------------------------------|
+| -------- | -------- | -------------------------------------------- |
| `docs` | `Array` | An array of the breadcrumbs up to that point |
| `doc` | `Object` | The current document being edited |
@@ -161,7 +166,9 @@ own `breadcrumbs` field to each collection manually. Set this property to the `n
Note:
- If you opt out of automatically being provided a `parent` or `breadcrumbs` field, you need to make sure that both fields are placed at the top-level of your document. They cannot exist within any nested data structures like a `group`, `array`, or `blocks`.
+ If you opt out of automatically being provided a `parent` or `breadcrumbs` field, you need to make
+ sure that both fields are placed at the top-level of your document. They cannot exist within any
+ nested data structures like a `group`, `array`, or `blocks`.
## Overrides
@@ -170,48 +177,49 @@ You can also extend the built-in `parent` and `breadcrumbs` fields per collectio
and `createBreadcrumbField` methods. They will merge your customizations overtop the plugin's base field configurations.
```ts
-import { CollectionConfig } from "payload/types";
-import { createParentField } from "@payloadcms/plugin-nested-docs/fields";
-import { createBreadcrumbsField } from "@payloadcms/plugin-nested-docs/fields";
+import { CollectionConfig } from 'payload/types'
+import { createParentField } from '@payloadcms/plugin-nested-docs/fields'
+import { createBreadcrumbsField } from '@payloadcms/plugin-nested-docs/fields'
const examplePageConfig: CollectionConfig = {
- slug: "pages",
+ slug: 'pages',
fields: [
createParentField(
// First argument is equal to the slug of the collection
// that the field references
- "pages",
+ 'pages',
// Second argument is equal to field overrides that you specify,
// which will be merged into the base parent field config
{
admin: {
- position: "sidebar",
+ position: 'sidebar',
},
// Note: if you override the `filterOptions` of the `parent` field,
// be sure to continue to prevent the document from referencing itself as the parent like this:
// filterOptions: ({ id }) => ({ id: {not_equals: id }})`
- }
+ },
),
createBreadcrumbsField(
// First argument is equal to the slug of the collection
// that the field references
- "pages",
+ 'pages',
// Argument equal to field overrides that you specify,
// which will be merged into the base `breadcrumbs` field config
{
- label: "Page Breadcrumbs",
- }
+ label: 'Page Breadcrumbs',
+ },
),
],
-};
+}
```
Note:
- If overriding the `name` of either `breadcrumbs` or `parent` fields, you must specify the `breadcrumbsFieldSlug` or `parentFieldSlug` respectively.
+ If overriding the `name` of either `breadcrumbs` or `parent` fields, you must specify the
+ `breadcrumbsFieldSlug` or `parentFieldSlug` respectively.
## Localization
diff --git a/docs/plugins/redirects.mdx b/docs/plugins/redirects.mdx
index ec924843b7..fdd8fca4a0 100644
--- a/docs/plugins/redirects.mdx
+++ b/docs/plugins/redirects.mdx
@@ -13,7 +13,12 @@ This plugin allows you to easily manage redirects for your application from with
For example, if you have a page at `/about` and you want to change it to `/about-us`, you can create a redirect from the old page to the new one, then you can use this data to write HTTP redirects into your front-end application. This will ensure that users are redirected to the correct page without penalty because search engines are notified of the change at the request level. This is a very lightweight plugin that will allow you to integrate managed redirects for any front-end framework.
- This plugin is completely open-source and the [source code can be found here](https://github.com/payloadcms/payload/tree/main/packages/plugin-redirects). If you need help, check out our [Community Help](https://payloadcms.com/community-help). If you think you've found a bug, please [open a new issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%redirects&template=bug_report.md&title=plugin-redirects%3A) with as much detail as possible.
+ This plugin is completely open-source and the [source code can be found
+ here](https://github.com/payloadcms/payload/tree/main/packages/plugin-redirects). If you need
+ help, check out our [Community Help](https://payloadcms.com/community-help). If you think you've
+ found a bug, please [open a new
+ issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%redirects&template=bug_report.md&title=plugin-redirects%3A)
+ with as much detail as possible.
##### Core features
@@ -35,39 +40,39 @@ Install the plugin using any JavaScript package manager like [Yarn](https://yarn
In the `plugins` array of your [Payload config](https://payloadcms.com/docs/configuration/overview), call the plugin with [options](#options):
```ts
-import { buildConfig } from "payload/config";
-import redirects from "@payloadcms/plugin-redirects";
+import { buildConfig } from 'payload/config'
+import redirects from '@payloadcms/plugin-redirects'
const config = buildConfig({
collections: [
{
- slug: "pages",
+ slug: 'pages',
fields: [],
},
],
plugins: [
redirects({
- collections: ["pages"],
+ collections: ['pages'],
}),
],
-});
+})
-export default config;
+export default config
```
### Options
-| Option | Type | Description |
-| --- | --- | --- |
-| `collections` | `string[]` | An array of collection slugs to populate in the `to` field of each redirect. |
-| `overrides` | `object` | A partial collection config that allows you to override anything on the `redirects` collection. |
+| Option | Type | Description |
+| ------------- | ---------- | ----------------------------------------------------------------------------------------------- |
+| `collections` | `string[]` | An array of collection slugs to populate in the `to` field of each redirect. |
+| `overrides` | `object` | A partial collection config that allows you to override anything on the `redirects` collection. |
## TypeScript
All types can be directly imported:
```ts
-import { PluginConfig } from "@payloadcms/plugin-redirects/types";
+import { PluginConfig } from '@payloadcms/plugin-redirects/types'
```
## Examples
diff --git a/docs/plugins/search.mdx b/docs/plugins/search.mdx
index 8c297845ce..c7d7937c4a 100644
--- a/docs/plugins/search.mdx
+++ b/docs/plugins/search.mdx
@@ -17,7 +17,12 @@ To query search results, use all the existing Payload APIs that you are already
This plugin is a great way to implement a fast, immersive search experience such as a search bar in a front-end application. Many applications may not need the power and complexity of a third-party service like Algolia or ElasticSearch. This plugin provides a first-party alternative that is easy to set up and runs entirely on your own database.
- This plugin is completely open-source and the [source code can be found here](https://github.com/payloadcms/payload/tree/main/packages/plugin-search). If you need help, check out our [Community Help](https://payloadcms.com/community-help). If you think you've found a bug, please [open a new issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%20search&template=bug_report.md&title=plugin-search%3A) with as much detail as possible.
+ This plugin is completely open-source and the [source code can be found
+ here](https://github.com/payloadcms/payload/tree/main/packages/plugin-search). If you need help,
+ check out our [Community Help](https://payloadcms.com/community-help). If you think you've found a
+ bug, please [open a new
+ issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%20search&template=bug_report.md&title=plugin-search%3A)
+ with as much detail as possible.
##### Core Features
diff --git a/docs/plugins/seo.mdx b/docs/plugins/seo.mdx
index 920da0b4cb..43e97ac892 100644
--- a/docs/plugins/seo.mdx
+++ b/docs/plugins/seo.mdx
@@ -15,7 +15,12 @@ As users are editing documents within the admin panel, they have the option to "
To help you visualize what your page might look like in a search engine, a preview is rendered on page just beneath the meta fields. This preview is updated in real-time as you edit your metadata. There are also visual indicators to help you write effective meta, such as a character counter for the title and description fields. You can even inject your own custom fields into the `meta` field group as your application requires, like `og:title` or `json-ld`. If you've ever used something like Yoast SEO, this plugin might feel very familiar.
- This plugin is completely open-source and the [source code can be found here](https://github.com/payloadcms/payload/tree/main/packages/plugin-seo). If you need help, check out our [Community Help](https://payloadcms.com/community-help). If you think you've found a bug, please [open a new issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%20seo&template=bug_report.md&title=plugin-seo%3A) with as much detail as possible.
+ This plugin is completely open-source and the [source code can be found
+ here](https://github.com/payloadcms/payload/tree/main/packages/plugin-seo). If you need help,
+ check out our [Community Help](https://payloadcms.com/community-help). If you think you've found a
+ bug, please [open a new
+ issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%20seo&template=bug_report.md&title=plugin-seo%3A)
+ with as much detail as possible.
##### Core features
@@ -86,10 +91,10 @@ An array of global slugs to enable SEO. Enabled globals receive a `meta` field w
An array of fields that allows you to inject your own custom fields onto the `meta` field group. The following fields are provided by default:
- - `title`: text
- - `description`: textarea
- - `image`: upload (if an `uploadsCollection` is provided)
- - `preview`: ui
+- `title`: text
+- `description`: textarea
+- `image`: upload (if an `uploadsCollection` is provided)
+- `preview`: ui
##### `uploadsCollection`
@@ -100,7 +105,9 @@ Set the `uploadsCollection` to your application's upload-enabled collection slug
When the `tabbedUI` property is `true`, it appends an `SEO` tab onto your config using Payload's [Tabs Field](https://payloadcms.com/docs/fields/tabs). If your collection is not already tab-enabled, meaning the first field in your config is not of type `tabs`, then one will be created for you called `Content`. Defaults to `false`.
- If you wish to continue to use top-level or sidebar fields with `tabbedUI`, you must not let the default `Content` tab get created for you (see the note above). Instead, you must define the first field of your config with type `tabs` and place all other fields adjacent to this one.
+ If you wish to continue to use top-level or sidebar fields with `tabbedUI`, you must not let the
+ default `Content` tab get created for you (see the note above). Instead, you must define the first
+ field of your config with type `tabs` and place all other fields adjacent to this one.
##### `generateTitle`
@@ -126,7 +133,7 @@ A function that allows you to return any meta description, including from docume
{
// ...
seoPlugin({
- generateDescription: ({ ...docInfo, doc, locale }) => doc?.excerpt?.value
+ generateDescription: ({ ...docInfo, doc, locale }) => doc?.excerpt?.value,
})
}
```
@@ -140,7 +147,7 @@ A function that allows you to return any meta image, including from document's c
{
// ...
seoPlugin({
- generateImage: ({ ...docInfo, doc, locale }) => doc?.featuredImage?.value
+ generateImage: ({ ...docInfo, doc, locale }) => doc?.featuredImage?.value,
})
}
```
@@ -154,7 +161,8 @@ A function called by the search preview component to display the actual URL of y
{
// ...
seoPlugin({
- generateURL: ({ ...docInfo, doc, locale }) => `https://yoursite.com/${collection?.slug}/${doc?.slug?.value}`
+ generateURL: ({ ...docInfo, doc, locale }) =>
+ `https://yoursite.com/${collection?.slug}/${doc?.slug?.value}`,
})
}
```
@@ -168,7 +176,7 @@ Rename the meta group interface name that is generated for TypeScript and GraphQ
{
// ...
seoPlugin({
- interfaceName: 'customInterfaceNameSEO'
+ interfaceName: 'customInterfaceNameSEO',
})
}
```
diff --git a/docs/plugins/stripe.mdx b/docs/plugins/stripe.mdx
index a7c9347620..08c85f8c80 100644
--- a/docs/plugins/stripe.mdx
+++ b/docs/plugins/stripe.mdx
@@ -17,7 +17,12 @@ To build a checkout flow on your front-end you can either use [Stripe Checkout](
The beauty of this plugin is the entirety of your application's content and business logic can be handled in Payload while Stripe handles solely the billing and payment processing. You can build a completely proprietary application that is endlessly customizable and extendable, on APIs and databases that you own. Hosted services like Shopify or BigCommerce might fracture your application's content then charge you for access.
- This plugin is completely open-source and the [source code can be found here](https://github.com/payloadcms/payload/tree/main/packages/plugin-stripe). If you need help, check out our [Community Help](https://payloadcms.com/community-help). If you think you've found a bug, please [open a new issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%20stripe&template=bug_report.md&title=plugin-stripe%3A) with as much detail as possible.
+ This plugin is completely open-source and the [source code can be found
+ here](https://github.com/payloadcms/payload/tree/main/packages/plugin-stripe). If you need help,
+ check out our [Community Help](https://payloadcms.com/community-help). If you think you've found a
+ bug, please [open a new
+ issue](https://github.com/payloadcms/payload/issues/new?assignees=&labels=plugin%3A%20stripe&template=bug_report.md&title=plugin-stripe%3A)
+ with as much detail as possible.
##### Core features
@@ -58,14 +63,14 @@ export default config
### Options
-| Option | Type | Default | Description |
-| --- | --- | --- | --- |
-| `stripeSecretKey` \* | string | `undefined` | Your Stripe secret key |
-| `stripeWebhooksEndpointSecret` | string | `undefined` | Your Stripe webhook endpoint secret |
-| `rest` | boolean | `false` | When `true`, opens the `/api/stripe/rest` endpoint |
-| `webhooks` | object \| function | `undefined` | Either a function to handle all webhooks events, or an object of Stripe webhook handlers, keyed to the name of the event |
-| `sync` | array | `undefined` | An array of sync configs |
-| `logs` | boolean | `false` | When `true`, logs sync events to the console as they happen |
+| Option | Type | Default | Description |
+| ------------------------------ | ------------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------ |
+| `stripeSecretKey` \* | string | `undefined` | Your Stripe secret key |
+| `stripeWebhooksEndpointSecret` | string | `undefined` | Your Stripe webhook endpoint secret |
+| `rest` | boolean | `false` | When `true`, opens the `/api/stripe/rest` endpoint |
+| `webhooks` | object \| function | `undefined` | Either a function to handle all webhooks events, or an object of Stripe webhook handlers, keyed to the name of the event |
+| `sync` | array | `undefined` | An array of sync configs |
+| `logs` | boolean | `false` | When `true`, logs sync events to the console as they happen |
_\* An asterisk denotes that a property is required._
@@ -73,10 +78,10 @@ _\* An asterisk denotes that a property is required._
The following custom endpoints are automatically opened for you:
-| Endpoint | Method | Description |
-| --- | --- | --- |
-| `/api/stripe/rest` | `POST` | Proxies the [Stripe REST API](https://stripe.com/docs/api) behind [Payload access control](https://payloadcms.com/docs/access-control/overview) and returns the result. See the [REST Proxy](#stripe-rest-proxy) section for more details. |
-| `/api/stripe/webhooks` | `POST` | Handles all Stripe webhook events |
+| Endpoint | Method | Description |
+| ---------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `/api/stripe/rest` | `POST` | Proxies the [Stripe REST API](https://stripe.com/docs/api) behind [Payload access control](https://payloadcms.com/docs/access-control/overview) and returns the result. See the [REST Proxy](#stripe-rest-proxy) section for more details. |
+| `/api/stripe/webhooks` | `POST` | Handles all Stripe webhook events |
##### Stripe REST Proxy
@@ -104,7 +109,8 @@ const res = await fetch(`/api/stripe/rest`, {
Note:
- The `/api` part of these routes may be different based on the settings defined in your Payload config.
+ The `/api` part of these routes may be different based on the settings defined in your Payload
+ config.
## Webhooks
@@ -220,7 +226,8 @@ This option will setup a basic sync between Payload collections and Stripe resou
Note:
- If you wish to enable a _two-way_ sync, be sure to setup [`webhooks`](#webhooks) and pass the `stripeWebhooksEndpointSecret` through your config.
+ If you wish to enable a _two-way_ sync, be sure to setup [`webhooks`](#webhooks) and pass the
+ `stripeWebhooksEndpointSecret` through your config.
```ts
@@ -255,7 +262,10 @@ export default config
Note:
- Due to limitations in the Stripe API, this currently only works with top-level fields. This is because every Stripe object is a separate entity, making it difficult to abstract into a simple reusable library. In the future, we may find a pattern around this. But for now, cases like that will need to be hard-coded.
+ Due to limitations in the Stripe API, this currently only works with top-level fields. This is
+ because every Stripe object is a separate entity, making it difficult to abstract into a simple
+ reusable library. In the future, we may find a pattern around this. But for now, cases like that
+ will need to be hard-coded.
Using `sync` will do the following:
@@ -288,4 +298,3 @@ import {
## Examples
The [Templates Directory](https://github.com/payloadcms/payload/tree/main/templates) contains an official [E-commerce Template](https://github.com/payloadcms/payload/tree/main/templates/ecommerce) which demonstrates exactly how to configure this plugin in Payload and implement it on your front-end. You can also check out [How to Build An E-Commerce Site With Next.js](https://payloadcms.com/blog/how-to-build-an-e-commerce-site-with-nextjs) post for a bit more context around this template.
-
diff --git a/docs/production/deployment.mdx b/docs/production/deployment.mdx
index 2c3b87f780..c9408f3e9a 100644
--- a/docs/production/deployment.mdx
+++ b/docs/production/deployment.mdx
@@ -44,7 +44,10 @@ Because _**you**_ are in complete control of who can do what with your data, you
wield that power responsibly before deploying to Production.
- By default, all Access Control functions require that a user is successfully logged in to Payload to create, read, update, or delete data. {' '}
+
+ By default, all Access Control functions require that a user is successfully logged in to
+ Payload to create, read, update, or delete data.
+ {' '}
But, if you allow public user registration, for example, you will want to make sure that your
access control functions are more strict - permitting only appropriate users to
perform appropriate actions.
diff --git a/docs/queries/overview.mdx b/docs/queries/overview.mdx
index 59ab9b53e3..d54148159b 100644
--- a/docs/queries/overview.mdx
+++ b/docs/queries/overview.mdx
@@ -9,7 +9,9 @@ keywords: query, documents, overview, documentation, Content Management System,
Payload provides an extremely granular querying language through all APIs. Each API takes the same syntax and fully supports all options.
- Here, "querying" relates to filtering or searching through documents within a Collection. {' '}
+
+ Here, "querying" relates to filtering or searching through documents within a Collection.
+ {' '}
You can build queries to pass to Find operations as well as to [restrict which documents certain
users can access](/docs/access-control/overview) via access control functions.
diff --git a/docs/rich-text/lexical.mdx b/docs/rich-text/lexical.mdx
index b2b7866abd..dc488dc4d3 100644
--- a/docs/rich-text/lexical.mdx
+++ b/docs/rich-text/lexical.mdx
@@ -11,7 +11,9 @@ One of Payload's goals is to build the best rich text editor experience that we
Classically, we've used SlateJS to work toward this goal, but building custom elements into Slate has proven to be more difficult than we'd like, and we've been keeping our options open.
- Payload's Lexical rich text editor is currently in beta. It's stable enough to use as you build on Payload, so if you're up for helping us fine-tune it, you should use it. But if you're looking for stability, use Slate instead.
+ Payload's Lexical rich text editor is currently in beta. It's stable enough to use as you build on
+ Payload, so if you're up for helping us fine-tune it, you should use it. But if you're looking for
+ stability, use Slate instead.
Lexical is extremely impressive and trivializes a lot of the hard parts of building new elements into a rich text editor. It has a few distinct advantages over Slate, including the following:
@@ -38,7 +40,7 @@ export default buildConfig({
// your collections here
],
// Pass the Lexical editor to the root config
- editor: lexicalEditor({})
+ editor: lexicalEditor({}),
})
```
@@ -46,9 +48,7 @@ You can also override Lexical settings on a field-by-field basis as follows:
```ts
import type { CollectionConfig } from 'payload/types'
-import {
- lexicalEditor
-} from '@payloadcms/richtext-lexical'
+import { lexicalEditor } from '@payloadcms/richtext-lexical'
export const Pages: CollectionConfig = {
slug: 'pages',
@@ -57,9 +57,9 @@ export const Pages: CollectionConfig = {
name: 'content',
type: 'richText',
// Pass the Lexical editor here and override base settings as necessary
- editor: lexicalEditor({})
- }
- ]
+ editor: lexicalEditor({}),
+ },
+ ],
}
```
@@ -82,7 +82,7 @@ import {
BlocksFeature,
LinkFeature,
UploadFeature,
- lexicalEditor
+ lexicalEditor,
} from '@payloadcms/richtext-lexical'
import { Banner } from '../blocks/Banner'
import { CallToAction } from '../blocks/CallToAction'
@@ -126,12 +126,9 @@ import { CallToAction } from '../blocks/CallToAction'
// This is incredibly powerful. You can re-use your Payload blocks
// directly in the Lexical editor as follows:
BlocksFeature({
- blocks: [
- Banner,
- CallToAction,
- ],
+ blocks: [Banner, CallToAction],
}),
- ]
+ ],
})
}
```
@@ -141,7 +138,7 @@ import { CallToAction } from '../blocks/CallToAction'
Here's an overview of all the included features:
| Feature Name | Included by default | Description |
-|--------------------------------|---------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| ------------------------------ | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`BoldTextFeature`** | Yes | Handles the bold text format |
| **`ItalicTextFeature`** | Yes | Handles the italic text format |
| **`UnderlineTextFeature`** | Yes | Handles the underline text format |
@@ -153,7 +150,7 @@ Here's an overview of all the included features:
| **`HeadingFeature`** | Yes | Adds Heading Nodes (by default, H1 - H6, but that can be customized) |
| **`AlignFeature`** | Yes | Allows you to align text left, centered and right |
| **`IndentFeature`** | Yes | Allows you to indent text with the tab key |
-| **`UnorderedListFeature`** | Yes | Adds unordered lists (ul) |
+| **`UnorderedListFeature`** | Yes | Adds unordered lists (ul) |
| **`OrderedListFeature`** | Yes | Adds ordered lists (ol) |
| **`CheckListFeature`** | Yes | Adds checklists |
| **`LinkFeature`** | Yes | Allows you to create internal and external links |
@@ -187,11 +184,7 @@ To add HTML generation directly within the collection, follow the example below:
```ts
import type { CollectionConfig } from 'payload/types'
-import {
- HTMLConverterFeature,
- lexicalEditor,
- lexicalHTML
-} from '@payloadcms/richtext-lexical'
+import { HTMLConverterFeature, lexicalEditor, lexicalHTML } from '@payloadcms/richtext-lexical'
const Pages: CollectionConfig = {
slug: 'pages',
@@ -211,6 +204,7 @@ const Pages: CollectionConfig = {
],
}
```
+
The `lexicalHTML()` function creates a new field that automatically converts the referenced lexical richText field into HTML through an afterRead hook.
#### Generating HTML in the Frontend:
@@ -225,13 +219,17 @@ import {
consolidateHTMLConverters,
} from '@payloadcms/richtext-lexical'
-async function lexicalToHTML(editorData: SerializedEditorState, editorConfig: SanitizedEditorConfig) {
+async function lexicalToHTML(
+ editorData: SerializedEditorState,
+ editorConfig: SanitizedEditorConfig,
+) {
return await convertLexicalToHTML({
converters: consolidateHTMLConverters({ editorConfig }),
data: editorData,
})
}
```
+
This method employs `convertLexicalToHTML` from `@payloadcms/richtext-lexical`, which converts the serialized editor state into HTML.
Because every `Feature` is able to provide html converters, and because the `htmlFeature` can modify those or provide their own, we need to consolidate them with the default html Converters using the `consolidateHTMLConverters` function.
@@ -286,9 +284,13 @@ export const UploadFeature = (props?: UploadFeatureProps): FeatureProvider => {
//...
},
],
- plugins: [/*...*/],
+ plugins: [
+ /*...*/
+ ],
props: props,
- slashMenu: {/*...*/},
+ slashMenu: {
+ /*...*/
+ },
}
},
key: 'upload',
@@ -299,6 +301,7 @@ export const UploadFeature = (props?: UploadFeatureProps): FeatureProvider => {
### Headless Editor
Lexical provides a seamless way to perform conversions between various other formats:
+
- HTML to Lexical (or, importing HTML into the lexical editor)
- Markdown to Lexical (or, importing Markdown into the lexical editor)
- Lexical to Markdown
@@ -307,12 +310,9 @@ A headless editor can perform such conversions outside of the main editor instan
```ts
import { createHeadlessEditor } from '@lexical/headless' // <= make sure this package is installed
-import {
- getEnabledNodes,
- sanitizeEditorConfig,
-} from '@payloadcms/richtext-lexical'
+import { getEnabledNodes, sanitizeEditorConfig } from '@payloadcms/richtext-lexical'
-const yourEditorConfig; // <= your editor config here
+const yourEditorConfig // <= your editor config here
const headlessEditor = createHeadlessEditor({
nodes: getEnabledNodes({
@@ -345,23 +345,26 @@ Once you have your headless editor instance, you can use it to convert HTML to L
```ts
import { $generateNodesFromDOM } from '@lexical/html'
-import { $getRoot,$getSelection } from 'lexical'
-import { JSDOM } from 'jsdom';
+import { $getRoot, $getSelection } from 'lexical'
+import { JSDOM } from 'jsdom'
-headlessEditor.update(() => {
- // In a headless environment you can use a package such as JSDom to parse the HTML string.
- const dom = new JSDOM(htmlString)
+headlessEditor.update(
+ () => {
+ // In a headless environment you can use a package such as JSDom to parse the HTML string.
+ const dom = new JSDOM(htmlString)
- // Once you have the DOM instance it's easy to generate LexicalNodes.
- const nodes = $generateNodesFromDOM(headlessEditor, dom.window.document)
+ // Once you have the DOM instance it's easy to generate LexicalNodes.
+ const nodes = $generateNodesFromDOM(headlessEditor, dom.window.document)
- // Select the root
- $getRoot().select()
+ // Select the root
+ $getRoot().select()
- // Insert them at a selection.
- const selection = $getSelection()
- selection.insertNodes(nodes)
-}, { discrete: true })
+ // Insert them at a selection.
+ const selection = $getSelection()
+ selection.insertNodes(nodes)
+ },
+ { discrete: true },
+)
// Do this if you then want to get the editor JSON
const editorJSON = headlessEditor.getEditorState().toJSON()
@@ -374,7 +377,8 @@ This has been taken from the [lexical serialization & deserialization docs](http
Note:
- Using the discrete: true flag ensures instant updates to the editor state. If immediate reading of the updated state isn't necessary, you can omit the flag.
+ Using the discrete: true flag ensures instant updates to the editor state. If
+ immediate reading of the updated state isn't necessary, you can omit the flag.
### Markdown => Lexical
@@ -388,7 +392,12 @@ import { sanitizeEditorConfig } from '@payloadcms/richtext-lexical'
const yourSanitizedEditorConfig = sanitizeEditorConfig(yourEditorConfig) // <= your editor config here
const markdown = `# Hello World`
-headlessEditor.update(() => { $convertFromMarkdownString(markdown, yourSanitizedEditorConfig.features.markdownTransformers) }, { discrete: true })
+headlessEditor.update(
+ () => {
+ $convertFromMarkdownString(markdown, yourSanitizedEditorConfig.features.markdownTransformers)
+ },
+ { discrete: true },
+)
// Do this if you then want to get the editor JSON
const editorJSON = headlessEditor.getEditorState().toJSON()
@@ -406,7 +415,7 @@ Here's the code for it:
```ts
import { $convertToMarkdownString } from '@lexical/markdown'
import { sanitizeEditorConfig } from '@payloadcms/richtext-lexical'
-import type { SerializedEditorState } from "lexical"
+import type { SerializedEditorState } from 'lexical'
const yourSanitizedEditorConfig = sanitizeEditorConfig(yourEditorConfig) // <= your editor config here
const yourEditorState: SerializedEditorState // <= your current editor state here
@@ -427,7 +436,6 @@ headlessEditor.getEditorState().read(() => {
The `.setEditorState()` function immediately updates your editor state. Thus, there's no need for the `discrete: true` flag when reading the state afterward.
-
### Lexical => Plain Text
Export content from the Lexical editor into plain text using these steps:
@@ -438,8 +446,8 @@ Export content from the Lexical editor into plain text using these steps:
Here's the code for it:
```ts
-import type { SerializedEditorState } from "lexical"
-import { $getRoot } from "lexical"
+import type { SerializedEditorState } from 'lexical'
+import { $getRoot } from 'lexical'
const yourEditorState: SerializedEditorState // <= your current editor state here
@@ -451,9 +459,10 @@ try {
}
// Export to plain text
-const plainTextContent = headlessEditor.getEditorState().read(() => {
- return $getRoot().getTextContent()
-}) || ''
+const plainTextContent =
+ headlessEditor.getEditorState().read(() => {
+ return $getRoot().getTextContent()
+ }) || ''
```
## Migrating from Slate
@@ -469,10 +478,7 @@ Simply add the `SlateToLexicalFeature` to your editor:
```ts
import type { CollectionConfig } from 'payload/types'
-import {
- SlateToLexicalFeature,
- lexicalEditor,
-} from '@payloadcms/richtext-lexical'
+import { SlateToLexicalFeature, lexicalEditor } from '@payloadcms/richtext-lexical'
const Pages: CollectionConfig = {
slug: 'pages',
@@ -481,10 +487,7 @@ const Pages: CollectionConfig = {
name: 'nameOfYourRichTextField',
type: 'richText',
editor: lexicalEditor({
- features: ({ defaultFeatures }) => [
- ...defaultFeatures,
- SlateToLexicalFeature({})
- ],
+ features: ({ defaultFeatures }) => [...defaultFeatures, SlateToLexicalFeature({})],
}),
},
],
@@ -494,6 +497,7 @@ const Pages: CollectionConfig = {
and done! Now, everytime this lexical editor is initialized, it converts the slate date to lexical on-the-fly. If the data is already in lexical format, it will just pass it through.
This is by far the easiest way to migrate from Slate to Lexical, although it does come with a few caveats:
+
- There is a performance hit when initializing the lexical editor
- The editor will still output the Slate data in the output JSON, as the on-the-fly converter only runs for the admin panel
@@ -535,7 +539,8 @@ export async function convertAll(payload: Payload, collectionName: string, field
const promises = batch.map(async (doc: YourDocumentType) => {
const richText = doc[fieldName]
- if (richText && Array.isArray(richText) && !('root' in richText)) { // It's Slate data - skip already-converted data
+ if (richText && Array.isArray(richText) && !('root' in richText)) {
+ // It's Slate data - skip already-converted data
const converted = convertSlateToLexical({
converters: converters,
slateData: richText,
@@ -604,7 +609,7 @@ import type { CollectionConfig } from 'payload/types'
import {
SlateToLexicalFeature,
lexicalEditor,
- defaultSlateConverters
+ defaultSlateConverters,
} from '@payloadcms/richtext-lexical'
import { YourCustomConverter } from '../converters/YourCustomConverter'
@@ -619,10 +624,7 @@ const Pages: CollectionConfig = {
features: ({ defaultFeatures }) => [
...defaultFeatures,
SlateToLexicalFeature({
- converters: [
- ...defaultSlateConverters,
- YourCustomConverter
- ]
+ converters: [...defaultSlateConverters, YourCustomConverter],
}),
],
}),
diff --git a/docs/rich-text/slate.mdx b/docs/rich-text/slate.mdx
index 1424143c85..630d3855cc 100644
--- a/docs/rich-text/slate.mdx
+++ b/docs/rich-text/slate.mdx
@@ -16,7 +16,6 @@ To use the Slate editor, first you need to install it:
npm install --save @payloadcms/richtext-slate
```
-
After installation, you can pass it to your top-level Payload config:
```ts
@@ -28,7 +27,7 @@ export default buildConfig({
// your collections here
],
// Pass the Slate editor to the root config
- editor: slateEditor({})
+ editor: slateEditor({}),
})
```
@@ -52,11 +51,11 @@ export const Pages: CollectionConfig = {
],
leaves: [
// customize leaves allowed in Slate editor here
- ]
- }
- })
- }
- ]
+ ],
+ },
+ }),
+ },
+ ],
}
```
diff --git a/docs/upload/overview.mdx b/docs/upload/overview.mdx
index b0ccfd8461..5f01049269 100644
--- a/docs/upload/overview.mdx
+++ b/docs/upload/overview.mdx
@@ -40,21 +40,21 @@ Every Payload Collection can opt-in to supporting Uploads by specifying the `upl
### Collection Upload Options
-| Option | Description |
-| ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **`staticURL`** \* | The URL path to use to access your uploads. Relative path like `/media` will be served by payload. Full path like `https://example.com/media` needs to be served by another web server. |
-| **`staticDir`** \* | The folder directory to use to store media in. Can be either an absolute path or relative to the directory that contains your config. |
-| **`adminThumbnail`** | Set the way that the Admin panel will display thumbnails for this Collection. [More](#admin-thumbnails) |
-| **`crop`** | Set to `false` to disable the cropping tool in the Admin panel. Crop is enabled by default. [More](#crop-and-focal-point-selector) |
-| **`disableLocalStorage`** | Completely disable uploading files to disk locally. [More](#disabling-local-upload-storage) |
+| Option | Description |
+| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **`staticURL`** \* | The URL path to use to access your uploads. Relative path like `/media` will be served by payload. Full path like `https://example.com/media` needs to be served by another web server. |
+| **`staticDir`** \* | The folder directory to use to store media in. Can be either an absolute path or relative to the directory that contains your config. |
+| **`adminThumbnail`** | Set the way that the Admin panel will display thumbnails for this Collection. [More](#admin-thumbnails) |
+| **`crop`** | Set to `false` to disable the cropping tool in the Admin panel. Crop is enabled by default. [More](#crop-and-focal-point-selector) |
+| **`disableLocalStorage`** | Completely disable uploading files to disk locally. [More](#disabling-local-upload-storage) |
| **`focalPoint`** | Set to `false` to disable the focal point selection tool in the Admin panel. The focal point selector is only available when `imageSizes` or `resizeOptions` are defined. [More](#crop-and-focal-point-selector) |
-| **`formatOptions`** | An object with `format` and `options` that are used with the Sharp image library to format the upload file. [More](https://sharp.pixelplumbing.com/api-output#toformat) |
-| **`handlers`** | Array of Express request handlers to execute before the built-in Payload static middleware executes. |
-| **`imageSizes`** | If specified, image uploads will be automatically resized in accordance to these image sizes. [More](#image-sizes) |
-| **`mimeTypes`** | Restrict mimeTypes in the file picker. Array of valid mimetypes or mimetype wildcards [More](#mimetypes) |
-| **`staticOptions`** | Set options for `express.static` to use while serving your static files. [More](http://expressjs.com/en/resources/middleware/serve-static.html) |
-| **`resizeOptions`** | An object passed to the the Sharp image library to resize the uploaded file. [More](https://sharp.pixelplumbing.com/api-resize) |
-| **`filesRequiredOnCreate`** | Mandate file data on creation, default is true. |
+| **`formatOptions`** | An object with `format` and `options` that are used with the Sharp image library to format the upload file. [More](https://sharp.pixelplumbing.com/api-output#toformat) |
+| **`handlers`** | Array of Express request handlers to execute before the built-in Payload static middleware executes. |
+| **`imageSizes`** | If specified, image uploads will be automatically resized in accordance to these image sizes. [More](#image-sizes) |
+| **`mimeTypes`** | Restrict mimeTypes in the file picker. Array of valid mimetypes or mimetype wildcards [More](#mimetypes) |
+| **`staticOptions`** | Set options for `express.static` to use while serving your static files. [More](http://expressjs.com/en/resources/middleware/serve-static.html) |
+| **`resizeOptions`** | An object passed to the the Sharp image library to resize the uploaded file. [More](https://sharp.pixelplumbing.com/api-resize) |
+| **`filesRequiredOnCreate`** | Mandate file data on creation, default is true. |
_An asterisk denotes that a property above is required._
@@ -154,15 +154,13 @@ When an uploaded image is smaller than the defined image size, we have 3 options
`withoutEnlargement: undefined | false | true`
-1.`undefined` [default]: uploading images with smaller width AND height than the image size will return null
-2. `false`: always enlarge images to the image size
-3. `true`: if the image is smaller than the image size, return the original image
+1.`undefined` [default]: uploading images with smaller width AND height than the image size will return null 2. `false`: always enlarge images to the image size 3. `true`: if the image is smaller than the image size, return the original image
Note:
- By default, the image size will return NULL when the uploaded image is smaller than the defined image size.
- Use the `withoutEnlargement` prop to change this.
+ By default, the image size will return NULL when the uploaded image is smaller than the defined
+ image size. Use the `withoutEnlargement` prop to change this.
### Crop and Focal Point Selector
@@ -209,8 +207,7 @@ export const Media: CollectionConfig = {
// ... image sizes here
],
// highlight-start
- adminThumbnail: ({ doc }) =>
- `https://google.com/custom-path-to-file/${doc.filename}`,
+ adminThumbnail: ({ doc }) => `https://google.com/custom-path-to-file/${doc.filename}`,
// highlight-end
},
}
diff --git a/docs/versions/autosave.mdx b/docs/versions/autosave.mdx
index 252a87775c..ef0949aef8 100644
--- a/docs/versions/autosave.mdx
+++ b/docs/versions/autosave.mdx
@@ -19,8 +19,8 @@ _If Autosave is enabled, drafts will be created automatically as the document is
Collections and Globals both support the same options for configuring autosave. You can either set `versions.drafts.autosave` to `true`, or pass an object to configure autosave properties.
-| Drafts Autosave Options | Description |
-| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Drafts Autosave Options | Description |
+| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `interval` | Define an `interval` in milliseconds to automatically save progress while documents are edited. Document updates are "debounced" at this interval. Defaults to `800`. |
**Example config with versions, drafts, and autosave enabled:**
diff --git a/examples/auth/next-app/.prettierrc.js b/examples/auth/next-app/.prettierrc.js
index 70c17c995f..61df3839e8 100644
--- a/examples/auth/next-app/.prettierrc.js
+++ b/examples/auth/next-app/.prettierrc.js
@@ -1,8 +1,8 @@
module.exports = {
printWidth: 100,
- parser: "typescript",
+ parser: 'typescript',
semi: false,
singleQuote: true,
- trailingComma: "all",
- arrowParens: "avoid",
-};
+ trailingComma: 'all',
+ arrowParens: 'avoid',
+}
diff --git a/examples/auth/next-app/app/payload-types.ts b/examples/auth/next-app/app/payload-types.ts
index b768d72037..2550234fe2 100644
--- a/examples/auth/next-app/app/payload-types.ts
+++ b/examples/auth/next-app/app/payload-types.ts
@@ -8,23 +8,23 @@
export interface Config {
collections: {
- users: User;
- };
- globals: {};
+ users: User
+ }
+ globals: {}
}
export interface User {
- 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;
+ 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/next-pages/.prettierrc.js b/examples/auth/next-pages/.prettierrc.js
index 70c17c995f..61df3839e8 100644
--- a/examples/auth/next-pages/.prettierrc.js
+++ b/examples/auth/next-pages/.prettierrc.js
@@ -1,8 +1,8 @@
module.exports = {
printWidth: 100,
- parser: "typescript",
+ parser: 'typescript',
semi: false,
singleQuote: true,
- trailingComma: "all",
- arrowParens: "avoid",
-};
+ trailingComma: 'all',
+ arrowParens: 'avoid',
+}
diff --git a/examples/auth/next-pages/src/payload-types.ts b/examples/auth/next-pages/src/payload-types.ts
index b768d72037..2550234fe2 100644
--- a/examples/auth/next-pages/src/payload-types.ts
+++ b/examples/auth/next-pages/src/payload-types.ts
@@ -8,23 +8,23 @@
export interface Config {
collections: {
- users: User;
- };
- globals: {};
+ users: User
+ }
+ globals: {}
}
export interface User {
- 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;
+ 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/payload/.gitignore b/examples/auth/payload/.gitignore
index d1247e70cc..5af2a2fc95 100644
--- a/examples/auth/payload/.gitignore
+++ b/examples/auth/payload/.gitignore
@@ -1,5 +1,4 @@
build
dist
node_modules
-package-lock.json
-.env
+package - lock.json.env
diff --git a/examples/auth/payload/.prettierrc.js b/examples/auth/payload/.prettierrc.js
index 70c17c995f..61df3839e8 100644
--- a/examples/auth/payload/.prettierrc.js
+++ b/examples/auth/payload/.prettierrc.js
@@ -1,8 +1,8 @@
module.exports = {
printWidth: 100,
- parser: "typescript",
+ parser: 'typescript',
semi: false,
singleQuote: true,
- trailingComma: "all",
- arrowParens: "avoid",
-};
+ trailingComma: 'all',
+ arrowParens: 'avoid',
+}
diff --git a/examples/custom-server/.gitignore b/examples/custom-server/.gitignore
index 06007eac47..8f17897000 100644
--- a/examples/custom-server/.gitignore
+++ b/examples/custom-server/.gitignore
@@ -1,7 +1,4 @@
build
dist
node_modules
-package-lock.json
-.env
-.next
-.vercel
+package - lock.json.env.next.vercel
diff --git a/examples/custom-server/.prettierrc.js b/examples/custom-server/.prettierrc.js
index 70c17c995f..61df3839e8 100644
--- a/examples/custom-server/.prettierrc.js
+++ b/examples/custom-server/.prettierrc.js
@@ -1,8 +1,8 @@
module.exports = {
printWidth: 100,
- parser: "typescript",
+ parser: 'typescript',
semi: false,
singleQuote: true,
- trailingComma: "all",
- arrowParens: "avoid",
-};
+ trailingComma: 'all',
+ arrowParens: 'avoid',
+}
diff --git a/packages/db-mongodb/README.md b/packages/db-mongodb/README.md
index 40506d6651..6fe35e72f6 100644
--- a/packages/db-mongodb/README.md
+++ b/packages/db-mongodb/README.md
@@ -23,8 +23,6 @@ export default buildConfig({
}),
// ...rest of config
})
-
```
More detailed usage can be found in the [Payload Docs](https://payloadcms.com/docs/configuration/overview).
-
diff --git a/packages/db-mongodb/src/connect.ts b/packages/db-mongodb/src/connect.ts
index 284ca2291d..f8406e0bd9 100644
--- a/packages/db-mongodb/src/connect.ts
+++ b/packages/db-mongodb/src/connect.ts
@@ -1,8 +1,9 @@
/* eslint-disable @typescript-eslint/no-var-requires */
import type { ConnectOptions } from 'mongoose'
-import mongoose from 'mongoose'
import type { Connect } from 'payload/database'
+import mongoose from 'mongoose'
+
import type { MongooseAdapter } from './index.js'
export const connect: Connect = async function connect(
@@ -36,8 +37,6 @@ export const connect: Connect = async function connect(
const client = this.connection.getClient()
-
-
if (!client.options.replicaSet) {
this.transactionOptions = false
this.beginTransaction = undefined
diff --git a/packages/db-mongodb/src/createGlobal.ts b/packages/db-mongodb/src/createGlobal.ts
index 8d7a866513..4da54d738e 100644
--- a/packages/db-mongodb/src/createGlobal.ts
+++ b/packages/db-mongodb/src/createGlobal.ts
@@ -17,7 +17,7 @@ export const createGlobal: CreateGlobal = async function createGlobal(
}
const options = withSession(this, req.transactionID)
- let [result] = (await Model.create([global], options)) as any
+ let [result] = await Model.create([global], options)
result = JSON.parse(JSON.stringify(result))
diff --git a/packages/db-mongodb/src/findGlobal.ts b/packages/db-mongodb/src/findGlobal.ts
index 83cd50c4b2..3b5899f712 100644
--- a/packages/db-mongodb/src/findGlobal.ts
+++ b/packages/db-mongodb/src/findGlobal.ts
@@ -10,7 +10,7 @@ import { withSession } from './withSession.js'
export const findGlobal: FindGlobal = async function findGlobal(
this: MongooseAdapter,
- { locale, req = {} as PayloadRequest, slug, where },
+ { slug, locale, req = {} as PayloadRequest, where },
) {
const Model = this.globals
const options = {
@@ -25,7 +25,7 @@ export const findGlobal: FindGlobal = async function findGlobal(
where: combineQueries({ globalType: { equals: slug } }, where),
})
- let doc = (await Model.findOne(query, {}, options)) as any
+ let doc = await Model.findOne(query, {}, options)
if (!doc) {
return null
diff --git a/packages/db-mongodb/src/index.ts b/packages/db-mongodb/src/index.ts
index 00b016c338..dad0ef9a0c 100644
--- a/packages/db-mongodb/src/index.ts
+++ b/packages/db-mongodb/src/index.ts
@@ -1,12 +1,12 @@
import type { TransactionOptions } from 'mongodb'
-import type { ClientSession, Connection, ConnectOptions } from 'mongoose'
-import mongoose from 'mongoose'
+import type { ClientSession, ConnectOptions, Connection } from 'mongoose'
import type { Payload } from 'payload'
import type { BaseDatabaseAdapter, DatabaseAdapterObj } from 'payload/database'
-import { createDatabaseAdapter } from 'payload/database'
import fs from 'fs'
+import mongoose from 'mongoose'
import path from 'path'
+import { createDatabaseAdapter } from 'payload/database'
import type { CollectionModel, GlobalModel } from './types.js'
@@ -46,13 +46,13 @@ export interface Args {
/** Set false to disable $facet aggregation in non-supporting databases, Defaults to true */
useFacet?: boolean
}
+ /** Set to true to disable hinting to MongoDB to use 'id' as index. This is currently done when counting documents for pagination. Disabling this optimization might fix some problems with AWS DocumentDB. Defaults to false */
+ disableIndexHints?: boolean
+ migrationDir?: string
/**
* typed as any to avoid dependency
*/
mongoMemoryServer?: any
- /** Set to true to disable hinting to MongoDB to use 'id' as index. This is currently done when counting documents for pagination. Disabling this optimization might fix some problems with AWS DocumentDB. Defaults to false */
- disableIndexHints?: boolean
- migrationDir?: string
transactionOptions?: TransactionOptions | false
/** The URL to connect to MongoDB or false to start payload and prevent connecting */
url: false | string
@@ -94,8 +94,8 @@ export function mongooseAdapter({
autoPluralization = true,
connectOptions,
disableIndexHints = false,
- mongoMemoryServer,
migrationDir: migrationDirArg,
+ mongoMemoryServer,
transactionOptions = {},
url,
}: Args): DatabaseAdapterObj {
diff --git a/packages/db-mongodb/src/migrateFresh.ts b/packages/db-mongodb/src/migrateFresh.ts
index 516e84969b..4633e41b9e 100644
--- a/packages/db-mongodb/src/migrateFresh.ts
+++ b/packages/db-mongodb/src/migrateFresh.ts
@@ -23,9 +23,9 @@ export async function migrateFresh(
const { confirm: acceptWarning } = await prompts(
{
name: 'confirm',
+ type: 'confirm',
initial: false,
message: `WARNING: This will drop your database and run all migrations. Are you sure you want to proceed?`,
- type: 'confirm',
},
{
onCancel: () => {
diff --git a/packages/db-mongodb/src/updateGlobal.ts b/packages/db-mongodb/src/updateGlobal.ts
index aa21cf23a8..150d43d145 100644
--- a/packages/db-mongodb/src/updateGlobal.ts
+++ b/packages/db-mongodb/src/updateGlobal.ts
@@ -8,7 +8,7 @@ import { withSession } from './withSession.js'
export const updateGlobal: UpdateGlobal = async function updateGlobal(
this: MongooseAdapter,
- { data, req = {} as PayloadRequest, slug },
+ { slug, data, req = {} as PayloadRequest },
) {
const Model = this.globals
const options = {
diff --git a/packages/db-postgres/README.md b/packages/db-postgres/README.md
index 03718898f0..a818a90e51 100644
--- a/packages/db-postgres/README.md
+++ b/packages/db-postgres/README.md
@@ -21,12 +21,10 @@ export default buildConfig({
db: postgresAdapter({
pool: {
connectionString: process.env.DATABASE_URI,
- }
+ },
}),
// ...rest of config
})
-
```
More detailed usage can be found in the [Payload Docs](https://payloadcms.com/docs/configuration/overview).
-
diff --git a/packages/db-postgres/src/create.ts b/packages/db-postgres/src/create.ts
index 8a7af35a84..4af0b2c05e 100644
--- a/packages/db-postgres/src/create.ts
+++ b/packages/db-postgres/src/create.ts
@@ -19,8 +19,8 @@ export const create: Create = async function create(
db,
fields: collection.fields,
operation: 'create',
- tableName: toSnakeCase(collectionSlug),
req,
+ tableName: toSnakeCase(collectionSlug),
})
return result
diff --git a/packages/db-postgres/src/createGlobal.ts b/packages/db-postgres/src/createGlobal.ts
index 29d4c9f48b..965e5c36f3 100644
--- a/packages/db-postgres/src/createGlobal.ts
+++ b/packages/db-postgres/src/createGlobal.ts
@@ -9,7 +9,7 @@ import { upsertRow } from './upsertRow/index.js'
export async function createGlobal(
this: PostgresAdapter,
- { data, req = {} as PayloadRequest, slug }: CreateGlobalArgs,
+ { slug, data, req = {} as PayloadRequest }: CreateGlobalArgs,
): Promise {
const db = this.sessions[req.transactionID]?.db || this.drizzle
const globalConfig = this.payload.globals.config.find((config) => config.slug === slug)
@@ -20,8 +20,8 @@ export async function createGlobal(
db,
fields: globalConfig.fields,
operation: 'create',
- tableName: toSnakeCase(slug),
req,
+ tableName: toSnakeCase(slug),
})
return result
diff --git a/packages/db-postgres/src/createGlobalVersion.ts b/packages/db-postgres/src/createGlobalVersion.ts
index b170cab9af..a860e187bc 100644
--- a/packages/db-postgres/src/createGlobalVersion.ts
+++ b/packages/db-postgres/src/createGlobalVersion.ts
@@ -1,8 +1,8 @@
import type { TypeWithVersion } from 'payload/database'
-import { type CreateGlobalVersionArgs } from 'payload/database'
import type { PayloadRequest, TypeWithID } from 'payload/types'
import { sql } from 'drizzle-orm'
+import { type CreateGlobalVersionArgs } from 'payload/database'
import { buildVersionGlobalFields } from 'payload/versions'
import toSnakeCase from 'to-snake-case'
@@ -29,8 +29,8 @@ export async function createGlobalVersion(
db,
fields: buildVersionGlobalFields(global),
operation: 'create',
- tableName,
req,
+ tableName,
})
const table = this.tables[tableName]
diff --git a/packages/db-postgres/src/createVersion.ts b/packages/db-postgres/src/createVersion.ts
index 9f5f091f43..c8326a2fc4 100644
--- a/packages/db-postgres/src/createVersion.ts
+++ b/packages/db-postgres/src/createVersion.ts
@@ -35,8 +35,8 @@ export async function createVersion(
db,
fields: buildVersionCollectionFields(collection),
operation: 'create',
- tableName,
req,
+ tableName,
})
const table = this.tables[tableName]
diff --git a/packages/db-postgres/src/findGlobal.ts b/packages/db-postgres/src/findGlobal.ts
index 76da374761..547bec5b06 100644
--- a/packages/db-postgres/src/findGlobal.ts
+++ b/packages/db-postgres/src/findGlobal.ts
@@ -8,7 +8,7 @@ import { findMany } from './find/findMany.js'
export const findGlobal: FindGlobal = async function findGlobal(
this: PostgresAdapter,
- { locale, req, slug, where },
+ { slug, locale, req, where },
) {
const globalConfig = this.payload.globals.config.find((config) => config.slug === slug)
const tableName = toSnakeCase(slug)
diff --git a/packages/db-postgres/src/queries/getTableColumnFromPath.ts b/packages/db-postgres/src/queries/getTableColumnFromPath.ts
index 3683170bf2..ac86d6b346 100644
--- a/packages/db-postgres/src/queries/getTableColumnFromPath.ts
+++ b/packages/db-postgres/src/queries/getTableColumnFromPath.ts
@@ -95,7 +95,7 @@ export const getTableColumnFromPath = ({
field: {
name: 'id',
type: adapter.idType === 'uuid' ? 'text' : 'number',
- } as TextField | NumberField,
+ } as NumberField | TextField,
table: adapter.tables[newTableName],
}
}
diff --git a/packages/db-postgres/src/queries/parseParams.ts b/packages/db-postgres/src/queries/parseParams.ts
index 7c2a4c8ff1..14262f9867 100644
--- a/packages/db-postgres/src/queries/parseParams.ts
+++ b/packages/db-postgres/src/queries/parseParams.ts
@@ -10,8 +10,8 @@ import type { GenericColumn, PostgresAdapter } from '../types.js'
import type { BuildQueryJoinAliases, BuildQueryJoins } from './buildQuery.js'
import { buildAndOrConditions } from './buildAndOrConditions.js'
-import { createJSONQuery } from './createJSONQuery/index.js'
import { convertPathToJSONTraversal } from './createJSONQuery/convertPathToJSONTraversal.js'
+import { createJSONQuery } from './createJSONQuery/index.js'
import { getTableColumnFromPath } from './getTableColumnFromPath.js'
import { operatorMap } from './operatorMap.js'
import { sanitizeQueryValue } from './sanitizeQueryValue.js'
diff --git a/packages/db-postgres/src/transform/read/hasManyText.ts b/packages/db-postgres/src/transform/read/hasManyText.ts
index af6b8e836e..1392c73d24 100644
--- a/packages/db-postgres/src/transform/read/hasManyText.ts
+++ b/packages/db-postgres/src/transform/read/hasManyText.ts
@@ -4,11 +4,11 @@ import type { TextField } from 'payload/types'
type Args = {
field: TextField
locale?: string
- textRows: Record[]
ref: Record
+ textRows: Record[]
}
-export const transformHasManyText = ({ field, locale, textRows, ref }: Args) => {
+export const transformHasManyText = ({ field, locale, ref, textRows }: Args) => {
const result = textRows.map(({ text }) => text)
if (locale) {
diff --git a/packages/db-postgres/src/transform/read/index.ts b/packages/db-postgres/src/transform/read/index.ts
index 69a0a8c47e..aeb4f911f2 100644
--- a/packages/db-postgres/src/transform/read/index.ts
+++ b/packages/db-postgres/src/transform/read/index.ts
@@ -48,11 +48,11 @@ export const transform = ({ config, data, fields }: Transf
deletions,
fieldPrefix: '',
fields,
- texts,
numbers,
path: '',
relationships,
table: data,
+ texts,
})
deletions.forEach((deletion) => deletion())
diff --git a/packages/db-postgres/src/transform/write/array.ts b/packages/db-postgres/src/transform/write/array.ts
index 7f30a1a53b..5ac87ae60c 100644
--- a/packages/db-postgres/src/transform/write/array.ts
+++ b/packages/db-postgres/src/transform/write/array.ts
@@ -18,7 +18,6 @@ type Args = {
data: unknown
field: ArrayField
locale?: string
- texts: Record[]
numbers: Record[]
path: string
relationships: Record[]
@@ -26,6 +25,7 @@ type Args = {
selects: {
[tableName: string]: Record[]
}
+ texts: Record[]
}
export const transformArray = ({
@@ -37,12 +37,12 @@ export const transformArray = ({
data,
field,
locale,
- texts,
numbers,
path,
relationships,
relationshipsToDelete,
selects,
+ texts,
}: Args) => {
const newRows: ArrayRowToInsert[] = []
const hasUUID = adapter.tables[arrayTableName]._uuid
@@ -88,7 +88,6 @@ export const transformArray = ({
fieldPrefix: '',
fields: field.fields,
locales: newRow.locales,
- texts,
numbers,
parentTableName: arrayTableName,
path: `${path || ''}${field.name}.${i}.`,
@@ -96,6 +95,7 @@ export const transformArray = ({
relationshipsToDelete,
row: newRow.row,
selects,
+ texts,
})
newRows.push(newRow)
diff --git a/packages/db-postgres/src/transform/write/blocks.ts b/packages/db-postgres/src/transform/write/blocks.ts
index 4271969aff..809e95e81a 100644
--- a/packages/db-postgres/src/transform/write/blocks.ts
+++ b/packages/db-postgres/src/transform/write/blocks.ts
@@ -18,7 +18,6 @@ type Args = {
data: Record[]
field: BlockField
locale?: string
- texts: Record[]
numbers: Record[]
path: string
relationships: Record[]
@@ -26,6 +25,7 @@ type Args = {
selects: {
[tableName: string]: Record[]
}
+ texts: Record[]
}
export const transformBlocks = ({
adapter,
@@ -35,12 +35,12 @@ export const transformBlocks = ({
data,
field,
locale,
- texts,
numbers,
path,
relationships,
relationshipsToDelete,
selects,
+ texts,
}: Args) => {
data.forEach((blockRow, i) => {
if (typeof blockRow.blockType !== 'string') return
@@ -86,7 +86,6 @@ export const transformBlocks = ({
fieldPrefix: '',
fields: matchedBlock.fields,
locales: newRow.locales,
- texts,
numbers,
parentTableName: blockTableName,
path: `${path || ''}${field.name}.${i}.`,
@@ -94,6 +93,7 @@ export const transformBlocks = ({
relationshipsToDelete,
row: newRow.row,
selects,
+ texts,
})
blocks[blockType].push(newRow)
diff --git a/packages/db-postgres/src/transform/write/index.ts b/packages/db-postgres/src/transform/write/index.ts
index 9cd4bdd218..24307e8163 100644
--- a/packages/db-postgres/src/transform/write/index.ts
+++ b/packages/db-postgres/src/transform/write/index.ts
@@ -27,12 +27,12 @@ export const transformForWrite = ({
blocks: {},
blocksToDelete: new Set(),
locales: {},
- texts: [],
numbers: [],
relationships: [],
relationshipsToDelete: [],
row: {},
selects: {},
+ texts: [],
}
// This function is responsible for building up the
@@ -48,7 +48,6 @@ export const transformForWrite = ({
fieldPrefix: '',
fields,
locales: rowToInsert.locales,
- texts: rowToInsert.texts,
numbers: rowToInsert.numbers,
parentTableName: tableName,
path,
@@ -56,6 +55,7 @@ export const transformForWrite = ({
relationshipsToDelete: rowToInsert.relationshipsToDelete,
row: rowToInsert.row,
selects: rowToInsert.selects,
+ texts: rowToInsert.texts,
})
return rowToInsert
diff --git a/packages/db-postgres/src/transform/write/texts.ts b/packages/db-postgres/src/transform/write/texts.ts
index 5cf396349c..e90934ab49 100644
--- a/packages/db-postgres/src/transform/write/texts.ts
+++ b/packages/db-postgres/src/transform/write/texts.ts
@@ -8,8 +8,8 @@ export const transformTexts = ({ baseRow, data, texts }: Args) => {
data.forEach((val, i) => {
texts.push({
...baseRow,
- text: val,
order: i + 1,
+ text: val,
})
})
}
diff --git a/packages/db-postgres/src/transform/write/traverseFields.ts b/packages/db-postgres/src/transform/write/traverseFields.ts
index 85988dba22..3e23256ea6 100644
--- a/packages/db-postgres/src/transform/write/traverseFields.ts
+++ b/packages/db-postgres/src/transform/write/traverseFields.ts
@@ -45,7 +45,6 @@ type Args = {
locales: {
[locale: string]: Record
}
- texts: Record[]
numbers: Record[]
/**
* This is the name of the parent table
@@ -58,6 +57,7 @@ type Args = {
selects: {
[tableName: string]: Record[]
}
+ texts: Record[]
}
export const traverseFields = ({
@@ -73,7 +73,6 @@ export const traverseFields = ({
fields,
forcedLocale,
locales,
- texts,
numbers,
parentTableName,
path,
@@ -81,6 +80,7 @@ export const traverseFields = ({
relationshipsToDelete,
row,
selects,
+ texts,
}: Args) => {
fields.forEach((field) => {
let columnName = ''
@@ -111,12 +111,12 @@ export const traverseFields = ({
data: localeData,
field,
locale: localeKey,
- texts,
numbers,
path,
relationships,
relationshipsToDelete,
selects,
+ texts,
})
arrays[arrayTableName] = arrays[arrayTableName].concat(newRows)
@@ -132,12 +132,12 @@ export const traverseFields = ({
blocksToDelete,
data: data[field.name],
field,
- texts,
numbers,
path,
relationships,
relationshipsToDelete,
selects,
+ texts,
})
arrays[arrayTableName] = arrays[arrayTableName].concat(newRows)
@@ -163,12 +163,12 @@ export const traverseFields = ({
data: localeData,
field,
locale: localeKey,
- texts,
numbers,
path,
relationships,
relationshipsToDelete,
selects,
+ texts,
})
}
})
@@ -181,12 +181,12 @@ export const traverseFields = ({
blocksToDelete,
data: fieldData,
field,
- texts,
numbers,
path,
relationships,
relationshipsToDelete,
selects,
+ texts,
})
}
@@ -210,7 +210,6 @@ export const traverseFields = ({
fields: field.fields,
forcedLocale: localeKey,
locales,
- texts,
numbers,
parentTableName,
path: `${path || ''}${field.name}.`,
@@ -218,6 +217,7 @@ export const traverseFields = ({
relationshipsToDelete,
row,
selects,
+ texts,
})
})
} else {
@@ -233,7 +233,6 @@ export const traverseFields = ({
fieldPrefix: `${fieldName}_`,
fields: field.fields,
locales,
- texts,
numbers,
parentTableName,
path: `${path || ''}${field.name}.`,
@@ -241,6 +240,7 @@ export const traverseFields = ({
relationshipsToDelete,
row,
selects,
+ texts,
})
}
}
@@ -267,7 +267,6 @@ export const traverseFields = ({
fields: tab.fields,
forcedLocale: localeKey,
locales,
- texts,
numbers,
parentTableName,
path: `${path || ''}${tab.name}.`,
@@ -275,6 +274,7 @@ export const traverseFields = ({
relationshipsToDelete,
row,
selects,
+ texts,
})
})
} else {
@@ -290,7 +290,6 @@ export const traverseFields = ({
fieldPrefix: `${fieldPrefix || ''}${tab.name}_`,
fields: tab.fields,
locales,
- texts,
numbers,
parentTableName,
path: `${path || ''}${tab.name}.`,
@@ -298,6 +297,7 @@ export const traverseFields = ({
relationshipsToDelete,
row,
selects,
+ texts,
})
}
}
@@ -314,7 +314,6 @@ export const traverseFields = ({
fieldPrefix,
fields: tab.fields,
locales,
- texts,
numbers,
parentTableName,
path,
@@ -322,6 +321,7 @@ export const traverseFields = ({
relationshipsToDelete,
row,
selects,
+ texts,
})
}
})
@@ -340,7 +340,6 @@ export const traverseFields = ({
fieldPrefix,
fields: field.fields,
locales,
- texts,
numbers,
parentTableName,
path,
@@ -348,6 +347,7 @@ export const traverseFields = ({
relationshipsToDelete,
row,
selects,
+ texts,
})
}
diff --git a/packages/db-postgres/src/transform/write/types.ts b/packages/db-postgres/src/transform/write/types.ts
index 361a7ccf82..b0339eda79 100644
--- a/packages/db-postgres/src/transform/write/types.ts
+++ b/packages/db-postgres/src/transform/write/types.ts
@@ -34,7 +34,6 @@ export type RowToInsert = {
locales: {
[locale: string]: Record
}
- texts: Record[]
numbers: Record[]
relationships: Record[]
relationshipsToDelete: RelationshipToDelete[]
@@ -42,4 +41,5 @@ export type RowToInsert = {
selects: {
[tableName: string]: Record[]
}
+ texts: Record[]
}
diff --git a/packages/db-postgres/src/update.ts b/packages/db-postgres/src/update.ts
index 54cc596328..68b7c7f245 100644
--- a/packages/db-postgres/src/update.ts
+++ b/packages/db-postgres/src/update.ts
@@ -4,6 +4,7 @@ import toSnakeCase from 'to-snake-case'
import type { ChainedMethods } from './find/chainMethods.js'
import type { PostgresAdapter } from './types.js'
+
import { chainMethods } from './find/chainMethods.js'
import buildQuery from './queries/buildQuery.js'
import { upsertRow } from './upsertRow/index.js'
@@ -70,8 +71,8 @@ export const updateOne: UpdateOne = async function updateOne(
db,
fields: collection.fields,
operation: 'update',
- tableName: toSnakeCase(collectionSlug),
req,
+ tableName: toSnakeCase(collectionSlug),
})
return result
diff --git a/packages/db-postgres/src/updateGlobal.ts b/packages/db-postgres/src/updateGlobal.ts
index 641ecac03e..3fd6bff725 100644
--- a/packages/db-postgres/src/updateGlobal.ts
+++ b/packages/db-postgres/src/updateGlobal.ts
@@ -9,7 +9,7 @@ import { upsertRow } from './upsertRow/index.js'
export async function updateGlobal(
this: PostgresAdapter,
- { data, req = {} as PayloadRequest, slug }: UpdateGlobalArgs,
+ { slug, data, req = {} as PayloadRequest }: UpdateGlobalArgs,
): Promise {
const db = this.sessions[req.transactionID]?.db || this.drizzle
const globalConfig = this.payload.globals.config.find((config) => config.slug === slug)
@@ -23,8 +23,8 @@ export async function updateGlobal(
data,
db,
fields: globalConfig.fields,
- tableName,
req,
+ tableName,
})
return result
diff --git a/packages/db-postgres/src/updateGlobalVersion.ts b/packages/db-postgres/src/updateGlobalVersion.ts
index 2676fd8061..5e1aee29a2 100644
--- a/packages/db-postgres/src/updateGlobalVersion.ts
+++ b/packages/db-postgres/src/updateGlobalVersion.ts
@@ -43,9 +43,9 @@ export async function updateGlobalVersion(
db,
fields,
operation: 'update',
+ req,
tableName,
where,
- req,
})
return result
diff --git a/packages/db-postgres/src/updateVersion.ts b/packages/db-postgres/src/updateVersion.ts
index 354f20c787..8dcb9e997f 100644
--- a/packages/db-postgres/src/updateVersion.ts
+++ b/packages/db-postgres/src/updateVersion.ts
@@ -41,9 +41,9 @@ export async function updateVersion(
db,
fields,
operation: 'update',
+ req,
tableName,
where,
- req,
})
return result
diff --git a/packages/db-postgres/src/upsertRow/types.ts b/packages/db-postgres/src/upsertRow/types.ts
index 9ec878d51a..eec4a4586a 100644
--- a/packages/db-postgres/src/upsertRow/types.ts
+++ b/packages/db-postgres/src/upsertRow/types.ts
@@ -9,8 +9,8 @@ type BaseArgs = {
db: DrizzleDB
fields: Field[]
path?: string
- tableName: string
req: PayloadRequest
+ tableName: string
}
type CreateArgs = BaseArgs & {
diff --git a/packages/graphql/src/index.ts b/packages/graphql/src/index.ts
index 3891d316c8..2d3d0c2d11 100644
--- a/packages/graphql/src/index.ts
+++ b/packages/graphql/src/index.ts
@@ -1,21 +1,21 @@
/* eslint-disable no-param-reassign */
-import * as GraphQL from 'graphql'
-import { OperationArgs } from 'graphql-http'
-
-import {
- fieldExtensionsEstimator,
- simpleEstimator,
- createComplexityRule,
-} from 'graphql-query-complexity'
-
+import type { OperationArgs } from 'graphql-http'
import type { GraphQLInfo } from 'payload/config'
import type { SanitizedConfig } from 'payload/types'
+
+import * as GraphQL from 'graphql'
+import {
+ createComplexityRule,
+ fieldExtensionsEstimator,
+ simpleEstimator,
+} from 'graphql-query-complexity'
+
import accessResolver from './resolvers/auth/access.js'
-import initCollections from './schema/initCollections.js'
-import initGlobals from './schema/initGlobals.js'
import buildFallbackLocaleInputType from './schema/buildFallbackLocaleInputType.js'
import buildLocaleInputType from './schema/buildLocaleInputType.js'
import buildPoliciesType from './schema/buildPoliciesType.js'
+import initCollections from './schema/initCollections.js'
+import initGlobals from './schema/initGlobals.js'
import { wrapCustomFields } from './utilities/wrapCustomResolver.js'
export async function configToSchema(config: SanitizedConfig): Promise<{
@@ -34,7 +34,17 @@ export async function configToSchema(config: SanitizedConfig): Promise<{
config: config.globals,
}
- let graphqlResult: GraphQLInfo = {
+ const graphqlResult: GraphQLInfo = {
+ Mutation: {
+ name: 'Mutation',
+ fields: {},
+ },
+ Query: {
+ name: 'Query',
+ fields: {},
+ },
+ collections,
+ globals,
types: {
arrayTypes: {},
blockInputTypes: {},
@@ -42,16 +52,6 @@ export async function configToSchema(config: SanitizedConfig): Promise<{
groupTypes: {},
tabTypes: {},
},
- Query: {
- name: 'Query',
- fields: {},
- },
- Mutation: {
- name: 'Mutation',
- fields: {},
- },
- collections,
- globals,
}
if (config.localization) {
@@ -65,8 +65,8 @@ export async function configToSchema(config: SanitizedConfig): Promise<{
initGlobals({ config, graphqlResult })
graphqlResult.Query.fields['Access'] = {
- resolve: accessResolver(config),
type: buildPoliciesType(config),
+ resolve: accessResolver(config),
}
if (typeof config.graphQL.queries === 'function') {
diff --git a/packages/graphql/src/resolvers/auth/access.ts b/packages/graphql/src/resolvers/auth/access.ts
index 624a1be9bf..f40142d764 100644
--- a/packages/graphql/src/resolvers/auth/access.ts
+++ b/packages/graphql/src/resolvers/auth/access.ts
@@ -1,9 +1,11 @@
-import { accessOperation } from 'payload/operations'
import type { SanitizedConfig } from 'payload/types'
-import formatName from '../../utilities/formatName.js'
-import { Context } from '../types.js'
+import { accessOperation } from 'payload/operations'
import { isolateObjectProperty } from 'payload/utilities'
+
+import type { Context } from '../types.js'
+
+import formatName from '../../utilities/formatName.js'
const formatConfigNames = (results, configs) => {
const formattedResults = { ...results }
diff --git a/packages/graphql/src/resolvers/auth/forgotPassword.ts b/packages/graphql/src/resolvers/auth/forgotPassword.ts
index 6f593ee030..7c8933e3a7 100644
--- a/packages/graphql/src/resolvers/auth/forgotPassword.ts
+++ b/packages/graphql/src/resolvers/auth/forgotPassword.ts
@@ -1,7 +1,8 @@
-import { forgotPasswordOperation } from 'payload/operations'
import type { Collection } from 'payload/types'
+import { forgotPasswordOperation } from 'payload/operations'
import { isolateObjectProperty } from 'payload/utilities'
+
import type { Context } from '../types.js'
function forgotPasswordResolver(collection: Collection): any {
diff --git a/packages/graphql/src/resolvers/auth/init.ts b/packages/graphql/src/resolvers/auth/init.ts
index df681dad96..faaace2135 100644
--- a/packages/graphql/src/resolvers/auth/init.ts
+++ b/packages/graphql/src/resolvers/auth/init.ts
@@ -1,5 +1,6 @@
import { initOperation } from 'payload/operations'
import { isolateObjectProperty } from 'payload/utilities'
+
import type { Context } from '../types.js'
function initResolver(collection: string) {
diff --git a/packages/graphql/src/resolvers/auth/login.ts b/packages/graphql/src/resolvers/auth/login.ts
index 2a71d6d254..7cfe683824 100644
--- a/packages/graphql/src/resolvers/auth/login.ts
+++ b/packages/graphql/src/resolvers/auth/login.ts
@@ -1,8 +1,9 @@
-import { loginOperation } from 'payload/operations'
-import { generatePayloadCookie } from 'payload/auth'
import type { Collection } from 'payload/types'
+import { generatePayloadCookie } from 'payload/auth'
+import { loginOperation } from 'payload/operations'
import { isolateObjectProperty } from 'payload/utilities'
+
import type { Context } from '../types.js'
function loginResolver(collection: Collection): any {
@@ -19,9 +20,9 @@ function loginResolver(collection: Collection): any {
const result = await loginOperation(options)
const cookie = generatePayloadCookie({
- token: result.token,
- payload: context.req.payload,
collectionConfig: collection.config,
+ payload: context.req.payload,
+ token: result.token,
})
context.headers['Set-Cookie'] = cookie
diff --git a/packages/graphql/src/resolvers/auth/logout.ts b/packages/graphql/src/resolvers/auth/logout.ts
index 780793f969..7e65b544f7 100644
--- a/packages/graphql/src/resolvers/auth/logout.ts
+++ b/packages/graphql/src/resolvers/auth/logout.ts
@@ -1,8 +1,9 @@
-import { logoutOperation } from 'payload/operations'
-import { generateExpiredPayloadCookie } from 'payload/auth'
import type { Collection } from 'payload/types'
+import { generateExpiredPayloadCookie } from 'payload/auth'
+import { logoutOperation } from 'payload/operations'
import { isolateObjectProperty } from 'payload/utilities'
+
import type { Context } from '../types.js'
function logoutResolver(collection: Collection): any {
diff --git a/packages/graphql/src/resolvers/auth/me.ts b/packages/graphql/src/resolvers/auth/me.ts
index 136cbef067..b406b59682 100644
--- a/packages/graphql/src/resolvers/auth/me.ts
+++ b/packages/graphql/src/resolvers/auth/me.ts
@@ -1,7 +1,8 @@
-import { meOperation } from 'payload/operations'
import type { Collection } from 'payload/types'
+import { meOperation } from 'payload/operations'
import { isolateObjectProperty } from 'payload/utilities'
+
import type { Context } from '../types.js'
function meResolver(collection: Collection): any {
diff --git a/packages/graphql/src/resolvers/auth/refresh.ts b/packages/graphql/src/resolvers/auth/refresh.ts
index 921f51fa87..5747d86d62 100644
--- a/packages/graphql/src/resolvers/auth/refresh.ts
+++ b/packages/graphql/src/resolvers/auth/refresh.ts
@@ -1,8 +1,9 @@
-import { refreshOperation } from 'payload/operations'
-import { generatePayloadCookie, extractJWT } from 'payload/auth'
import type { Collection } from 'payload/types'
+import { extractJWT, generatePayloadCookie } from 'payload/auth'
+import { refreshOperation } from 'payload/operations'
import { isolateObjectProperty } from 'payload/utilities'
+
import type { Context } from '../types.js'
function refreshResolver(collection: Collection): any {
@@ -24,9 +25,9 @@ function refreshResolver(collection: Collection): any {
const result = await refreshOperation(options)
const cookie = generatePayloadCookie({
- token: result.refreshedToken,
- payload: context.req.payload,
collectionConfig: collection.config,
+ payload: context.req.payload,
+ token: result.refreshedToken,
})
context.headers['Set-Cookie'] = cookie
diff --git a/packages/graphql/src/resolvers/auth/resetPassword.ts b/packages/graphql/src/resolvers/auth/resetPassword.ts
index ae03b19a4e..6610b5c003 100644
--- a/packages/graphql/src/resolvers/auth/resetPassword.ts
+++ b/packages/graphql/src/resolvers/auth/resetPassword.ts
@@ -1,8 +1,9 @@
-import { resetPasswordOperation } from 'payload/operations'
-import { generatePayloadCookie } from 'payload/auth'
import type { Collection } from 'payload/types'
+import { generatePayloadCookie } from 'payload/auth'
+import { resetPasswordOperation } from 'payload/operations'
import { isolateObjectProperty } from 'payload/utilities'
+
import type { Context } from '../types.js'
function resetPasswordResolver(collection: Collection): any {
@@ -20,9 +21,9 @@ function resetPasswordResolver(collection: Collection): any {
const result = await resetPasswordOperation(options)
const cookie = generatePayloadCookie({
- token: result.token,
- payload: context.req.payload,
collectionConfig: collection.config,
+ payload: context.req.payload,
+ token: result.token,
})
context.headers['Set-Cookie'] = cookie
diff --git a/packages/graphql/src/resolvers/auth/unlock.ts b/packages/graphql/src/resolvers/auth/unlock.ts
index a1a4cd4e99..4bb15242dd 100644
--- a/packages/graphql/src/resolvers/auth/unlock.ts
+++ b/packages/graphql/src/resolvers/auth/unlock.ts
@@ -1,7 +1,8 @@
-import { unlockOperation } from 'payload/operations'
import type { Collection } from 'payload/types'
+import { unlockOperation } from 'payload/operations'
import { isolateObjectProperty } from 'payload/utilities'
+
import type { Context } from '../types.js'
function unlockResolver(collection: Collection) {
diff --git a/packages/graphql/src/resolvers/auth/verifyEmail.ts b/packages/graphql/src/resolvers/auth/verifyEmail.ts
index cd097dd2f5..ce4ffde6e3 100644
--- a/packages/graphql/src/resolvers/auth/verifyEmail.ts
+++ b/packages/graphql/src/resolvers/auth/verifyEmail.ts
@@ -1,7 +1,8 @@
-import { verifyEmailOperation } from 'payload/operations'
import type { Collection } from 'payload/types'
+import { verifyEmailOperation } from 'payload/operations'
import { isolateObjectProperty } from 'payload/utilities'
+
import type { Context } from '../types.js'
function verifyEmailResolver(collection: Collection) {
diff --git a/packages/graphql/src/resolvers/collections/create.ts b/packages/graphql/src/resolvers/collections/create.ts
index ebd5bea98f..1fd319dd1c 100644
--- a/packages/graphql/src/resolvers/collections/create.ts
+++ b/packages/graphql/src/resolvers/collections/create.ts
@@ -1,10 +1,11 @@
-import { createOperation } from 'payload/operations'
-import type { MarkOptional } from 'ts-essentials'
import type { GeneratedTypes } from 'payload'
import type { PayloadRequest } from 'payload/types'
import type { Collection } from 'payload/types'
+import type { MarkOptional } from 'ts-essentials'
+import { createOperation } from 'payload/operations'
import { isolateObjectProperty } from 'payload/utilities'
+
import type { Context } from '../types.js'
export type Resolver = (
diff --git a/packages/graphql/src/resolvers/collections/delete.ts b/packages/graphql/src/resolvers/collections/delete.ts
index fd8aeaf753..1004ac6daa 100644
--- a/packages/graphql/src/resolvers/collections/delete.ts
+++ b/packages/graphql/src/resolvers/collections/delete.ts
@@ -1,9 +1,10 @@
-import { deleteByIDOperation } from 'payload/operations'
import type { GeneratedTypes } from 'payload'
import type { PayloadRequest } from 'payload/types'
import type { Collection } from 'payload/types'
+import { deleteByIDOperation } from 'payload/operations'
import { isolateObjectProperty } from 'payload/utilities'
+
import type { Context } from '../types.js'
export type Resolver = (
diff --git a/packages/graphql/src/resolvers/collections/docAccess.ts b/packages/graphql/src/resolvers/collections/docAccess.ts
index 0255215bb5..cd37f72dad 100644
--- a/packages/graphql/src/resolvers/collections/docAccess.ts
+++ b/packages/graphql/src/resolvers/collections/docAccess.ts
@@ -1,8 +1,9 @@
-import { docAccessOperation } from 'payload/operations'
-import type { Collection, PayloadRequest } from 'payload/types'
import type { CollectionPermission, GlobalPermission } from 'payload/auth'
+import type { Collection, PayloadRequest } from 'payload/types'
+import { docAccessOperation } from 'payload/operations'
import { isolateObjectProperty } from 'payload/utilities'
+
import type { Context } from '../types.js'
export type Resolver = (
@@ -19,8 +20,8 @@ export function docAccessResolver(collection: Collection): Resolver {
async function resolver(_, args, context: Context) {
return docAccessOperation({
id: args.id,
- req: isolateObjectProperty(context.req, 'transactionID'),
collection,
+ req: isolateObjectProperty(context.req, 'transactionID'),
})
}
diff --git a/packages/graphql/src/resolvers/collections/find.ts b/packages/graphql/src/resolvers/collections/find.ts
index 1d22972546..a7edb1cd1e 100644
--- a/packages/graphql/src/resolvers/collections/find.ts
+++ b/packages/graphql/src/resolvers/collections/find.ts
@@ -1,9 +1,10 @@
-import { findOperation } from 'payload/operations'
import type { PaginatedDocs } from 'payload/database'
import type { PayloadRequest, Where } from 'payload/types'
import type { Collection } from 'payload/types'
+import { findOperation } from 'payload/operations'
import { isolateObjectProperty } from 'payload/utilities'
+
import type { Context } from '../types.js'
export type Resolver = (
diff --git a/packages/graphql/src/resolvers/collections/findByID.ts b/packages/graphql/src/resolvers/collections/findByID.ts
index eb7c482e17..8171e52a65 100644
--- a/packages/graphql/src/resolvers/collections/findByID.ts
+++ b/packages/graphql/src/resolvers/collections/findByID.ts
@@ -1,9 +1,10 @@
-import { findByIDOperation } from 'payload/operations'
import type { GeneratedTypes } from 'payload'
import type { PayloadRequest } from 'payload/types'
import type { Collection } from 'payload/types'
+import { findByIDOperation } from 'payload/operations'
import { isolateObjectProperty } from 'payload/utilities'
+
import type { Context } from '../types.js'
export type Resolver = (
diff --git a/packages/graphql/src/resolvers/collections/findVersionByID.ts b/packages/graphql/src/resolvers/collections/findVersionByID.ts
index dfa1ca7929..75cb6349c4 100644
--- a/packages/graphql/src/resolvers/collections/findVersionByID.ts
+++ b/packages/graphql/src/resolvers/collections/findVersionByID.ts
@@ -1,9 +1,10 @@
-import { findVersionByIDOperation } from 'payload/operations'
import type { PayloadRequest } from 'payload/types'
-import type { TypeWithVersion } from 'payload/versions'
import type { Collection, TypeWithID } from 'payload/types'
+import type { TypeWithVersion } from 'payload/versions'
+import { findVersionByIDOperation } from 'payload/operations'
import { isolateObjectProperty } from 'payload/utilities'
+
import type { Context } from '../types.js'
export type Resolver = (
diff --git a/packages/graphql/src/resolvers/collections/findVersions.ts b/packages/graphql/src/resolvers/collections/findVersions.ts
index 75e7cf472e..a87861b5f2 100644
--- a/packages/graphql/src/resolvers/collections/findVersions.ts
+++ b/packages/graphql/src/resolvers/collections/findVersions.ts
@@ -1,9 +1,10 @@
-import { findVersionsOperation } from 'payload/operations'
-import type { PayloadRequest, Where } from 'payload/types'
import type { PaginatedDocs } from 'payload/database'
+import type { PayloadRequest, Where } from 'payload/types'
import type { Collection } from 'payload/types'
+import { findVersionsOperation } from 'payload/operations'
import { isolateObjectProperty } from 'payload/utilities'
+
import type { Context } from '../types.js'
export type Resolver = (
diff --git a/packages/graphql/src/resolvers/collections/restoreVersion.ts b/packages/graphql/src/resolvers/collections/restoreVersion.ts
index faac97f6f1..0aa5ef94a0 100644
--- a/packages/graphql/src/resolvers/collections/restoreVersion.ts
+++ b/packages/graphql/src/resolvers/collections/restoreVersion.ts
@@ -1,8 +1,9 @@
-import { restoreVersionOperation } from 'payload/operations'
import type { PayloadRequest } from 'payload/types'
import type { Collection } from 'payload/types'
+import { restoreVersionOperation } from 'payload/operations'
import { isolateObjectProperty } from 'payload/utilities'
+
import type { Context } from '../types.js'
export type Resolver = (
diff --git a/packages/graphql/src/resolvers/collections/update.ts b/packages/graphql/src/resolvers/collections/update.ts
index caa4033016..5c1fab7bcf 100644
--- a/packages/graphql/src/resolvers/collections/update.ts
+++ b/packages/graphql/src/resolvers/collections/update.ts
@@ -1,9 +1,10 @@
-import { updateByIDOperation } from 'payload/operations'
import type { GeneratedTypes } from 'payload'
import type { PayloadRequest } from 'payload/types'
import type { Collection } from 'payload/types'
+import { updateByIDOperation } from 'payload/operations'
import { isolateObjectProperty } from 'payload/utilities'
+
import type { Context } from '../types.js'
export type Resolver = (
diff --git a/packages/graphql/src/resolvers/globals/docAccess.ts b/packages/graphql/src/resolvers/globals/docAccess.ts
index 526ca7ed85..8093d9d95a 100644
--- a/packages/graphql/src/resolvers/globals/docAccess.ts
+++ b/packages/graphql/src/resolvers/globals/docAccess.ts
@@ -1,8 +1,9 @@
-import { docAccessOperationGlobal } from 'payload/operations'
-import type { PayloadRequest, SanitizedGlobalConfig } from 'payload/types'
import type { CollectionPermission, GlobalPermission } from 'payload/auth'
+import type { PayloadRequest, SanitizedGlobalConfig } from 'payload/types'
+import { docAccessOperationGlobal } from 'payload/operations'
import { isolateObjectProperty } from 'payload/utilities'
+
import type { Context } from '../types.js'
export type Resolver = (
diff --git a/packages/graphql/src/resolvers/globals/findOne.ts b/packages/graphql/src/resolvers/globals/findOne.ts
index 223cbd2bf7..c5d499e4fa 100644
--- a/packages/graphql/src/resolvers/globals/findOne.ts
+++ b/packages/graphql/src/resolvers/globals/findOne.ts
@@ -1,7 +1,8 @@
-import { findOneOperation } from 'payload/operations'
import type { Document, SanitizedGlobalConfig } from 'payload/types'
+import { findOneOperation } from 'payload/operations'
import { isolateObjectProperty } from 'payload/utilities'
+
import type { Context } from '../types.js'
export default function findOneResolver(globalConfig: SanitizedGlobalConfig): Document {
diff --git a/packages/graphql/src/resolvers/globals/findVersionByID.ts b/packages/graphql/src/resolvers/globals/findVersionByID.ts
index f54fe9c86a..a203e5e677 100644
--- a/packages/graphql/src/resolvers/globals/findVersionByID.ts
+++ b/packages/graphql/src/resolvers/globals/findVersionByID.ts
@@ -1,7 +1,8 @@
-import { findVersionByIDOperationGlobal } from 'payload/operations'
import type { Document, PayloadRequest, SanitizedGlobalConfig } from 'payload/types'
+import { findVersionByIDOperationGlobal } from 'payload/operations'
import { isolateObjectProperty } from 'payload/utilities'
+
import type { Context } from '../types.js'
export type Resolver = (
diff --git a/packages/graphql/src/resolvers/globals/findVersions.ts b/packages/graphql/src/resolvers/globals/findVersions.ts
index fce72284e1..389ea34ff1 100644
--- a/packages/graphql/src/resolvers/globals/findVersions.ts
+++ b/packages/graphql/src/resolvers/globals/findVersions.ts
@@ -1,7 +1,8 @@
-import { findVersionsOperationGlobal } from 'payload/operations'
import type { Document, PayloadRequest, SanitizedGlobalConfig, Where } from 'payload/types'
+import { findVersionsOperationGlobal } from 'payload/operations'
import { isolateObjectProperty } from 'payload/utilities'
+
import type { Context } from '../types.js'
export type Resolver = (
diff --git a/packages/graphql/src/resolvers/globals/restoreVersion.ts b/packages/graphql/src/resolvers/globals/restoreVersion.ts
index a2a365b670..03fa6fbe03 100644
--- a/packages/graphql/src/resolvers/globals/restoreVersion.ts
+++ b/packages/graphql/src/resolvers/globals/restoreVersion.ts
@@ -1,7 +1,8 @@
-import { restoreVersionOperationGlobal } from 'payload/operations'
import type { Document, PayloadRequest, SanitizedGlobalConfig } from 'payload/types'
+import { restoreVersionOperationGlobal } from 'payload/operations'
import { isolateObjectProperty } from 'payload/utilities'
+
import type { Context } from '../types.js'
type Resolver = (
diff --git a/packages/graphql/src/resolvers/globals/update.ts b/packages/graphql/src/resolvers/globals/update.ts
index c0cd7b886d..1c1ed66882 100644
--- a/packages/graphql/src/resolvers/globals/update.ts
+++ b/packages/graphql/src/resolvers/globals/update.ts
@@ -1,9 +1,10 @@
-import { updateOperationGlobal } from 'payload/operations'
-import type { DeepPartial } from 'ts-essentials'
import type { GeneratedTypes } from 'payload'
import type { PayloadRequest, SanitizedGlobalConfig } from 'payload/types'
+import type { DeepPartial } from 'ts-essentials'
+import { updateOperationGlobal } from 'payload/operations'
import { isolateObjectProperty } from 'payload/utilities'
+
import type { Context } from '../types.js'
type Resolver = (
diff --git a/packages/graphql/src/resolvers/types.ts b/packages/graphql/src/resolvers/types.ts
index 42332d80f7..353067796c 100644
--- a/packages/graphql/src/resolvers/types.ts
+++ b/packages/graphql/src/resolvers/types.ts
@@ -1,8 +1,8 @@
-import { PayloadRequest } from 'payload/types'
+import type { PayloadRequest } from 'payload/types'
export type Context = {
- req: PayloadRequest
headers: {
[key: string]: string
}
+ req: PayloadRequest
}
diff --git a/packages/graphql/src/schema/buildFallbackLocaleInputType.ts b/packages/graphql/src/schema/buildFallbackLocaleInputType.ts
index ab7695b1d1..ac0168026a 100644
--- a/packages/graphql/src/schema/buildFallbackLocaleInputType.ts
+++ b/packages/graphql/src/schema/buildFallbackLocaleInputType.ts
@@ -1,7 +1,7 @@
-import { GraphQLEnumType } from 'graphql'
-
import type { SanitizedLocalizationConfig } from 'payload/config'
+import { GraphQLEnumType } from 'graphql'
+
import formatName from '../utilities/formatName.js'
const buildFallbackLocaleInputType = (
diff --git a/packages/graphql/src/schema/buildLocaleInputType.ts b/packages/graphql/src/schema/buildLocaleInputType.ts
index b799ee6663..7be6bdff93 100644
--- a/packages/graphql/src/schema/buildLocaleInputType.ts
+++ b/packages/graphql/src/schema/buildLocaleInputType.ts
@@ -1,9 +1,8 @@
import type { GraphQLScalarType } from 'graphql'
+import type { SanitizedLocalizationConfig } from 'payload/config'
import { GraphQLEnumType } from 'graphql'
-import type { SanitizedLocalizationConfig } from 'payload/config'
-
import formatName from '../utilities/formatName.js'
const buildLocaleInputType = (
diff --git a/packages/graphql/src/schema/buildMutationInputType.ts b/packages/graphql/src/schema/buildMutationInputType.ts
index a47ce5770c..619e2eaf4d 100644
--- a/packages/graphql/src/schema/buildMutationInputType.ts
+++ b/packages/graphql/src/schema/buildMutationInputType.ts
@@ -1,22 +1,7 @@
/* eslint-disable no-use-before-define */
import type { GraphQLInputFieldConfig, GraphQLScalarType, GraphQLType } from 'graphql'
-
-import {
- GraphQLBoolean,
- GraphQLEnumType,
- GraphQLFloat,
- GraphQLInputObjectType,
- GraphQLInt,
- GraphQLList,
- GraphQLNonNull,
- GraphQLString,
-} from 'graphql'
-import { GraphQLJSON } from 'graphql-type-json'
-
import type { GraphQLInfo } from 'payload/config'
import type {
- SanitizedCollectionConfig,
- SanitizedConfig,
ArrayField,
BlockField,
CheckboxField,
@@ -33,20 +18,34 @@ import type {
RelationshipField,
RichTextField,
RowField,
+ SanitizedCollectionConfig,
+ SanitizedConfig,
SelectField,
TabsField,
TextField,
TextareaField,
UploadField,
} from 'payload/types'
+
+import {
+ GraphQLBoolean,
+ GraphQLEnumType,
+ GraphQLFloat,
+ GraphQLInputObjectType,
+ GraphQLInt,
+ GraphQLList,
+ GraphQLNonNull,
+ GraphQLString,
+} from 'graphql'
+import { GraphQLJSON } from 'graphql-type-json'
import { fieldAffectsData, optionIsObject, tabHasName } from 'payload/types'
import { toWords } from 'payload/utilities'
+import { flattenTopLevelFields } from 'payload/utilities'
-import { groupOrTabHasRequiredSubfield } from '../utilities/groupOrTabHasRequiredSubfield.js'
import combineParentName from '../utilities/combineParentName.js'
import formatName from '../utilities/formatName.js'
+import { groupOrTabHasRequiredSubfield } from '../utilities/groupOrTabHasRequiredSubfield.js'
import withNullableType from './withNullableType.js'
-import { flattenTopLevelFields } from 'payload/utilities'
const idFieldTypes = {
number: GraphQLInt,
@@ -73,31 +72,31 @@ export type InputObjectTypeConfig = {
}
type BuildMutationInputTypeArgs = {
- name: string
+ config: SanitizedConfig
fields: Field[]
- parentName: string
forceNullable?: boolean
graphqlResult: GraphQLInfo
- config: SanitizedConfig
+ name: string
+ parentName: string
}
export function buildMutationInputType({
name,
+ config,
fields,
- parentName,
forceNullable = false,
graphqlResult,
- config,
+ parentName,
}: BuildMutationInputTypeArgs): GraphQLInputObjectType | null {
const fieldToSchemaMap = {
array: (inputObjectTypeConfig: InputObjectTypeConfig, field: ArrayField) => {
const fullName = combineParentName(parentName, toWords(field.name, true))
let type: GraphQLList | GraphQLType = buildMutationInputType({
name: fullName,
- fields: field.fields,
- parentName: fullName,
- graphqlResult,
config,
+ fields: field.fields,
+ graphqlResult,
+ parentName: fullName,
})
if (!type) return inputObjectTypeConfig
@@ -139,10 +138,10 @@ export function buildMutationInputType({
const fullName = combineParentName(parentName, toWords(field.name, true))
let type: GraphQLType = buildMutationInputType({
name: fullName,
- fields: field.fields,
- parentName: fullName,
- graphqlResult,
config,
+ fields: field.fields,
+ graphqlResult,
+ parentName: fullName,
})
if (!type) return inputObjectTypeConfig
@@ -271,10 +270,10 @@ export function buildMutationInputType({
const requiresAtLeastOneField = groupOrTabHasRequiredSubfield(field)
let type: GraphQLType = buildMutationInputType({
name: fullName,
- fields: tab.fields,
- parentName: fullName,
- graphqlResult,
config,
+ fields: tab.fields,
+ graphqlResult,
+ parentName: fullName,
})
if (!type) return acc
diff --git a/packages/graphql/src/schema/buildObjectType.ts b/packages/graphql/src/schema/buildObjectType.ts
index d19d78a9c9..3b334b496f 100644
--- a/packages/graphql/src/schema/buildObjectType.ts
+++ b/packages/graphql/src/schema/buildObjectType.ts
@@ -2,6 +2,32 @@
/* eslint-disable no-await-in-loop */
/* eslint-disable no-restricted-syntax */
import type { GraphQLFieldConfig, GraphQLType } from 'graphql'
+import type { GraphQLInfo } from 'payload/config'
+import type {
+ ArrayField,
+ BlockField,
+ CheckboxField,
+ CodeField,
+ CollapsibleField,
+ DateField,
+ EmailField,
+ Field,
+ GroupField,
+ JSONField,
+ NumberField,
+ PointField,
+ RadioField,
+ RelationshipField,
+ RichTextAdapter,
+ RichTextField,
+ RowField,
+ SanitizedConfig,
+ SelectField,
+ TabsField,
+ TextField,
+ TextareaField,
+ UploadField,
+} from 'payload/types'
import {
GraphQLBoolean,
@@ -17,43 +43,17 @@ import {
import { DateTimeResolver, EmailAddressResolver } from 'graphql-scalars'
/* eslint-disable no-use-before-define */
import { GraphQLJSON } from 'graphql-type-json'
-
-import type { GraphQLInfo } from 'payload/config'
-import type {
- RichTextAdapter,
- SanitizedConfig,
- ArrayField,
- BlockField,
- CheckboxField,
- CodeField,
- CollapsibleField,
- DateField,
- EmailField,
- Field,
- GroupField,
- JSONField,
- NumberField,
- PointField,
- RadioField,
- RelationshipField,
- RichTextField,
- RowField,
- SelectField,
- TabsField,
- TextField,
- TextareaField,
- UploadField,
-} from 'payload/types'
-
import { tabHasName } from 'payload/types'
import { toWords } from 'payload/utilities'
+
+import type { Context } from '../resolvers/types.js'
+
import combineParentName from '../utilities/combineParentName.js'
import formatName from '../utilities/formatName.js'
import formatOptions from '../utilities/formatOptions.js'
import buildWhereInputType from './buildWhereInputType.js'
import isFieldNullable from './isFieldNullable.js'
import withNullableType from './withNullableType.js'
-import { Context } from '../resolvers/types.js'
type LocaleInputType = {
fallbackLocale: {
@@ -73,22 +73,22 @@ export type ObjectTypeConfig = {
type Args = {
baseFields?: ObjectTypeConfig
+ config: SanitizedConfig
fields: Field[]
forceNullable?: boolean
+ graphqlResult: GraphQLInfo
name: string
parentName: string
- graphqlResult: GraphQLInfo
- config: SanitizedConfig
}
function buildObjectType({
name,
baseFields = {},
+ config,
fields,
forceNullable,
- parentName,
graphqlResult,
- config,
+ parentName,
}: Args): GraphQLObjectType {
const fieldToSchemaMap = {
array: (objectTypeConfig: ObjectTypeConfig, field: ArrayField) => {
@@ -98,11 +98,11 @@ function buildObjectType({
if (!graphqlResult.types.arrayTypes[interfaceName]) {
const objectType = buildObjectType({
name: interfaceName,
+ config,
fields: field.fields,
forceNullable: isFieldNullable(field, forceNullable),
- parentName: interfaceName,
graphqlResult,
- config,
+ parentName: interfaceName,
})
if (Object.keys(objectType.getFields()).length) {
@@ -131,6 +131,7 @@ function buildObjectType({
const objectType = buildObjectType({
name: interfaceName,
+ config,
fields: [
...block.fields,
{
@@ -139,9 +140,8 @@ function buildObjectType({
},
],
forceNullable,
- parentName: interfaceName,
graphqlResult,
- config,
+ parentName: interfaceName,
})
if (Object.keys(objectType.getFields()).length) {
@@ -206,11 +206,11 @@ function buildObjectType({
if (!graphqlResult.types.groupTypes[interfaceName]) {
const objectType = buildObjectType({
name: interfaceName,
+ config,
fields: field.fields,
forceNullable: isFieldNullable(field, forceNullable),
- parentName: interfaceName,
graphqlResult,
- config,
+ parentName: interfaceName,
})
if (Object.keys(objectType.getFields()).length) {
@@ -339,6 +339,11 @@ function buildObjectType({
}
const relationship = {
+ type: withNullableType(
+ field,
+ hasManyValues ? new GraphQLList(new GraphQLNonNull(type)) : type,
+ forceNullable,
+ ),
args: relationshipArgs,
extensions: { complexity: 10 },
async resolve(parent, args, context: Context) {
@@ -439,11 +444,6 @@ function buildObjectType({
return null
},
- type: withNullableType(
- field,
- hasManyValues ? new GraphQLList(new GraphQLNonNull(type)) : type,
- forceNullable,
- ),
}
return {
@@ -454,6 +454,7 @@ function buildObjectType({
richText: (objectTypeConfig: ObjectTypeConfig, field: RichTextField) => ({
...objectTypeConfig,
[field.name]: {
+ type: withNullableType(field, GraphQLJSON, forceNullable),
args: {
depth: {
type: GraphQLInt,
@@ -486,7 +487,6 @@ function buildObjectType({
return parent[field.name]
},
- type: withNullableType(field, GraphQLJSON, forceNullable),
},
}),
row: (objectTypeConfig: ObjectTypeConfig, field: RowField) =>
@@ -520,11 +520,11 @@ function buildObjectType({
if (!graphqlResult.types.groupTypes[interfaceName]) {
const objectType = buildObjectType({
name: interfaceName,
+ config,
fields: tab.fields,
forceNullable,
- parentName: interfaceName,
graphqlResult,
- config,
+ parentName: interfaceName,
})
if (Object.keys(objectType.getFields()).length) {
@@ -596,6 +596,7 @@ function buildObjectType({
const relatedCollectionSlug = field.relationTo
const upload = {
+ type,
args: uploadArgs,
extensions: { complexity: 20 },
async resolve(parent, args, context: Context) {
@@ -624,7 +625,6 @@ function buildObjectType({
return null
},
- type,
}
const whereFields = graphqlResult.collections[relationTo].config.fields
diff --git a/packages/graphql/src/schema/buildPoliciesType.ts b/packages/graphql/src/schema/buildPoliciesType.ts
index 770114b70b..462027d8ed 100644
--- a/packages/graphql/src/schema/buildPoliciesType.ts
+++ b/packages/graphql/src/schema/buildPoliciesType.ts
@@ -1,15 +1,16 @@
-import { GraphQLBoolean, GraphQLNonNull, GraphQLObjectType } from 'graphql'
-import { GraphQLJSONObject } from 'graphql-type-json'
import type {
CollectionConfig,
- SanitizedCollectionConfig,
Field,
GlobalConfig,
- SanitizedGlobalConfig,
+ SanitizedCollectionConfig,
SanitizedConfig,
+ SanitizedGlobalConfig,
} from 'payload/types'
+import { GraphQLBoolean, GraphQLNonNull, GraphQLObjectType } from 'graphql'
+import { GraphQLJSONObject } from 'graphql-type-json'
import { toWords } from 'payload/utilities'
+
import formatName from '../utilities/formatName.js'
type OperationType = 'create' | 'delete' | 'read' | 'readVersions' | 'unlock' | 'update'
@@ -142,8 +143,8 @@ type BuildPolicyType = {
}
)
export function buildPolicyType(args: BuildPolicyType): GraphQLObjectType {
- const { entity, scope, type, typeSuffix } = args
- const { fields, graphQL, slug, versions } = entity
+ const { type, entity, scope, typeSuffix } = args
+ const { slug, fields, graphQL, versions } = entity
let operations = []
@@ -210,8 +211,8 @@ export default function buildPoliciesType(config: SanitizedConfig): GraphQLObjec
return
}
const collectionPolicyType = buildPolicyType({
- entity: collection,
type: 'collection',
+ entity: collection,
typeSuffix: 'Access',
})
@@ -225,8 +226,8 @@ export default function buildPoliciesType(config: SanitizedConfig): GraphQLObjec
return
}
const globalPolicyType = buildPolicyType({
- entity: global,
type: 'global',
+ entity: global,
typeSuffix: 'Access',
})
diff --git a/packages/graphql/src/schema/buildWhereInputType.ts b/packages/graphql/src/schema/buildWhereInputType.ts
index 782f7e5377..fdf9595866 100644
--- a/packages/graphql/src/schema/buildWhereInputType.ts
+++ b/packages/graphql/src/schema/buildWhereInputType.ts
@@ -1,14 +1,14 @@
/* eslint-disable @typescript-eslint/no-use-before-define */
-/* eslint-disable no-use-before-define */
-import { GraphQLInputObjectType, GraphQLList } from 'graphql'
-
import type { Field, FieldAffectingData } from 'payload/types'
+/* eslint-disable no-use-before-define */
+import { GraphQLInputObjectType, GraphQLList } from 'graphql'
import { fieldAffectsData, fieldHasSubFields, fieldIsPresentationalOnly } from 'payload/types'
+import { flattenTopLevelFields } from 'payload/utilities'
+
import formatName from '../utilities/formatName.js'
import fieldToSchemaMap from './fieldToWhereInputSchemaMap.js'
import { withOperators } from './withOperators.js'
-import { flattenTopLevelFields } from 'payload/utilities'
type Args = {
fields: Field[]
diff --git a/packages/graphql/src/schema/fieldToWhereInputSchemaMap.ts b/packages/graphql/src/schema/fieldToWhereInputSchemaMap.ts
index f36b4e5caf..c92a8daf05 100644
--- a/packages/graphql/src/schema/fieldToWhereInputSchemaMap.ts
+++ b/packages/graphql/src/schema/fieldToWhereInputSchemaMap.ts
@@ -1,6 +1,3 @@
-import { GraphQLEnumType, GraphQLInputObjectType } from 'graphql'
-import GraphQLJSONImport from 'graphql-type-json'
-
import type {
ArrayField,
CheckboxField,
@@ -23,6 +20,9 @@ import type {
UploadField,
} from 'payload/types'
+import { GraphQLEnumType, GraphQLInputObjectType } from 'graphql'
+import GraphQLJSONImport from 'graphql-type-json'
+
import combineParentName from '../utilities/combineParentName.js'
import formatName from '../utilities/formatName.js'
import recursivelyBuildNestedPaths from './recursivelyBuildNestedPaths.js'
diff --git a/packages/graphql/src/schema/initCollections.ts b/packages/graphql/src/schema/initCollections.ts
index fb8ec5bdb1..8d108c4681 100644
--- a/packages/graphql/src/schema/initCollections.ts
+++ b/packages/graphql/src/schema/initCollections.ts
@@ -1,4 +1,7 @@
/* eslint-disable no-param-reassign */
+import type { GraphQLInfo } from 'payload/config'
+import type { Collection, Field, SanitizedCollectionConfig, SanitizedConfig } from 'payload/types'
+
import {
GraphQLBoolean,
GraphQLInt,
@@ -6,14 +9,12 @@ import {
GraphQLObjectType,
GraphQLString,
} from 'graphql'
-
-import { flattenTopLevelFields, formatNames, toWords } from 'payload/utilities'
import { fieldAffectsData } from 'payload/types'
+import { flattenTopLevelFields, formatNames, toWords } from 'payload/utilities'
import { buildVersionCollectionFields } from 'payload/versions'
-import type { GraphQLInfo } from 'payload/config'
-import type { Field, Collection, SanitizedCollectionConfig, SanitizedConfig } from 'payload/types'
import type { ObjectTypeConfig } from './buildObjectType.js'
+
import forgotPassword from '../resolvers/auth/forgotPassword.js'
import init from '../resolvers/auth/init.js'
import login from '../resolvers/auth/login.js'
@@ -23,12 +24,6 @@ import refresh from '../resolvers/auth/refresh.js'
import resetPassword from '../resolvers/auth/resetPassword.js'
import unlock from '../resolvers/auth/unlock.js'
import verifyEmail from '../resolvers/auth/verifyEmail.js'
-import { buildMutationInputType, getCollectionIDType } from './buildMutationInputType.js'
-import buildObjectType from './buildObjectType.js'
-import buildPaginatedListType from './buildPaginatedListType.js'
-import { buildPolicyType } from './buildPoliciesType.js'
-import buildWhereInputType from './buildWhereInputType.js'
-import formatName from '../utilities/formatName.js'
import createResolver from '../resolvers/collections/create.js'
import getDeleteResolver from '../resolvers/collections/delete.js'
import { docAccessResolver } from '../resolvers/collections/docAccess.js'
@@ -38,6 +33,12 @@ import findVersionByIDResolver from '../resolvers/collections/findVersionByID.js
import findVersionsResolver from '../resolvers/collections/findVersions.js'
import restoreVersionResolver from '../resolvers/collections/restoreVersion.js'
import updateResolver from '../resolvers/collections/update.js'
+import formatName from '../utilities/formatName.js'
+import { buildMutationInputType, getCollectionIDType } from './buildMutationInputType.js'
+import buildObjectType from './buildObjectType.js'
+import buildPaginatedListType from './buildPaginatedListType.js'
+import { buildPolicyType } from './buildPoliciesType.js'
+import buildWhereInputType from './buildWhereInputType.js'
type InitCollectionsGraphQLArgs = {
config: SanitizedConfig
@@ -101,11 +102,11 @@ function initCollectionsGraphQL({ config, graphqlResult }: InitCollectionsGraphQ
collection.graphQL.type = buildObjectType({
name: singularName,
baseFields,
+ config,
fields,
forceNullable: forceNullableObjectType,
- parentName: singularName,
graphqlResult,
- config,
+ parentName: singularName,
})
collection.graphQL.paginatedType = buildPaginatedListType(pluralName, collection.graphQL.type)
@@ -119,18 +120,18 @@ function initCollectionsGraphQL({ config, graphqlResult }: InitCollectionsGraphQ
if (collectionConfig.auth && !collectionConfig.auth.disableLocalStrategy) {
fields.push({
name: 'password',
+ type: 'text',
label: 'Password',
required: true,
- type: 'text',
})
}
const createMutationInputType = buildMutationInputType({
name: singularName,
- fields,
- parentName: singularName,
- graphqlResult,
config,
+ fields,
+ graphqlResult,
+ parentName: singularName,
})
if (createMutationInputType) {
collection.graphQL.mutationInputType = new GraphQLNonNull(createMutationInputType)
@@ -138,17 +139,18 @@ function initCollectionsGraphQL({ config, graphqlResult }: InitCollectionsGraphQ
const updateMutationInputType = buildMutationInputType({
name: `${singularName}Update`,
+ config,
fields: fields.filter((field) => !(fieldAffectsData(field) && field.name === 'id')),
- parentName: `${singularName}Update`,
forceNullable: true,
graphqlResult,
- config,
+ parentName: `${singularName}Update`,
})
if (updateMutationInputType) {
collection.graphQL.updateMutationInputType = new GraphQLNonNull(updateMutationInputType)
}
graphqlResult.Query.fields[singularName] = {
+ type: collection.graphQL.type,
args: {
id: { type: new GraphQLNonNull(idType) },
draft: { type: GraphQLBoolean },
@@ -160,10 +162,10 @@ function initCollectionsGraphQL({ config, graphqlResult }: InitCollectionsGraphQ
: {}),
},
resolve: findByIDResolver(collection),
- type: collection.graphQL.type,
}
graphqlResult.Query.fields[pluralName] = {
+ type: buildPaginatedListType(pluralName, collection.graphQL.type),
args: {
draft: { type: GraphQLBoolean },
where: { type: collection.graphQL.whereInputType },
@@ -178,23 +180,23 @@ function initCollectionsGraphQL({ config, graphqlResult }: InitCollectionsGraphQ
sort: { type: GraphQLString },
},
resolve: findResolver(collection),
- type: buildPaginatedListType(pluralName, collection.graphQL.type),
}
graphqlResult.Query.fields[`docAccess${singularName}`] = {
+ type: buildPolicyType({
+ type: 'collection',
+ entity: collectionConfig,
+ scope: 'docAccess',
+ typeSuffix: 'DocAccess',
+ }),
args: {
id: { type: new GraphQLNonNull(idType) },
},
resolve: docAccessResolver(collection),
- type: buildPolicyType({
- entity: collectionConfig,
- scope: 'docAccess',
- type: 'collection',
- typeSuffix: 'DocAccess',
- }),
}
graphqlResult.Mutation.fields[`create${singularName}`] = {
+ type: collection.graphQL.type,
args: {
...(createMutationInputType
? { data: { type: collection.graphQL.mutationInputType } }
@@ -207,10 +209,10 @@ function initCollectionsGraphQL({ config, graphqlResult }: InitCollectionsGraphQ
: {}),
},
resolve: createResolver(collection),
- type: collection.graphQL.type,
}
graphqlResult.Mutation.fields[`update${singularName}`] = {
+ type: collection.graphQL.type,
args: {
id: { type: new GraphQLNonNull(idType) },
autosave: { type: GraphQLBoolean },
@@ -225,15 +227,14 @@ function initCollectionsGraphQL({ config, graphqlResult }: InitCollectionsGraphQ
: {}),
},
resolve: updateResolver(collection),
- type: collection.graphQL.type,
}
graphqlResult.Mutation.fields[`delete${singularName}`] = {
+ type: collection.graphQL.type,
args: {
id: { type: new GraphQLNonNull(idType) },
},
resolve: getDeleteResolver(collection),
- type: collection.graphQL.type,
}
if (collectionConfig.versions) {
@@ -246,26 +247,27 @@ function initCollectionsGraphQL({ config, graphqlResult }: InitCollectionsGraphQ
},
{
name: 'createdAt',
- label: 'Created At',
type: 'date',
+ label: 'Created At',
},
{
name: 'updatedAt',
- label: 'Updated At',
type: 'date',
+ label: 'Updated At',
},
]
collection.graphQL.versionType = buildObjectType({
name: `${singularName}Version`,
+ config,
fields: versionCollectionFields,
forceNullable: forceNullableObjectType,
- parentName: `${singularName}Version`,
graphqlResult,
- config,
+ parentName: `${singularName}Version`,
})
graphqlResult.Query.fields[`version${formatName(singularName)}`] = {
+ type: collection.graphQL.versionType,
args: {
id: { type: versionIDType },
...(config.localization
@@ -276,9 +278,12 @@ function initCollectionsGraphQL({ config, graphqlResult }: InitCollectionsGraphQ
: {}),
},
resolve: findVersionByIDResolver(collection),
- type: collection.graphQL.versionType,
}
graphqlResult.Query.fields[`versions${pluralName}`] = {
+ type: buildPaginatedListType(
+ `versions${formatName(pluralName)}`,
+ collection.graphQL.versionType,
+ ),
args: {
where: {
type: buildWhereInputType({
@@ -298,17 +303,13 @@ function initCollectionsGraphQL({ config, graphqlResult }: InitCollectionsGraphQ
sort: { type: GraphQLString },
},
resolve: findVersionsResolver(collection),
- type: buildPaginatedListType(
- `versions${formatName(pluralName)}`,
- collection.graphQL.versionType,
- ),
}
graphqlResult.Mutation.fields[`restoreVersion${formatName(singularName)}`] = {
+ type: collection.graphQL.type,
args: {
id: { type: versionIDType },
},
resolve: restoreVersionResolver(collection),
- type: collection.graphQL.type,
}
}
@@ -318,28 +319,27 @@ function initCollectionsGraphQL({ config, graphqlResult }: InitCollectionsGraphQ
: [
{
name: 'email',
- required: true,
type: 'email',
+ required: true,
},
]
collection.graphQL.JWT = buildObjectType({
name: formatName(`${slug}JWT`),
+ config,
fields: [
...collectionConfig.fields.filter((field) => fieldAffectsData(field) && field.saveToJWT),
...authFields,
{
name: 'collection',
- required: true,
type: 'text',
+ required: true,
},
],
- parentName: formatName(`${slug}JWT`),
graphqlResult,
- config,
+ parentName: formatName(`${slug}JWT`),
})
graphqlResult.Query.fields[`me${singularName}`] = {
- resolve: me(collection),
type: new GraphQLObjectType({
name: formatName(`${slug}Me`),
fields: {
@@ -357,18 +357,15 @@ function initCollectionsGraphQL({ config, graphqlResult }: InitCollectionsGraphQ
},
},
}),
+ resolve: me(collection),
}
graphqlResult.Query.fields[`initialized${singularName}`] = {
- resolve: init(collection.config.slug),
type: GraphQLBoolean,
+ resolve: init(collection.config.slug),
}
graphqlResult.Mutation.fields[`refreshToken${singularName}`] = {
- args: {
- token: { type: GraphQLString },
- },
- resolve: refresh(collection),
type: new GraphQLObjectType({
name: formatName(`${slug}Refreshed${singularName}`),
fields: {
@@ -383,30 +380,29 @@ function initCollectionsGraphQL({ config, graphqlResult }: InitCollectionsGraphQ
},
},
}),
+ args: {
+ token: { type: GraphQLString },
+ },
+ resolve: refresh(collection),
}
graphqlResult.Mutation.fields[`logout${singularName}`] = {
- resolve: logout(collection),
type: GraphQLString,
+ resolve: logout(collection),
}
if (!collectionConfig.auth.disableLocalStrategy) {
if (collectionConfig.auth.maxLoginAttempts > 0) {
graphqlResult.Mutation.fields[`unlock${singularName}`] = {
+ type: new GraphQLNonNull(GraphQLBoolean),
args: {
email: { type: new GraphQLNonNull(GraphQLString) },
},
resolve: unlock(collection),
- type: new GraphQLNonNull(GraphQLBoolean),
}
}
graphqlResult.Mutation.fields[`login${singularName}`] = {
- args: {
- email: { type: GraphQLString },
- password: { type: GraphQLString },
- },
- resolve: login(collection),
type: new GraphQLObjectType({
name: formatName(`${slug}LoginResult`),
fields: {
@@ -421,24 +417,24 @@ function initCollectionsGraphQL({ config, graphqlResult }: InitCollectionsGraphQ
},
},
}),
+ args: {
+ email: { type: GraphQLString },
+ password: { type: GraphQLString },
+ },
+ resolve: login(collection),
}
graphqlResult.Mutation.fields[`forgotPassword${singularName}`] = {
+ type: new GraphQLNonNull(GraphQLBoolean),
args: {
disableEmail: { type: GraphQLBoolean },
email: { type: new GraphQLNonNull(GraphQLString) },
expiration: { type: GraphQLInt },
},
resolve: forgotPassword(collection),
- type: new GraphQLNonNull(GraphQLBoolean),
}
graphqlResult.Mutation.fields[`resetPassword${singularName}`] = {
- args: {
- password: { type: GraphQLString },
- token: { type: GraphQLString },
- },
- resolve: resetPassword(collection),
type: new GraphQLObjectType({
name: formatName(`${slug}ResetPassword`),
fields: {
@@ -446,14 +442,19 @@ function initCollectionsGraphQL({ config, graphqlResult }: InitCollectionsGraphQ
user: { type: collection.graphQL.type },
},
}),
+ args: {
+ password: { type: GraphQLString },
+ token: { type: GraphQLString },
+ },
+ resolve: resetPassword(collection),
}
graphqlResult.Mutation.fields[`verifyEmail${singularName}`] = {
+ type: GraphQLBoolean,
args: {
token: { type: GraphQLString },
},
resolve: verifyEmail(collection),
- type: GraphQLBoolean,
}
}
}
diff --git a/packages/graphql/src/schema/recursivelyBuildNestedPaths.ts b/packages/graphql/src/schema/recursivelyBuildNestedPaths.ts
index 28704c7e8a..3051efb9bb 100644
--- a/packages/graphql/src/schema/recursivelyBuildNestedPaths.ts
+++ b/packages/graphql/src/schema/recursivelyBuildNestedPaths.ts
@@ -1,6 +1,7 @@
import type { FieldWithSubFields, TabsField } from 'payload/types'
import { fieldAffectsData, fieldIsPresentationalOnly } from 'payload/types'
+
import fieldToSchemaMap from './fieldToWhereInputSchemaMap.js'
type Args = {
@@ -65,8 +66,8 @@ const recursivelyBuildNestedPaths = ({ field, nestedFieldName2, parentName }: Ar
return [
...nestedFields,
{
- key: nestedPathName,
type: fieldSchema,
+ key: nestedPathName,
},
]
}
diff --git a/packages/graphql/src/schema/withNullableType.ts b/packages/graphql/src/schema/withNullableType.ts
index 554d603c7f..a71628f79f 100644
--- a/packages/graphql/src/schema/withNullableType.ts
+++ b/packages/graphql/src/schema/withNullableType.ts
@@ -1,9 +1,8 @@
import type { GraphQLType } from 'graphql'
+import type { FieldAffectingData } from 'payload/types'
import { GraphQLNonNull } from 'graphql'
-import type { FieldAffectingData } from 'payload/types'
-
const withNullableType = (
field: FieldAffectingData,
type: GraphQLType,
diff --git a/packages/graphql/src/schema/withOperators.ts b/packages/graphql/src/schema/withOperators.ts
index 1ee9f473b3..d03bf41c1b 100644
--- a/packages/graphql/src/schema/withOperators.ts
+++ b/packages/graphql/src/schema/withOperators.ts
@@ -1,4 +1,5 @@
import type { GraphQLType } from 'graphql'
+import type { FieldAffectingData, NumberField, RadioField, SelectField } from 'payload/types'
import {
GraphQLBoolean,
@@ -11,10 +12,8 @@ import {
} from 'graphql'
import { DateTimeResolver, EmailAddressResolver } from 'graphql-scalars'
import { GraphQLJSON } from 'graphql-type-json'
-
-import type { FieldAffectingData, NumberField, RadioField, SelectField } from 'payload/types'
-
import { optionIsObject } from 'payload/types'
+
import combineParentName from '../utilities/combineParentName.js'
import formatName from '../utilities/formatName.js'
import operators from './operators.js'
@@ -38,10 +37,10 @@ type dynamicTypes = 'radio' | 'select'
const GeoJSONObject = new GraphQLInputObjectType({
name: 'GeoJSONObject',
fields: {
+ type: { type: GraphQLString },
coordinates: {
type: GraphQLJSON,
},
- type: { type: GraphQLString },
},
})
diff --git a/packages/graphql/src/utilities/wrapCustomResolver.ts b/packages/graphql/src/utilities/wrapCustomResolver.ts
index 93a915d41d..a82fd8e3f2 100644
--- a/packages/graphql/src/utilities/wrapCustomResolver.ts
+++ b/packages/graphql/src/utilities/wrapCustomResolver.ts
@@ -1,6 +1,5 @@
import type { ObjMap } from 'graphql/jsutils/ObjMap.js'
import type { GraphQLFieldConfig, GraphQLFieldResolver } from 'graphql/type/definition.js'
-
import type { PayloadRequest } from 'payload/types'
import { isolateObjectProperty } from 'payload/utilities'
diff --git a/packages/live-preview/src/ready.ts b/packages/live-preview/src/ready.ts
index 944fe93eef..a5c8c1fe2a 100644
--- a/packages/live-preview/src/ready.ts
+++ b/packages/live-preview/src/ready.ts
@@ -9,8 +9,8 @@ export const ready = (args: { serverURL: string }): void => {
windowToPostTo?.postMessage(
{
- ready: true,
type: 'payload-live-preview',
+ ready: true,
},
serverURL,
)
diff --git a/packages/next/src/routes/rest/globals/findOne.ts b/packages/next/src/routes/rest/globals/findOne.ts
index 028b3b382a..248b10b387 100644
--- a/packages/next/src/routes/rest/globals/findOne.ts
+++ b/packages/next/src/routes/rest/globals/findOne.ts
@@ -9,11 +9,11 @@ export const findOne: GlobalRouteHandler = async ({ globalConfig, req }) => {
const depth = searchParams.get('depth')
const result = await findOneOperation({
+ slug: globalConfig.slug,
depth: isNumber(depth) ? Number(depth) : undefined,
draft: searchParams.get('draft') === 'true',
globalConfig,
req,
- slug: globalConfig.slug,
})
return Response.json(result, {
diff --git a/packages/next/src/routes/rest/globals/update.ts b/packages/next/src/routes/rest/globals/update.ts
index 81365b72a4..10088530c2 100644
--- a/packages/next/src/routes/rest/globals/update.ts
+++ b/packages/next/src/routes/rest/globals/update.ts
@@ -11,13 +11,13 @@ export const update: GlobalRouteHandler = async ({ globalConfig, req }) => {
const autosave = searchParams.get('autosave') === 'true'
const result = await updateOperationGlobal({
+ slug: globalConfig.slug,
autosave,
data: req.data,
depth: isNumber(depth) ? Number(depth) : undefined,
draft,
globalConfig,
req,
- slug: globalConfig.slug,
})
let message = req.t('general:updatedSuccessfully')
diff --git a/packages/next/src/views/ForgotPassword/index.tsx b/packages/next/src/views/ForgotPassword/index.tsx
index 25686891de..89587a8209 100644
--- a/packages/next/src/views/ForgotPassword/index.tsx
+++ b/packages/next/src/views/ForgotPassword/index.tsx
@@ -1,9 +1,9 @@
+import type { AdminViewProps } from 'payload/types'
+
import { Button, Email, Form, FormSubmit, Translation } from '@payloadcms/ui'
import LinkImport from 'next/link.js'
import React, { Fragment } from 'react'
-import type { AdminViewProps } from 'payload/types'
-
export { generateForgotPasswordMetadata } from './meta.js'
const Link = (LinkImport.default || LinkImport) as unknown as typeof LinkImport.default
diff --git a/packages/next/src/views/List/index.tsx b/packages/next/src/views/List/index.tsx
index e3c407ddbd..b9c0c19264 100644
--- a/packages/next/src/views/List/index.tsx
+++ b/packages/next/src/views/List/index.tsx
@@ -1,3 +1,5 @@
+import type { AdminViewProps } from 'payload/types'
+
import {
HydrateClientUser,
ListInfoProvider,
@@ -8,7 +10,6 @@ import { notFound } from 'next/navigation.js'
import { isEntityHidden } from 'payload/utilities'
import React, { Fragment } from 'react'
-import type { AdminViewProps } from 'payload/types'
import type { DefaultListViewProps, ListPreferences } from './Default/types.js'
import { Unauthorized } from '../Unauthorized/index.js'
diff --git a/packages/next/src/views/Logout/index.tsx b/packages/next/src/views/Logout/index.tsx
index 64d2ddf7f3..3053040afb 100644
--- a/packages/next/src/views/Logout/index.tsx
+++ b/packages/next/src/views/Logout/index.tsx
@@ -1,8 +1,8 @@
+import type { AdminViewProps } from 'payload/types'
+
import { MinimalTemplate } from '@payloadcms/ui'
import React from 'react'
-import type { AdminViewProps } from 'payload/types'
-
import { LogoutClient } from './LogoutClient.js'
import './index.scss'
diff --git a/packages/next/src/views/ResetPassword/index.tsx b/packages/next/src/views/ResetPassword/index.tsx
index 8faadf5c53..81380a727e 100644
--- a/packages/next/src/views/ResetPassword/index.tsx
+++ b/packages/next/src/views/ResetPassword/index.tsx
@@ -1,3 +1,5 @@
+import type { AdminViewProps } from 'payload/types'
+
import {
Button,
ConfirmPassword,
@@ -11,8 +13,6 @@ import {
import LinkImport from 'next/link.js'
import React from 'react'
-import type { AdminViewProps } from 'payload/types'
-
import './index.scss'
export const resetPasswordBaseClass = 'reset-password'
diff --git a/packages/next/src/views/Version/Restore/types.ts b/packages/next/src/views/Version/Restore/types.ts
index 51ecf66ad6..6d3d59d62c 100644
--- a/packages/next/src/views/Version/Restore/types.ts
+++ b/packages/next/src/views/Version/Restore/types.ts
@@ -4,7 +4,7 @@ export type Props = {
className?: string
collectionSlug?: SanitizedCollectionConfig['slug']
globalSlug?: SanitizedGlobalConfig['slug']
- label: SanitizedCollectionConfig['labels']['singular'] | SanitizedGlobalConfig['label']
+ label: SanitizedCollectionConfig['labels']['singular']
originalDocID: number | string
versionDate: string
versionID: string
diff --git a/packages/payload/src/auth/operations/forgotPassword.ts b/packages/payload/src/auth/operations/forgotPassword.ts
index cafee1980b..1f6150113e 100644
--- a/packages/payload/src/auth/operations/forgotPassword.ts
+++ b/packages/payload/src/auth/operations/forgotPassword.ts
@@ -1,6 +1,6 @@
import crypto from 'crypto'
-import { URL } from 'url'
import httpStatus from 'http-status'
+import { URL } from 'url'
import type { Collection } from '../../collections/config/types.js'
import type { PayloadRequest } from '../../types/index.js'
diff --git a/packages/payload/src/auth/operations/resetPassword.ts b/packages/payload/src/auth/operations/resetPassword.ts
index 58df3d8163..7d263e2e8e 100644
--- a/packages/payload/src/auth/operations/resetPassword.ts
+++ b/packages/payload/src/auth/operations/resetPassword.ts
@@ -1,5 +1,5 @@
-import jwt from 'jsonwebtoken'
import httpStatus from 'http-status'
+import jwt from 'jsonwebtoken'
import type { Collection } from '../../collections/config/types.js'
import type { PayloadRequest } from '../../types/index.js'
diff --git a/packages/payload/src/config/load.ts b/packages/payload/src/config/load.ts
index 5d25bb8156..de31d770a5 100644
--- a/packages/payload/src/config/load.ts
+++ b/packages/payload/src/config/load.ts
@@ -1,9 +1,6 @@
-/* eslint-disable import/no-dynamic-require */
import type pino from 'pino'
-/* eslint-disable global-require */
import { createRequire } from 'module'
-// eslint-disable-next-line import/no-extraneous-dependencies
import path from 'path'
import type { SanitizedConfig } from './types.js'
diff --git a/packages/payload/src/exports/README.md b/packages/payload/src/exports/README.md
index dd73a1476c..30359f3c27 100644
--- a/packages/payload/src/exports/README.md
+++ b/packages/payload/src/exports/README.md
@@ -1,8 +1,3 @@
Important:
When you export anything with a scss or svg, or any component with a hook, it should be exported from a file within payload/components
-
-
-
-
-
diff --git a/packages/payload/src/utilities/createLocalReq.ts b/packages/payload/src/utilities/createLocalReq.ts
index a8effeb0da..07cfb10030 100644
--- a/packages/payload/src/utilities/createLocalReq.ts
+++ b/packages/payload/src/utilities/createLocalReq.ts
@@ -1,5 +1,5 @@
-import type { Payload, RequestContext } from '../index.js'
import type { User } from '../auth/types.js'
+import type { Payload, RequestContext } from '../index.js'
import type { PayloadRequest } from '../types/index.js'
import { getDataLoader } from '../collections/dataloader.js'
diff --git a/packages/payload/src/utilities/fieldSchemaToJSON.ts b/packages/payload/src/utilities/fieldSchemaToJSON.ts
index b9e068ef6c..9b8ddda66e 100644
--- a/packages/payload/src/utilities/fieldSchemaToJSON.ts
+++ b/packages/payload/src/utilities/fieldSchemaToJSON.ts
@@ -19,8 +19,8 @@ export const fieldSchemaToJSON = (fields: Field[]): FieldSchemaJSON => {
case 'group':
acc.push({
name: field.name,
- fields: fieldSchemaToJSON(field.fields),
type: field.type,
+ fields: fieldSchemaToJSON(field.fields),
})
break
@@ -28,6 +28,7 @@ export const fieldSchemaToJSON = (fields: Field[]): FieldSchemaJSON => {
case 'array':
acc.push({
name: field.name,
+ type: field.type,
fields: fieldSchemaToJSON([
...field.fields,
{
@@ -35,7 +36,6 @@ export const fieldSchemaToJSON = (fields: Field[]): FieldSchemaJSON => {
type: 'text',
},
]),
- type: field.type,
})
break
@@ -43,6 +43,7 @@ export const fieldSchemaToJSON = (fields: Field[]): FieldSchemaJSON => {
case 'blocks':
acc.push({
name: field.name,
+ type: field.type,
blocks: field.blocks.reduce((acc, block) => {
acc[block.slug] = {
fields: fieldSchemaToJSON([
@@ -56,7 +57,6 @@ export const fieldSchemaToJSON = (fields: Field[]): FieldSchemaJSON => {
return acc
}, {}),
- type: field.type,
})
break
@@ -73,8 +73,8 @@ export const fieldSchemaToJSON = (fields: Field[]): FieldSchemaJSON => {
if ('name' in tab) {
tabFields.push({
name: tab.name,
- fields: fieldSchemaToJSON(tab.fields),
type: field.type,
+ fields: fieldSchemaToJSON(tab.fields),
})
return
}
@@ -91,9 +91,9 @@ export const fieldSchemaToJSON = (fields: Field[]): FieldSchemaJSON => {
case 'upload':
acc.push({
name: field.name,
+ type: field.type,
hasMany: 'hasMany' in field ? Boolean(field.hasMany) : false, // TODO: type this
relationTo: field.relationTo,
- type: field.type,
})
break
diff --git a/packages/payload/src/utilities/getEntityPolicies.ts b/packages/payload/src/utilities/getEntityPolicies.ts
index a8df06e394..f5452cc537 100644
--- a/packages/payload/src/utilities/getEntityPolicies.ts
+++ b/packages/payload/src/utilities/getEntityPolicies.ts
@@ -30,7 +30,7 @@ type CreateAccessPromise = (args: {
}) => Promise
export async function getEntityPolicies(args: T): Promise> {
- const { id, entity, operations, req, type } = args
+ const { id, type, entity, operations, req } = args
const { data, payload, user } = req
const isLoggedIn = !!user
@@ -44,9 +44,9 @@ export async function getEntityPolicies(args: T): Promise = {
diff --git a/packages/plugin-nested-docs/src/fields/breadcrumbs.ts b/packages/plugin-nested-docs/src/fields/breadcrumbs.ts
index 862e1a3393..7eaadf38c5 100644
--- a/packages/plugin-nested-docs/src/fields/breadcrumbs.ts
+++ b/packages/plugin-nested-docs/src/fields/breadcrumbs.ts
@@ -5,8 +5,8 @@ export const createBreadcrumbsField = (
overrides: Partial = {},
): Field => ({
name: 'breadcrumbs',
- localized: true,
type: 'array',
+ localized: true,
...(overrides || {}),
admin: {
readOnly: true,
@@ -15,32 +15,32 @@ export const createBreadcrumbsField = (
fields: [
{
name: 'doc',
+ type: 'relationship',
admin: {
disabled: true,
},
maxDepth: 0,
relationTo,
- type: 'relationship',
},
{
+ type: 'row',
fields: [
{
name: 'url',
+ type: 'text',
admin: {
width: '50%',
},
label: 'URL',
- type: 'text',
},
{
name: 'label',
+ type: 'text',
admin: {
width: '50%',
},
- type: 'text',
},
],
- type: 'row',
},
...(overrides?.fields || []),
],
diff --git a/packages/plugin-nested-docs/src/fields/parent.ts b/packages/plugin-nested-docs/src/fields/parent.ts
index 32048ab32e..87086819e7 100644
--- a/packages/plugin-nested-docs/src/fields/parent.ts
+++ b/packages/plugin-nested-docs/src/fields/parent.ts
@@ -15,9 +15,9 @@ export const createParentField = (
},
// filterOptions are assigned dynamically based on the pluginConfig
// filterOptions: parentFilterOptions(),
+ type: 'relationship',
maxDepth: 1,
relationTo,
- type: 'relationship',
...(overrides || {}),
})
diff --git a/packages/plugin-sentry/src/startSentry.ts b/packages/plugin-sentry/src/startSentry.ts
index 7759124a39..fbaf726d67 100644
--- a/packages/plugin-sentry/src/startSentry.ts
+++ b/packages/plugin-sentry/src/startSentry.ts
@@ -17,7 +17,7 @@ export const startSentry = (pluginOptions: PluginOptions, payload: Payload): voi
try {
Sentry.init({
...options?.init,
- dsn: dsn,
+ dsn,
integrations: [
...(options?.init?.integrations || []),
new Sentry.Integrations.Http({ tracing: true }),
diff --git a/packages/plugin-stripe/src/fields/getFields.ts b/packages/plugin-stripe/src/fields/getFields.ts
index 80c68d645e..19c4267df3 100644
--- a/packages/plugin-stripe/src/fields/getFields.ts
+++ b/packages/plugin-stripe/src/fields/getFields.ts
@@ -15,27 +15,28 @@ interface Args {
export const getFields = ({ collection, stripeConfig, syncConfig }: Args): Field[] => {
const stripeIDField: Field = {
name: 'stripeID',
+ type: 'text',
admin: {
position: 'sidebar',
readOnly: true,
},
label: 'Stripe ID',
saveToJWT: true,
- type: 'text',
}
const skipSyncField: Field = {
name: 'skipSync',
+ type: 'checkbox',
admin: {
position: 'sidebar',
readOnly: true,
},
label: 'Skip Sync',
- type: 'checkbox',
}
const docUrlField: Field = {
name: 'docUrl',
+ type: 'ui',
admin: {
components: {
Field: (args) =>
@@ -48,7 +49,6 @@ export const getFields = ({ collection, stripeConfig, syncConfig }: Args): Field
},
position: 'sidebar',
},
- type: 'ui',
}
const fields = [...collection.fields, stripeIDField, skipSyncField, docUrlField]
diff --git a/packages/plugin-stripe/src/hooks/createNewInStripe.ts b/packages/plugin-stripe/src/hooks/createNewInStripe.ts
index d0ce9e64e1..38b62c18f1 100644
--- a/packages/plugin-stripe/src/hooks/createNewInStripe.ts
+++ b/packages/plugin-stripe/src/hooks/createNewInStripe.ts
@@ -52,15 +52,12 @@ export const createNewInStripe: CollectionBeforeValidateHookWithArgs = async (ar
if (syncConfig) {
// combine all fields of this object and match their respective values within the document
- let syncedFields = syncConfig.fields.reduce(
- (acc, field) => {
- const { fieldPath, stripeProperty } = field
+ let syncedFields = syncConfig.fields.reduce((acc, field) => {
+ const { fieldPath, stripeProperty } = field
- acc[stripeProperty] = dataRef[fieldPath]
- return acc
- },
- {} as Record,
- )
+ acc[stripeProperty] = dataRef[fieldPath]
+ return acc
+ }, {} as Record)
syncedFields = deepen(syncedFields)
@@ -75,7 +72,7 @@ export const createNewInStripe: CollectionBeforeValidateHookWithArgs = async (ar
try {
// NOTE: Typed as "any" because the "create" method is not standard across all Stripe resources
const stripeResource = await stripe?.[syncConfig.stripeResourceType]?.create(
- syncedFields as any,
+ syncedFields,
)
if (logs)
@@ -108,7 +105,7 @@ export const createNewInStripe: CollectionBeforeValidateHookWithArgs = async (ar
// NOTE: Typed as "any" because the "create" method is not standard across all Stripe resources
const stripeResource = await stripe?.[syncConfig.stripeResourceType]?.create(
- syncedFields as any,
+ syncedFields,
)
if (logs)
diff --git a/packages/plugin-stripe/src/hooks/syncExistingWithStripe.ts b/packages/plugin-stripe/src/hooks/syncExistingWithStripe.ts
index 011e10d035..6c1ec8e5c8 100644
--- a/packages/plugin-stripe/src/hooks/syncExistingWithStripe.ts
+++ b/packages/plugin-stripe/src/hooks/syncExistingWithStripe.ts
@@ -39,15 +39,12 @@ export const syncExistingWithStripe: CollectionBeforeChangeHookWithArgs = async
if (syncConfig) {
if (operation === 'update') {
// combine all fields of this object and match their respective values within the document
- let syncedFields = syncConfig.fields.reduce(
- (acc, field) => {
- const { fieldPath, stripeProperty } = field
+ let syncedFields = syncConfig.fields.reduce((acc, field) => {
+ const { fieldPath, stripeProperty } = field
- acc[stripeProperty] = data[fieldPath]
- return acc
- },
- {} as Record,
- )
+ acc[stripeProperty] = data[fieldPath]
+ return acc
+ }, {} as Record)
syncedFields = deepen(syncedFields)
diff --git a/packages/plugin-stripe/src/ui/LinkToDoc.tsx b/packages/plugin-stripe/src/ui/LinkToDoc.tsx
index da1f80f433..0652c350d5 100644
--- a/packages/plugin-stripe/src/ui/LinkToDoc.tsx
+++ b/packages/plugin-stripe/src/ui/LinkToDoc.tsx
@@ -32,7 +32,7 @@ export const LinkToDoc: React.FC<
>
View in Stripe
- {/* @ts-ignore */}
+ {/* @ts-expect-error */}
{/* */}
{
const foundDoc = payloadQuery.docs[0] as any
// combine all properties of the Stripe doc and match their respective fields within the document
- let syncedData = syncConfig.fields.reduce(
- (acc, field) => {
- const { fieldPath, stripeProperty } = field
+ let syncedData = syncConfig.fields.reduce((acc, field) => {
+ const { fieldPath, stripeProperty } = field
- acc[fieldPath] = stripeDoc[stripeProperty]
- return acc
- },
- {} as Record
,
- )
+ acc[fieldPath] = stripeDoc[stripeProperty]
+ return acc
+ }, {} as Record)
syncedData = deepen({
...syncedData,
diff --git a/packages/richtext-lexical/src/field/features/link/plugins/autoLink/index.tsx b/packages/richtext-lexical/src/field/features/link/plugins/autoLink/index.tsx
index 3b7c31efed..3855d7ba8f 100644
--- a/packages/richtext-lexical/src/field/features/link/plugins/autoLink/index.tsx
+++ b/packages/richtext-lexical/src/field/features/link/plugins/autoLink/index.tsx
@@ -423,7 +423,7 @@ const URL_REGEX =
/((https?:\/\/(www\.)?)|(www\.))[-\w@:%.+~#=]{1,256}\.[a-zA-Z\d()]{1,6}\b([-\w()@:%+.~#?&/=]*)/
const EMAIL_REGEX =
- /(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\])|(([a-zA-Z\-\d]+\.)+[a-zA-Z]{2,}))/
+ /(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\])|(([a-z\-\d]+\.)+[a-z]{2,}))/i
const MATCHERS = [
createLinkMatcherWithRegExp(URL_REGEX, (text) => {
diff --git a/packages/richtext-lexical/tsconfig.json b/packages/richtext-lexical/tsconfig.json
index 978bb548a8..26c6c2cb73 100644
--- a/packages/richtext-lexical/tsconfig.json
+++ b/packages/richtext-lexical/tsconfig.json
@@ -21,5 +21,10 @@
"src/**/*.spec.tsx"
],
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.d.ts", "src/**/*.json"],
- "references": [{ "path": "../payload" }, { "path": "../translations" }, { "path": "../ui" }, { "path": "../next" }]
+ "references": [
+ { "path": "../payload" },
+ { "path": "../translations" },
+ { "path": "../ui" },
+ { "path": "../next" }
+ ]
}
diff --git a/packages/translations/src/types.ts b/packages/translations/src/types.ts
index 6a1c5a4939..8b981f8e12 100644
--- a/packages/translations/src/types.ts
+++ b/packages/translations/src/types.ts
@@ -47,7 +47,7 @@ export type InitTFunction = (args: {
export type InitI18n = (args: {
config: I18nOptions
+ context: 'api' | 'client'
language?: string
translations: Translations
- context: 'api' | 'client'
}) => I18n
diff --git a/packages/translations/src/utilities/getTranslation.ts b/packages/translations/src/utilities/getTranslation.ts
index 8f754a6afa..b63aa759cf 100644
--- a/packages/translations/src/utilities/getTranslation.ts
+++ b/packages/translations/src/utilities/getTranslation.ts
@@ -1,5 +1,6 @@
import type { JSX } from 'react'
-import { I18n } from '../types.js'
+
+import type { I18n } from '../types.js'
export const getTranslation = (
label: JSX.Element | Record | string,
diff --git a/packages/translations/src/utilities/init.ts b/packages/translations/src/utilities/init.ts
index e27fcc571e..ba8dab4ade 100644
--- a/packages/translations/src/utilities/init.ts
+++ b/packages/translations/src/utilities/init.ts
@@ -1,4 +1,5 @@
-import { Translations, InitTFunction, InitI18n, I18n } from '../types.js'
+import type { I18n, InitI18n, InitTFunction, Translations } from '../types.js'
+
import { deepMerge } from './deepMerge.js'
/**
@@ -73,7 +74,7 @@ const replaceVars = ({
[key: string]: any
}
}) => {
- const parts = translationString.split(/({{.*?}})/)
+ const parts = translationString.split(/(\{\{.*?\}\})/)
return parts
.map((part) => {
@@ -198,7 +199,6 @@ const initTFunction: InitTFunction = (args) => {
const languagePreference = matchLanguage(language)
return {
- translations: mergedTranslations,
t: (key, vars) => {
return t({
key,
@@ -206,6 +206,7 @@ const initTFunction: InitTFunction = (args) => {
vars,
})
},
+ translations: mergedTranslations,
}
}
@@ -229,9 +230,9 @@ function memoize(fn: Function, keys: string[]) {
export const initI18n: InitI18n = memoize(
({
config,
+ context,
language = 'en',
translations: incomingTranslations,
- context,
}: Parameters[0]) => {
const { t, translations } = initTFunction({
config,
diff --git a/packages/ui/src/elements/DraggableSortable/DraggableSortableItem/types.ts b/packages/ui/src/elements/DraggableSortable/DraggableSortableItem/types.ts
index 20ba9a5b13..0425710f7f 100644
--- a/packages/ui/src/elements/DraggableSortable/DraggableSortableItem/types.ts
+++ b/packages/ui/src/elements/DraggableSortable/DraggableSortableItem/types.ts
@@ -1,5 +1,4 @@
import type { UseDraggableArguments } from '@dnd-kit/core'
-// eslint-disable-next-line import/no-unresolved
import type { SyntheticListenerMap } from '@dnd-kit/core/dist/hooks/utilities'
import type React from 'react'
diff --git a/packages/ui/src/elements/DraggableSortable/types.ts b/packages/ui/src/elements/DraggableSortable/types.ts
index d28a49a1d6..302ec1ac87 100644
--- a/packages/ui/src/elements/DraggableSortable/types.ts
+++ b/packages/ui/src/elements/DraggableSortable/types.ts
@@ -1,4 +1,3 @@
-/* eslint-disable import/no-extraneous-dependencies */
import type { DragEndEvent } from '@dnd-kit/core'
import type { Ref } from 'react'
diff --git a/packages/ui/src/elements/DraggableSortable/useDraggableSortable/types.ts b/packages/ui/src/elements/DraggableSortable/useDraggableSortable/types.ts
index 71f31779c2..0c0787cc03 100644
--- a/packages/ui/src/elements/DraggableSortable/useDraggableSortable/types.ts
+++ b/packages/ui/src/elements/DraggableSortable/useDraggableSortable/types.ts
@@ -1,4 +1,3 @@
-/* eslint-disable import/no-unresolved */
import type { SyntheticListenerMap } from '@dnd-kit/core/dist/hooks/utilities'
import type { HTMLAttributes } from 'react'
diff --git a/packages/ui/src/elements/EditUpload/index.scss b/packages/ui/src/elements/EditUpload/index.scss
index af7171f596..d526c88bc7 100644
--- a/packages/ui/src/elements/EditUpload/index.scss
+++ b/packages/ui/src/elements/EditUpload/index.scss
@@ -25,8 +25,7 @@ $header-height: base(5);
}
}
- [dir='rtl']
- &__actions {
+ [dir='rtl'] &__actions {
margin-right: auto;
margin-left: unset;
}
diff --git a/packages/ui/src/elements/Header/index.scss b/packages/ui/src/elements/Header/index.scss
index 92735d8440..f4ff2c14d1 100644
--- a/packages/ui/src/elements/Header/index.scss
+++ b/packages/ui/src/elements/Header/index.scss
@@ -12,9 +12,9 @@
// place the localizer outside the `overflow: hidden` container so that the popup is visible
// this means we need to use a placeholder div so that the space is retained in the DOM
-[dir='rtl'] &__localizer {
+ [dir='rtl'] &__localizer {
right: unset;
- left: base(4.5)
+ left: base(4.5);
}
&__localizer {
position: absolute;
diff --git a/packages/ui/src/elements/Localizer/LocalizerLabel/index.tsx b/packages/ui/src/elements/Localizer/LocalizerLabel/index.tsx
index efe40450ca..e36f0e96e5 100644
--- a/packages/ui/src/elements/Localizer/LocalizerLabel/index.tsx
+++ b/packages/ui/src/elements/Localizer/LocalizerLabel/index.tsx
@@ -24,10 +24,9 @@ export const LocalizerLabel: React.FC<{
>
{`${t('general:locale')}:`}
- {`${getTranslation(
- locale.label,
- i18n,
- )}`}
+
+ {`${getTranslation(locale.label, i18n)}`}
+
diff --git a/packages/ui/src/elements/Nav/index.tsx b/packages/ui/src/elements/Nav/index.tsx
index 9844a79f7e..1b7a9b598a 100644
--- a/packages/ui/src/elements/Nav/index.tsx
+++ b/packages/ui/src/elements/Nav/index.tsx
@@ -118,9 +118,7 @@ export const DefaultNav: React.FC<{
})}
{Array.isArray(afterNavLinks) && afterNavLinks.map((Component, i) => )}
-
+
diff --git a/packages/ui/src/elements/Popup/PopupButtonList/index.scss b/packages/ui/src/elements/Popup/PopupButtonList/index.scss
index be4d105044..7d70602a7c 100644
--- a/packages/ui/src/elements/Popup/PopupButtonList/index.scss
+++ b/packages/ui/src/elements/Popup/PopupButtonList/index.scss
@@ -6,8 +6,7 @@
flex-direction: column;
text-align: left;
gap: 3px;
- [dir='rtl']
- &__text-align--left {
+ [dir='rtl'] &__text-align--left {
text-align: right;
}
&__text-align--left {
@@ -17,15 +16,13 @@
&__text-align--center {
text-align: center;
}
- [dir='rtl']
- &__text-align--right {
+ [dir='rtl'] &__text-align--right {
text-align: left;
}
&__text-align--right {
text-align: right;
}
-
&__button {
@extend %btn-reset;
padding-left: var(--list-button-padding);
diff --git a/packages/ui/src/elements/Popup/index.scss b/packages/ui/src/elements/Popup/index.scss
index f9a4439197..c7417097b2 100644
--- a/packages/ui/src/elements/Popup/index.scss
+++ b/packages/ui/src/elements/Popup/index.scss
@@ -80,11 +80,10 @@
////////////////////////////////
// HORIZONTAL ALIGNMENT
////////////////////////////////
- [dir='rtl']
- &--h-align-left {
+ [dir='rtl'] &--h-align-left {
.popup__caret {
right: var(--popup-padding);
- left: unset
+ left: unset;
}
}
&--h-align-left {
@@ -104,16 +103,15 @@
}
}
- [dir='rtl']
- &--h-align-right {
+ [dir='rtl'] &--h-align-right {
.popup__content {
right: unset;
- left:0
+ left: 0;
}
.popup__caret {
right: unset;
- left: var(--popup-padding)
+ left: var(--popup-padding);
}
}
diff --git a/packages/ui/src/forms/Submit/index.tsx b/packages/ui/src/forms/Submit/index.tsx
index 0e1c297559..05a68fca71 100644
--- a/packages/ui/src/forms/Submit/index.tsx
+++ b/packages/ui/src/forms/Submit/index.tsx
@@ -10,7 +10,7 @@ import './index.scss'
const baseClass = 'form-submit'
const FormSubmit = forwardRef
((props, ref) => {
- const { buttonId: id, children, disabled: disabledFromProps, type = 'submit' } = props
+ const { type = 'submit', buttonId: id, children, disabled: disabledFromProps } = props
const processing = useFormProcessing()
const { disabled } = useForm()
const canSave = !(disabledFromProps || processing || disabled)
diff --git a/packages/ui/src/forms/fields/Relationship/select-components/MultiValueLabel/index.tsx b/packages/ui/src/forms/fields/Relationship/select-components/MultiValueLabel/index.tsx
index 6f1ab4d7bc..ce207b0146 100644
--- a/packages/ui/src/forms/fields/Relationship/select-components/MultiValueLabel/index.tsx
+++ b/packages/ui/src/forms/fields/Relationship/select-components/MultiValueLabel/index.tsx
@@ -19,11 +19,11 @@ export const MultiValueLabel: React.FC> = (props) => {
const {
data: { label, relationTo, value },
selectProps: {
- // @ts-ignore-next-line // TODO Fix this - moduleResolution 16 breaks our declare module
+ // @ts-expect-error-next-line // TODO Fix this - moduleResolution 16 breaks our declare module
customProps: {
- // @ts-ignore-next-line// TODO Fix this - moduleResolution 16 breaks our declare module
+ // @ts-expect-error-next-line// TODO Fix this - moduleResolution 16 breaks our declare module
draggableProps,
- // @ts-ignore-next-line // TODO Fix this - moduleResolution 16 breaks our declare module
+ // @ts-expect-error-next-line // TODO Fix this - moduleResolution 16 breaks our declare module
setDrawerIsOpen,
// onSave,
} = {},
diff --git a/packages/ui/src/forms/fields/Relationship/select-components/SingleValue/index.tsx b/packages/ui/src/forms/fields/Relationship/select-components/SingleValue/index.tsx
index c341d79c83..842b464a26 100644
--- a/packages/ui/src/forms/fields/Relationship/select-components/SingleValue/index.tsx
+++ b/packages/ui/src/forms/fields/Relationship/select-components/SingleValue/index.tsx
@@ -19,7 +19,7 @@ export const SingleValue: React.FC> = (props) => {
const {
children,
data: { label, relationTo, value },
- // @ts-ignore-next-line // TODO Fix this - moduleResolution 16 breaks our declare module
+ // @ts-expect-error-next-line // TODO Fix this - moduleResolution 16 breaks our declare module
selectProps: { customProps: { onSave, setDrawerIsOpen } = {} } = {},
} = props
diff --git a/templates/ecommerce/.eslintrc.cjs b/templates/ecommerce/.eslintrc.cjs
index 5e238e6a7f..cbb655ef53 100644
--- a/templates/ecommerce/.eslintrc.cjs
+++ b/templates/ecommerce/.eslintrc.cjs
@@ -1,6 +1,38 @@
+/** @type {import('eslint').Linter.Config} */
module.exports = {
- root: true,
extends: ['plugin:@next/next/recommended', '@payloadcms'],
ignorePatterns: ['**/payload-types.ts'],
- plugins: ['prettier'],
+ overrides: [
+ {
+ extends: ['plugin:@typescript-eslint/disable-type-checked'],
+ files: ['*.js', '*.cjs', '*.json', '*.md', '*.yml', '*.yaml'],
+ },
+ {
+ files: ['package.json', 'tsconfig.json'],
+ rules: {
+ 'perfectionist/sort-array-includes': 'off',
+ 'perfectionist/sort-astro-attributes': 'off',
+ 'perfectionist/sort-classes': 'off',
+ 'perfectionist/sort-enums': 'off',
+ 'perfectionist/sort-exports': 'off',
+ 'perfectionist/sort-imports': 'off',
+ 'perfectionist/sort-interfaces': 'off',
+ 'perfectionist/sort-jsx-props': 'off',
+ 'perfectionist/sort-keys': 'off',
+ 'perfectionist/sort-maps': 'off',
+ 'perfectionist/sort-named-exports': 'off',
+ 'perfectionist/sort-named-imports': 'off',
+ 'perfectionist/sort-object-types': 'off',
+ 'perfectionist/sort-objects': 'off',
+ 'perfectionist/sort-svelte-attributes': 'off',
+ 'perfectionist/sort-union-types': 'off',
+ 'perfectionist/sort-vue-attributes': 'off',
+ },
+ },
+ ],
+ parserOptions: {
+ project: ['./tsconfig.json'],
+ tsconfigRootDir: __dirname,
+ },
+ root: true,
}
diff --git a/templates/ecommerce/.prettierignore b/templates/ecommerce/.prettierignore
index e732bb4ea2..996b10e158 100644
--- a/templates/ecommerce/.prettierignore
+++ b/templates/ecommerce/.prettierignore
@@ -1 +1,14 @@
**/payload-types.ts
+.tmp
+**/.git
+**/.hg
+**/.pnp.*
+**/.svn
+**/.yarn/**
+**/build
+**/dist/**
+**/node_modules
+**/temp
+**/docs/**
+tsconfig.json
+
diff --git a/templates/ecommerce/.prettierrc.js b/templates/ecommerce/.prettierrc.js
deleted file mode 100644
index 61df3839e8..0000000000
--- a/templates/ecommerce/.prettierrc.js
+++ /dev/null
@@ -1,8 +0,0 @@
-module.exports = {
- printWidth: 100,
- parser: 'typescript',
- semi: false,
- singleQuote: true,
- trailingComma: 'all',
- arrowParens: 'avoid',
-}
diff --git a/templates/ecommerce/.prettierrc.json b/templates/ecommerce/.prettierrc.json
new file mode 100644
index 0000000000..cb8ee2671d
--- /dev/null
+++ b/templates/ecommerce/.prettierrc.json
@@ -0,0 +1,6 @@
+{
+ "singleQuote": true,
+ "trailingComma": "all",
+ "printWidth": 100,
+ "semi": false
+}
diff --git a/templates/ecommerce/.vscode/launch.json b/templates/ecommerce/.vscode/launch.json
index dfc04d4dc7..35316d56d8 100644
--- a/templates/ecommerce/.vscode/launch.json
+++ b/templates/ecommerce/.vscode/launch.json
@@ -8,7 +8,7 @@
"command": "yarn dev",
"name": "Debug Ecommerce",
"request": "launch",
- "type": "node-terminal",
- },
+ "type": "node-terminal"
+ }
]
}
diff --git a/templates/ecommerce/README.md b/templates/ecommerce/README.md
index a8f0b3797d..9fb2481aab 100644
--- a/templates/ecommerce/README.md
+++ b/templates/ecommerce/README.md
@@ -30,17 +30,17 @@ If you have not done so already, you need to have standalone copy of this repo o
#### Method 1 (recommended)
- Go to Payload Cloud and [clone this template](https://payloadcms.com/new/clone/ecommerce). This will create a new repository on your GitHub account with this template's code which you can then clone to your own machine.
+Go to Payload Cloud and [clone this template](https://payloadcms.com/new/clone/ecommerce). This will create a new repository on your GitHub account with this template's code which you can then clone to your own machine.
#### Method 2
- Use the `create-payload-app` CLI to clone this template directly to your machine:
+Use the `create-payload-app` CLI to clone this template directly to your machine:
npx create-payload-app@latest my-project -t ecommerce
#### Method 3
- Use the `git` CLI to clone this template directly to your machine:
+Use the `git` CLI to clone this template directly to your machine:
git clone -n --depth=1 --filter=tree:0 https://github.com/payloadcms/payload my-project && cd my-project && git sparse-checkout set --no-cone templates/ecommerce && git checkout && rm -rf .git && git init && git add . && git mv -f templates/ecommerce/{.,}* . && git add . && git commit -m "Initial commit"
@@ -59,7 +59,7 @@ The Payload config is tailored specifically to the needs of most e-commerce busi
### Collections
-See the [Collections](https://payloadcms.com/docs/configuration/collections) docs for details on how to extend this functionality.
+See the [Collections](https://payloadcms.com/docs/configuration/collections) docs for details on how to extend this functionality.
- #### Users (Authentication)
@@ -145,6 +145,7 @@ Logged-in users can have their shopping carts saved to their profiles as they sh
Payload itself handles no currency exchange. All payments are processed and billed using [Stripe](https://stripe.com). This means you must have access to a Stripe account via an API key, see [Connect Stripe](#connect-stripe) for how to get one. When you create a product in Payload that you wish to sell, it must be connected to a Stripe product by selecting one from the field in the product's sidebar, see [Products](#products) for more details. Once set, data is automatically synced between the two platforms in the following ways:
1. Stripe to Payload using [Stripe Webhooks](https://stripe.com/docs/webhooks):
+
- `product.created`
- `product.updated`
- `price.updated`
@@ -279,7 +280,7 @@ If you prefer another front-end framework or would like to use Payload as a stan
For more details on how setup a custom server, see the official [Custom Server Example](https://github.com/payloadcms/payload/tree/main/examples/custom-server).
-## Development
+## Development
To spin up this example locally, follow the [Quick Start](#quick-start). Then [Connect Stripe](#connect-stripe) to enable payments, and [Seed](#seed) the database with a few products and pages.
@@ -299,13 +300,12 @@ To seed the database with a few products and pages you can run `yarn seed`. This
> 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.
-
### Conflicting routes
->In a monorepo when routes are bootstrapped to the same host, they can conflict with Payload's own routes if they have the same name. In our template we've named the Nextjs API routes to `next` to avoid this conflict.
+> In a monorepo when routes are bootstrapped to the same host, they can conflict with Payload's own routes if they have the same name. In our template we've named the Nextjs API routes to `next` to avoid this conflict.
>
->This can happen with any other routes conflicting with Payload such as `admin` and we recommend using different names for custom routes.
->Alternatively you can also rename Payload's own routes via the [configuration](https://payloadcms.com/docs/configuration/overview).
+> This can happen with any other routes conflicting with Payload such as `admin` and we recommend using different names for custom routes.
+> Alternatively you can also rename Payload's own routes via the [configuration](https://payloadcms.com/docs/configuration/overview).
## Production
diff --git a/templates/ecommerce/csp.js b/templates/ecommerce/csp.js
index 7d1bbab108..84b18d17bd 100644
--- a/templates/ecommerce/csp.js
+++ b/templates/ecommerce/csp.js
@@ -1,5 +1,20 @@
const policies = {
+ 'child-src': ["'self'"],
+ 'connect-src': [
+ "'self'",
+ 'https://checkout.stripe.com',
+ 'https://api.stripe.com',
+ 'https://maps.googleapis.com',
+ ],
'default-src': ["'self'"],
+ 'font-src': ["'self'"],
+ 'frame-src': [
+ "'self'",
+ 'https://checkout.stripe.com',
+ 'https://js.stripe.com',
+ 'https://hooks.stripe.com',
+ ],
+ 'img-src': ["'self'", 'https://*.stripe.com', 'https://raw.githubusercontent.com'],
'script-src': [
"'self'",
"'unsafe-inline'",
@@ -8,22 +23,7 @@ const policies = {
'https://js.stripe.com',
'https://maps.googleapis.com',
],
- 'child-src': ["'self'"],
'style-src': ["'self'", "'unsafe-inline'", 'https://fonts.googleapis.com'],
- 'img-src': ["'self'", 'https://*.stripe.com', 'https://raw.githubusercontent.com'],
- 'font-src': ["'self'"],
- 'frame-src': [
- "'self'",
- 'https://checkout.stripe.com',
- 'https://js.stripe.com',
- 'https://hooks.stripe.com',
- ],
- 'connect-src': [
- "'self'",
- 'https://checkout.stripe.com',
- 'https://api.stripe.com',
- 'https://maps.googleapis.com',
- ],
}
module.exports = Object.entries(policies)
diff --git a/templates/ecommerce/eject.ts b/templates/ecommerce/eject.ts
index 2ed2a53921..f3f119dd5b 100644
--- a/templates/ecommerce/eject.ts
+++ b/templates/ecommerce/eject.ts
@@ -10,12 +10,12 @@ const files = ['./next.config.js', './next-env.d.ts', './redirects.js']
const directories = ['./src/app']
const eject = async (): Promise => {
- files.forEach(file => {
+ files.forEach((file) => {
fs.unlinkSync(path.join(__dirname, file))
})
- directories.forEach(directory => {
- fs.rm(path.join(__dirname, directory), { recursive: true }, err => {
+ directories.forEach((directory) => {
+ fs.rm(path.join(__dirname, directory), { recursive: true }, (err) => {
if (err) throw err
})
})
diff --git a/templates/ecommerce/next.config.js b/templates/ecommerce/next.config.js
index 5dbb1d046b..4f068b477a 100644
--- a/templates/ecommerce/next.config.js
+++ b/templates/ecommerce/next.config.js
@@ -3,14 +3,6 @@ const ContentSecurityPolicy = require('./csp')
const redirects = require('./redirects')
const nextConfig = {
- reactStrictMode: true,
- swcMinify: true,
- images: {
- domains: ['localhost', process.env.NEXT_PUBLIC_SERVER_URL]
- .filter(Boolean)
- .map(url => url.replace(/https?:\/\//, '')),
- },
- redirects,
async headers() {
const headers = []
@@ -34,17 +26,25 @@ const nextConfig = {
// It works by explicitly whitelisting trusted sources of content for your website
// This will block all inline scripts and styles except for those that are allowed
headers.push({
- source: '/(.*)',
headers: [
{
key: 'Content-Security-Policy',
value: ContentSecurityPolicy,
},
],
+ source: '/(.*)',
})
return headers
},
+ images: {
+ domains: ['localhost', process.env.NEXT_PUBLIC_SERVER_URL]
+ .filter(Boolean)
+ .map((url) => url.replace(/https?:\/\//, '')),
+ },
+ reactStrictMode: true,
+ redirects,
+ swcMinify: true,
}
module.exports = nextConfig
diff --git a/templates/ecommerce/nodemon.json b/templates/ecommerce/nodemon.json
index 3694a38ab5..f94c3a7eef 100644
--- a/templates/ecommerce/nodemon.json
+++ b/templates/ecommerce/nodemon.json
@@ -1,10 +1,8 @@
{
"$schema": "https://json.schemastore.org/nodemon.json",
- "watch": ["server.ts"],
"exec": "ts-node --project tsconfig.server.json src/server.ts -- -I",
"ext": "js ts",
- "ignore" : [
- "src/app"
- ],
- "stdin": false
+ "ignore": ["src/app"],
+ "stdin": false,
+ "watch": ["server.ts"]
}
diff --git a/templates/ecommerce/package.json b/templates/ecommerce/package.json
index b6c34bdb7f..49f81fa19b 100644
--- a/templates/ecommerce/package.json
+++ b/templates/ecommerce/package.json
@@ -48,26 +48,16 @@
},
"devDependencies": {
"@next/eslint-plugin-next": "^13.1.6",
- "@payloadcms/eslint-config": "^0.0.1",
+ "@payloadcms/eslint-config": "^1.1.1",
"@swc/core": "1.3.76",
"@types/escape-html": "^1.0.2",
"@types/express": "^4.17.9",
"@types/node": "18.11.3",
"@types/qs": "^6.9.8",
"@types/react": "18.0.21",
- "@typescript-eslint/eslint-plugin": "^5.51.0",
- "@typescript-eslint/parser": "^5.51.0",
"copyfiles": "^2.4.1",
- "eslint": "^8.19.0",
- "eslint-config-prettier": "^8.5.0",
- "eslint-import-resolver-alias": "^1.1.2",
- "eslint-plugin-filenames": "^1.3.2",
- "eslint-plugin-import": "2.25.4",
- "eslint-plugin-prettier": "^4.0.0",
- "eslint-plugin-react-hooks": "^4.6.0",
- "eslint-plugin-simple-import-sort": "^10.0.0",
"nodemon": "^2.0.6",
- "prettier": "^2.7.1",
+ "prettier": "^3.0.3",
"slate": "0.91.4",
"ts-node": "10.9.1",
"typescript": "^4.8.4"
diff --git a/templates/ecommerce/redirects.js b/templates/ecommerce/redirects.js
index dbb6e5e1bf..9e81b7095c 100644
--- a/templates/ecommerce/redirects.js
+++ b/templates/ecommerce/redirects.js
@@ -5,7 +5,7 @@
module.exports = async () => {
const internetExplorerRedirect = {
- source: '/:path((?!ie-incompatible.html$).*)', // all pages except the incompatibility page
+ destination: '/ie-incompatible.html',
has: [
{
type: 'header',
@@ -14,7 +14,7 @@ module.exports = async () => {
},
],
permanent: false,
- destination: '/ie-incompatible.html',
+ source: '/:path((?!ie-incompatible.html$).*)', // all pages except the incompatibility page
}
try {
@@ -28,8 +28,8 @@ module.exports = async () => {
let dynamicRedirects = []
if (docs) {
- docs.forEach(doc => {
- const { from, to: { type, url, reference } = {} } = doc
+ docs.forEach((doc) => {
+ const { from, to: { type, reference, url } = {} } = doc
let source = from
.replace(process.env.NEXT_PUBLIC_SERVER_URL, '')
@@ -55,9 +55,9 @@ module.exports = async () => {
}
const redirect = {
- source,
destination,
permanent: true,
+ source,
}
if (source.startsWith('/') && destination && source !== destination) {
diff --git a/templates/ecommerce/src/app/(pages)/[slug]/page.tsx b/templates/ecommerce/src/app/(pages)/[slug]/page.tsx
index c44435d45b..97ce360bf9 100644
--- a/templates/ecommerce/src/app/(pages)/[slug]/page.tsx
+++ b/templates/ecommerce/src/app/(pages)/[slug]/page.tsx
@@ -1,9 +1,11 @@
-import React from 'react'
-import { Metadata } from 'next'
+import type { Metadata } from 'next'
+
import { draftMode } from 'next/headers'
import { notFound } from 'next/navigation'
+import React from 'react'
+
+import type { Page } from '../../../payload/payload-types'
-import { Page } from '../../../payload/payload-types'
import { staticHome } from '../../../payload/seed/home-static'
import { fetchDoc } from '../../_api/fetchDoc'
import { fetchDocs } from '../../_api/fetchDocs'
@@ -26,8 +28,8 @@ export default async function Page({ params: { slug = 'home' } }) {
try {
page = await fetchDoc({
- collection: 'pages',
slug,
+ collection: 'pages',
draft: isDraftMode,
})
} catch (error) {
@@ -77,8 +79,8 @@ export async function generateMetadata({ params: { slug = 'home' } }): Promise({
- collection: 'pages',
slug,
+ collection: 'pages',
draft: isDraftMode,
})
} catch (error) {
diff --git a/templates/ecommerce/src/app/(pages)/account/AccountForm/index.module.scss b/templates/ecommerce/src/app/(pages)/account/AccountForm/index.module.scss
index c8a66e0946..9798e6489c 100644
--- a/templates/ecommerce/src/app/(pages)/account/AccountForm/index.module.scss
+++ b/templates/ecommerce/src/app/(pages)/account/AccountForm/index.module.scss
@@ -1,4 +1,4 @@
-@import "../../../_css/common";
+@import '../../../_css/common';
.form {
margin-bottom: var(--base);
diff --git a/templates/ecommerce/src/app/(pages)/account/AccountForm/index.tsx b/templates/ecommerce/src/app/(pages)/account/AccountForm/index.tsx
index fa247719cc..95c7783c5c 100644
--- a/templates/ecommerce/src/app/(pages)/account/AccountForm/index.tsx
+++ b/templates/ecommerce/src/app/(pages)/account/AccountForm/index.tsx
@@ -1,14 +1,13 @@
'use client'
+import { useRouter } from 'next/navigation'
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 = {
@@ -21,13 +20,13 @@ type FormData = {
const AccountForm: React.FC = () => {
const [error, setError] = useState('')
const [success, setSuccess] = useState('')
- const { user, setUser } = useAuth()
+ const { setUser, user } = useAuth()
const [changePassword, setChangePassword] = useState(false)
const {
- register,
- handleSubmit,
formState: { errors, isLoading },
+ handleSubmit,
+ register,
reset,
watch,
} = useForm()
@@ -42,12 +41,12 @@ const AccountForm: React.FC = () => {
if (user) {
const response = await fetch(`${process.env.NEXT_PUBLIC_SERVER_URL}/api/users/${user.id}`, {
// Make sure to include cookies with fetch
- credentials: 'include',
- method: 'PATCH',
body: JSON.stringify(data),
+ credentials: 'include',
headers: {
'Content-Type': 'application/json',
},
+ method: 'PATCH',
})
if (response.ok) {
@@ -57,8 +56,8 @@ const AccountForm: React.FC = () => {
setError('')
setChangePassword(false)
reset({
- email: json.doc.email,
name: json.doc.name,
+ email: json.doc.email,
password: '',
passwordConfirm: '',
})
@@ -82,8 +81,8 @@ const AccountForm: React.FC = () => {
// Once user is loaded, reset form to have default values
if (user) {
reset({
- email: user.email,
name: user.name,
+ email: user.email,
password: '',
passwordConfirm: '',
})
@@ -91,69 +90,69 @@ const AccountForm: React.FC = () => {
}, [user, router, reset, changePassword])
return (
-
)
diff --git a/templates/ecommerce/src/app/(pages)/account/page.tsx b/templates/ecommerce/src/app/(pages)/account/page.tsx
index 61da7e08dd..844e400bce 100644
--- a/templates/ecommerce/src/app/(pages)/account/page.tsx
+++ b/templates/ecommerce/src/app/(pages)/account/page.tsx
@@ -1,6 +1,7 @@
-import React, { Fragment } from 'react'
-import { Metadata } from 'next'
+import type { Metadata } from 'next'
+
import Link from 'next/link'
+import React, { Fragment } from 'react'
import { Button } from '../../_components/Button'
import { Gutter } from '../../_components/Gutter'
@@ -10,7 +11,6 @@ import { LowImpactHero } from '../../_heros/LowImpact'
import { getMeUser } from '../../_utilities/getMeUser'
import { mergeOpenGraph } from '../../_utilities/mergeOpenGraph'
import AccountForm from './AccountForm'
-
import classes from './index.module.scss'
export default async function Account() {
@@ -26,7 +26,6 @@ export default async function Account() {
@@ -70,7 +70,7 @@ export default async function Account() {
{user?.purchases?.map((purchase, index) => {
return (
-
+
{typeof purchase === 'string' ? (
{purchase}
) : (
@@ -93,23 +93,23 @@ export default async function Account() {
intent. As you order products, they will appear in your "purchased products" list.
-
+
)
}
export const metadata: Metadata = {
- title: 'Account',
description: 'Create an account or log in to your existing account.',
openGraph: mergeOpenGraph({
title: 'Account',
url: '/account',
}),
+ title: 'Account',
}
diff --git a/templates/ecommerce/src/app/(pages)/cart/CartPage/index.module.scss b/templates/ecommerce/src/app/(pages)/cart/CartPage/index.module.scss
index 33916abf64..3e1a0e70b5 100644
--- a/templates/ecommerce/src/app/(pages)/cart/CartPage/index.module.scss
+++ b/templates/ecommerce/src/app/(pages)/cart/CartPage/index.module.scss
@@ -31,7 +31,7 @@
color: var(--theme-warning-500);
}
-:global([data-theme="light"]) {
+:global([data-theme='light']) {
.warning {
color: var(--theme-error-500);
}
@@ -91,7 +91,7 @@
padding: calc(var(--base) * 0.25) calc(var(--base) * 0.25);
}
-:global([data-theme="dark"]) {
+:global([data-theme='dark']) {
.quantity {
background-color: var(--theme-elevation-150);
}
diff --git a/templates/ecommerce/src/app/(pages)/cart/CartPage/index.tsx b/templates/ecommerce/src/app/(pages)/cart/CartPage/index.tsx
index 602fcd29cd..d86282a22c 100644
--- a/templates/ecommerce/src/app/(pages)/cart/CartPage/index.tsx
+++ b/templates/ecommerce/src/app/(pages)/cart/CartPage/index.tsx
@@ -1,9 +1,10 @@
'use client'
-import React, { Fragment } from 'react'
import Link from 'next/link'
+import React, { Fragment } from 'react'
+
+import type { Page, Settings } from '../../../../payload/payload-types'
-import { Page, Settings } from '../../../../payload/payload-types'
import { Button } from '../../../_components/Button'
import { HR } from '../../../_components/HR'
import { LoadingShimmer } from '../../../_components/LoadingShimmer'
@@ -12,19 +13,18 @@ import { Price } from '../../../_components/Price'
import { RemoveFromCartButton } from '../../../_components/RemoveFromCartButton'
import { useAuth } from '../../../_providers/Auth'
import { useCart } from '../../../_providers/Cart'
-
import classes from './index.module.scss'
export const CartPage: React.FC<{
- settings: Settings
page: Page
-}> = props => {
+ settings: Settings
+}> = (props) => {
const { settings } = props
const { productsPage } = settings || {}
const { user } = useAuth()
- const { cart, cartIsEmpty, addItemToCart, cartTotal, hasInitializedCart } = useCart()
+ const { addItemToCart, cart, cartIsEmpty, cartTotal, hasInitializedCart } = useCart()
return (
@@ -48,7 +48,7 @@ export const CartPage: React.FC<{
{!user && (
{' '}
- Log in
+ Log in
{` to view a saved cart.`}
)}
@@ -62,7 +62,7 @@ export const CartPage: React.FC<{
{!user && (
{' '}
- Log in
+ Log in
{` to save your progress.`}
)}
@@ -70,9 +70,9 @@ export const CartPage: React.FC<{
{cart?.items?.map((item, index) => {
if (typeof item.product === 'object') {
const {
- quantity,
product,
- product: { id, title, meta, stripeProductID },
+ product: { id, meta, stripeProductID, title },
+ quantity,
} = item
const isLast = index === (cart?.items?.length || 0) - 1
@@ -82,14 +82,14 @@ export const CartPage: React.FC<{
return (
-
+
{!metaImage && No image }
{metaImage && typeof metaImage !== 'string' && (
)}
@@ -104,11 +104,11 @@ export const CartPage: React.FC<{
>
edit this product in the admin panel
- {'.'}
+ .
)}
-
+
{title}
@@ -116,22 +116,22 @@ export const CartPage: React.FC<{
Quantity
{
+ onChange={(e) => {
addItemToCart({
product,
quantity: Number(e.target.value),
})
}}
+ // fallback to empty string to avoid uncontrolled input error
+ type="number"
+ // this allows the user to user their backspace key to clear the input
+ value={typeof quantity === 'number' ? quantity : ''}
/>
-
+
{!isLast && }
@@ -143,10 +143,10 @@ export const CartPage: React.FC<{
{`Total: ${cartTotal.formatted}`}
)}
diff --git a/templates/ecommerce/src/app/(pages)/cart/page.tsx b/templates/ecommerce/src/app/(pages)/cart/page.tsx
index 8c0777f8d3..2330240802 100644
--- a/templates/ecommerce/src/app/(pages)/cart/page.tsx
+++ b/templates/ecommerce/src/app/(pages)/cart/page.tsx
@@ -1,8 +1,10 @@
-import React, { Fragment } from 'react'
-import { Metadata } from 'next'
-import { notFound } from 'next/navigation'
+import type { Metadata } from 'next'
+
+import { notFound } from 'next/navigation'
+import React, { Fragment } from 'react'
+
+import type { Page, Settings } from '../../../payload/payload-types'
-import { Page, Settings } from '../../../payload/payload-types'
import { staticCart } from '../../../payload/seed/cart-static'
import { fetchDoc } from '../../_api/fetchDoc'
import { fetchSettings } from '../../_api/fetchGlobals'
@@ -12,7 +14,6 @@ import { Hero } from '../../_components/Hero'
import { Message } from '../../_components/Message'
import { generateMeta } from '../../_utilities/generateMeta'
import { CartPage } from './CartPage'
-
import classes from './index.module.scss'
// Force this page to be dynamic so that Next.js does not cache it
@@ -24,8 +25,8 @@ export default async function Cart() {
try {
page = await fetchDoc({
- collection: 'pages',
slug: 'cart',
+ collection: 'pages',
})
} catch (error) {
// when deploying this template on Payload Cloud, this page needs to build before the APIs are live
@@ -67,18 +68,18 @@ export default async function Cart() {
{'To enable checkout, you must '}
- {'obtain your Stripe API Keys'}
+ obtain your Stripe API Keys
{' then set them as environment variables. See the '}
- {'README'}
+ README
{' for more details.'}
@@ -88,7 +89,7 @@ export default async function Cart() {
)}
-
+
@@ -100,8 +101,8 @@ export async function generateMetadata(): Promise {
try {
page = await fetchDoc({
- collection: 'pages',
slug: 'cart',
+ collection: 'pages',
})
} catch (error) {
// don't throw an error if the fetch fails
diff --git a/templates/ecommerce/src/app/(pages)/checkout/CheckoutForm/index.module.scss b/templates/ecommerce/src/app/(pages)/checkout/CheckoutForm/index.module.scss
index 54a3ab1d73..b4f0a82fce 100644
--- a/templates/ecommerce/src/app/(pages)/checkout/CheckoutForm/index.module.scss
+++ b/templates/ecommerce/src/app/(pages)/checkout/CheckoutForm/index.module.scss
@@ -1,4 +1,4 @@
-@import "../../../_css/common";
+@import '../../../_css/common';
.form {
display: flex;
diff --git a/templates/ecommerce/src/app/(pages)/checkout/CheckoutForm/index.tsx b/templates/ecommerce/src/app/(pages)/checkout/CheckoutForm/index.tsx
index 3baea340f7..00ceba3df1 100644
--- a/templates/ecommerce/src/app/(pages)/checkout/CheckoutForm/index.tsx
+++ b/templates/ecommerce/src/app/(pages)/checkout/CheckoutForm/index.tsx
@@ -1,37 +1,37 @@
'use client'
-import React, { useCallback } from 'react'
import { PaymentElement, useElements, useStripe } from '@stripe/react-stripe-js'
import { useRouter } from 'next/navigation'
+import React, { useCallback } from 'react'
+
+import type { Order } from '../../../../payload/payload-types'
-import { Order } from '../../../../payload/payload-types'
import { Button } from '../../../_components/Button'
import { Message } from '../../../_components/Message'
import { priceFromJSON } from '../../../_components/Price'
import { useCart } from '../../../_providers/Cart'
-
import classes from './index.module.scss'
export const CheckoutForm: React.FC<{}> = () => {
const stripe = useStripe()
const elements = useElements()
- const [error, setError] = React.useState(null)
+ const [error, setError] = React.useState(null)
const [isLoading, setIsLoading] = React.useState(false)
const router = useRouter()
const { cart, cartTotal } = useCart()
const handleSubmit = useCallback(
- async e => {
+ async (e) => {
e.preventDefault()
setIsLoading(true)
try {
const { error: stripeError, paymentIntent } = await stripe?.confirmPayment({
- elements: elements!,
- redirect: 'if_required',
confirmParams: {
return_url: `${process.env.NEXT_PUBLIC_SERVER_URL}/order-confirmation`,
},
+ elements,
+ redirect: 'if_required',
})
if (stripeError) {
@@ -46,34 +46,34 @@ export const CheckoutForm: React.FC<{}> = () => {
// Instead, we clear the cart in an `afterChange` hook on the `orders` collection in Payload
try {
const orderReq = await fetch(`${process.env.NEXT_PUBLIC_SERVER_URL}/api/orders`, {
- method: 'POST',
- credentials: 'include',
- headers: {
- 'Content-Type': 'application/json',
- },
body: JSON.stringify({
- total: cartTotal.raw,
- stripePaymentIntentID: paymentIntent.id,
items: (cart?.items || [])?.map(({ product, quantity }) => ({
- product: typeof product === 'string' ? product : product.id,
- quantity,
price:
typeof product === 'object'
? priceFromJSON(product.priceJSON, 1, true)
: undefined,
+ product: typeof product === 'string' ? product : product.id,
+ quantity,
})),
+ stripePaymentIntentID: paymentIntent.id,
+ total: cartTotal.raw,
}),
+ credentials: 'include',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ method: 'POST',
})
if (!orderReq.ok) throw new Error(orderReq.statusText || 'Something went wrong.')
const {
- error: errorFromRes,
doc,
+ error: errorFromRes,
}: {
- message?: string
- error?: string
doc: Order
+ error?: string
+ message?: string
} = await orderReq.json()
if (errorFromRes) throw new Error(errorFromRes)
@@ -96,16 +96,16 @@ export const CheckoutForm: React.FC<{}> = () => {
)
return (
-
diff --git a/templates/ecommerce/src/app/(pages)/checkout/CheckoutPage/index.module.scss b/templates/ecommerce/src/app/(pages)/checkout/CheckoutPage/index.module.scss
index 99d77955bb..19ad2ebb5f 100644
--- a/templates/ecommerce/src/app/(pages)/checkout/CheckoutPage/index.module.scss
+++ b/templates/ecommerce/src/app/(pages)/checkout/CheckoutPage/index.module.scss
@@ -1,4 +1,4 @@
-@import "../../../_css/common";
+@import '../../../_css/common';
.items {
margin-bottom: var(--base);
@@ -27,7 +27,7 @@
color: var(--theme-warning-500);
}
-:global([data-theme="light"]) {
+:global([data-theme='light']) {
.warning {
color: var(--theme-error-500);
}
diff --git a/templates/ecommerce/src/app/(pages)/checkout/CheckoutPage/index.tsx b/templates/ecommerce/src/app/(pages)/checkout/CheckoutPage/index.tsx
index 50b4026ab1..994b2b7555 100644
--- a/templates/ecommerce/src/app/(pages)/checkout/CheckoutPage/index.tsx
+++ b/templates/ecommerce/src/app/(pages)/checkout/CheckoutPage/index.tsx
@@ -1,12 +1,13 @@
'use client'
-import React, { Fragment, useEffect } from 'react'
import { Elements } from '@stripe/react-stripe-js'
import { loadStripe } from '@stripe/stripe-js'
import Link from 'next/link'
import { useRouter } from 'next/navigation'
+import React, { Fragment, useEffect } from 'react'
+
+import type { Settings } from '../../../../payload/payload-types'
-import { Settings } from '../../../../payload/payload-types'
import { Button } from '../../../_components/Button'
import { HR } from '../../../_components/HR'
import { LoadingShimmer } from '../../../_components/LoadingShimmer'
@@ -17,7 +18,6 @@ import { useCart } from '../../../_providers/Cart'
import { useTheme } from '../../../_providers/Theme'
import cssVariables from '../../../cssVariables'
import { CheckoutForm } from '../CheckoutForm'
-
import classes from './index.module.scss'
const apiKey = `${process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY}`
@@ -25,14 +25,14 @@ const stripe = loadStripe(apiKey)
export const CheckoutPage: React.FC<{
settings: Settings
-}> = props => {
+}> = (props) => {
const {
settings: { productsPage },
} = props
const { user } = useAuth()
const router = useRouter()
- const [error, setError] = React.useState(null)
+ const [error, setError] = React.useState(null)
const [clientSecret, setClientSecret] = React.useState()
const hasMadePaymentIntent = React.useRef(false)
const { theme } = useTheme()
@@ -54,8 +54,8 @@ export const CheckoutPage: React.FC<{
const paymentReq = await fetch(
`${process.env.NEXT_PUBLIC_SERVER_URL}/api/create-payment-intent`,
{
- method: 'POST',
credentials: 'include',
+ method: 'POST',
},
)
@@ -98,9 +98,9 @@ export const CheckoutPage: React.FC<{
{cart?.items?.map((item, index) => {
if (typeof item.product === 'object') {
const {
- quantity,
product,
- product: { id, stripeProductID, title, meta },
+ product: { id, meta, stripeProductID, title },
+ quantity,
} = item
if (!quantity) return null
@@ -117,9 +117,9 @@ export const CheckoutPage: React.FC<{
{metaImage && typeof metaImage !== 'string' && (
)}
@@ -132,11 +132,11 @@ export const CheckoutPage: React.FC<{
>
edit this product in the admin panel
- {'.'}
+ .
)}
{title}
-
+
{!isLast && }
@@ -156,36 +156,36 @@ export const CheckoutPage: React.FC<{
{!clientSecret && error && (
)}
{clientSecret && (
{error && {`Error: ${error}`}
}
diff --git a/templates/ecommerce/src/app/(pages)/checkout/index.module.scss b/templates/ecommerce/src/app/(pages)/checkout/index.module.scss
index 76f117695c..251e344050 100644
--- a/templates/ecommerce/src/app/(pages)/checkout/index.module.scss
+++ b/templates/ecommerce/src/app/(pages)/checkout/index.module.scss
@@ -1,4 +1,4 @@
-@import "../../_css/common";
+@import '../../_css/common';
.checkoutPage {
margin-bottom: var(--block-padding);
diff --git a/templates/ecommerce/src/app/(pages)/checkout/page.tsx b/templates/ecommerce/src/app/(pages)/checkout/page.tsx
index d57c04d0be..64559f9492 100644
--- a/templates/ecommerce/src/app/(pages)/checkout/page.tsx
+++ b/templates/ecommerce/src/app/(pages)/checkout/page.tsx
@@ -1,7 +1,9 @@
-import React, { Fragment } from 'react'
-import { Metadata } from 'next'
+import type { Metadata } from 'next'
+
+import React, { Fragment } from 'react'
+
+import type { Settings } from '../../../payload/payload-types'
-import { Settings } from '../../../payload/payload-types'
import { fetchSettings } from '../../_api/fetchGlobals'
import { Gutter } from '../../_components/Gutter'
import { Message } from '../../_components/Message'
@@ -9,7 +11,6 @@ import { LowImpactHero } from '../../_heros/LowImpact'
import { getMeUser } from '../../_utilities/getMeUser'
import { mergeOpenGraph } from '../../_utilities/mergeOpenGraph'
import { CheckoutPage } from './CheckoutPage'
-
import classes from './index.module.scss'
export default async function Checkout() {
@@ -39,18 +40,18 @@ export default async function Checkout() {
{'To enable checkout, you must '}
- {'obtain your Stripe API Keys'}
+ obtain your Stripe API Keys
{' then set them as environment variables. See the '}
- {'README'}
+ README
{' for more details.'}
@@ -59,7 +60,6 @@ export default async function Checkout() {
)}
@@ -107,10 +108,10 @@ export default async function Checkout() {
}
export const metadata: Metadata = {
- title: 'Account',
description: 'Create an account or log in to your existing account.',
openGraph: mergeOpenGraph({
title: 'Account',
url: '/account',
}),
+ title: 'Account',
}
diff --git a/templates/ecommerce/src/app/(pages)/create-account/CreateAccountForm/index.module.scss b/templates/ecommerce/src/app/(pages)/create-account/CreateAccountForm/index.module.scss
index d2fcd65bf7..021dd51e27 100644
--- a/templates/ecommerce/src/app/(pages)/create-account/CreateAccountForm/index.module.scss
+++ b/templates/ecommerce/src/app/(pages)/create-account/CreateAccountForm/index.module.scss
@@ -1,4 +1,4 @@
-@import "../../../_css/common";
+@import '../../../_css/common';
.form {
margin-bottom: var(--base);
diff --git a/templates/ecommerce/src/app/(pages)/create-account/CreateAccountForm/index.tsx b/templates/ecommerce/src/app/(pages)/create-account/CreateAccountForm/index.tsx
index b61cf4e817..c6c0fdc6fd 100644
--- a/templates/ecommerce/src/app/(pages)/create-account/CreateAccountForm/index.tsx
+++ b/templates/ecommerce/src/app/(pages)/create-account/CreateAccountForm/index.tsx
@@ -1,15 +1,14 @@
'use client'
-import React, { useCallback, useRef, useState } from 'react'
-import { useForm } from 'react-hook-form'
import Link from 'next/link'
import { useRouter, useSearchParams } from 'next/navigation'
+import React, { useCallback, useRef, useState } from 'react'
+import { useForm } from 'react-hook-form'
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 = {
@@ -24,12 +23,12 @@ const CreateAccountForm: React.FC = () => {
const { login } = useAuth()
const router = useRouter()
const [loading, setLoading] = useState(false)
- const [error, setError] = useState(null)
+ const [error, setError] = useState(null)
const {
- register,
- handleSubmit,
formState: { errors },
+ handleSubmit,
+ register,
watch,
} = useForm()
@@ -39,11 +38,11 @@ const CreateAccountForm: React.FC = () => {
const onSubmit = useCallback(
async (data: FormData) => {
const response = await fetch(`${process.env.NEXT_PUBLIC_SERVER_URL}/api/users`, {
- method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json',
},
+ method: 'POST',
})
if (!response.ok) {
@@ -61,7 +60,7 @@ const CreateAccountForm: React.FC = () => {
try {
await login(data)
clearTimeout(timer)
- if (redirect) router.push(redirect as string)
+ if (redirect) router.push(redirect)
else router.push(`/account?success=${encodeURIComponent('Account created successfully')}`)
} catch (_) {
clearTimeout(timer)
@@ -72,44 +71,43 @@ const CreateAccountForm: React.FC = () => {
)
return (
-
)
@@ -132,11 +133,11 @@ export default async function Order({ params: { id } }) {
export async function generateMetadata({ params: { id } }): Promise {
return {
- title: `Order ${id}`,
description: `Order details for order ${id}.`,
openGraph: mergeOpenGraph({
title: `Order ${id}`,
url: `/orders/${id}`,
}),
+ title: `Order ${id}`,
}
}
diff --git a/templates/ecommerce/src/app/(pages)/orders/page.tsx b/templates/ecommerce/src/app/(pages)/orders/page.tsx
index 75a261d75c..8b0dae3e15 100644
--- a/templates/ecommerce/src/app/(pages)/orders/page.tsx
+++ b/templates/ecommerce/src/app/(pages)/orders/page.tsx
@@ -1,9 +1,11 @@
-import React from 'react'
-import { Metadata } from 'next'
+import type { Metadata } from 'next'
+
import Link from 'next/link'
import { notFound } from 'next/navigation'
+import React from 'react'
+
+import type { Order } from '../../../payload/payload-types'
-import { Order } from '../../../payload/payload-types'
import { Button } from '../../_components/Button'
import { Gutter } from '../../_components/Gutter'
import { HR } from '../../_components/HR'
@@ -11,7 +13,6 @@ import { RenderParams } from '../../_components/RenderParams'
import { formatDateTime } from '../../_utilities/formatDateTime'
import { getMeUser } from '../../_utilities/getMeUser'
import { mergeOpenGraph } from '../../_utilities/mergeOpenGraph'
-
import classes from './index.module.scss'
export default async function Orders() {
@@ -25,20 +26,20 @@ export default async function Orders() {
try {
orders = await fetch(`${process.env.NEXT_PUBLIC_SERVER_URL}/api/orders`, {
- headers: {
- 'Content-Type': 'application/json',
- Authorization: `JWT ${token}`,
- },
cache: 'no-store',
+ headers: {
+ Authorization: `JWT ${token}`,
+ 'Content-Type': 'application/json',
+ },
})
- ?.then(async res => {
+ ?.then(async (res) => {
if (!res.ok) notFound()
const json = await res.json()
if ('error' in json && json.error) notFound()
if ('errors' in json && json.errors) notFound()
return json
})
- ?.then(json => json.docs)
+ ?.then((json) => json.docs)
} catch (error) {
// when deploying this template on Payload Cloud, this page needs to build before the APIs are live
// so swallow the error here and simply render the page with fallback data where necessary
@@ -56,7 +57,7 @@ export default async function Orders() {
{orders && orders.length > 0 && (
{orders?.map((order, index) => (
-
+
{`Order ${order.id}`}
@@ -65,17 +66,17 @@ export default async function Orders() {
{'Total: '}
{new Intl.NumberFormat('en-US', {
- style: 'currency',
currency: 'usd',
+ style: 'currency',
}).format(order.total / 100)}
{index !== orders.length - 1 && }
@@ -84,16 +85,16 @@ export default async function Orders() {
)}
-
+
)
}
export const metadata: Metadata = {
- title: 'Orders',
description: 'Your orders.',
openGraph: mergeOpenGraph({
title: 'Orders',
url: '/orders',
}),
+ title: 'Orders',
}
diff --git a/templates/ecommerce/src/app/(pages)/products/[slug]/page.tsx b/templates/ecommerce/src/app/(pages)/products/[slug]/page.tsx
index 6705ec5bf7..ccaee00b84 100644
--- a/templates/ecommerce/src/app/(pages)/products/[slug]/page.tsx
+++ b/templates/ecommerce/src/app/(pages)/products/[slug]/page.tsx
@@ -1,9 +1,11 @@
-import React from 'react'
-import { Metadata } from 'next'
+import type { Metadata } from 'next'
+
import { draftMode } from 'next/headers'
import { notFound } from 'next/navigation'
+import React from 'react'
+
+import type { Product, Product as ProductType } from '../../../../payload/payload-types'
-import { Product, Product as ProductType } from '../../../../payload/payload-types'
import { fetchDoc } from '../../../_api/fetchDoc'
import { fetchDocs } from '../../../_api/fetchDocs'
import { Blocks } from '../../../_components/Blocks'
@@ -22,8 +24,8 @@ export default async function Product({ params: { slug } }) {
try {
product = await fetchDoc({
- collection: 'products',
slug,
+ collection: 'products',
draft: isDraftMode,
})
} catch (error) {
@@ -40,14 +42,13 @@ export default async function Product({ params: { slug } }) {
- {product?.enablePaywall && }
+ {product?.enablePaywall && }
)
@@ -102,8 +104,8 @@ export async function generateMetadata({ params: { slug } }): Promise
try {
product = await fetchDoc({
- collection: 'products',
slug,
+ collection: 'products',
draft: isDraftMode,
})
} catch (error) {}
diff --git a/templates/ecommerce/src/app/(pages)/recover-password/RecoverPasswordForm/index.module.scss b/templates/ecommerce/src/app/(pages)/recover-password/RecoverPasswordForm/index.module.scss
index a4b66d32f0..972924205c 100644
--- a/templates/ecommerce/src/app/(pages)/recover-password/RecoverPasswordForm/index.module.scss
+++ b/templates/ecommerce/src/app/(pages)/recover-password/RecoverPasswordForm/index.module.scss
@@ -1,4 +1,4 @@
-@import "../../../_css/common";
+@import '../../../_css/common';
.error {
color: red;
@@ -20,4 +20,3 @@
.message {
margin-bottom: var(--base);
}
-
diff --git a/templates/ecommerce/src/app/(pages)/recover-password/RecoverPasswordForm/index.tsx b/templates/ecommerce/src/app/(pages)/recover-password/RecoverPasswordForm/index.tsx
index 7329b88215..88f99bdac6 100644
--- a/templates/ecommerce/src/app/(pages)/recover-password/RecoverPasswordForm/index.tsx
+++ b/templates/ecommerce/src/app/(pages)/recover-password/RecoverPasswordForm/index.tsx
@@ -1,13 +1,12 @@
'use client'
+import Link from 'next/link'
import React, { Fragment, useCallback, useState } from 'react'
import { useForm } from 'react-hook-form'
-import Link from 'next/link'
import { Button } from '../../../_components/Button'
import { Input } from '../../../_components/Input'
import { Message } from '../../../_components/Message'
-
import classes from './index.module.scss'
type FormData = {
@@ -19,20 +18,20 @@ export const RecoverPasswordForm: React.FC = () => {
const [success, setSuccess] = useState(false)
const {
- register,
- handleSubmit,
formState: { errors },
+ handleSubmit,
+ register,
} = useForm()
const onSubmit = useCallback(async (data: FormData) => {
const response = await fetch(
`${process.env.NEXT_PUBLIC_SERVER_URL}/api/users/forgot-password`,
{
- method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json',
},
+ method: 'POST',
},
)
@@ -55,24 +54,23 @@ export const RecoverPasswordForm: React.FC = () => {
{`Please enter your email below. You will receive an email message with instructions on
how to reset your password. To manage your all users, `}
- login to the admin dashboard
- {'.'}
+ login to the admin dashboard.
-
-
+
+
diff --git a/templates/ecommerce/src/app/(pages)/recover-password/index.module.scss b/templates/ecommerce/src/app/(pages)/recover-password/index.module.scss
index f8ca34afc0..8efcaedd30 100644
--- a/templates/ecommerce/src/app/(pages)/recover-password/index.module.scss
+++ b/templates/ecommerce/src/app/(pages)/recover-password/index.module.scss
@@ -1,4 +1,4 @@
-@import "../../_css/common";
+@import '../../_css/common';
.recoverPassword {
margin-bottom: var(--block-padding);
diff --git a/templates/ecommerce/src/app/(pages)/recover-password/page.tsx b/templates/ecommerce/src/app/(pages)/recover-password/page.tsx
index c2739234c8..9a6e1f8224 100644
--- a/templates/ecommerce/src/app/(pages)/recover-password/page.tsx
+++ b/templates/ecommerce/src/app/(pages)/recover-password/page.tsx
@@ -1,10 +1,10 @@
+import type { Metadata } from 'next'
+
import React from 'react'
-import { Metadata } from 'next'
import { Gutter } from '../../_components/Gutter'
import { mergeOpenGraph } from '../../_utilities/mergeOpenGraph'
import { RecoverPasswordForm } from './RecoverPasswordForm'
-
import classes from './index.module.scss'
export default async function RecoverPassword() {
@@ -16,10 +16,10 @@ export default async function RecoverPassword() {
}
export const metadata: Metadata = {
- title: 'Recover Password',
description: 'Enter your email address to recover your password.',
openGraph: mergeOpenGraph({
title: 'Recover Password',
url: '/recover-password',
}),
+ title: 'Recover Password',
}
diff --git a/templates/ecommerce/src/app/(pages)/reset-password/ResetPasswordForm/index.module.scss b/templates/ecommerce/src/app/(pages)/reset-password/ResetPasswordForm/index.module.scss
index e0e52429a3..0be4a8800b 100644
--- a/templates/ecommerce/src/app/(pages)/reset-password/ResetPasswordForm/index.module.scss
+++ b/templates/ecommerce/src/app/(pages)/reset-password/ResetPasswordForm/index.module.scss
@@ -1,4 +1,4 @@
-@import "../../../_css/common";
+@import '../../../_css/common';
.form {
width: 66.66%;
diff --git a/templates/ecommerce/src/app/(pages)/reset-password/ResetPasswordForm/index.tsx b/templates/ecommerce/src/app/(pages)/reset-password/ResetPasswordForm/index.tsx
index 6c455013c8..4c4caa7bd6 100644
--- a/templates/ecommerce/src/app/(pages)/reset-password/ResetPasswordForm/index.tsx
+++ b/templates/ecommerce/src/app/(pages)/reset-password/ResetPasswordForm/index.tsx
@@ -1,14 +1,13 @@
'use client'
+import { useRouter, useSearchParams } from 'next/navigation'
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 = {
@@ -24,9 +23,9 @@ export const ResetPasswordForm: React.FC = () => {
const token = searchParams.get('token')
const {
- register,
- handleSubmit,
formState: { errors },
+ handleSubmit,
+ register,
reset,
} = useForm()
@@ -35,11 +34,11 @@ export const ResetPasswordForm: React.FC = () => {
const response = await fetch(
`${process.env.NEXT_PUBLIC_SERVER_URL}/api/users/reset-password`,
{
- method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json',
},
+ method: 'POST',
},
)
@@ -65,22 +64,22 @@ export const ResetPasswordForm: React.FC = () => {
}, [reset, token])
return (
-
-
+
+
)
diff --git a/templates/ecommerce/src/app/(pages)/reset-password/page.tsx b/templates/ecommerce/src/app/(pages)/reset-password/page.tsx
index 1d18a8aa9e..0cb9786af9 100644
--- a/templates/ecommerce/src/app/(pages)/reset-password/page.tsx
+++ b/templates/ecommerce/src/app/(pages)/reset-password/page.tsx
@@ -1,10 +1,10 @@
+import type { Metadata } from 'next'
+
import React from 'react'
-import { Metadata } from 'next'
import { Gutter } from '../../_components/Gutter'
import { mergeOpenGraph } from '../../_utilities/mergeOpenGraph'
import { ResetPasswordForm } from './ResetPasswordForm'
-
import classes from './index.module.scss'
export default async function ResetPassword() {
@@ -18,10 +18,10 @@ export default async function ResetPassword() {
}
export const metadata: Metadata = {
- title: 'Reset Password',
description: 'Enter a new password.',
openGraph: mergeOpenGraph({
title: 'Reset Password',
url: '/reset-password',
}),
+ title: 'Reset Password',
}
diff --git a/templates/ecommerce/src/app/(pages)/styleguide/buttons/page.tsx b/templates/ecommerce/src/app/(pages)/styleguide/buttons/page.tsx
index b12d702cba..6d8080e1d0 100644
--- a/templates/ecommerce/src/app/(pages)/styleguide/buttons/page.tsx
+++ b/templates/ecommerce/src/app/(pages)/styleguide/buttons/page.tsx
@@ -1,6 +1,7 @@
-import React, { Fragment } from 'react'
-import { Metadata } from 'next'
+import type { Metadata } from 'next'
+
import Link from 'next/link'
+import React, { Fragment } from 'react'
import { CallToActionBlock } from '../../../_blocks/CallToAction'
import { Button } from '../../../_components/Button'
@@ -21,11 +22,11 @@ export default async function ButtonsPage() {
-
+
-
+
-
+
@@ -33,10 +34,10 @@ export default async function ButtonsPage() {
}
export const metadata: Metadata = {
- title: 'Buttons',
description: 'Styleguide for Buttons',
openGraph: mergeOpenGraph({
title: 'Buttons',
url: '/styleguide/buttons',
}),
+ title: 'Buttons',
}
diff --git a/templates/ecommerce/src/app/(pages)/styleguide/call-to-action/page.tsx b/templates/ecommerce/src/app/(pages)/styleguide/call-to-action/page.tsx
index 6e6c833573..9c0eb1f909 100644
--- a/templates/ecommerce/src/app/(pages)/styleguide/call-to-action/page.tsx
+++ b/templates/ecommerce/src/app/(pages)/styleguide/call-to-action/page.tsx
@@ -1,6 +1,7 @@
-import React, { Fragment } from 'react'
-import { Metadata } from 'next'
+import type { Metadata } from 'next'
+
import Link from 'next/link'
+import React, { Fragment } from 'react'
import { CallToActionBlock } from '../../../_blocks/CallToAction'
import { Gutter } from '../../../_components/Gutter'
@@ -21,6 +22,17 @@ export default async function CallToActionPage() {
@@ -90,10 +91,10 @@ export default async function CallToActionPage() {
}
export const metadata: Metadata = {
- title: 'Call To Action Block',
description: 'Styleguide for the Call To Action Block',
openGraph: mergeOpenGraph({
title: 'Call To Action Block',
url: '/styleguide/call-to-action',
}),
+ title: 'Call To Action Block',
}
diff --git a/templates/ecommerce/src/app/(pages)/styleguide/content-block/page.tsx b/templates/ecommerce/src/app/(pages)/styleguide/content-block/page.tsx
index 105dd80a2a..965126da1c 100644
--- a/templates/ecommerce/src/app/(pages)/styleguide/content-block/page.tsx
+++ b/templates/ecommerce/src/app/(pages)/styleguide/content-block/page.tsx
@@ -1,6 +1,7 @@
-import React, { Fragment } from 'react'
-import { Metadata } from 'next'
+import type { Metadata } from 'next'
+
import Link from 'next/link'
+import React, { Fragment } from 'react'
import { ContentBlock } from '../../../_blocks/Content'
import { Gutter } from '../../../_components/Gutter'
@@ -23,12 +24,12 @@ export default async function ContentBlockPage() {
blockType="content"
columns={[
{
- size: 'full',
richText: [
{
text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
},
],
+ size: 'full',
},
]}
/>
@@ -38,10 +39,10 @@ export default async function ContentBlockPage() {
}
export const metadata: Metadata = {
- title: 'Content Block',
description: 'Styleguide for the Content Block',
openGraph: mergeOpenGraph({
title: 'Content Block',
url: '/styleguide/content-block',
}),
+ title: 'Content Block',
}
diff --git a/templates/ecommerce/src/app/(pages)/styleguide/media-block/page.tsx b/templates/ecommerce/src/app/(pages)/styleguide/media-block/page.tsx
index d74f1d2b67..17c33111f0 100644
--- a/templates/ecommerce/src/app/(pages)/styleguide/media-block/page.tsx
+++ b/templates/ecommerce/src/app/(pages)/styleguide/media-block/page.tsx
@@ -1,6 +1,7 @@
-import React, { Fragment } from 'react'
-import { Metadata } from 'next'
+import type { Metadata } from 'next'
+
import Link from 'next/link'
+import React, { Fragment } from 'react'
import staticImage from '../../../../../public/static-image.jpg'
import { MediaBlock } from '../../../_blocks/MediaBlock'
@@ -20,13 +21,13 @@ export default async function MediaBlockPage() {
Media Block
-
+
@@ -35,10 +36,10 @@ export default async function MediaBlockPage() {
}
export const metadata: Metadata = {
- title: 'Media Block',
description: 'Styleguide for media block.',
openGraph: mergeOpenGraph({
title: 'Media Block',
url: '/styleguide/media-block',
}),
+ title: 'Media Block',
}
diff --git a/templates/ecommerce/src/app/(pages)/styleguide/message/page.tsx b/templates/ecommerce/src/app/(pages)/styleguide/message/page.tsx
index f6c5764045..2055d27015 100644
--- a/templates/ecommerce/src/app/(pages)/styleguide/message/page.tsx
+++ b/templates/ecommerce/src/app/(pages)/styleguide/message/page.tsx
@@ -1,6 +1,7 @@
-import React, { Fragment } from 'react'
-import { Metadata } from 'next'
+import type { Metadata } from 'next'
+
import Link from 'next/link'
+import React, { Fragment } from 'react'
import { Gutter } from '../../../_components/Gutter'
import { Message } from '../../../_components/Message'
@@ -34,10 +35,10 @@ export default async function MessageComponentPage() {
}
export const metadata: Metadata = {
- title: 'Message Component',
description: 'Styleguide for message component.',
openGraph: mergeOpenGraph({
title: 'Message Component',
url: '/styleguide/message',
}),
+ title: 'Message Component',
}
diff --git a/templates/ecommerce/src/app/(pages)/styleguide/page.tsx b/templates/ecommerce/src/app/(pages)/styleguide/page.tsx
index f7d3a74ffe..cb9aa20402 100644
--- a/templates/ecommerce/src/app/(pages)/styleguide/page.tsx
+++ b/templates/ecommerce/src/app/(pages)/styleguide/page.tsx
@@ -1,6 +1,7 @@
-import React from 'react'
-import { Metadata } from 'next'
+import type { Metadata } from 'next'
+
import Link from 'next/link'
+import React from 'react'
import { Gutter } from '../../_components/Gutter'
import { VerticalPadding } from '../../_components/VerticalPadding'
@@ -30,10 +31,10 @@ export default async function Typography() {
}
export const metadata: Metadata = {
- title: 'Styleguide',
description: 'Styleguide',
openGraph: mergeOpenGraph({
title: 'Styleguide',
url: '/styleguide',
}),
+ title: 'Styleguide',
}
diff --git a/templates/ecommerce/src/app/(pages)/styleguide/typography/page.tsx b/templates/ecommerce/src/app/(pages)/styleguide/typography/page.tsx
index 87a6939860..f9eea69266 100644
--- a/templates/ecommerce/src/app/(pages)/styleguide/typography/page.tsx
+++ b/templates/ecommerce/src/app/(pages)/styleguide/typography/page.tsx
@@ -1,6 +1,7 @@
-import React from 'react'
-import { Metadata } from 'next'
+import type { Metadata } from 'next'
+
import Link from 'next/link'
+import React from 'react'
import { Gutter } from '../../../_components/Gutter'
import { VerticalPadding } from '../../../_components/VerticalPadding'
@@ -45,10 +46,10 @@ export default async function Typography() {
}
export const metadata: Metadata = {
- title: 'Typography',
description: 'Styleguide for typography.',
openGraph: mergeOpenGraph({
title: 'Typography',
url: '/styleguide/typography',
}),
+ title: 'Typography',
}
diff --git a/templates/ecommerce/src/app/_api/fetchDoc.ts b/templates/ecommerce/src/app/_api/fetchDoc.ts
index 8f2c3f53ad..b122f6930b 100644
--- a/templates/ecommerce/src/app/_api/fetchDoc.ts
+++ b/templates/ecommerce/src/app/_api/fetchDoc.ts
@@ -1,6 +1,7 @@
import type { RequestCookie } from 'next/dist/compiled/@edge-runtime/cookies'
import type { Config } from '../../payload/payload-types'
+
import { ORDER } from '../_graphql/orders'
import { PAGE } from '../_graphql/pages'
import { PRODUCT } from '../_graphql/products'
@@ -8,27 +9,27 @@ import { GRAPHQL_API_URL } from './shared'
import { payloadToken } from './token'
const queryMap = {
+ orders: {
+ key: 'Orders',
+ query: ORDER,
+ },
pages: {
- query: PAGE,
key: 'Pages',
+ query: PAGE,
},
products: {
- query: PRODUCT,
key: 'Products',
- },
- orders: {
- query: ORDER,
- key: 'Orders',
+ query: PRODUCT,
},
}
export const fetchDoc = async (args: {
collection: keyof Config['collections']
- slug?: string
- id?: string
draft?: boolean
+ id?: string
+ slug?: string
}): Promise => {
- const { collection, slug, draft } = args || {}
+ const { slug, collection, draft } = args || {}
if (!queryMap[collection]) throw new Error(`Collection ${collection} not found`)
@@ -40,13 +41,6 @@ export const fetchDoc = async (args: {
}
const doc: T = await fetch(`${GRAPHQL_API_URL}/api/graphql`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- ...(token?.value && draft ? { Authorization: `JWT ${token.value}` } : {}),
- },
- cache: 'no-store',
- next: { tags: [`${collection}_${slug}`] },
body: JSON.stringify({
query: queryMap[collection].query,
variables: {
@@ -54,9 +48,16 @@ export const fetchDoc = async (args: {
draft,
},
}),
+ cache: 'no-store',
+ headers: {
+ 'Content-Type': 'application/json',
+ ...(token?.value && draft ? { Authorization: `JWT ${token.value}` } : {}),
+ },
+ method: 'POST',
+ next: { tags: [`${collection}_${slug}`] },
})
- ?.then(res => res.json())
- ?.then(res => {
+ ?.then((res) => res.json())
+ ?.then((res) => {
if (res.errors) throw new Error(res?.errors?.[0]?.message ?? 'Error fetching doc')
return res?.data?.[queryMap[collection].key]?.docs?.[0]
})
diff --git a/templates/ecommerce/src/app/_api/fetchDocs.ts b/templates/ecommerce/src/app/_api/fetchDocs.ts
index 657863d1e2..9c50176a23 100644
--- a/templates/ecommerce/src/app/_api/fetchDocs.ts
+++ b/templates/ecommerce/src/app/_api/fetchDocs.ts
@@ -1,6 +1,7 @@
import type { RequestCookie } from 'next/dist/compiled/@edge-runtime/cookies'
import type { Config } from '../../payload/payload-types'
+
import { ORDERS } from '../_graphql/orders'
import { PAGES } from '../_graphql/pages'
import { PRODUCTS } from '../_graphql/products'
@@ -8,17 +9,17 @@ import { GRAPHQL_API_URL } from './shared'
import { payloadToken } from './token'
const queryMap = {
+ orders: {
+ key: 'Orders',
+ query: ORDERS,
+ },
pages: {
- query: PAGES,
key: 'Pages',
+ query: PAGES,
},
products: {
- query: PRODUCTS,
key: 'Products',
- },
- orders: {
- query: ORDERS,
- key: 'Orders',
+ query: PRODUCTS,
},
}
@@ -36,19 +37,19 @@ export const fetchDocs = async (
}
const docs: T[] = await fetch(`${GRAPHQL_API_URL}/api/graphql`, {
- method: 'POST',
+ body: JSON.stringify({
+ query: queryMap[collection].query,
+ }),
+ cache: 'no-store',
headers: {
'Content-Type': 'application/json',
...(token?.value && draft ? { Authorization: `JWT ${token.value}` } : {}),
},
- cache: 'no-store',
+ method: 'POST',
next: { tags: [collection] },
- body: JSON.stringify({
- query: queryMap[collection].query,
- }),
})
- ?.then(res => res.json())
- ?.then(res => {
+ ?.then((res) => res.json())
+ ?.then((res) => {
if (res.errors) throw new Error(res?.errors?.[0]?.message ?? 'Error fetching docs')
return res?.data?.[queryMap[collection].key]?.docs
diff --git a/templates/ecommerce/src/app/_api/fetchGlobals.ts b/templates/ecommerce/src/app/_api/fetchGlobals.ts
index 4402ad45c3..74d520a21a 100644
--- a/templates/ecommerce/src/app/_api/fetchGlobals.ts
+++ b/templates/ecommerce/src/app/_api/fetchGlobals.ts
@@ -1,4 +1,5 @@
import type { Footer, Header, Settings } from '../../payload/payload-types'
+
import { FOOTER_QUERY, HEADER_QUERY, SETTINGS_QUERY } from '../_graphql/globals'
import { GRAPHQL_API_URL } from './shared'
@@ -6,20 +7,20 @@ export async function fetchSettings(): Promise {
if (!process.env.NEXT_PUBLIC_SERVER_URL) throw new Error('NEXT_PUBLIC_SERVER_URL not found')
const settings = await fetch(`${GRAPHQL_API_URL}/api/graphql`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- cache: 'no-store',
body: JSON.stringify({
query: SETTINGS_QUERY,
}),
+ cache: 'no-store',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ method: 'POST',
})
- ?.then(res => {
+ ?.then((res) => {
if (!res.ok) throw new Error('Error fetching doc')
return res.json()
})
- ?.then(res => {
+ ?.then((res) => {
if (res?.errors) throw new Error(res?.errors[0]?.message || 'Error fetching settings')
return res.data?.Settings
})
@@ -31,20 +32,20 @@ export async function fetchHeader(): Promise {
if (!GRAPHQL_API_URL) throw new Error('NEXT_PUBLIC_SERVER_URL not found')
const header = await fetch(`${GRAPHQL_API_URL}/api/graphql`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- cache: 'no-store',
body: JSON.stringify({
query: HEADER_QUERY,
}),
+ cache: 'no-store',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ method: 'POST',
})
- ?.then(res => {
+ ?.then((res) => {
if (!res.ok) throw new Error('Error fetching doc')
return res.json()
})
- ?.then(res => {
+ ?.then((res) => {
if (res?.errors) throw new Error(res?.errors[0]?.message || 'Error fetching header')
return res.data?.Header
})
@@ -56,19 +57,19 @@ export async function fetchFooter(): Promise {
if (!GRAPHQL_API_URL) throw new Error('NEXT_PUBLIC_SERVER_URL not found')
const footer = await fetch(`${GRAPHQL_API_URL}/api/graphql`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
body: JSON.stringify({
query: FOOTER_QUERY,
}),
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ method: 'POST',
})
- .then(res => {
+ .then((res) => {
if (!res.ok) throw new Error('Error fetching doc')
return res.json()
})
- ?.then(res => {
+ ?.then((res) => {
if (res?.errors) throw new Error(res?.errors[0]?.message || 'Error fetching footer')
return res.data?.Footer
})
@@ -77,9 +78,9 @@ export async function fetchFooter(): Promise {
}
export const fetchGlobals = async (): Promise<{
- settings: Settings
- header: Header
footer: Footer
+ header: Header
+ settings: Settings
}> => {
// initiate requests in parallel, then wait for them to resolve
// this will eagerly start to the fetch requests at the same time
@@ -95,8 +96,8 @@ export const fetchGlobals = async (): Promise<{
])
return {
- settings,
- header,
footer,
+ header,
+ settings,
}
}
diff --git a/templates/ecommerce/src/app/_api/getMe.ts b/templates/ecommerce/src/app/_api/getMe.ts
index 2751f7a97a..69f63744ff 100644
--- a/templates/ecommerce/src/app/_api/getMe.ts
+++ b/templates/ecommerce/src/app/_api/getMe.ts
@@ -2,6 +2,7 @@ import { cookies } from 'next/headers'
import { redirect } from 'next/navigation'
import type { User } from '../../payload/payload-types'
+
import { ME_QUERY } from '../_graphql/me'
import { GRAPHQL_API_URL } from './shared'
@@ -9,23 +10,23 @@ export const getMe = async (args?: {
nullUserRedirect?: string
userRedirect?: string
}): Promise<{
- user: User
token: string
+ user: User
}> => {
const { nullUserRedirect, userRedirect } = args || {}
const cookieStore = cookies()
const token = cookieStore.get('payload-token')?.value
const meUserReq = await fetch(`${GRAPHQL_API_URL}/api/graphql`, {
- method: 'POST',
+ body: JSON.stringify({
+ query: ME_QUERY,
+ }),
+ cache: 'no-store',
headers: {
Authorization: `JWT ${token}`,
'Content-Type': 'application/json',
},
- cache: 'no-store',
- body: JSON.stringify({
- query: ME_QUERY,
- }),
+ method: 'POST',
})
const {
@@ -43,7 +44,7 @@ export const getMe = async (args?: {
}
return {
- user,
token,
+ user,
}
}
diff --git a/templates/ecommerce/src/app/_blocks/ArchiveBlock/index.tsx b/templates/ecommerce/src/app/_blocks/ArchiveBlock/index.tsx
index f7c035f32d..fdfbc55b86 100644
--- a/templates/ecommerce/src/app/_blocks/ArchiveBlock/index.tsx
+++ b/templates/ecommerce/src/app/_blocks/ArchiveBlock/index.tsx
@@ -1,44 +1,44 @@
import React from 'react'
+import type { ArchiveBlockProps } from './types'
+
import { CollectionArchive } from '../../_components/CollectionArchive'
import { Gutter } from '../../_components/Gutter'
import RichText from '../../_components/RichText'
-import { ArchiveBlockProps } from './types'
-
import classes from './index.module.scss'
export const ArchiveBlock: React.FC<
ArchiveBlockProps & {
id?: string
}
-> = props => {
+> = (props) => {
const {
- introContent,
id,
- relationTo,
- populateBy,
+ categories,
+ introContent,
limit,
+ populateBy,
populatedDocs,
populatedDocsTotal,
+ relationTo,
selectedDocs,
- categories,
} = props
return (
-
+
{introContent && (
)}
diff --git a/templates/ecommerce/src/app/_blocks/CallToAction/index.module.scss b/templates/ecommerce/src/app/_blocks/CallToAction/index.module.scss
index 8246bd19f2..babbe2e8d8 100644
--- a/templates/ecommerce/src/app/_blocks/CallToAction/index.module.scss
+++ b/templates/ecommerce/src/app/_blocks/CallToAction/index.module.scss
@@ -10,7 +10,7 @@ $spacer-h: calc(var(--block-padding) / 2);
color: var(--theme-elevation-1000);
}
-:global([data-theme="dark"]) {
+:global([data-theme='dark']) {
.callToAction {
background-color: var(--theme-elevation-0);
color: var(--theme-elevation-1000);
@@ -22,7 +22,7 @@ $spacer-h: calc(var(--block-padding) / 2);
color: var(--theme-elevation-0);
}
-:global([data-theme="dark"]) {
+:global([data-theme='dark']) {
.invert {
background-color: var(--theme-elevation-900);
color: var(--theme-elevation-0);
diff --git a/templates/ecommerce/src/app/_blocks/CallToAction/index.tsx b/templates/ecommerce/src/app/_blocks/CallToAction/index.tsx
index 1b78d340cb..b645b1182c 100644
--- a/templates/ecommerce/src/app/_blocks/CallToAction/index.tsx
+++ b/templates/ecommerce/src/app/_blocks/CallToAction/index.tsx
@@ -1,11 +1,11 @@
import React from 'react'
-import { Page } from '../../../payload/payload-types'
+import type { Page } from '../../../payload/payload-types'
+
import { Gutter } from '../../_components/Gutter'
import { CMSLink } from '../../_components/Link'
import RichText from '../../_components/RichText'
import { VerticalPadding } from '../../_components/VerticalPadding'
-
import classes from './index.module.scss'
type Props = Extract
@@ -14,7 +14,7 @@ export const CallToActionBlock: React.FC<
Props & {
id?: string
}
-> = ({ links, richText, invertBackground }) => {
+> = ({ invertBackground, links, richText }) => {
return (
@@ -13,7 +13,7 @@ export const ContentBlock: React.FC<
Props & {
id?: string
}
-> = props => {
+> = (props) => {
const { columns } = props
return (
@@ -22,10 +22,10 @@ export const ContentBlock: React.FC<
{columns &&
columns.length > 0 &&
columns.map((col, index) => {
- const { enableLink, richText, link, size } = col
+ const { enableLink, link, richText, size } = col
return (
-
+
{enableLink && }
diff --git a/templates/ecommerce/src/app/_blocks/MediaBlock/index.module.scss b/templates/ecommerce/src/app/_blocks/MediaBlock/index.module.scss
index 382b807b42..a67ce6abe4 100644
--- a/templates/ecommerce/src/app/_blocks/MediaBlock/index.module.scss
+++ b/templates/ecommerce/src/app/_blocks/MediaBlock/index.module.scss
@@ -4,5 +4,5 @@
.caption {
color: var(--theme-elevation-500);
- margin-top: var(--base)
+ margin-top: var(--base);
}
diff --git a/templates/ecommerce/src/app/_blocks/MediaBlock/index.tsx b/templates/ecommerce/src/app/_blocks/MediaBlock/index.tsx
index af448e06e4..2d6025badb 100644
--- a/templates/ecommerce/src/app/_blocks/MediaBlock/index.tsx
+++ b/templates/ecommerce/src/app/_blocks/MediaBlock/index.tsx
@@ -1,19 +1,20 @@
-import React from 'react'
-import { StaticImageData } from 'next/image'
+import type { StaticImageData } from 'next/image'
+
+import React from 'react'
+
+import type { Page } from '../../../payload/payload-types'
-import { Page } from '../../../payload/payload-types'
import { Gutter } from '../../_components/Gutter'
import { Media } from '../../_components/Media'
import RichText from '../../_components/RichText'
-
import classes from './index.module.scss'
type Props = Extract
& {
- staticImage?: StaticImageData
id?: string
+ staticImage?: StaticImageData
}
-export const MediaBlock: React.FC = props => {
+export const MediaBlock: React.FC = (props) => {
const { media, position = 'default', staticImage } = props
let caption
diff --git a/templates/ecommerce/src/app/_blocks/RelatedProducts/index.tsx b/templates/ecommerce/src/app/_blocks/RelatedProducts/index.tsx
index 02c0d35bf6..92c67da8ef 100644
--- a/templates/ecommerce/src/app/_blocks/RelatedProducts/index.tsx
+++ b/templates/ecommerce/src/app/_blocks/RelatedProducts/index.tsx
@@ -1,22 +1,22 @@
import React from 'react'
-import { Product } from '../../../payload/payload-types'
+import type { Product } from '../../../payload/payload-types'
+
import { Card } from '../../_components/Card'
import { Gutter } from '../../_components/Gutter'
import RichText from '../../_components/RichText'
-
import classes from './index.module.scss'
export type RelatedProductsProps = {
- blockType: 'relatedProducts'
blockName: string
+ blockType: 'relatedProducts'
+ docs?: (Product | string)[]
introContent?: any
- docs?: (string | Product)[]
relationTo: 'products'
}
-export const RelatedProducts: React.FC = props => {
- const { introContent, docs, relationTo } = props
+export const RelatedProducts: React.FC = (props) => {
+ const { docs, introContent, relationTo } = props
return (
@@ -32,7 +32,6 @@ export const RelatedProducts: React.FC
= props => {
return (
= props => {
]
.filter(Boolean)
.join(' ')}
+ key={index}
>
-
+
)
})}
diff --git a/templates/ecommerce/src/app/_components/AddToCartButton/index.tsx b/templates/ecommerce/src/app/_components/AddToCartButton/index.tsx
index edce5442d7..d1430f79dc 100644
--- a/templates/ecommerce/src/app/_components/AddToCartButton/index.tsx
+++ b/templates/ecommerce/src/app/_components/AddToCartButton/index.tsx
@@ -1,23 +1,24 @@
'use client'
-import React, { useEffect, useState } from 'react'
import { useRouter } from 'next/navigation'
+import React, { useEffect, useState } from 'react'
+
+import type { Product } from '../../../payload/payload-types'
+import type { Props } from '../Button'
-import { Product } from '../../../payload/payload-types'
import { useCart } from '../../_providers/Cart'
-import { Button, Props } from '../Button'
-
+import { Button } from '../Button'
import classes from './index.module.scss'
export const AddToCartButton: React.FC<{
+ appearance?: Props['appearance']
+ className?: string
product: Product
quantity?: number
- className?: string
- appearance?: Props['appearance']
-}> = props => {
- const { product, quantity = 1, className, appearance = 'primary' } = props
+}> = (props) => {
+ const { appearance = 'primary', className, product, quantity = 1 } = props
- const { cart, addItemToCart, isProductInCart, hasInitializedCart } = useCart()
+ const { addItemToCart, cart, hasInitializedCart, isProductInCart } = useCart()
const [isInCart, setIsInCart] = useState()
const router = useRouter()
@@ -28,10 +29,6 @@ export const AddToCartButton: React.FC<{
return (
{
@@ -53,6 +53,7 @@ export const AddToCartButton: React.FC<{
}
: undefined
}
+ type={!isInCart ? 'button' : undefined}
/>
)
}
diff --git a/templates/ecommerce/src/app/_components/AdminBar/index.module.scss b/templates/ecommerce/src/app/_components/AdminBar/index.module.scss
index 01854a8514..726c4b4992 100644
--- a/templates/ecommerce/src/app/_components/AdminBar/index.module.scss
+++ b/templates/ecommerce/src/app/_components/AdminBar/index.module.scss
@@ -10,7 +10,7 @@
transition: opacity 150ms linear;
}
-:global([data-theme="dark"]) {
+:global([data-theme='dark']) {
.adminBar {
background-color: var(--theme-elevation-0);
}
diff --git a/templates/ecommerce/src/app/_components/AdminBar/index.tsx b/templates/ecommerce/src/app/_components/AdminBar/index.tsx
index d83c80b79c..5696954196 100644
--- a/templates/ecommerce/src/app/_components/AdminBar/index.tsx
+++ b/templates/ecommerce/src/app/_components/AdminBar/index.tsx
@@ -1,19 +1,20 @@
'use client'
-import React, { useEffect } from 'react'
+import type { PayloadAdminBarProps } from 'payload-admin-bar'
+
import { useSelectedLayoutSegments } from 'next/navigation'
-import { PayloadAdminBar, PayloadAdminBarProps } from 'payload-admin-bar'
+import { PayloadAdminBar } from 'payload-admin-bar'
+import React, { useEffect } from 'react'
import { useAuth } from '../../_providers/Auth'
import { Gutter } from '../Gutter'
-
import classes from './index.module.scss'
const Title: React.FC = () => Dashboard
export const AdminBar: React.FC<{
adminBarProps?: PayloadAdminBarProps
-}> = props => {
+}> = (props) => {
const { adminBarProps } = props || {}
const segments = useSelectedLayoutSegments()
const collection = segments?.[1] === 'products' ? 'products' : 'pages'
@@ -36,25 +37,25 @@ export const AdminBar: React.FC<{
}
style={{
+ backgroundColor: 'transparent',
+ padding: 0,
position: 'relative',
zIndex: 'unset',
- padding: 0,
- backgroundColor: 'transparent',
}}
/>
diff --git a/templates/ecommerce/src/app/_components/BackgroundColor/index.module.scss b/templates/ecommerce/src/app/_components/BackgroundColor/index.module.scss
index 13dd061f53..f1b2cdd7db 100644
--- a/templates/ecommerce/src/app/_components/BackgroundColor/index.module.scss
+++ b/templates/ecommerce/src/app/_components/BackgroundColor/index.module.scss
@@ -3,7 +3,7 @@
color: var(--theme-bg);
}
-:global([data-theme="dark"]) {
+:global([data-theme='dark']) {
.invert {
background-color: var(--theme-elevation-100);
color: var(--theme-text);
diff --git a/templates/ecommerce/src/app/_components/BackgroundColor/index.tsx b/templates/ecommerce/src/app/_components/BackgroundColor/index.tsx
index 578a34b496..1af1433c31 100644
--- a/templates/ecommerce/src/app/_components/BackgroundColor/index.tsx
+++ b/templates/ecommerce/src/app/_components/BackgroundColor/index.tsx
@@ -3,17 +3,17 @@ import React from 'react'
import classes from './index.module.scss'
type Props = {
- invert?: boolean
- className?: string
children?: React.ReactNode
+ className?: string
id?: string
+ invert?: boolean
}
-export const BackgroundColor: React.FC = props => {
- const { id, className, children, invert } = props
+export const BackgroundColor: React.FC = (props) => {
+ const { id, children, className, invert } = props
return (
-
+
{children}
)
diff --git a/templates/ecommerce/src/app/_components/Blocks/index.tsx b/templates/ecommerce/src/app/_components/Blocks/index.tsx
index 94647dcda7..76ef1c39ad 100644
--- a/templates/ecommerce/src/app/_components/Blocks/index.tsx
+++ b/templates/ecommerce/src/app/_components/Blocks/index.tsx
@@ -1,6 +1,8 @@
import React, { Fragment } from 'react'
-import { Page } from '../../../payload/payload-types.js'
+import type { Page } from '../../../payload/payload-types.js'
+import type { VerticalPaddingOptions } from '../VerticalPadding/index'
+
import { ArchiveBlock } from '../../_blocks/ArchiveBlock'
import { CallToActionBlock } from '../../_blocks/CallToAction'
import { ContentBlock } from '../../_blocks/Content'
@@ -8,21 +10,21 @@ import { MediaBlock } from '../../_blocks/MediaBlock'
import { RelatedProducts, type RelatedProductsProps } from '../../_blocks/RelatedProducts'
import { toKebabCase } from '../../_utilities/toKebabCase'
import { BackgroundColor } from '../BackgroundColor/index'
-import { VerticalPadding, VerticalPaddingOptions } from '../VerticalPadding/index'
+import { VerticalPadding } from '../VerticalPadding/index'
const blockComponents = {
- cta: CallToActionBlock,
- content: ContentBlock,
- mediaBlock: MediaBlock,
archive: ArchiveBlock,
+ content: ContentBlock,
+ cta: CallToActionBlock,
+ mediaBlock: MediaBlock,
relatedProducts: RelatedProducts,
}
export const Blocks: React.FC<{
blocks: (Page['layout'][0] | RelatedProductsProps)[]
disableTopPadding?: boolean
-}> = props => {
- const { disableTopPadding, blocks } = props
+}> = (props) => {
+ const { blocks, disableTopPadding } = props
const hasBlocks = blocks && Array.isArray(blocks) && blocks.length > 0
@@ -62,8 +64,8 @@ export const Blocks: React.FC<{
if (Block) {
return (
-
-
+
+
void
- href?: string
- newTab?: boolean
+ appearance?: 'default' | 'none' | 'primary' | 'secondary'
className?: string
- type?: 'submit' | 'button'
disabled?: boolean
+ el?: 'a' | 'button' | 'link'
+ href?: string
invert?: boolean
+ label?: string
+ newTab?: boolean
+ onClick?: () => void
+ type?: 'button' | 'submit'
}
export const Button: React.FC = ({
- el: elFromProps = 'link',
- label,
- newTab,
- href,
+ type = 'button',
appearance,
className: classNameFromProps,
- onClick,
- type = 'button',
disabled,
+ el: elFromProps = 'link',
+ href,
invert,
+ label,
+ newTab,
+ onClick,
}) => {
let el = elFromProps
- const newTabProps = newTab ? { target: '_blank', rel: 'noopener noreferrer' } : {}
+ const newTabProps = newTab ? { rel: 'noopener noreferrer', target: '_blank' } : {}
const className = [
classes.button,
@@ -53,7 +55,7 @@ export const Button: React.FC = ({
if (el === 'link') {
return (
-
+
{content}
)
@@ -63,12 +65,12 @@ export const Button: React.FC = ({
return (
{content}
diff --git a/templates/ecommerce/src/app/_components/Card/index.module.scss b/templates/ecommerce/src/app/_components/Card/index.module.scss
index 081e6b5803..afcd018f5c 100644
--- a/templates/ecommerce/src/app/_components/Card/index.module.scss
+++ b/templates/ecommerce/src/app/_components/Card/index.module.scss
@@ -1,6 +1,6 @@
@import '../../_css/common';
-.card {
+.card {
border: 1px var(--theme-elevation-200) solid;
border-radius: 4px;
height: 100%;
diff --git a/templates/ecommerce/src/app/_components/Card/index.tsx b/templates/ecommerce/src/app/_components/Card/index.tsx
index 98bfce8e3a..c7920833a9 100644
--- a/templates/ecommerce/src/app/_components/Card/index.tsx
+++ b/templates/ecommerce/src/app/_components/Card/index.tsx
@@ -1,12 +1,12 @@
'use client'
-import React, { Fragment, useEffect, useState } from 'react'
import Link from 'next/link'
+import React, { Fragment, useEffect, useState } from 'react'
+
+import type { Product } from '../../../payload/payload-types'
-import { Product } from '../../../payload/payload-types'
import { Media } from '../Media'
import { Price } from '../Price'
-
import classes from './index.module.scss'
const priceFromJSON = (priceJSON): string => {
@@ -36,18 +36,18 @@ const priceFromJSON = (priceJSON): string => {
export const Card: React.FC<{
alignItems?: 'center'
className?: string
- showCategories?: boolean
- hideImagesOnMobile?: boolean
- title?: string
- relationTo?: 'products'
doc?: Product
-}> = props => {
+ hideImagesOnMobile?: boolean
+ relationTo?: 'products'
+ showCategories?: boolean
+ title?: string
+}> = (props) => {
const {
+ className,
+ doc,
+ doc: { slug, categories, meta, priceJSON, title } = {},
showCategories,
title: titleFromProps,
- doc,
- doc: { slug, title, categories, meta, priceJSON } = {},
- className,
} = props
const { description, image: metaImage } = meta || {}
@@ -68,10 +68,10 @@ export const Card: React.FC<{
return (
-
+
{!metaImage &&
No image
}
{metaImage && typeof metaImage !== 'string' && (
-
+
)}
@@ -103,7 +103,7 @@ export const Card: React.FC<{
)}
{titleToUse && (
-
+
{titleToUse}
diff --git a/templates/ecommerce/src/app/_components/CartLink/index.tsx b/templates/ecommerce/src/app/_components/CartLink/index.tsx
index d120a677b2..5ab7af9fdf 100644
--- a/templates/ecommerce/src/app/_components/CartLink/index.tsx
+++ b/templates/ecommerce/src/app/_components/CartLink/index.tsx
@@ -1,15 +1,14 @@
'use client'
-import React, { Fragment, useEffect, useState } from 'react'
import Link from 'next/link'
+import React, { Fragment, useEffect, useState } from 'react'
import { useCart } from '../../_providers/Cart'
-
import classes from './index.module.scss'
export const CartLink: React.FC<{
className?: string
-}> = props => {
+}> = (props) => {
const { className } = props
const { cart } = useCart()
const [length, setLength] = useState
()
diff --git a/templates/ecommerce/src/app/_components/Chevron/index.tsx b/templates/ecommerce/src/app/_components/Chevron/index.tsx
index 3421d10b80..4364a211f3 100644
--- a/templates/ecommerce/src/app/_components/Chevron/index.tsx
+++ b/templates/ecommerce/src/app/_components/Chevron/index.tsx
@@ -6,19 +6,19 @@ export const Chevron: React.FC<{
}> = ({ className, rotate }) => {
return (
diff --git a/templates/ecommerce/src/app/_components/CollectionArchive/index.module.scss b/templates/ecommerce/src/app/_components/CollectionArchive/index.module.scss
index 3d302be9fe..dbe4cddda6 100644
--- a/templates/ecommerce/src/app/_components/CollectionArchive/index.module.scss
+++ b/templates/ecommerce/src/app/_components/CollectionArchive/index.module.scss
@@ -6,7 +6,7 @@
left: 0;
top: calc(var(--base) * -5);
@include mid-break {
- top: calc(var(--base) * -2);
+ top: calc(var(--base) * -2);
}
}
diff --git a/templates/ecommerce/src/app/_components/CollectionArchive/index.tsx b/templates/ecommerce/src/app/_components/CollectionArchive/index.tsx
index 7b1ecba204..eb1525b39f 100644
--- a/templates/ecommerce/src/app/_components/CollectionArchive/index.tsx
+++ b/templates/ecommerce/src/app/_components/CollectionArchive/index.tsx
@@ -1,15 +1,15 @@
'use client'
-import React, { Fragment, useCallback, useEffect, useRef, useState } from 'react'
import qs from 'qs'
+import React, { Fragment, useCallback, useEffect, useRef, useState } from 'react'
import type { Product } from '../../../payload/payload-types'
import type { ArchiveBlockProps } from '../../_blocks/ArchiveBlock/types'
+
import { Card } from '../Card'
import { Gutter } from '../Gutter'
import { PageRange } from '../PageRange'
import { Pagination } from '../Pagination'
-
import classes from './index.module.scss'
type Result = {
@@ -37,7 +37,7 @@ export type Props = {
sort?: string
}
-export const CollectionArchive: React.FC = props => {
+export const CollectionArchive: React.FC = (props) => {
const {
categories: catsFromProps,
className,
@@ -58,7 +58,7 @@ export const CollectionArchive: React.FC = props => {
: populateBy === 'selection'
? selectedDocs
: []
- )?.map(doc => doc.value),
+ )?.map((doc) => doc.value),
hasNextPage: false,
hasPrevPage: false,
nextPage: 1,
@@ -76,7 +76,7 @@ export const CollectionArchive: React.FC = props => {
const [page, setPage] = useState(1)
const categories = (catsFromProps || [])
- .map(cat => (typeof cat === 'object' ? cat?.id : cat))
+ .map((cat) => (typeof cat === 'object' ? cat?.id : cat))
.join(',')
const scrollToRef = useCallback(() => {
diff --git a/templates/ecommerce/src/app/_components/Footer/index.module.scss b/templates/ecommerce/src/app/_components/Footer/index.module.scss
index eb9d5e11ad..8938ab4e22 100644
--- a/templates/ecommerce/src/app/_components/Footer/index.module.scss
+++ b/templates/ecommerce/src/app/_components/Footer/index.module.scss
@@ -10,7 +10,7 @@
}
}
-:global([data-theme="dark"]) {
+:global([data-theme='dark']) {
.footer {
background-color: var(--theme-elevation-50);
color: var(--theme-elevation-1000);
diff --git a/templates/ecommerce/src/app/_components/Footer/index.tsx b/templates/ecommerce/src/app/_components/Footer/index.tsx
index 63be39e717..514484374f 100644
--- a/templates/ecommerce/src/app/_components/Footer/index.tsx
+++ b/templates/ecommerce/src/app/_components/Footer/index.tsx
@@ -1,12 +1,12 @@
-import React from 'react'
import Link from 'next/link'
+import React from 'react'
+
+import type { Footer } from '../../../payload/payload-types'
-import { Footer } from '../../../payload/payload-types'
import { fetchFooter, fetchGlobals } from '../../_api/fetchGlobals'
import { ThemeSelector } from '../../_providers/Theme/ThemeSelector'
import { Gutter } from '../Gutter'
import { CMSLink } from '../Link'
-
import classes from './index.module.scss'
export async function Footer() {
@@ -29,8 +29,8 @@ export async function Footer() {
@@ -43,12 +43,12 @@ export async function Footer() {
Admin
Source Code
-
+
Payload
diff --git a/templates/ecommerce/src/app/_components/Gutter/index.tsx b/templates/ecommerce/src/app/_components/Gutter/index.tsx
index 3cabc4ac58..3845a1a62f 100644
--- a/templates/ecommerce/src/app/_components/Gutter/index.tsx
+++ b/templates/ecommerce/src/app/_components/Gutter/index.tsx
@@ -1,21 +1,22 @@
-import React, { forwardRef, Ref } from 'react'
+import type { Ref } from 'react'
+
+import React, { forwardRef } from 'react'
import classes from './index.module.scss'
type Props = {
- left?: boolean
- right?: boolean
- className?: string
children: React.ReactNode
+ className?: string
+ left?: boolean
ref?: Ref
+ right?: boolean
}
export const Gutter: React.FC = forwardRef((props, ref) => {
- const { left = true, right = true, className, children } = props
+ const { children, className, left = true, right = true } = props
return (
= forwardRef((props,
]
.filter(Boolean)
.join(' ')}
+ ref={ref}
>
{children}
diff --git a/templates/ecommerce/src/app/_components/HR/index.tsx b/templates/ecommerce/src/app/_components/HR/index.tsx
index 6685170eb8..1485cdb02f 100644
--- a/templates/ecommerce/src/app/_components/HR/index.tsx
+++ b/templates/ecommerce/src/app/_components/HR/index.tsx
@@ -4,7 +4,7 @@ import classes from './index.module.scss'
export const HR: React.FC<{
className?: string
-}> = props => {
+}> = (props) => {
const { className } = props
return
diff --git a/templates/ecommerce/src/app/_components/Header/Nav/index.tsx b/templates/ecommerce/src/app/_components/Header/Nav/index.tsx
index 18b1e80f95..60a2c26368 100644
--- a/templates/ecommerce/src/app/_components/Header/Nav/index.tsx
+++ b/templates/ecommerce/src/app/_components/Header/Nav/index.tsx
@@ -1,13 +1,14 @@
'use client'
-import React from 'react'
import Link from 'next/link'
+import React from 'react'
-import { Header as HeaderType, User } from '../../../../payload/payload-types'
+import type { Header as HeaderType } from '../../../../payload/payload-types'
+
+import { User } from '../../../../payload/payload-types'
import { useAuth } from '../../../_providers/Auth'
import { CartLink } from '../../CartLink'
import { CMSLink } from '../../Link'
-
import classes from './index.module.scss'
export const HeaderNav: React.FC<{ header: HeaderType }> = ({ header }) => {
diff --git a/templates/ecommerce/src/app/_components/Header/index.module.scss b/templates/ecommerce/src/app/_components/Header/index.module.scss
index 9478b92ec8..7a648b2a55 100644
--- a/templates/ecommerce/src/app/_components/Header/index.module.scss
+++ b/templates/ecommerce/src/app/_components/Header/index.module.scss
@@ -15,7 +15,7 @@
width: 150px;
}
-:global([data-theme="light"]) {
+:global([data-theme='light']) {
.logo {
filter: invert(1);
}
diff --git a/templates/ecommerce/src/app/_components/Header/index.tsx b/templates/ecommerce/src/app/_components/Header/index.tsx
index 8244c56f78..38ef3287fb 100644
--- a/templates/ecommerce/src/app/_components/Header/index.tsx
+++ b/templates/ecommerce/src/app/_components/Header/index.tsx
@@ -2,14 +2,14 @@
/* eslint-disable @next/next/no-img-element */
}
-import React from 'react'
import Link from 'next/link'
+import React from 'react'
+
+import type { Header } from '../../../payload/payload-types'
-import { Header } from '../../../payload/payload-types'
import { fetchHeader } from '../../_api/fetchGlobals'
import { Gutter } from '../Gutter'
import { HeaderNav } from './Nav'
-
import classes from './index.module.scss'
export async function Header() {
@@ -25,7 +25,7 @@ export async function Header() {
}
return (
- <>
+
@@ -35,14 +35,14 @@ export async function Header() {
Instead, we just use CSS to invert the color via `filter: invert(1)` based on `[data-theme="dark"]`
*/}
- >
+
)
}
diff --git a/templates/ecommerce/src/app/_components/Hero/index.tsx b/templates/ecommerce/src/app/_components/Hero/index.tsx
index d534975003..16025c48fd 100644
--- a/templates/ecommerce/src/app/_components/Hero/index.tsx
+++ b/templates/ecommerce/src/app/_components/Hero/index.tsx
@@ -1,17 +1,18 @@
import React from 'react'
-import { Page } from '../../../payload/payload-types'
+import type { Page } from '../../../payload/payload-types'
+
import { HighImpactHero } from '../../_heros/HighImpact'
import { LowImpactHero } from '../../_heros/LowImpact'
import { MediumImpactHero } from '../../_heros/MediumImpact'
const heroes = {
highImpact: HighImpactHero,
- mediumImpact: MediumImpactHero,
lowImpact: LowImpactHero,
+ mediumImpact: MediumImpactHero,
}
-export const Hero: React.FC = props => {
+export const Hero: React.FC = (props) => {
const { type } = props || {}
if (!type || type === 'none') return null
diff --git a/templates/ecommerce/src/app/_components/Input/index.module.scss b/templates/ecommerce/src/app/_components/Input/index.module.scss
index 8a71e663ac..60fddd6774 100644
--- a/templates/ecommerce/src/app/_components/Input/index.module.scss
+++ b/templates/ecommerce/src/app/_components/Input/index.module.scss
@@ -36,7 +36,7 @@
color: var(--color-error-500);
}
-:global([data-theme="dark"]) {
+:global([data-theme='dark']) {
.input {
background-color: var(--theme-elevation-150);
}
diff --git a/templates/ecommerce/src/app/_components/Input/index.tsx b/templates/ecommerce/src/app/_components/Input/index.tsx
index 19715d7b1b..f099e57719 100644
--- a/templates/ecommerce/src/app/_components/Input/index.tsx
+++ b/templates/ecommerce/src/app/_components/Input/index.tsx
@@ -1,32 +1,34 @@
+import type { FieldValues, UseFormRegister } from 'react-hook-form'
+
import React from 'react'
-import { FieldValues, UseFormRegister, Validate } from 'react-hook-form'
+import { Validate } from 'react-hook-form'
import classes from './index.module.scss'
type Props = {
- name: string
+ disabled?: boolean
+ error: any
label: string
+ name: string
register: UseFormRegister
required?: boolean
- error: any
- type?: 'text' | 'number' | 'password' | 'email'
+ type?: 'email' | 'number' | 'password' | 'text'
validate?: (value: string) => boolean | string
- disabled?: boolean
}
export const Input: React.FC = ({
name,
- label,
- required,
- register,
- error,
type = 'text',
- validate,
disabled,
+ error,
+ label,
+ register,
+ required,
+ validate,
}) => {
return (
-
+
{label}
{required ? * : ''}
@@ -39,8 +41,8 @@ export const Input: React.FC = ({
...(type === 'email'
? {
pattern: {
- value: /\S+@\S+\.\S+/,
message: 'Please enter a valid email',
+ value: /\S[^\s@]*@\S+\.\S+/,
},
}
: {}),
diff --git a/templates/ecommerce/src/app/_components/Link/index.tsx b/templates/ecommerce/src/app/_components/Link/index.tsx
index 818b622d44..053f38fec6 100644
--- a/templates/ecommerce/src/app/_components/Link/index.tsx
+++ b/templates/ecommerce/src/app/_components/Link/index.tsx
@@ -1,34 +1,36 @@
-import React from 'react'
import Link from 'next/link'
+import React from 'react'
-import { Page } from '../../../payload/payload-types'
-import { Button, Props as ButtonProps } from '../Button'
+import type { Page } from '../../../payload/payload-types'
+import type { Props as ButtonProps } from '../Button'
+
+import { Button } from '../Button'
type CMSLinkType = {
- type?: 'custom' | 'reference'
- url?: string
- newTab?: boolean
- reference?: {
- value: string | Page
- relationTo: 'pages'
- }
- label?: string
appearance?: ButtonProps['appearance']
children?: React.ReactNode
className?: string
invert?: ButtonProps['invert']
+ label?: string
+ newTab?: boolean
+ reference?: {
+ relationTo: 'pages'
+ value: Page | string
+ }
+ type?: 'custom' | 'reference'
+ url?: string
}
export const CMSLink: React.FC = ({
type,
- url,
- newTab,
- reference,
- label,
appearance,
children,
className,
invert,
+ label,
+ newTab,
+ reference,
+ url,
}) => {
const href =
type === 'reference' && typeof reference?.value === 'object' && reference.value.slug
@@ -40,11 +42,11 @@ export const CMSLink: React.FC = ({
if (!href) return null
if (!appearance) {
- const newTabProps = newTab ? { target: '_blank', rel: 'noopener noreferrer' } : {}
+ const newTabProps = newTab ? { rel: 'noopener noreferrer', target: '_blank' } : {}
if (href || url) {
return (
-
+
{label && label}
{children && children}
@@ -54,12 +56,12 @@ export const CMSLink: React.FC = ({
return (
)
}
diff --git a/templates/ecommerce/src/app/_components/LoadingShimmer/index.module.scss b/templates/ecommerce/src/app/_components/LoadingShimmer/index.module.scss
index ba0242e9f9..1cd76ac6d7 100644
--- a/templates/ecommerce/src/app/_components/LoadingShimmer/index.module.scss
+++ b/templates/ecommerce/src/app/_components/LoadingShimmer/index.module.scss
@@ -1,29 +1,29 @@
@import '../../_css/common';
@keyframes shimmer {
- 0% {
- opacity: 1;
- }
- 50% {
- opacity: .75;
- }
- 100% {
- opacity: 1;
- }
+ 0% {
+ opacity: 1;
+ }
+ 50% {
+ opacity: 0.75;
+ }
+ 100% {
+ opacity: 1;
+ }
}
.loading {
- & > *:not(:last-child) {
- margin-bottom: var(--base);
- }
+ & > *:not(:last-child) {
+ margin-bottom: var(--base);
+ }
}
.shimmer {
- width: 100%;
- height: calc(var(--base) * 2.5); // same as input height `formInput`
- background-color: var(--theme-elevation-200);
- border-radius: 1px;
- opacity: 1;
- will-change: opacity;
- animation: shimmer 1s infinite;
+ width: 100%;
+ height: calc(var(--base) * 2.5); // same as input height `formInput`
+ background-color: var(--theme-elevation-200);
+ border-radius: 1px;
+ opacity: 1;
+ will-change: opacity;
+ animation: shimmer 1s infinite;
}
diff --git a/templates/ecommerce/src/app/_components/LoadingShimmer/index.tsx b/templates/ecommerce/src/app/_components/LoadingShimmer/index.tsx
index bc8c8891a5..647962083e 100644
--- a/templates/ecommerce/src/app/_components/LoadingShimmer/index.tsx
+++ b/templates/ecommerce/src/app/_components/LoadingShimmer/index.tsx
@@ -3,15 +3,15 @@ import React from 'react'
import classes from './index.module.scss'
export const LoadingShimmer: React.FC<{
- number?: number
height?: number // in `base` units
-}> = props => {
+ number?: number
+}> = (props) => {
const arrayFromNumber = Array.from(Array(props.number || 1).keys())
return (
{arrayFromNumber.map((_, index) => (
-
+
))}
)
diff --git a/templates/ecommerce/src/app/_components/Media/Image/index.tsx b/templates/ecommerce/src/app/_components/Media/Image/index.tsx
index aa68241aad..128532a182 100644
--- a/templates/ecommerce/src/app/_components/Media/Image/index.tsx
+++ b/templates/ecommerce/src/app/_components/Media/Image/index.tsx
@@ -1,25 +1,27 @@
'use client'
+import type { StaticImageData } from 'next/image'
+
+import NextImage from 'next/image'
import React from 'react'
-import NextImage, { StaticImageData } from 'next/image'
+
+import type { Props as MediaProps } from '../types'
import cssVariables from '../../../cssVariables'
-import { Props as MediaProps } from '../types'
-
import classes from './index.module.scss'
const { breakpoints } = cssVariables
-export const Image: React.FC = props => {
+export const Image: React.FC = (props) => {
const {
+ alt: altFromProps,
+ fill,
imgClassName,
onClick,
onLoad: onLoadFromProps,
- resource,
priority,
- fill,
+ resource,
src: srcFromProps,
- alt: altFromProps,
} = props
const [isLoading, setIsLoading] = React.useState(true)
@@ -31,10 +33,10 @@ export const Image: React.FC = props => {
if (!src && resource && typeof resource !== 'string') {
const {
- width: fullWidth,
- height: fullHeight,
- filename: fullFilename,
alt: altFromResource,
+ filename: fullFilename,
+ height: fullHeight,
+ width: fullWidth,
} = resource
width = fullWidth
@@ -53,11 +55,12 @@ export const Image: React.FC = props => {
return (
{
setIsLoading(false)
@@ -65,11 +68,10 @@ export const Image: React.FC = props => {
onLoadFromProps()
}
}}
- fill={fill}
- width={!fill ? width : undefined}
- height={!fill ? height : undefined}
- sizes={sizes}
priority={priority}
+ sizes={sizes}
+ src={src}
+ width={!fill ? width : undefined}
/>
)
}
diff --git a/templates/ecommerce/src/app/_components/Media/Video/index.tsx b/templates/ecommerce/src/app/_components/Media/Video/index.tsx
index b0d09f4f7c..70f3d7e9f2 100644
--- a/templates/ecommerce/src/app/_components/Media/Video/index.tsx
+++ b/templates/ecommerce/src/app/_components/Media/Video/index.tsx
@@ -2,12 +2,12 @@
import React, { useEffect, useRef } from 'react'
-import { Props as MediaProps } from '../types'
+import type { Props as MediaProps } from '../types'
import classes from './index.module.scss'
-export const Video: React.FC = props => {
- const { videoClassName, resource, onClick } = props
+export const Video: React.FC = (props) => {
+ const { onClick, resource, videoClassName } = props
const videoRef = useRef(null)
// const [showFallback] = useState()
@@ -27,13 +27,13 @@ export const Video: React.FC = props => {
return (
diff --git a/templates/ecommerce/src/app/_components/Media/index.tsx b/templates/ecommerce/src/app/_components/Media/index.tsx
index 0cebca49cd..3462e60a31 100644
--- a/templates/ecommerce/src/app/_components/Media/index.tsx
+++ b/templates/ecommerce/src/app/_components/Media/index.tsx
@@ -1,14 +1,17 @@
-import React, { ElementType, Fragment } from 'react'
+import type { ElementType } from 'react'
+
+import React, { Fragment } from 'react'
+
+import type { Props } from './types'
import { Image } from './Image'
-import { Props } from './types'
import { Video } from './Video'
-export const Media: React.FC = props => {
- const { className, resource, htmlElement = 'div' } = props
+export const Media: React.FC = (props) => {
+ const { className, htmlElement = 'div', resource } = props
const isVideo = typeof resource !== 'string' && resource?.mimeType?.includes('video')
- const Tag = (htmlElement as ElementType) || Fragment
+ const Tag = htmlElement || Fragment
return (
void
onLoad?: () => void
- ref?: Ref
+ priority?: boolean // for NextImage only
+ ref?: Ref
+ resource?: MediaType | string // for Payload media
+ size?: string // for NextImage only
+ src?: StaticImageData // for static media
+ videoClassName?: string
}
diff --git a/templates/ecommerce/src/app/_components/Message/index.module.scss b/templates/ecommerce/src/app/_components/Message/index.module.scss
index 899932a15b..c81fe5bf72 100644
--- a/templates/ecommerce/src/app/_components/Message/index.module.scss
+++ b/templates/ecommerce/src/app/_components/Message/index.module.scss
@@ -26,7 +26,7 @@
color: var(--theme-success-900);
}
-:global([data-theme="dark"]) {
+:global([data-theme='dark']) {
.default {
background-color: var(--theme-elevation-900);
color: var(--theme-elevation-100);
diff --git a/templates/ecommerce/src/app/_components/Message/index.tsx b/templates/ecommerce/src/app/_components/Message/index.tsx
index 3cd8060868..6abd3ba342 100644
--- a/templates/ecommerce/src/app/_components/Message/index.tsx
+++ b/templates/ecommerce/src/app/_components/Message/index.tsx
@@ -3,12 +3,12 @@ import React from 'react'
import classes from './index.module.scss'
export const Message: React.FC<{
- message?: React.ReactNode
+ className?: string
error?: React.ReactNode
+ message?: React.ReactNode
success?: React.ReactNode
warning?: React.ReactNode
- className?: string
-}> = ({ message, error, success, warning, className }) => {
+}> = ({ className, error, message, success, warning }) => {
const messageToRender = message || error || success || warning
if (messageToRender) {
diff --git a/templates/ecommerce/src/app/_components/PageRange/index.tsx b/templates/ecommerce/src/app/_components/PageRange/index.tsx
index 8320a7c7dd..8b1899ec43 100644
--- a/templates/ecommerce/src/app/_components/PageRange/index.tsx
+++ b/templates/ecommerce/src/app/_components/PageRange/index.tsx
@@ -24,7 +24,7 @@ export const PageRange: React.FC<{
currentPage?: number
limit?: number
totalDocs?: number
-}> = props => {
+}> = (props) => {
const {
className,
collection,
diff --git a/templates/ecommerce/src/app/_components/Pagination/index.tsx b/templates/ecommerce/src/app/_components/Pagination/index.tsx
index 6d3c06cd42..8c6a34b770 100644
--- a/templates/ecommerce/src/app/_components/Pagination/index.tsx
+++ b/templates/ecommerce/src/app/_components/Pagination/index.tsx
@@ -1,30 +1,29 @@
import React from 'react'
import { Chevron } from '../Chevron'
-
import classes from './index.module.scss'
export const Pagination: React.FC<{
+ className?: string
+ onClick: (page: number) => void
page: number
totalPages: number
- onClick: (page: number) => void
- className?: string
-}> = props => {
- const { page, totalPages, onClick, className } = props
+}> = (props) => {
+ const { className, onClick, page, totalPages } = props
const hasNextPage = page < totalPages
const hasPrevPage = page > 1
return (
{
onClick(page - 1)
}}
+ type="button"
>
-
+
@@ -32,14 +31,14 @@ export const Pagination: React.FC<{
{
onClick(page + 1)
}}
+ type="button"
>
-
+
)
diff --git a/templates/ecommerce/src/app/_components/PaywallBlocks/index.tsx b/templates/ecommerce/src/app/_components/PaywallBlocks/index.tsx
index 3efb7ac70c..2589464766 100644
--- a/templates/ecommerce/src/app/_components/PaywallBlocks/index.tsx
+++ b/templates/ecommerce/src/app/_components/PaywallBlocks/index.tsx
@@ -1,9 +1,10 @@
'use client'
-import React, { useEffect } from 'react'
import Link from 'next/link'
+import React, { useEffect } from 'react'
+
+import type { Page } from '../../../payload/payload-types'
-import { Page } from '../../../payload/payload-types'
import { PRODUCT_PAYWALL } from '../../_graphql/products'
import { useAuth } from '../../_providers/Auth'
import { Blocks } from '../Blocks'
@@ -13,10 +14,10 @@ import { Message } from '../Message'
import { VerticalPadding } from '../VerticalPadding'
export const PaywallBlocks: React.FC<{
- productSlug: string
disableTopPadding?: boolean
-}> = props => {
- const { productSlug, disableTopPadding } = props
+ productSlug: string
+}> = (props) => {
+ const { disableTopPadding, productSlug } = props
const { user } = useAuth()
const [isLoading, setIsLoading] = React.useState(false)
@@ -36,20 +37,20 @@ export const PaywallBlocks: React.FC<{
try {
const paywall = await fetch(`${process.env.NEXT_PUBLIC_SERVER_URL}/api/graphql`, {
- method: 'POST',
- credentials: 'include',
- headers: {
- 'Content-Type': 'application/json',
- },
body: JSON.stringify({
query: PRODUCT_PAYWALL,
variables: {
slug: productSlug,
},
}),
+ credentials: 'include',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ method: 'POST',
})
- ?.then(res => res.json())
- ?.then(res => res?.data?.Products.docs[0]?.paywall)
+ ?.then((res) => res.json())
+ ?.then((res) => res?.data?.Products.docs[0]?.paywall)
if (paywall) {
setBlocks(paywall)
@@ -59,7 +60,7 @@ export const PaywallBlocks: React.FC<{
// this is to prevent a flash of the loading shimmer on fast networks
const end = Date.now()
if (end - start < 1000) {
- await new Promise(resolve => setTimeout(resolve, 500 - (end - start)))
+ await new Promise((resolve) => setTimeout(resolve, 500 - (end - start)))
}
setIsLoading(false)
@@ -82,13 +83,13 @@ export const PaywallBlocks: React.FC<{
+
{`This content is gated behind a paywall. You must be `}
logged in
{` as an admin or have purchased this product to view this content.`}
- >
+
}
/>
diff --git a/templates/ecommerce/src/app/_components/Price/index.tsx b/templates/ecommerce/src/app/_components/Price/index.tsx
index 3635b841eb..5dc31f5b57 100644
--- a/templates/ecommerce/src/app/_components/Price/index.tsx
+++ b/templates/ecommerce/src/app/_components/Price/index.tsx
@@ -2,10 +2,10 @@
import React, { useEffect, useState } from 'react'
-import { Product } from '../../../payload/payload-types'
+import type { Product } from '../../../payload/payload-types'
+
import { AddToCartButton } from '../AddToCartButton'
import { RemoveFromCartButton } from '../RemoveFromCartButton'
-
import classes from './index.module.scss'
export const priceFromJSON = (priceJSON: string, quantity: number = 1, raw?: boolean): string => {
@@ -20,8 +20,8 @@ export const priceFromJSON = (priceJSON: string, quantity: number = 1, raw?: boo
if (raw) return priceValue.toString()
price = (priceValue / 100).toLocaleString('en-US', {
- style: 'currency',
currency: 'USD', // TODO: use `parsed.currency`
+ style: 'currency',
})
if (priceType === 'recurring') {
@@ -40,11 +40,11 @@ export const priceFromJSON = (priceJSON: string, quantity: number = 1, raw?: boo
}
export const Price: React.FC<{
+ button?: 'addToCart' | 'removeFromCart' | false
product: Product
quantity?: number
- button?: 'addToCart' | 'removeFromCart' | false
-}> = props => {
- const { product, product: { priceJSON } = {}, button = 'addToCart', quantity } = props
+}> = (props) => {
+ const { button = 'addToCart', product, product: { priceJSON } = {}, quantity } = props
const [price, setPrice] = useState<{
actualPrice: string
@@ -72,7 +72,7 @@ export const Price: React.FC<{
)}
{button && button === 'addToCart' && (
-
+
)}
{button && button === 'removeFromCart' && }
diff --git a/templates/ecommerce/src/app/_components/RemoveFromCartButton/index.tsx b/templates/ecommerce/src/app/_components/RemoveFromCartButton/index.tsx
index 4e3cf5aef1..b27e4ce4fa 100644
--- a/templates/ecommerce/src/app/_components/RemoveFromCartButton/index.tsx
+++ b/templates/ecommerce/src/app/_components/RemoveFromCartButton/index.tsx
@@ -1,14 +1,14 @@
import React from 'react'
-import { Product } from '../../../payload/payload-types'
-import { useCart } from '../../_providers/Cart'
+import type { Product } from '../../../payload/payload-types'
+import { useCart } from '../../_providers/Cart'
import classes from './index.module.scss'
export const RemoveFromCartButton: React.FC<{
className?: string
product: Product
-}> = props => {
+}> = (props) => {
const { className, product } = props
const { deleteItemFromCart, isProductInCart } = useCart()
@@ -21,11 +21,11 @@ export const RemoveFromCartButton: React.FC<{
return (
{
deleteItemFromCart(product)
}}
- className={[className, classes.removeFromCartButton].filter(Boolean).join(' ')}
+ type="button"
>
Remove
diff --git a/templates/ecommerce/src/app/_components/RenderParams/Component.tsx b/templates/ecommerce/src/app/_components/RenderParams/Component.tsx
index 13285dbe51..f911d35786 100644
--- a/templates/ecommerce/src/app/_components/RenderParams/Component.tsx
+++ b/templates/ecommerce/src/app/_components/RenderParams/Component.tsx
@@ -1,26 +1,25 @@
'use client'
-import { useEffect } from 'react'
import { useSearchParams } from 'next/navigation'
+import { useEffect } from 'react'
import { Message } from '../Message'
-
import classes from './index.module.scss'
export type Props = {
- params?: string[]
- message?: string
className?: string
- onParams?: (paramValues: ((string | null | undefined) | string[])[]) => void
+ message?: string
+ onParams?: (paramValues: ((null | string | undefined) | string[])[]) => void
+ params?: string[]
}
export const RenderParamsComponent: React.FC
= ({
- params = ['error', 'warning', 'success', 'message'],
className,
onParams,
+ params = ['error', 'warning', 'success', 'message'],
}) => {
const searchParams = useSearchParams()
- const paramValues = params.map(param => searchParams?.get(param))
+ const paramValues = params.map((param) => searchParams?.get(param))
useEffect(() => {
if (paramValues.length && onParams) {
diff --git a/templates/ecommerce/src/app/_components/RenderParams/index.tsx b/templates/ecommerce/src/app/_components/RenderParams/index.tsx
index d7a834dda5..dd8b1f9517 100644
--- a/templates/ecommerce/src/app/_components/RenderParams/index.tsx
+++ b/templates/ecommerce/src/app/_components/RenderParams/index.tsx
@@ -1,12 +1,14 @@
import { Suspense } from 'react'
-import { Props, RenderParamsComponent } from './Component'
+import type { Props } from './Component'
+
+import { RenderParamsComponent } from './Component'
// Using `useSearchParams` from `next/navigation` causes the entire route to de-optimize into client-side rendering
// To fix this, we wrap the component in a `Suspense` component
// See https://nextjs.org/docs/messages/deopted-into-client-rendering for more info
-export const RenderParams: React.FC = props => {
+export const RenderParams: React.FC = (props) => {
return (
diff --git a/templates/ecommerce/src/app/_components/RichText/index.tsx b/templates/ecommerce/src/app/_components/RichText/index.tsx
index 657d2d8d21..b0b28080cb 100644
--- a/templates/ecommerce/src/app/_components/RichText/index.tsx
+++ b/templates/ecommerce/src/app/_components/RichText/index.tsx
@@ -1,8 +1,7 @@
import React from 'react'
-import serialize from './serialize'
-
import classes from './index.module.scss'
+import serialize from './serialize'
const RichText: React.FC<{ className?: string; content: any }> = ({ className, content }) => {
if (!content) {
diff --git a/templates/ecommerce/src/app/_components/RichText/serialize.tsx b/templates/ecommerce/src/app/_components/RichText/serialize.tsx
index 89d6ac2ff9..b071b813d9 100644
--- a/templates/ecommerce/src/app/_components/RichText/serialize.tsx
+++ b/templates/ecommerce/src/app/_components/RichText/serialize.tsx
@@ -1,6 +1,6 @@
-import React, { Fragment } from 'react'
import escapeHTML from 'escape-html'
import Link from 'next/link'
+import React, { Fragment } from 'react'
import { Text } from 'slate'
import { Label } from '../Label'
@@ -11,14 +11,14 @@ import { CMSLink } from '../Link'
type Children = Leaf[]
type Leaf = {
- type: string
- value?: {
- url: string
- alt: string
- }
- children?: Children
- url?: string
[key: string]: unknown
+ children?: Children
+ type: string
+ url?: string
+ value?: {
+ alt: string
+ url: string
+ }
}
const serialize = (children?: Children): React.ReactNode[] =>
@@ -40,7 +40,7 @@ const serialize = (children?: Children): React.ReactNode[] =>
if (node.underline) {
text = (
-
+
{text}
)
@@ -48,7 +48,7 @@ const serialize = (children?: Children): React.ReactNode[] =>
if (node.strikethrough) {
text = (
-
+
{text}
)
@@ -86,10 +86,10 @@ const serialize = (children?: Children): React.ReactNode[] =>
return (
{serialize(node?.children)}
diff --git a/templates/ecommerce/src/app/_components/VerticalPadding/index.module.scss b/templates/ecommerce/src/app/_components/VerticalPadding/index.module.scss
index 2eaee30da5..a9db566e8c 100644
--- a/templates/ecommerce/src/app/_components/VerticalPadding/index.module.scss
+++ b/templates/ecommerce/src/app/_components/VerticalPadding/index.module.scss
@@ -12,4 +12,4 @@
.bottom-medium {
padding-bottom: calc(var(--block-padding) / 2);
-}
\ No newline at end of file
+}
diff --git a/templates/ecommerce/src/app/_components/VerticalPadding/index.tsx b/templates/ecommerce/src/app/_components/VerticalPadding/index.tsx
index 374aaba3d5..d17a341b11 100644
--- a/templates/ecommerce/src/app/_components/VerticalPadding/index.tsx
+++ b/templates/ecommerce/src/app/_components/VerticalPadding/index.tsx
@@ -5,17 +5,17 @@ import classes from './index.module.scss'
export type VerticalPaddingOptions = 'large' | 'medium' | 'none'
type Props = {
- top?: VerticalPaddingOptions
bottom?: VerticalPaddingOptions
children: React.ReactNode
className?: string
+ top?: VerticalPaddingOptions
}
export const VerticalPadding: React.FC = ({
- top = 'medium',
bottom = 'medium',
- className,
children,
+ className,
+ top = 'medium',
}) => {
return (
{
return (
-
+
)
diff --git a/templates/ecommerce/src/app/_components/icons/Menu/index.tsx b/templates/ecommerce/src/app/_components/icons/Menu/index.tsx
index 7fabd85751..c513d7ba79 100644
--- a/templates/ecommerce/src/app/_components/icons/Menu/index.tsx
+++ b/templates/ecommerce/src/app/_components/icons/Menu/index.tsx
@@ -2,10 +2,10 @@ import React from 'react'
export const MenuIcon: React.FC = () => {
return (
-
-
-
-
+
+
+
+
)
}
diff --git a/templates/ecommerce/src/app/_css/app.scss b/templates/ecommerce/src/app/_css/app.scss
index 438ede82c2..da67c2347f 100644
--- a/templates/ecommerce/src/app/_css/app.scss
+++ b/templates/ecommerce/src/app/_css/app.scss
@@ -1,7 +1,7 @@
@use './queries.scss' as *;
@use './colors.scss' as *;
@use './type.scss' as *;
-@import "./theme.scss";
+@import './theme.scss';
:root {
--base: 24px;
@@ -32,8 +32,8 @@ html {
-webkit-font-smoothing: antialiased;
opacity: 0;
- &[data-theme=dark],
- &[data-theme=light] {
+ &[data-theme='dark'],
+ &[data-theme='light'] {
opacity: initial;
}
}
@@ -94,7 +94,7 @@ p {
margin: var(--base) 0;
@include mid-break {
- margin: calc(var(--base) * .75) 0;
+ margin: calc(var(--base) * 0.75) 0;
}
}
@@ -108,12 +108,12 @@ a {
color: currentColor;
&:focus {
- opacity: .8;
+ opacity: 0.8;
outline: none;
}
&:active {
- opacity: .7;
+ opacity: 0.7;
outline: none;
}
}
diff --git a/templates/ecommerce/src/app/_css/colors.scss b/templates/ecommerce/src/app/_css/colors.scss
index a77dc79847..634cfb4245 100644
--- a/templates/ecommerce/src/app/_css/colors.scss
+++ b/templates/ecommerce/src/app/_css/colors.scss
@@ -83,5 +83,3 @@
--color-error-900: rgb(51, 22, 24);
--color-error-950: rgb(25, 11, 12);
}
-
-
diff --git a/templates/ecommerce/src/app/_css/common.scss b/templates/ecommerce/src/app/_css/common.scss
index 6b0f85715f..e66be0183d 100644
--- a/templates/ecommerce/src/app/_css/common.scss
+++ b/templates/ecommerce/src/app/_css/common.scss
@@ -1,2 +1,2 @@
@forward './queries.scss';
-@forward './type.scss';
\ No newline at end of file
+@forward './type.scss';
diff --git a/templates/ecommerce/src/app/_css/theme.scss b/templates/ecommerce/src/app/_css/theme.scss
index 5caf087879..17bd7caa9a 100644
--- a/templates/ecommerce/src/app/_css/theme.scss
+++ b/templates/ecommerce/src/app/_css/theme.scss
@@ -1,4 +1,4 @@
-[data-theme=light] {
+[data-theme='light'] {
--theme-success-50: var(--color-success-50);
--theme-success-100: var(--color-success-100);
--theme-success-150: var(--color-success-150);
@@ -117,7 +117,7 @@
}
}
-[data-theme=dark] {
+[data-theme='dark'] {
--theme-elevation-0: var(--color-base-1000);
--theme-elevation-50: var(--color-base-950);
--theme-elevation-100: var(--color-base-900);
diff --git a/templates/ecommerce/src/app/_graphql/link.ts b/templates/ecommerce/src/app/_graphql/link.ts
index fff0fc3197..9c211b4189 100644
--- a/templates/ecommerce/src/app/_graphql/link.ts
+++ b/templates/ecommerce/src/app/_graphql/link.ts
@@ -1,6 +1,6 @@
interface Args {
- disableLabel?: true
disableAppearance?: true
+ disableLabel?: true
}
export const LINK_FIELDS = ({ disableAppearance, disableLabel }: Args = {}): string => `{
diff --git a/templates/ecommerce/src/app/_heros/HighImpact/index.module.scss b/templates/ecommerce/src/app/_heros/HighImpact/index.module.scss
index 855b40cbba..d6bffc2a23 100644
--- a/templates/ecommerce/src/app/_heros/HighImpact/index.module.scss
+++ b/templates/ecommerce/src/app/_heros/HighImpact/index.module.scss
@@ -31,7 +31,7 @@
display: flex;
padding-top: var(--base);
flex-wrap: wrap;
- margin: calc(var(--base) * -.5);
+ margin: calc(var(--base) * -0.5);
& > * {
margin: calc(var(--base) / 2);
diff --git a/templates/ecommerce/src/app/_heros/HighImpact/index.tsx b/templates/ecommerce/src/app/_heros/HighImpact/index.tsx
index 95ead943ba..109616da9e 100644
--- a/templates/ecommerce/src/app/_heros/HighImpact/index.tsx
+++ b/templates/ecommerce/src/app/_heros/HighImpact/index.tsx
@@ -1,14 +1,14 @@
import React, { Fragment } from 'react'
-import { Page } from '../../../payload/payload-types'
+import type { Page } from '../../../payload/payload-types'
+
import { Gutter } from '../../_components/Gutter'
import { CMSLink } from '../../_components/Link'
import { Media } from '../../_components/Media'
import RichText from '../../_components/RichText'
-
import classes from './index.module.scss'
-export const HighImpactHero: React.FC = ({ richText, media, links }) => {
+export const HighImpactHero: React.FC = ({ links, media, richText }) => {
return (
@@ -29,12 +29,12 @@ export const HighImpactHero: React.FC
= ({ richText, media, links
{typeof media === 'object' && (
- {media?.caption && }
+ {media?.caption && }
)}
diff --git a/templates/ecommerce/src/app/_heros/LowImpact/index.tsx b/templates/ecommerce/src/app/_heros/LowImpact/index.tsx
index 749e0e587d..3b1a34c598 100644
--- a/templates/ecommerce/src/app/_heros/LowImpact/index.tsx
+++ b/templates/ecommerce/src/app/_heros/LowImpact/index.tsx
@@ -1,10 +1,10 @@
import React from 'react'
-import { Page } from '../../../payload/payload-types'
+import type { Page } from '../../../payload/payload-types'
+
import { Gutter } from '../../_components/Gutter'
import RichText from '../../_components/RichText'
import { VerticalPadding } from '../../_components/VerticalPadding'
-
import classes from './index.module.scss'
export const LowImpactHero: React.FC = ({ richText }) => {
diff --git a/templates/ecommerce/src/app/_heros/MediumImpact/index.tsx b/templates/ecommerce/src/app/_heros/MediumImpact/index.tsx
index 95f821d4f0..980844a51b 100644
--- a/templates/ecommerce/src/app/_heros/MediumImpact/index.tsx
+++ b/templates/ecommerce/src/app/_heros/MediumImpact/index.tsx
@@ -1,15 +1,15 @@
import React from 'react'
-import { Page } from '../../../payload/payload-types'
+import type { Page } from '../../../payload/payload-types'
+
import { Gutter } from '../../_components/Gutter'
import { CMSLink } from '../../_components/Link'
import { Media } from '../../_components/Media'
import RichText from '../../_components/RichText'
-
import classes from './index.module.scss'
-export const MediumImpactHero: React.FC = props => {
- const { richText, media, links } = props
+export const MediumImpactHero: React.FC = (props) => {
+ const { links, media, richText } = props
return (
diff --git a/templates/ecommerce/src/app/_heros/Product/index.tsx b/templates/ecommerce/src/app/_heros/Product/index.tsx
index 081220cd2b..4a7ab2f25f 100644
--- a/templates/ecommerce/src/app/_heros/Product/index.tsx
+++ b/templates/ecommerce/src/app/_heros/Product/index.tsx
@@ -1,14 +1,14 @@
-import React, { Fragment } from 'react'
import Link from 'next/link'
+import React, { Fragment } from 'react'
+
+import type { Product } from '../../../payload/payload-types'
-import { Product } from '../../../payload/payload-types'
import { AddToCartButton } from '../../_components/AddToCartButton'
import { Gutter } from '../../_components/Gutter'
import { Media } from '../../_components/Media'
import { Message } from '../../_components/Message'
import { Price } from '../../_components/Price'
import RichText from '../../_components/RichText'
-
import classes from './index.module.scss'
export const ProductHero: React.FC<{
@@ -16,10 +16,10 @@ export const ProductHero: React.FC<{
}> = ({ product }) => {
const {
id,
+ categories,
+ meta: { description, image: metaImage } = {},
stripeProductID,
title,
- categories,
- meta: { image: metaImage, description } = {},
} = product
return (
@@ -36,7 +36,7 @@ export const ProductHero: React.FC<{
>
edit this product in the admin panel
- {'.'}
+ .
}
/>
@@ -71,21 +71,21 @@ export const ProductHero: React.FC<{
navigate to the admin dashboard
- {'.'}
+ .
-
-
+
+
{!metaImage &&
No image
}
{metaImage && typeof metaImage !== 'string' && (
-
+
)}
{metaImage && typeof metaImage !== 'string' && metaImage?.caption && (
-
+
)}
diff --git a/templates/ecommerce/src/app/_providers/Auth/index.tsx b/templates/ecommerce/src/app/_providers/Auth/index.tsx
index 03a47ccb6f..19dc73cf2c 100644
--- a/templates/ecommerce/src/app/_providers/Auth/index.tsx
+++ b/templates/ecommerce/src/app/_providers/Auth/index.tsx
@@ -2,7 +2,7 @@
import React, { createContext, useCallback, useContext, useEffect, useState } from 'react'
-import { User } from '../../../payload/payload-types'
+import type { User } from '../../../payload/payload-types'
// eslint-disable-next-line no-unused-vars
type ResetPassword = (args: {
@@ -20,14 +20,14 @@ type Login = (args: { email: string; password: string }) => Promise // esl
type Logout = () => Promise
type AuthContext = {
- user?: User | null
- setUser: (user: User | null) => void // eslint-disable-line no-unused-vars
- logout: Logout
- login: Login
create: Create
- resetPassword: ResetPassword
forgotPassword: ForgotPassword
- status: undefined | 'loggedOut' | 'loggedIn'
+ login: Login
+ logout: Logout
+ resetPassword: ResetPassword
+ setUser: (user: User | null) => void // eslint-disable-line no-unused-vars
+ status: 'loggedIn' | 'loggedOut' | undefined
+ user?: User | null
}
const Context = createContext({} as AuthContext)
@@ -37,20 +37,20 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
// used to track the single event of logging in or logging out
// useful for `useEffect` hooks that should only run once
- const [status, setStatus] = useState()
- const create = useCallback(async args => {
+ const [status, setStatus] = useState<'loggedIn' | 'loggedOut' | undefined>()
+ const create = useCallback(async (args) => {
try {
const res = await fetch(`${process.env.NEXT_PUBLIC_SERVER_URL}/api/users/create`, {
- method: 'POST',
- credentials: 'include',
- headers: {
- 'Content-Type': 'application/json',
- },
body: JSON.stringify({
email: args.email,
password: args.password,
passwordConfirm: args.passwordConfirm,
}),
+ credentials: 'include',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ method: 'POST',
})
if (res.ok) {
@@ -66,22 +66,22 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
}
}, [])
- const login = useCallback(async args => {
+ const login = useCallback(async (args) => {
try {
const res = await fetch(`${process.env.NEXT_PUBLIC_SERVER_URL}/api/users/login`, {
- method: 'POST',
- credentials: 'include',
- headers: {
- 'Content-Type': 'application/json',
- },
body: JSON.stringify({
email: args.email,
password: args.password,
}),
+ credentials: 'include',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ method: 'POST',
})
if (res.ok) {
- const { user, errors } = await res.json()
+ const { errors, user } = await res.json()
if (errors) throw new Error(errors[0].message)
setUser(user)
setStatus('loggedIn')
@@ -97,11 +97,11 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
const logout = useCallback(async () => {
try {
const res = await fetch(`${process.env.NEXT_PUBLIC_SERVER_URL}/api/users/logout`, {
- method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/json',
},
+ method: 'POST',
})
if (res.ok) {
@@ -119,11 +119,11 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
const fetchMe = async () => {
try {
const res = await fetch(`${process.env.NEXT_PUBLIC_SERVER_URL}/api/users/me`, {
- method: 'GET',
credentials: 'include',
headers: {
'Content-Type': 'application/json',
},
+ method: 'GET',
})
if (res.ok) {
@@ -142,17 +142,17 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
fetchMe()
}, [])
- const forgotPassword = useCallback(async args => {
+ const forgotPassword = useCallback(async (args) => {
try {
const res = await fetch(`${process.env.NEXT_PUBLIC_SERVER_URL}/api/users/forgot-password`, {
- method: 'POST',
+ body: JSON.stringify({
+ email: args.email,
+ }),
credentials: 'include',
headers: {
'Content-Type': 'application/json',
},
- body: JSON.stringify({
- email: args.email,
- }),
+ method: 'POST',
})
if (res.ok) {
@@ -167,19 +167,19 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
}
}, [])
- const resetPassword = useCallback(async args => {
+ const resetPassword = useCallback(async (args) => {
try {
const res = await fetch(`${process.env.NEXT_PUBLIC_SERVER_URL}/api/users/reset-password`, {
- method: 'POST',
- credentials: 'include',
- headers: {
- 'Content-Type': 'application/json',
- },
body: JSON.stringify({
password: args.password,
passwordConfirm: args.passwordConfirm,
token: args.token,
}),
+ credentials: 'include',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ method: 'POST',
})
if (res.ok) {
@@ -198,14 +198,14 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
return (
{children}
diff --git a/templates/ecommerce/src/app/_providers/Cart/index.tsx b/templates/ecommerce/src/app/_providers/Cart/index.tsx
index f254efc526..5f0a890ba2 100644
--- a/templates/ecommerce/src/app/_providers/Cart/index.tsx
+++ b/templates/ecommerce/src/app/_providers/Cart/index.tsx
@@ -10,29 +10,31 @@ import React, {
useState,
} from 'react'
-import { Product, User } from '../../../payload/payload-types'
+import type { Product, User } from '../../../payload/payload-types'
+import type { CartItem } from './reducer'
+
import { useAuth } from '../Auth'
-import { CartItem, cartReducer } from './reducer'
+import { cartReducer } from './reducer'
export type CartContext = {
- cart: User['cart']
addItemToCart: (item: CartItem) => void
- deleteItemFromCart: (product: Product) => void
+ cart: User['cart']
cartIsEmpty: boolean | undefined
- clearCart: () => void
- isProductInCart: (product: Product) => boolean
cartTotal: {
formatted: string
raw: number
}
+ clearCart: () => void
+ deleteItemFromCart: (product: Product) => void
hasInitializedCart: boolean
+ isProductInCart: (product: Product) => boolean
}
const Context = createContext({} as CartContext)
export const useCart = () => useContext(Context)
-const arrayHasItems = array => Array.isArray(array) && array.length > 0
+const arrayHasItems = (array) => Array.isArray(array) && array.length > 0
/**
* ensure that cart items are fully populated, filter out any items that are not
@@ -41,7 +43,7 @@ const arrayHasItems = array => Array.isArray(array) && array.length > 0
const flattenCart = (cart: User['cart']): User['cart'] => ({
...cart,
items: cart.items
- .map(item => {
+ .map((item) => {
if (!item?.product || typeof item?.product !== 'object') {
return null
}
@@ -63,10 +65,10 @@ const flattenCart = (cart: User['cart']): User['cart'] => ({
// Step 4B: Sync the cart to Payload and clear local storage
// Step 5: If the user is logged out, sync the cart to local storage only
-export const CartProvider = props => {
+export const CartProvider = (props) => {
// const { setTimedNotification } = useNotifications();
const { children } = props
- const { user, status: authStatus } = useAuth()
+ const { status: authStatus, user } = useAuth()
const [cart, dispatchCart] = useReducer(cartReducer, {})
@@ -168,14 +170,14 @@ export const CartProvider = props => {
const syncCartToPayload = async () => {
const req = await fetch(`${process.env.NEXT_PUBLIC_SERVER_URL}/api/users/${user.id}`, {
// Make sure to include cookies with fetch
- credentials: 'include',
- method: 'PATCH',
body: JSON.stringify({
cart: flattenedCart,
}),
+ credentials: 'include',
headers: {
'Content-Type': 'application/json',
},
+ method: 'PATCH',
})
if (req.ok) {
@@ -213,7 +215,7 @@ export const CartProvider = props => {
)
// this method can be used to add new items AND update existing ones
- const addItemToCart = useCallback(incomingItem => {
+ const addItemToCart = useCallback((incomingItem) => {
dispatchCart({
type: 'ADD_ITEM',
payload: incomingItem,
@@ -250,8 +252,8 @@ export const CartProvider = props => {
setTotal({
formatted: (newTotal / 100).toLocaleString('en-US', {
- style: 'currency',
currency: 'USD',
+ style: 'currency',
}),
raw: newTotal,
})
@@ -260,14 +262,14 @@ export const CartProvider = props => {
return (
{children && children}
diff --git a/templates/ecommerce/src/app/_providers/Cart/reducer.ts b/templates/ecommerce/src/app/_providers/Cart/reducer.ts
index 347597804a..04171b8e42 100644
--- a/templates/ecommerce/src/app/_providers/Cart/reducer.ts
+++ b/templates/ecommerce/src/app/_providers/Cart/reducer.ts
@@ -6,20 +6,20 @@ type CartType = User['cart']
type CartAction =
| {
- type: 'SET_CART'
- payload: CartType
- }
- | {
- type: 'MERGE_CART'
- payload: CartType
- }
- | {
- type: 'ADD_ITEM'
payload: CartItem
+ type: 'ADD_ITEM'
+ }
+ | {
+ payload: CartType
+ type: 'MERGE_CART'
+ }
+ | {
+ payload: CartType
+ type: 'SET_CART'
}
| {
- type: 'DELETE_ITEM'
payload: Product
+ type: 'DELETE_ITEM'
}
| {
type: 'CLEAR_CART'
@@ -73,7 +73,7 @@ export const cartReducer = (cart: CartType, action: CartAction): CartType => {
typeof product === 'string' ? product === productId : product?.id === productId,
) // eslint-disable-line function-paren-newline
- let withAddedItem = [...(cart?.items || [])]
+ const withAddedItem = [...(cart?.items || [])]
if (indexInCart === -1) {
withAddedItem.push(incomingItem)
diff --git a/templates/ecommerce/src/app/_providers/Theme/InitTheme/index.tsx b/templates/ecommerce/src/app/_providers/Theme/InitTheme/index.tsx
index 12ab2541e3..206d655ee5 100644
--- a/templates/ecommerce/src/app/_providers/Theme/InitTheme/index.tsx
+++ b/templates/ecommerce/src/app/_providers/Theme/InitTheme/index.tsx
@@ -6,8 +6,6 @@ export const InitTheme: React.FC = () => {
return (
// eslint-disable-next-line @next/next/no-before-interactive-script-outside-document